private PartialImportedSongs GetSongsById(string playlistId, string pageToken, int maxResults, bool parseAll)
        {
            var songs = new List <ImportedSongInListContract>();

            var requestUrl = string.Format(playlistItemsFormat, YoutubeApiKey, playlistId, maxResults, pageToken);

            YoutubePlaylistItemResponse result;

            try {
                result = JsonRequest.ReadObject <YoutubePlaylistItemResponse>(requestUrl);
            } catch (Exception x) {
                log.Warn(x, "Unable to read Youtube playlist");
                throw new UnableToImportException("Unable to read Youtube playlist", x);
            }

            foreach (var item in result.Items)
            {
                var song = new ImportedSongInListContract(PVService.Youtube, item.Snippet.ResourceId.VideoId)
                {
                    Name      = item.Snippet.Title,
                    SortIndex = ((int?)item.Snippet.Position ?? 0) + 1,
                    Url       = string.Format("https://www.youtube.com/watch?v={0}", item.Snippet.ResourceId.VideoId)
                };
                songs.Add(song);
            }

            return(new PartialImportedSongs(songs.ToArray(), result.PageInfo.TotalResults ?? 0, result.NextPageToken));
        }
        public ImportedSongListContract Parse(string url, bool parseAll)
        {
            var id = GetId(url);

            var requestUrl = string.Format(playlistsFormat, YoutubeApiKey, id);
            YoutubePlaylistResponse result;

            try {
                result = JsonRequest.ReadObject <YoutubePlaylistResponse>(requestUrl);
            } catch (Exception x) {
                log.Warn(x, "Unable to read Youtube playlist");
                throw new UnableToImportException("Unable to read Youtube playlist");
            }

            if (!result.Items.Any())
            {
                log.Info("Youtube playlist not found");
                throw new UnableToImportException(string.Format("Youtube playlist not found: {0}", url));
            }

            var name        = result.Items[0].Snippet.Title;
            var description = result.Items[0].Snippet.Description;
            var created     = (result.Items[0].Snippet.PublishedAt ?? DateTimeOffset.Now).DateTime;

            var songs = GetSongsById(id, null, 10, parseAll);

            return(new ImportedSongListContract {
                Name = name, Description = description, CreateDate = created, Songs = songs
            });
        }
Example #3
0
        public VideoUrlParseResult ParseBySoundCloudUrl(string url)
        {
            var apikey = AppConfig.SoundCloudClientId;
            var apiUrl = string.Format("http://api.soundcloud.com/resolve?url=http://soundcloud.com/{0}&client_id={1}", url, apikey);

            SoundCloudResult result;

            bool HasStatusCode(WebException x, HttpStatusCode statusCode) => x.Response != null && ((HttpWebResponse)x.Response).StatusCode == statusCode;

            VideoUrlParseResult ReturnError(Exception x, string additionalInfo = null)
            {
                var msg = string.Format("Unable to load SoundCloud URL '{0}'.{1}", url, additionalInfo != null ? " " + additionalInfo + ".": string.Empty);

                log.Warn(x, msg);
                return(VideoUrlParseResult.CreateError(url, VideoUrlParseResultType.LoadError, new VideoParseException(msg, x)));
            }

            try {
                result = JsonRequest.ReadObject <SoundCloudResult>(apiUrl, timeoutMs: 10000);
            } catch (WebException x) when(HasStatusCode(x, HttpStatusCode.Forbidden))
            {
                // Forbidden most likely means the artist has prevented API access to their tracks, http://stackoverflow.com/a/36529330
                return(ReturnError(x, "This track cannot be embedded"));
            } catch (WebException x) when(HasStatusCode(x, HttpStatusCode.NotFound))
            {
                return(ReturnError(x, "Not found"));
            } catch (WebException x) {
                return(ReturnError(x));
            } catch (JsonSerializationException x) {
                return(ReturnError(x));
            }

            var trackId = result.Id;
            var title   = result.Title;

            if (trackId == null || title == null)
            {
                return(VideoUrlParseResult.CreateError(url, VideoUrlParseResultType.LoadError, "Unable to load SoundCloud URL: Invalid response."));
            }

            var author = result.User.Username;
            var length = result.Duration / 1000;

            var thumbUrl = result.Artwork_url;

            // Substitute song thumbnail with user avatar, if no actual thumbnail is provided. This is what the SoundCloud site does as well.
            if (string.IsNullOrEmpty(thumbUrl))
            {
                thumbUrl = result.User.Avatar_url;
            }

            var uploadDate = result.Created_at;

            var id       = new SoundCloudId(trackId, url);
            var authorId = result.User.Permalink;             // Using permalink because that's the public URL

            return(VideoUrlParseResult.CreateOk(url, PVService.SoundCloud, id.ToString(), VideoTitleParseResult.CreateSuccess(title, author, authorId, thumbUrl, length, uploadDate: uploadDate)));
        }
Example #4
0
        public YoutubeVideoResponse Video(string id)
        {
            var url = string.Format(videoQueryFormat, apiKey, id);

            return(JsonRequest.ReadObject <YoutubeVideoResponse>(url));
        }
Example #5
0
 public YoutubeVideoResponse Video(string id) => JsonRequest.ReadObject <YoutubeVideoResponse>(Url(id));