using AngleSharp; using AngleSharp.Dom; using AngleSharp.Html.Dom; public class YoutubeValidator : UriBasedSongValidatorBase { public override string UriValidatorRegex => @"^(https?://)?(www\.)?(youtube\.com/watch\?v=|youtu\.be/)([a-zA-Z0-9_-]{11})"; public override async Task CanExtractSongMetadataAsync(Uri songUri) { using(HttpClient httpClient = new HttpClient()) { var response = await httpClient.GetAsync(songUri); var config = Configuration.Default.WithDefaultLoader(); var context = BrowsingContext.New(config); using(var document = await context.OpenAsync(async req => req.Content(await response.Content.ReadAsStringAsync()))) { var documentContents = (document.ChildNodes[1] as HtmlElement).InnerHtml; var titleElement = document.QuerySelectorAll(".yt-video-attribute-view-model__title")[0]; var artistParentElement = document.QuerySelectorAll(".yt-video-attribute-view-model__secondary-subtitle")[0]; return titleElement != null && artistParentElement != null && artistParentElement.Children.Length > 0; } } } public override async Task ValidateAsync(Uri songUri) { var title = string.Empty; var artist = string.Empty; using(HttpClient httpClient = new HttpClient()) { var response = await httpClient.GetAsync(songUri); var config = Configuration.Default.WithDefaultLoader(); var context = BrowsingContext.New(config); using(var document = await context.OpenAsync(async req => req.Content(await response.Content.ReadAsStringAsync()))) { title = document.QuerySelectorAll(".yt-video-attribute-view-model__title")[0]?.InnerHtml; artist = document.QuerySelectorAll(".yt-video-attribute-view-model__secondary-subtitle")[0]?.Children[0]?.InnerHtml; } } var song = new Song { Name = title, Artist = artist, Url = songUri.ToString(), Provider = SongProvider.YouTube, SpotifyId = this.LookupSpotifyId(title, artist) }; return song; } }