using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Google.Apis.YouTube.v3; using Microsoft.EntityFrameworkCore; namespace YTManager.Tasks { public class FetchVideos { // Get a bunch of videos from youtube that the channel generated. public static async Task> Get_YTVideos(string channelID, int max = 50) { // YT API access key var youtubeService = new YouTubeService(new Google.Apis.Services.BaseClientService.Initializer() { ApiKey = "AIzaSyCuIYkMc5SktlnXRXNaDf2ObX-fQvtWCnQ", ApplicationName = "testingapppp" }); // Max cannot be larger than 50, so clamp it. max = max > 50 ? 50 : max; // Search youtube for all the relevant data of the channel. var videos_query = youtubeService.Search.List("snippet"); videos_query.ChannelId = channelID; videos_query.Order = SearchResource.ListRequest.OrderEnum.Date; videos_query.MaxResults = max; var videos_response = await videos_query.ExecuteAsync(); // Convert the response into models. var videos = videos_response.Items? .Where(i => i.Id.Kind == "youtube#video") .Select(newvid => new Models.Video { Title = newvid.Snippet.Title, Description = newvid.Snippet.Description, YoutubeID = newvid.Id.VideoId, AddedToYT = newvid.Snippet.PublishedAt.GetValueOrDefault(), AddedtoDB = DateTime.Now, ThumbnailURL = newvid.Snippet.Thumbnails.Medium.Url, Tags = new string[] {} }).ToList(); // Search youtube to get the length and tags for each video. var duration_query = youtubeService.Videos.List("contentDetails,snippet"); duration_query.Id = string.Join(',', videos.Select(v => v.YoutubeID)); var duration_response = await duration_query.ExecuteAsync(); // Pair each video with the result. foreach(var contentdetail in duration_response.Items.Where(i => i.Kind == "youtube#video")){ var vid = videos.Single(v => v.YoutubeID == contentdetail.Id); // Yes, really, ISO8601 time span => c#'s TimeSpan is not in TimeSpan, it's in xmlconvert! Wtf?! vid.Duration = System.Xml.XmlConvert.ToTimeSpan(contentdetail.ContentDetails.Duration); // Copy over all the created tags if any tags were provided. if (contentdetail.Snippet.Tags != null) vid.Tags = contentdetail.Snippet.Tags.Select(t => t.ToLower()).ToArray(); } // Send back the parsed vids. return videos; } // Gets some info about a youtube channel. public static async Task Get_YTChannel(string channelID) { // YT API access key var youtubeService = new YouTubeService(new Google.Apis.Services.BaseClientService.Initializer() { ApiKey = "AIzaSyCuIYkMc5SktlnXRXNaDf2ObX-fQvtWCnQ", ApplicationName = "testingapppp" }); // Search youtube for all the relevant data of the channel. var query = youtubeService.Channels.List("snippet"); query.Id = channelID; query.MaxResults = 1; var response = await query.ExecuteAsync(); // Parse the response into a channel. return new Models.Channel { Description = response.Items.First().Snippet.Description, Title = response.Items.First().Snippet.Title, ThumbnailURL = response.Items.First().Snippet.Thumbnails.Medium.Url, YoutubeID = channelID, AddedtoDB = DateTime.Now, Refreshed = DateTime.MinValue, UserTags = new string[]{}, Videos = { } }; } // Update videos for all our channels. public static async Task MassUpdate(string dbstr) { // Get the interface to the database. var ops = new DbContextOptionsBuilder(); ops.UseNpgsql(dbstr); // Get all the channels from the db that expired. var threshold = DateTime.Now.Subtract(TimeSpan.FromMinutes(60)); var channel_ids = await (new MediaDB(ops.Options)).Channels .Where(ch => ch.Refreshed < threshold) .Select(ch => ch.YoutubeID) .ToListAsync(); // For each channel, do an update. channel_ids.ForEach(async id => await ChannelUpdate(dbstr, id)); } // Update videos for just one channel. public static async Task ChannelUpdate(string dbstr, string youtubechannelIDstr) { // Get the interface to the database. var ops = new DbContextOptionsBuilder(); ops.UseNpgsql(dbstr); var db = new MediaDB(ops.Options); // Get the channel from the db when including it's videos. var channel = await db.Channels .Include(c => c.Videos) .SingleOrDefaultAsync(ch => ch.YoutubeID == youtubechannelIDstr); // Update the channel if it was found. if (channel != null) { // Get all the new videos for the channel. var Videos = await Get_YTVideos(channel.YoutubeID); // Get all the videos which haven't been put into this channels videos. var newvids = Videos .Where(nv => !channel.Videos.Any(cv => cv.YoutubeID == nv.YoutubeID)); // Say what channel all the videos came from. foreach (var v in newvids) v.Channel = channel; // Say the channel has been refreshed. channel.Refreshed = DateTime.Now; // Add all the videos to the databse. await db.Videos.AddRangeAsync(newvids); // Update the videos this channel refers to. channel.Videos.AddRange(newvids); // And say the database should be changed. await db.SaveChangesAsync(); } } } }