/// <summary> /// Initializes a new instance of the <see cref="OneDriveThumbnailSet"/> class. /// </summary> /// <param name="set">Original set from OneDrive SDK</param> internal OneDriveThumbnailSet(ThumbnailSet set) { Small = set.Small.Url; Medium = set.Medium.Url; Large = set.Large.Url; Source = set.Source?.Url; }
/// <inheritdoc /> public List <Video> SearchVideosAsync(string query, int maxPages) { query.GuardNotNull(nameof(query)); maxPages.GuardPositive(nameof(maxPages)); // Get all videos across pages var videos = new List <Video>(); for (var i = 1; i <= maxPages; i++) { // Get search results var searchResultsJson = GetSearchResultsAsync(query, i); // Get videos var videosJson = searchResultsJson["video"].EmptyIfNull().ToArray(); // Break if there are no videos if (!videosJson.Any()) { break; } // Parse videos foreach (var videoJson in videosJson) { // Basic info var videoId = videoJson["encrypted_id"].Value <string>(); var videoAuthor = videoJson["author"].Value <string>(); //var videoUploadDate = videoJson["added"].Value<string>().ParseDateTimeOffset("M/d/yy"); var videoUploadDate = videoJson["added"].Value <string>().ParseDateTimeOffset(); var videoTitle = videoJson["title"].Value <string>(); var videoDuration = TimeSpan.FromSeconds(videoJson["length_seconds"].Value <double>()); var videoDescription = videoJson["description"].Value <string>().HtmlDecode(); // Keywords var videoKeywordsJoined = videoJson["keywords"].Value <string>(); var videoKeywords = Regex .Matches(videoKeywordsJoined, @"(?<=(^|\s)(?<q>""?))([^""]|(""""))*?(?=\<q>(?=\s|$))") .Cast <Match>() .Select(m => m.Value) .Where(s => s.IsNotBlank()) .ToList(); // Statistics var videoViewCount = videoJson["views"].Value <string>().StripNonDigit().ParseLong(); var videoLikeCount = videoJson["likes"].Value <long>(); var videoDislikeCount = videoJson["dislikes"].Value <long>(); var videoStatistics = new Statistics(videoViewCount, videoLikeCount, videoDislikeCount); // Video var videoThumbnails = new ThumbnailSet(videoId); var video = new Video(videoId, videoAuthor, videoUploadDate, videoTitle, videoDescription, videoThumbnails, videoDuration, videoKeywords, videoStatistics); videos.Add(video); } } return(videos); }
/// <summary> /// Gets video information by ID. /// </summary> public async Task <Video> GetVideoAsync(string videoId) { videoId.GuardNotNull(nameof(videoId)); if (!ValidateVideoId(videoId)) { throw new ArgumentException($"Invalid YouTube video ID [{videoId}].", nameof(videoId)); } // Get video info var videoInfo = await GetVideoInfoAsync(videoId).ConfigureAwait(false); // Extract values var title = videoInfo["title"]; var author = videoInfo["author"]; var duration = TimeSpan.FromSeconds(videoInfo["length_seconds"].ParseDouble()); var viewCount = videoInfo["view_count"].ParseLong(); var keywords = videoInfo["keywords"].Split(","); // Get video watch page var watchPage = await GetVideoWatchPageAsync(videoId).ConfigureAwait(false); // Extract values var description = watchPage.QuerySelector("p#eow-description").TextEx(); var likeCount = watchPage.QuerySelector("button.like-button-renderer-like-button").Text() .StripNonDigit().ParseLongOrDefault(); var dislikeCount = watchPage.QuerySelector("button.like-button-renderer-dislike-button").Text() .StripNonDigit().ParseLongOrDefault(); var statistics = new Statistics(viewCount, likeCount, dislikeCount); var thumbnails = new ThumbnailSet(videoId); return(new Video(videoId, author, title, description, thumbnails, duration, keywords, statistics)); }
/// <summary> /// Initializes an instance of <see cref="Video"/>. /// </summary> public Video( VideoId id, string title, string author, ChannelId channelId, DateTimeOffset uploadDate, string description, TimeSpan duration, ThumbnailSet thumbnails, IReadOnlyList <string> keywords, Engagement engagement, IReadOnlyList <Chapter>?chapters = null) { Id = id; Title = title; Author = author; ChannelId = channelId; UploadDate = uploadDate; Description = description; Duration = duration; Thumbnails = thumbnails; Keywords = keywords; Engagement = engagement; Chapters = chapters; }
/// <inheritdoc /> public async Task <Video> GetVideoAsync(string videoId) { videoId.GuardNotNull(nameof(videoId)); if (!ValidateVideoId(videoId)) { throw new ArgumentException($"Invalid YouTube video ID [{videoId}].", nameof(videoId)); } // Get player response parser var playerResponseParser = await GetPlayerResponseParserAsync(videoId); // Parse info var author = playerResponseParser.ParseAuthor(); var title = playerResponseParser.ParseTitle(); var duration = playerResponseParser.ParseDuration(); var keywords = playerResponseParser.ParseKeywords(); // Get video watch page parser var videoWatchPageParser = await GetVideoWatchPageParserAsync(videoId); // Parse info var uploadDate = videoWatchPageParser.ParseUploadDate(); var description = videoWatchPageParser.ParseDescription(); var viewCount = videoWatchPageParser.ParseViewCount(); var likeCount = videoWatchPageParser.ParseLikeCount(); var dislikeCount = videoWatchPageParser.ParseDislikeCount(); var statistics = new Statistics(viewCount, likeCount, dislikeCount); var thumbnails = new ThumbnailSet(videoId); return(new Video(videoId, author, uploadDate, title, description, thumbnails, duration, keywords, statistics)); }
/// <inheritdoc /> public async Task <IReadOnlyList <Video> > SearchVideosAsync(string query, int maxPages) { query.GuardNotNull(nameof(query)); maxPages.GuardPositive(nameof(maxPages)); // Get all videos across pages var videos = new List <Video>(); for (var page = 1; page <= maxPages; page++) { // Get search results JSON var resultsJson = await GetSearchResultsJsonAsync(query, page).ConfigureAwait(false); // Get videos var countDelta = 0; foreach (var videoJson in resultsJson.SelectToken("video").EmptyIfNull()) { var epoch = new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero); // Extract video info var videoId = videoJson.SelectToken("encrypted_id").Value <string>(); var videoAuthor = videoJson.SelectToken("author").Value <string>(); var videoUploadDate = epoch + TimeSpan.FromSeconds(videoJson.SelectToken("time_created").Value <long>()); var videoTitle = videoJson.SelectToken("title").Value <string>(); var videoDescription = videoJson.SelectToken("description").Value <string>(); var videoDuration = TimeSpan.FromSeconds(videoJson.SelectToken("length_seconds").Value <double>()); var videoViewCount = videoJson.SelectToken("views").Value <string>().StripNonDigit().ParseLong(); var videoLikeCount = videoJson.SelectToken("likes").Value <long>(); var videoDislikeCount = videoJson.SelectToken("dislikes").Value <long>(); // Extract video keywords var videoKeywordsJoined = videoJson.SelectToken("keywords").Value <string>(); var videoKeywords = Regex.Matches(videoKeywordsJoined, "\"[^\"]+\"|\\S+") .Cast <Match>() .Select(m => m.Value) .Where(s => !s.IsNullOrWhiteSpace()) .Select(s => s.Trim('"')) .ToArray(); // Create statistics and thumbnails var videoStatistics = new Statistics(videoViewCount, videoLikeCount, videoDislikeCount); var videoThumbnails = new ThumbnailSet(videoId); // Add to list videos.Add(new Video(videoId, videoAuthor, videoUploadDate, videoTitle, videoDescription, videoThumbnails, videoDuration, videoKeywords, videoStatistics)); // Increment delta countDelta++; } // If no distinct videos were added to the list - break if (countDelta <= 0) { break; } } return(videos); }
/// <summary> /// Retrieve a specific size thumbnail's metadata. If it isn't already /// available make a call to the service to retrieve it. /// </summary> /// <param name="size"></param> /// <returns></returns> public async Task <Thumbnail> ThumbnailUrlAsync(string size = "large") { bool loadedThumbnails = this._sourceItem != null && this._sourceItem.Thumbnails != null && this._sourceItem.Thumbnails.CurrentPage != null; if (loadedThumbnails) { // See if we already have that thumbnail Thumbnail thumbnail = null; ThumbnailSet thumbnailSet = null; switch (size.ToLower()) { case "small": thumbnailSet = this._sourceItem.Thumbnails.CurrentPage.FirstOrDefault(set => set.Small != null); thumbnail = thumbnailSet == null ? null : thumbnailSet.Small; break; case "medium": thumbnailSet = this._sourceItem.Thumbnails.CurrentPage.FirstOrDefault(set => set.Medium != null); thumbnail = thumbnailSet == null ? null : thumbnailSet.Medium; break; case "large": thumbnailSet = this._sourceItem.Thumbnails.CurrentPage.FirstOrDefault(set => set.Large != null); thumbnail = thumbnailSet == null ? null : thumbnailSet.Large; break; default: thumbnailSet = this._sourceItem.Thumbnails.CurrentPage.FirstOrDefault(set => set[size] != null); thumbnail = thumbnailSet == null ? null : thumbnailSet[size]; break; } if (thumbnail != null) { return(thumbnail); } } if (!loadedThumbnails) { try { // Try to load the thumbnail from the service if we haven't loaded thumbnails. return(await this.oneDriveClient.Drive.Items[this._sourceItem.Id].Thumbnails["0"][size].Request().GetAsync()); } catch (OneDriveException exception) { if (exception.IsMatch(OneDriveErrorCode.ItemNotFound.ToString())) { // Just swallow not found. We don't want an error popup and we just won't render a thumbnail return(null); } } } return(null); }
public Stream GetValidImage(ThumbnailSet imageSet) { return(GetImageStream(imageSet.HighResUrl) ?? GetImageStream(imageSet.StandardResUrl) ?? GetImageStream(imageSet.MaxResUrl) ?? GetImageStream(imageSet.MediumResUrl) ?? GetDefaultImage()); }
public void ThumbnailSetExtensions_AdditionalDataNull() { var thumbnailSet = new ThumbnailSet(); var thumbnail = thumbnailSet["custom"]; Assert.IsNull(thumbnail, "Unexpected thumbnail returned."); }
private Video GetVideo() { var thumbnails = new ThumbnailSet("-TEST-TEST-"); var statistics = new Statistics(1337, 13, 37); return(new Video("-TEST-TEST-", "Test Author", DateTimeOffset.Now, "Test Video", "test", thumbnails, TimeSpan.FromMinutes(2), new string[0], statistics)); }
public void ThumbnailSetExtensions_AdditionalDataNull() { var thumbnailSet = new ThumbnailSet(); var thumbnail = thumbnailSet["custom"]; Assert.Null(thumbnail); }
/// <inheritdoc /> public async Task <Video> GetVideoAsync(string videoId) { videoId.GuardNotNull(nameof(videoId)); if (!ValidateVideoId(videoId)) { throw new ArgumentException($"Invalid YouTube video ID [{videoId}].", nameof(videoId)); } // Get video info dictionary var videoInfoDic = await GetVideoInfoDicAsync(videoId).ConfigureAwait(false); // Get player response JSON var playerResponseJson = JToken.Parse(videoInfoDic["player_response"]); // If video is unavailable - throw if (string.Equals(playerResponseJson.SelectToken("playabilityStatus.status")?.Value <string>(), "error", StringComparison.OrdinalIgnoreCase)) { throw new VideoUnavailableException(videoId, $"Video [{videoId}] is unavailable."); } // Extract video info var videoAuthor = playerResponseJson.SelectToken("videoDetails.author").Value <string>(); var videoTitle = playerResponseJson.SelectToken("videoDetails.title").Value <string>(); var videoDuration = TimeSpan.FromSeconds(playerResponseJson.SelectToken("videoDetails.lengthSeconds").Value <double>()); var videoKeywords = playerResponseJson.SelectToken("videoDetails.keywords").EmptyIfNull().Values <string>().ToArray(); var videoDescription = playerResponseJson.SelectToken("videoDetails.shortDescription").Value <string>(); var videoViewCount = playerResponseJson.SelectToken("videoDetails.viewCount")?.Value <long>() ?? 0; // some videos have no views var videoLoudness = playerResponseJson.SelectToken("playerConfig.audioConfig.loudnessDb").Value <double>(); // Get video watch page HTML var videoWatchPageHtml = await GetVideoWatchPageHtmlAsync(videoId).ConfigureAwait(false); // Extract upload date var videoUploadDate = videoWatchPageHtml.GetElementsBySelector("meta[itemprop=\"datePublished\"]") .First().GetAttribute("content").Value.ParseDateTimeOffset("yyyy-MM-dd"); // Extract like count var videoLikeCountRaw = videoWatchPageHtml.GetElementsByClassName("like-button-renderer-like-button") .FirstOrDefault()?.GetInnerText().StripNonDigit(); var videoLikeCount = !videoLikeCountRaw.IsNullOrWhiteSpace() ? videoLikeCountRaw.ParseLong() : 0; // Extract dislike count var videoDislikeCountRaw = videoWatchPageHtml.GetElementsByClassName("like-button-renderer-dislike-button") .FirstOrDefault()?.GetInnerText().StripNonDigit(); var videoDislikeCount = !videoDislikeCountRaw.IsNullOrWhiteSpace() ? videoDislikeCountRaw.ParseLong() : 0; // Create statistics and thumbnails var statistics = new Statistics(videoViewCount, videoLikeCount, videoDislikeCount); var thumbnails = new ThumbnailSet(videoId); return(new Video(videoId, videoAuthor, videoUploadDate, videoTitle, videoDescription, thumbnails, videoDuration, videoKeywords, statistics, videoLoudness)); }
private VideoInformation(VideoId id, string title, string author, DateTimeOffset?uploadDate, TimeSpan duration, ThumbnailSet thumbnails) { Id = id; Title = title; Author = author; UploadDate = uploadDate; Duration = duration; Thumbnails = thumbnails; }
public override async Task <byte[]> GetItemThumbnail(string itemId, string relativePath) { ThumbnailSet thumbnailSet = await this.oneDriveClient.GetThumbnailsAsync(itemId).ConfigureAwait(false); ThumbnailInfo thumbnail; if (!thumbnailSet.Thumbnails.TryGetValue("medium", out thumbnail)) { return(null); } return(await this.oneDriveClient.GetRawBytesFromOneDrive(thumbnail.Url).ConfigureAwait(false)); }
/// <summary> /// Initializes an instance of <see cref="Video" />. /// </summary> public Video( string id, string title, string author, DateTimeOffset uploadDate, ThumbnailSet thumbnails) { Id = id; Title = title; Author = author; UploadDate = uploadDate; Thumbnails = thumbnails; }
private async void SetMetaData(int position, string title, string artist, ThumbnailSet thumbnails) { string filePath = queue[position].Path; await Task.Run(async() => { Stream stream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite); var meta = TagLib.File.Create(new StreamFileAbstraction(filePath, stream, stream)); meta.Tag.Title = title; meta.Tag.Performers = new string[] { artist }; meta.Tag.Album = title + " - " + artist; meta.Tag.Comment = queue[position].YoutubeID; IPicture[] pictures = new IPicture[1]; Bitmap bitmap = Picasso.With(this).Load(await YoutubeManager.GetBestThumb(thumbnails)).Transform(new RemoveBlackBorder(true)).MemoryPolicy(MemoryPolicy.NoCache).Get(); byte[] data; using (var MemoryStream = new MemoryStream()) { bitmap.Compress(Bitmap.CompressFormat.Png, 0, MemoryStream); data = MemoryStream.ToArray(); } bitmap.Recycle(); pictures[0] = new Picture(data); meta.Tag.Pictures = pictures; meta.Save(); stream.Dispose(); }); MediaScannerConnection.ScanFile(this, new string[] { filePath }, null, this); if (queue[position].PlaylistName == null) { queue[position].State = DownloadState.Completed; } else { queue[position].State = DownloadState.Playlist; } if (!queue.Exists(x => x.State == DownloadState.None || x.State == DownloadState.Downloading || x.State == DownloadState.Initialization || x.State == DownloadState.MetaData || x.State == DownloadState.Playlist)) { StopForeground(true); DownloadQueue.instance?.Finish(); queue.Clear(); } else { UpdateList(position); } }
/// <inheritdoc /> public async Task <IReadOnlyList <Video> > SearchVideosAsync(string query, int maxPages) { query.GuardNotNull(nameof(query)); maxPages.GuardPositive(nameof(maxPages)); // Get all videos across pages var videos = new List <Video>(); for (var page = 1; page <= maxPages; page++) { // Get parser var parser = await GetPlaylistAjaxParserForSearchAsync(query, page); // Parse videos var countDelta = 0; foreach (var videoParser in parser.GetVideos()) { // Parse info var videoId = videoParser.ParseId(); var videoAuthor = videoParser.ParseAuthor(); var videoUploadDate = videoParser.ParseUploadDate(); var videoTitle = videoParser.ParseTitle(); var videoDescription = videoParser.ParseDescription(); var videoDuration = videoParser.ParseDuration(); var videoKeywords = videoParser.ParseKeywords(); var videoViewCount = videoParser.ParseViewCount(); var videoLikeCount = videoParser.ParseLikeCount(); var videoDislikeCount = videoParser.ParseDislikeCount(); var videoStatistics = new Statistics(videoViewCount, videoLikeCount, videoDislikeCount); var videoThumbnails = new ThumbnailSet(videoId); var video = new Video(videoId, videoAuthor, videoUploadDate, videoTitle, videoDescription, videoThumbnails, videoDuration, videoKeywords, videoStatistics); videos.Add(video); countDelta++; } // Break if no distinct videos were added to the list if (countDelta <= 0) { break; } } return(videos); }
/// <summary> /// Update the navigation property thumbnails in workbooks /// <param name="body"></param> /// <param name="requestConfiguration">Configuration for the request such as headers, query parameters, and middleware options.</param> /// </summary> public RequestInformation CreatePatchRequestInformation(ThumbnailSet body, Action<ThumbnailSetItemRequestBuilderPatchRequestConfiguration> requestConfiguration = default) { _ = body ?? throw new ArgumentNullException(nameof(body)); var requestInfo = new RequestInformation { HttpMethod = Method.PATCH, UrlTemplate = UrlTemplate, PathParameters = PathParameters, }; requestInfo.SetContentFromParsable(RequestAdapter, "application/json", body); if (requestConfiguration != null) { var requestConfig = new ThumbnailSetItemRequestBuilderPatchRequestConfiguration(); requestConfiguration.Invoke(requestConfig); requestInfo.AddRequestOptions(requestConfig.Options); requestInfo.AddHeaders(requestConfig.Headers); } return requestInfo; }
/// <inheritdoc /> public async Task <Video> GetVideoAsync(string videoId) { videoId.GuardNotNull(nameof(videoId)); if (!ValidateVideoId(videoId)) { throw new ArgumentException($"Invalid YouTube video ID [{videoId}].", nameof(videoId)); } // Get video info dictionary var videoInfoDic = await GetVideoInfoDicAsync(videoId); // Get player response JSON var playerResponseJson = JToken.Parse(videoInfoDic["player_response"]); // Extract video info var videoAuthor = playerResponseJson.SelectToken("videoDetails.author").Value <string>(); var videoTitle = playerResponseJson.SelectToken("videoDetails.title").Value <string>(); var videoDuration = TimeSpan.FromSeconds(playerResponseJson.SelectToken("videoDetails.lengthSeconds").Value <double>()); var videoKeywords = playerResponseJson.SelectToken("videoDetails.keywords").EmptyIfNull().Values <string>().ToArray(); var videoDescription = playerResponseJson.SelectToken("videoDetails.shortDescription").Value <string>(); var videoViewCount = playerResponseJson.SelectToken("videoDetails.viewCount")?.Value <long>() ?? 0; // some videos have no views // Get video watch page HTML var videoWatchPageHtml = await GetVideoWatchPageHtmlAsync(videoId); // Extract upload date var videoUploadDate = videoWatchPageHtml.QuerySelector("meta[itemprop=\"datePublished\"]").GetAttribute("content") .ParseDateTimeOffset("yyyy-MM-dd"); // Extract like count var videoLikeCountRaw = videoWatchPageHtml.QuerySelector("button.like-button-renderer-like-button")?.Text().StripNonDigit(); var videoLikeCount = !videoLikeCountRaw.IsNullOrWhiteSpace() ? videoLikeCountRaw.ParseLong() : 0; // Extract dislike count var videoDislikeCountRaw = videoWatchPageHtml.QuerySelector("button.like-button-renderer-dislike-button")?.Text().StripNonDigit(); var videoDislikeCount = !videoDislikeCountRaw.IsNullOrWhiteSpace() ? videoDislikeCountRaw.ParseLong() : 0; // Create statistics and thumbnails var statistics = new Statistics(videoViewCount, videoLikeCount, videoDislikeCount); var thumbnails = new ThumbnailSet(videoId); return(new Video(videoId, videoAuthor, videoUploadDate, videoTitle, videoDescription, thumbnails, videoDuration, videoKeywords, statistics)); }
public void ThumbnailSetExtensions_CustomThumbnailNotFound() { var expectedThumbnail = new Thumbnail { Url = "https://localhost" }; var thumbnailSet = new ThumbnailSet { AdditionalData = new Dictionary <string, object> { { "custom", expectedThumbnail } } }; var thumbnail = thumbnailSet["custom2"]; Assert.IsNull(thumbnail, "Unexpected thumbnail returned."); }
public void ThumbnailSetExtensions_CustomThumbnail() { var expectedThumbnail = new Thumbnail { Url = "https://localhost" }; var thumbnailSet = new ThumbnailSet { AdditionalData = new Dictionary <string, object> { { "custom", expectedThumbnail } } }; var thumbnail = thumbnailSet["custom"]; Assert.NotNull(thumbnail); Assert.Equal(expectedThumbnail.Url, thumbnail.Url); }
/// <summary> /// Initializes an instance of <see cref="Video"/>. /// </summary> public PlaylistVideo( VideoId id, string title, string author, ChannelId channelId, string description, TimeSpan duration, long viewCount, ThumbnailSet thumbnails) { Id = id; Title = title; Author = author; ChannelId = channelId; Description = description; Duration = duration; ViewCount = viewCount; Thumbnails = thumbnails; }
/// <summary> /// Initializes an instance of <see cref="Video"/>. /// </summary> public Video( VideoId id, string title, string author, DateTimeOffset uploadDate, string description, TimeSpan duration, ThumbnailSet thumbnails, IReadOnlyList <string> keywords, Engagement engagement) { Id = id; Title = title; Author = author; UploadDate = uploadDate; Description = description; Duration = duration; Thumbnails = thumbnails; Keywords = keywords; Engagement = engagement; }
/// <summary> /// Return the thumbnail with the greatest quality. /// </summary> /// <param name="thumbnails">This will create an array of the thumbnails in this order: MaxResUrl, StandardResUrl, HighResUrl</param> /// <returns></returns> public async static Task <string> GetBestThumb(ThumbnailSet Thumbnails) { string[] thumbnails = new string[] { Thumbnails.MaxResUrl, Thumbnails.StandardResUrl, Thumbnails.HighResUrl }; foreach (string thumb in thumbnails) { HttpWebRequest request = new HttpWebRequest(new Uri(thumb)) { Method = "HEAD" }; try { HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync(); if (response.StatusCode == HttpStatusCode.OK) { return(thumb); } } catch (WebException) { } } return(thumbnails.Last()); }
/// <inheritdoc /> public Video GetVideoAsync(string videoId) { videoId.GuardNotNull(nameof(videoId)); if (!ValidateVideoId(videoId)) { throw new ArgumentException($"Invalid YouTube video ID [{videoId}].", nameof(videoId)); } // Get video info var videoInfo = GetVideoInfoAsync(videoId); // .ConfigureAwait(false); // Extract values var title = videoInfo["title"]; var author = videoInfo["author"]; var duration = TimeSpan.FromSeconds(videoInfo["length_seconds"].ParseDouble()); var viewCount = videoInfo["view_count"].ParseLong(); var keywords = videoInfo["keywords"].Split(",").ToList(); // Get video watch page var watchPage = GetVideoWatchPageAsync(videoId); //.ConfigureAwait(false); // Extract values var uploadDate = watchPage.QuerySelector("meta[itemprop=\"datePublished\"]").GetAttributeValue("content", string.Empty) .ParseDateTimeOffset("yyyy-MM-dd"); var description = watchPage.QuerySelector("p#eow-description").TextEx(); var likeCount = watchPage.QuerySelector("button.like-button-renderer-like-button").InnerText .StripNonDigit().ParseLongOrDefault(); var dislikeCount = watchPage.QuerySelector("button.like-button-renderer-dislike-button").InnerText .StripNonDigit().ParseLongOrDefault(); var statistics = new Statistics(viewCount, likeCount, dislikeCount); var thumbnails = new ThumbnailSet(videoId); return(new Video(videoId, author, uploadDate, title, description, thumbnails, duration, keywords, statistics)); }
/// <inheritdoc /> public async Task <Playlist> GetPlaylistAsync(string playlistId, int maxPages) { if (!ValidatePlaylistId(playlistId)) { throw new ArgumentException($"Invalid YouTube playlist ID [{playlistId}].", nameof(playlistId)); } // Get all videos across pages JToken playlistJson; var page = 1; var index = 0; var videoIds = new HashSet <string>(); var videos = new List <Video>(); do { // Get playlist JSON playlistJson = await GetPlaylistJsonAsync(playlistId, index).ConfigureAwait(false); // Get videos var countDelta = 0; foreach (var videoJson in playlistJson.SelectTokens("video[*]")) { var epoch = new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero); // Extract video info var videoId = videoJson.SelectToken("encrypted_id").Value <string>(); var videoAuthor = videoJson.SelectToken("author").Value <string>(); var videoUploadDate = epoch + TimeSpan.FromSeconds(videoJson.SelectToken("time_created").Value <long>()); var videoTitle = videoJson.SelectToken("title").Value <string>(); var videoDescription = videoJson.SelectToken("description").Value <string>(); var videoDuration = TimeSpan.FromSeconds(videoJson.SelectToken("length_seconds").Value <double>()); var videoViewCount = videoJson.SelectToken("views").Value <string>().StripNonDigit().ParseLong(); var videoLikeCount = videoJson.SelectToken("likes").Value <long>(); var videoDislikeCount = videoJson.SelectToken("dislikes").Value <long>(); // Extract video keywords var videoKeywordsJoined = videoJson.SelectToken("keywords").Value <string>(); var videoKeywords = Regex.Matches(videoKeywordsJoined, "\"[^\"]+\"|\\S+") .Cast <Match>() .Select(m => m.Value) .Where(s => !string.IsNullOrWhiteSpace(s)) .Select(s => s.Trim('"')) .ToArray(); // Create statistics and thumbnails var videoStatistics = new Statistics(videoViewCount, videoLikeCount, videoDislikeCount); var videoThumbnails = new ThumbnailSet(videoId); // Add video to the list if it's not already there if (videoIds.Add(videoId)) { videos.Add(new Video(videoId, videoAuthor, videoUploadDate, videoTitle, videoDescription, videoThumbnails, videoDuration, videoKeywords, videoStatistics)); // Increment delta countDelta++; } } // If no distinct videos were added to the list - break if (countDelta <= 0) { break; } // Advance index and page index += countDelta; page++; } while (page <= maxPages); // Extract playlist info var author = playlistJson.SelectToken("author")?.Value <string>() ?? ""; // system playlists have no author var title = playlistJson.SelectToken("title").Value <string>(); var description = playlistJson.SelectToken("description")?.Value <string>() ?? ""; var viewCount = playlistJson.SelectToken("views")?.Value <long>() ?? 0; // system playlists have no views var likeCount = playlistJson.SelectToken("likes")?.Value <long>() ?? 0; // system playlists have no likes var dislikeCount = playlistJson.SelectToken("dislikes")?.Value <long>() ?? 0; // system playlists have no dislikes // Create statistics var statistics = new Statistics(viewCount, likeCount, dislikeCount); return(new Playlist(playlistId, author, title, description, statistics, videos)); }
/// <inheritdoc /> public async Task <Playlist> GetPlaylistAsync(string playlistId, int maxPages) { playlistId.GuardNotNull(nameof(playlistId)); maxPages.GuardPositive(nameof(maxPages)); if (!ValidatePlaylistId(playlistId)) { throw new ArgumentException($"Invalid YouTube playlist ID [{playlistId}].", nameof(playlistId)); } // Get all videos across pages JToken playlistJson; var page = 1; var index = 0; var videoIds = new HashSet <string>(); var videos = new List <Video>(); do { // Get playlist JSON playlistJson = await GetPlaylistJsonAsync(playlistId, index); // Get videos var countTotal = 0; var countDelta = 0; foreach (var videoJson in playlistJson.SelectToken("video").EmptyIfNull()) { // Extract video info var videoId = videoJson.SelectToken("encrypted_id").Value <string>(); var videoAuthor = videoJson.SelectToken("author").Value <string>(); var videoUploadDate = videoJson.SelectToken("added").Value <string>().ParseDateTimeOffset("M/d/yy"); var videoTitle = videoJson.SelectToken("title").Value <string>(); var videoDescription = videoJson.SelectToken("description").Value <string>(); var videoDuration = TimeSpan.FromSeconds(videoJson.SelectToken("length_seconds").Value <double>()); var videoViewCount = videoJson.SelectToken("views").Value <string>().StripNonDigit().ParseLong(); var videoLikeCount = videoJson.SelectToken("likes").Value <long>(); var videoDislikeCount = videoJson.SelectToken("dislikes").Value <long>(); // Extract video keywords var videoKeywordsJoined = videoJson.SelectToken("keywords").Value <string>(); var videoKeywords = Regex.Matches(videoKeywordsJoined, @"(?<=(^|\s)(?<q>""?))([^""]|(""""))*?(?=\<q>(?=\s|$))") .Cast <Match>() .Select(m => m.Value) .Where(s => !s.IsNullOrWhiteSpace()) .ToArray(); // Create statistics and thumbnails var videoStatistics = new Statistics(videoViewCount, videoLikeCount, videoDislikeCount); var videoThumbnails = new ThumbnailSet(videoId); // Add video to the list if it's not already there if (videoIds.Add(videoId)) { videos.Add(new Video(videoId, videoAuthor, videoUploadDate, videoTitle, videoDescription, videoThumbnails, videoDuration, videoKeywords, videoStatistics)); // Increment delta countDelta++; } // Increment total count countTotal++; } // If no distinct videos were added to the list - break if (countDelta <= 0) { break; } // Advance index and page index += countTotal; page++; } while (page <= maxPages); // Extract playlist info var author = playlistJson.SelectToken("author")?.Value <string>() ?? ""; // system playlists have no author var title = playlistJson.SelectToken("title").Value <string>(); var description = playlistJson.SelectToken("description")?.Value <string>() ?? ""; var viewCount = playlistJson.SelectToken("views")?.Value <long>() ?? 0; // system playlists have no views var likeCount = playlistJson.SelectToken("likes")?.Value <long>() ?? 0; // system playlists have no likes var dislikeCount = playlistJson.SelectToken("dislikes")?.Value <long>() ?? 0; // system playlists have no dislikes // Create statistics var statistics = new Statistics(viewCount, likeCount, dislikeCount); return(new Playlist(playlistId, author, title, description, statistics, videos)); }
/// <inheritdoc /> public async Task <IReadOnlyList <Video> > SearchVideosByFilterAsync(string query, int maxPages = 1, int pageSize = 20, SearchFilterType searchType = SearchFilterType.Default) { var videos = new List <Video>(); for (var page = 1; page <= maxPages; page++) { var counter = 0; var doc = await GetYoutubeHtmlResultAsync(query, page, searchType); var children = doc.GetElementsByClassName("item-section").FirstOrDefault()?.Children; if (children != null) { foreach (HtmlElement videoItem in children) { var videoType = VideoType.Video; if (videoItem.GetElementsByClassName("yt-lockup-playlist").Any()) { videoType = VideoType.Playlist; } else if (videoItem.GetElementsByClassName("yt-lockup-channel").Any()) { videoType = VideoType.Channel; } string videoId; string thumbVideoId; string videoAuthor; DateTimeOffset?videoUploadDate = null; // Need help converting 1 year ago, 1 day ago etc. the problem is with the language. it could be diffrent string videoTitle; string videoDescription; TimeSpan videoDuration; long videoViewCount; long videoLikeCount = 0; // cant find this long videoDislikeCount = 0; // cant find this string[] videoKeywords = new string[0]; // are not available int? totalVideos; ThumbnailSet videoThumbnails; Statistics videoStatistics; if (videoType == VideoType.Channel) { videoId = videoItem.Find("[data-channel-external-id]").FirstOrDefault()?.GetAttribute("data-channel-external-id")?.Value; if (string.IsNullOrEmpty(videoId)) { videoId = videoItem.Find("a [href]").FirstOrDefault()?.GetAttribute("href")?.Value; } thumbVideoId = videoItem.Find(".video-thumb span img").FirstOrDefault()?.GetAttribute("src")?.Value; } else if (string.IsNullOrWhiteSpace(videoId = thumbVideoId = videoItem.Find("[data-context-item-id]").FirstOrDefault()?.GetAttribute("data-context-item-id").Value)) { var idEl = videoItem.Find(".yt-lockup-thumbnail a [href]").FirstOrDefault(); if (idEl == null) { continue; // not valid div } var id = "youtube.com" + idEl?.GetAttribute("href").Value; if (videoType != VideoType.Video) { videoId = YoutubeClient.ParsePlaylistId(id); thumbVideoId = YoutubeClient.ParseVideoId(id); } else { videoId = thumbVideoId = YoutubeClient.ParseVideoId(id); } } if (string.IsNullOrWhiteSpace(videoTitle = videoItem.Find(".yt-lockup-title a span").FirstOrDefault()?.GetInnerText())) { videoTitle = videoItem.Find(".yt-lockup-title a").FirstOrDefault()?.GetInnerText(); } if (videoTitle.IsDeletedVideo()) { continue; } videoThumbnails = new ThumbnailSet(thumbVideoId, videoType); videoAuthor = (videoItem.Find(".yt-lockup-byline a").FirstOrDefault()?.GetInnerText() ?? videoTitle).Split("-").FirstOrDefault(); videoDescription = videoItem.Find(".yt-lockup-description").FirstOrDefault()?.GetInnerText() ?? string.Empty; videoDuration = videoItem.Find(".video-time").FirstOrDefault()?.GetInnerText().ParseTime() ?? TimeSpan.FromSeconds(0); videoViewCount = videoItem.Find(".yt-lockup-meta-info li").LastOrDefault()?.GetInnerText()?.StripNonDigit().ParseLongOrDefault() ?? 0; totalVideos = videoItem.Find(".formatted-video-count-label").FirstOrDefault()?.GetInnerText().StripNonDigit().ParseIntOrDefault(); videoStatistics = new Statistics(videoViewCount, videoLikeCount, videoDislikeCount); videos.Add(new Video(videoId, videoAuthor, videoUploadDate, videoTitle, videoDescription, videoThumbnails, videoDuration, videoKeywords, videoStatistics, totalVideos, videoType)); if (counter >= pageSize) { break; } counter++; } } } return(videos); }
/// <inheritdoc /> public async Task <Playlist> GetPlaylistAsync(string playlistId, int maxPages) { playlistId.GuardNotNull(nameof(playlistId)); maxPages.GuardPositive(nameof(maxPages)); if (!ValidatePlaylistId(playlistId)) { throw new ArgumentException($"Invalid YouTube playlist ID [{playlistId}].", nameof(playlistId)); } // Get all videos across pages var pagesDone = 0; var offset = 0; JToken playlistJson; var videoIds = new HashSet <string>(); var videos = new List <Video>(); do { // Get playlist info playlistJson = await GetPlaylistInfoAsync(playlistId, offset).ConfigureAwait(false); // Parse videos var total = 0; var delta = 0; foreach (var videoJson in playlistJson["video"]) { // Basic info var videoId = videoJson["encrypted_id"].Value <string>(); var videoAuthor = videoJson["author"].Value <string>(); var videoUploadDate = videoJson["added"].Value <DateTime>(); var videoTitle = videoJson["title"].Value <string>(); var videoDuration = TimeSpan.FromSeconds(videoJson["length_seconds"].Value <double>()); var videoDescription = videoJson["description"].Value <string>(); // Keywords var videoKeywordsJoined = videoJson["keywords"].Value <string>(); var videoKeywords = Regex .Matches(videoKeywordsJoined, @"(?<=(^|\s)(?<q>""?))([^""]|(""""))*?(?=\<q>(?=\s|$))") .Cast <Match>() .Select(m => m.Value) .Where(s => s.IsNotBlank()) .ToArray(); // Statistics var videoViewCount = videoJson["views"].Value <string>().StripNonDigit().ParseLong(); var videoLikeCount = videoJson["likes"].Value <long>(); var videoDislikeCount = videoJson["dislikes"].Value <long>(); var videoStatistics = new Statistics(videoViewCount, videoLikeCount, videoDislikeCount); // Video var videoThumbnails = new ThumbnailSet(videoId); var video = new Video(videoId, videoAuthor, videoUploadDate, videoTitle, videoDescription, videoThumbnails, videoDuration, videoKeywords, videoStatistics); // Add to list if not already there if (videoIds.Add(video.Id)) { videos.Add(video); delta++; } total++; } // Break if no distinct videos were added to the list if (delta <= 0) { break; } // Prepare for next page pagesDone++; offset += total; } while (pagesDone < maxPages); // Extract playlist info var title = playlistJson["title"].Value <string>(); var author = playlistJson["author"]?.Value <string>() ?? ""; // system playlists don't have an author var description = playlistJson["description"]?.Value <string>() ?? ""; // system playlists don't have description // Statistics var viewCount = playlistJson["views"]?.Value <long>() ?? 0; // watchlater does not have views var likeCount = playlistJson["likes"]?.Value <long>() ?? 0; // system playlists don't have likes var dislikeCount = playlistJson["dislikes"]?.Value <long>() ?? 0; // system playlists don't have dislikes var statistics = new Statistics(viewCount, likeCount, dislikeCount); return(new Playlist(playlistId, author, title, description, statistics, videos)); }
private async void List_SelectionChanged(object sender, SelectionChangedEventArgs e) { _cancelGetDetails.Cancel(false); _cancelGetDetails.Dispose(); _cancelGetDetails = new CancellationTokenSource(); if (_list.SelectedItem is DriveItem driveItem && driveItem.File != null) { try { SelectedFile = driveItem; FileSize = driveItem.Size ?? 0; LastModified = driveItem.LastModifiedDateTime?.LocalDateTime.ToString() ?? string.Empty; if (FileSelected != null) { FileSelected.Invoke(this, new FileSelectedEventArgs(driveItem)); } ThumbnailImageSource = null; VisualStateManager.GoToState(this, NavStatesFileReadonly, false); GraphServiceClient graphClient = await GraphServiceHelper.GetGraphServiceClientAsync(); if (graphClient != null) { Task <IDriveItemPermissionsCollectionPage> taskPermissions = graphClient.Drives[_driveId].Items[driveItem.Id].Permissions.Request().GetAsync(_cancelGetDetails.Token); IDriveItemPermissionsCollectionPage permissions = await taskPermissions; if (!taskPermissions.IsCanceled) { foreach (Permission permission in permissions) { if (permission.Roles.Contains("write") || permission.Roles.Contains("owner")) { VisualStateManager.GoToState(this, NavStatesFileEdit, false); break; } } Task <IDriveItemThumbnailsCollectionPage> taskThumbnails = graphClient.Drives[_driveId].Items[driveItem.Id].Thumbnails.Request().GetAsync(_cancelGetDetails.Token); IDriveItemThumbnailsCollectionPage thumbnails = await taskThumbnails; if (!taskThumbnails.IsCanceled) { ThumbnailSet thumbnailsSet = thumbnails.FirstOrDefault(); if (thumbnailsSet != null) { Thumbnail thumbnail = thumbnailsSet.Large; if (thumbnail.Url.Contains("inputFormat=svg")) { SvgImageSource source = new SvgImageSource(); using (Stream inputStream = await graphClient.Drives[_driveId].Items[driveItem.Id].Content.Request().GetAsync()) { SvgImageSourceLoadStatus status = await source.SetSourceAsync(inputStream.AsRandomAccessStream()); if (status == SvgImageSourceLoadStatus.Success) { ThumbnailImageSource = source; } } } else { ThumbnailImageSource = new BitmapImage(new Uri(thumbnail.Url)); } } } IsDetailPaneVisible = true; ShowDetailsPane(); } } } catch (Exception exception) { MessageDialog messageDialog = new MessageDialog(exception.Message); await messageDialog.ShowAsync(); } }