using System; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; using System.Threading.Tasks; using MoreLinq; using NLog; using Sony.Filtr.YouTube.Api; using Sony.Filtr.YouTube.Channels; using Sony.Filtr.YouTube.Charts; using Sony.Filtr.YouTube.Videos; namespace Sony.Filtr.Tasks.Tasks.Youtube { public class ImportYouTubeTopChartsTask : IScheduledTask { private readonly YouTubeApi _youtubeApi; private readonly YouTubeChartsManager _youTubeChartsManager; private readonly YouTubeVideoManager _youTubeVideoManager; private readonly YouTubeChannelManager _youTubeChannelManager; private readonly Logger _logger; public ImportYouTubeTopChartsTask(YouTubeApi youtubeApi, YouTubeChartsManager youTubeChartsManager, YouTubeVideoManager youTubeVideoManager, YouTubeChannelManager youTubeChannelManager) { _youtubeApi = youtubeApi; _youTubeChartsManager = youTubeChartsManager; _youTubeVideoManager = youTubeVideoManager; _youTubeChannelManager = youTubeChannelManager; _logger = LogManager.GetLogger("ImportYouTubeTopChartsTask"); } public async Task ExecuteAsync(Guid scheduledTaskLogId) { var today = DateTime.Today; _logger.Debug("Fetching playlists from database"); var playlists = GetPlaylistToProcess(today); _logger.Debug($"Found {playlists.Count} playlist to process"); foreach(var chartPlaylist in playlists) { try { await ImportChartsDataAsync(chartPlaylist, today); } catch(Exception e) { _logger.Error(e); } } return null; } private async Task ImportChartsDataAsync(YouTubeChartPlaylist chartPlaylist, DateTime today) { var playlistId = chartPlaylist.PlaylistId; _logger.Debug($"Begin fetching for playlist {playlistId}"); //var playlist = await _youtubeApi.GetPlaylistAsync(playlistId); var playlistItems = await _youtubeApi.GetAllPlaylistItemsAsync(playlistId); if (playlistItems != null) { _logger.Debug($"Found {playlistItems.Count} playlist items in {playlistId}"); var videoIds = playlistItems.Select(p => p.snippet.resourceId.videoId).ToList(); var actualVideos = await _youtubeApi.GetAllVideosAsync(videoIds); var joinedVideos = playlistItems.Join(actualVideos, item => item.snippet.resourceId.videoId, item => item.id, (item, videoItem) => new { PlaylistItem = item, Video = videoItem }).ToList(); var youtubeChartEntries = joinedVideos.Select((v, index) => BuildYouTubeChartEntry(v.Video, index)).ToList(); await _youTubeChartsManager.AddChartEntriesAsync(chartPlaylist.CountryCode, today, chartPlaylist.ChartType, youtubeChartEntries); var videos = actualVideos.Select(p => new YouTubeVideo(p)); await _youTubeVideoManager.AddVideosAsync(videos); var channels = actualVideos.Select(p => new YouTubeChannel() { Id = p.snippet.channelId, Title = p.snippet.channelTitle }).DistinctBy(p => p.Id).ToList(); await _youTubeChannelManager.AddChannelsAsync(channels); _logger.Debug($"Done saving chart for {playlistId}"); } else { _logger.Warn($"Could not get playlists items for {playlistId}"); } } private List GetPlaylistToProcess(DateTime today) { var playlists = _youTubeChartsManager.GetChartPlaylists(); _logger.Debug($"Found {playlists.Count} in database"); var existingFetchedPlaylists = _youTubeChartsManager.GetCharts(today); var playlistToFetch = playlists.Where(p => !existingFetchedPlaylists.Any(pi => pi.ChartType == p.ChartType && pi.CountryCode == p.CountryCode)).ToList(); return playlistToFetch; } private static YouTubeChartEntry BuildYouTubeChartEntry(FullVideoItem video, int index) { return new YouTubeChartEntry() { VideoId = video.id, Title = video.snippet.title, ChannelId = video.snippet.channelId, ChannelTitle = video.snippet.channelTitle, Position = index }; } private async Task ExportChartPlaylistsAsync(List allPlaylistFromChannel) { CultureInfo cultureInfo = CultureInfo.GetCultureInfo("sv-SE"); using (var saveFile = File.Open("ChartPlaylists.csv", FileMode.OpenOrCreate)) { using (var fileWriter = new StreamWriter(saveFile)) { foreach (var playlist in allPlaylistFromChannel) { var csvLine = string.Join("|", playlist.id, playlist.snippet.title, playlist.snippet.description); await fileWriter.WriteLineAsync(csvLine); } } } } } }