using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; using System.Net.Http.Headers; using System.Threading; using System.Threading.Tasks; using Flurl; using Sony.Filtr.Contracts.Abstractions; using Sony.Filtr.Contracts.Entities; using Sony.Filtr.Utility; namespace Sony.Filtr.YouTube.Api { public class AuthenticatedYoutubeApi : YouTubeApi { private readonly string apiKey; public AuthenticatedYoutubeApi(ServiceAccount serviceAccount, IServiceAccountManager serviceAccountManager, GoogleOAuth2Api googleOAuth2Api, IRateLimiter rateLimiter, string apiKey) : base(BuildAuthenticatedClient(serviceAccount, serviceAccountManager, googleOAuth2Api, rateLimiter)) { this.apiKey = apiKey; } private static HttpClient BuildAuthenticatedClient(ServiceAccount serviceAccount, IServiceAccountManager serviceAccountManager, GoogleOAuth2Api googleOAuth2Api, IRateLimiter rateLimiter) { var rateLimitedHandler = new RateLimitedHttpMessageHandler(new HttpClientHandler() { AutomaticDecompression = DecompressionMethods.GZip }, rateLimiter); var youtubeOAuthMessageHandler = new YouTubeOAuthHttpMessageHandler(serviceAccount, serviceAccountManager, googleOAuth2Api, rateLimitedHandler); HttpClient client = new HttpClient(youtubeOAuthMessageHandler); client.DefaultRequestHeaders.AcceptEncoding.Add(new StringWithQualityHeaderValue("gzip")); client.DefaultRequestHeaders.UserAgent.ParseAdd("Filtr/1.0 (gzip)"); return client; } public async Task AddVideoToPlaylistAsync(string playlistId, Id videoId, int? position = null) { var url = new Url("https://www.googleapis.com/youtube/v3/playlistItems"); url.SetQueryParam("part", "snippet"); await this.PostAsync( url, new { snippet = new { playlistId = playlistId, resourceId = new { videoId = videoId.videoId, kind = "youtube#video" }, position = position } }, "Could not add videos to youtube playlists"); } public async Task AddVideosToPlaylistAsync(string playlistId, List videoIds, CancellationToken cancellationToken) { foreach (var videoId in videoIds) { var youtubeId = new Id() { videoId = videoId }; await AddVideoToPlaylistAsync(playlistId, youtubeId); } } public async Task DeletePlaylistItemsAsync(string playlistItemId) { if (String.IsNullOrWhiteSpace(playlistItemId)) { return; } var url = new Url("https://www.googleapis.com/youtube/v3/playlistItems"); //var url = new Url("https://youtube.googleapis.com/youtube/v3/playlistItems"); url.SetQueryParam("id", playlistItemId); url.SetQueryParam("key", this.apiKey); await this.DeleteAsync(url, $"Could not delete playlist item in youtube playlist '{playlistItemId}'"); } public async Task DeletePlaylistItemsAsync(IEnumerable playlistItems) { if (playlistItems == null || !playlistItems.Any()) { return Array.Empty(); } List failedPlaylistItemIds = new List(); foreach (var playlistItem in playlistItems) { try { await DeletePlaylistItemsAsync(playlistItem); } catch (Exception ex) { failedPlaylistItemIds.Add(playlistItem); } } return failedPlaylistItemIds.ToArray(); } public async Task UpdatePlaylistItemAsync(PlaylistItem playlistItem) { if (playlistItem == null) { return; } var url = new Url("https://www.googleapis.com/youtube/v3/playlistItems"); url.SetQueryParam("part", "snippet"); await this.PutAsync(url, new SimplePlaylistItem(playlistItem), "Could not update playlist item in youtube playlist."); } public async Task UpdatePlaylistAsync(Playlist playlist) { if (playlist == null) { return; } var url = new Url("https://www.googleapis.com/youtube/v3/playlists"); url.SetQueryParam("part", "snippet"); await this.PutAsync(url, playlist, "Could not update playlist"); } private Task DeleteAsync(string url, string errorMessage = null) { return this.DoRequestAsync(url, (httpClient, u) => httpClient.DeleteAsync(u), errorMessage); } private Task PostAsync(string url, T json, string errorMessage = null) { return this.DoRequestAsync(url, json, (httpClient, u, j) => httpClient.PostAsJsonAsync(u, j), errorMessage); } private Task PutAsync(string url, T json, string errorMessage = null) { return this.DoRequestAsync(url, json, (httpClient, u, j) => httpClient.PutAsJsonAsync(u, j), errorMessage); } private async Task DoRequestAsync(string url, T json, Func> requester, string errorMessage = null) { var response = await requester(this.GetDefaultClient(), url, json); if (!response.IsSuccessStatusCode) { throw YoutubeApiException.FromHttpResponseMessage(response, errorMessage); } return response; } private async Task DoRequestAsync(string url, Func> requester, string errorMessage = null) { var response = await requester(this.GetDefaultClient(), url); if (!response.IsSuccessStatusCode) { throw YoutubeApiException.FromHttpResponseMessage(response, errorMessage); } return response; } } }