Example #1
0
        public VideoUrlParseResult ParseBySoundCloudUrl(string url)
        {
            var apiUrl = string.Format("http://api.soundcloud.com/resolve?url=http://soundcloud.com/{0}&client_id=YOUR_CLIENT_ID", url);

            var       request = WebRequest.Create(apiUrl);
            XDocument doc;

            try {
                using (var response = request.GetResponse())
                    using (var stream = response.GetResponseStream()) {
                        doc = XDocument.Load(stream);
                    }
            } catch (WebException x) {
                log.WarnException("Unable to load SoundCloud URL " + url, x);
                return(VideoUrlParseResult.CreateError(url, VideoUrlParseResultType.LoadError, new VideoParseException("Unable to load SoundCloud URL: " + x.Message, x)));
            }

            var trackIdElem = doc.XPathSelectElement("//track/id");
            var titleElem   = doc.XPathSelectElement("//track/title");

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

            var trackId  = trackIdElem.Value;
            var title    = titleElem.Value;
            var author   = XmlHelper.GetNodeTextOrEmpty(doc, "//track/user/username");
            var thumbUrl = XmlHelper.GetNodeTextOrEmpty(doc, "//track/artwork-url");
            var id       = new SoundCloudId(trackId, url);

            return(VideoUrlParseResult.CreateOk(url, PVService.SoundCloud, id.ToString(), VideoTitleParseResult.CreateSuccess(title, author, thumbUrl)));
        }
Example #2
0
        public override async Task <VideoUrlParseResult> ParseByUrlAsync(string url, bool getTitle)
        {
            var id = GetIdByUrl(url);

            if (string.IsNullOrEmpty(id))
            {
                return(VideoUrlParseResult.CreateError(url, VideoUrlParseResultType.NoMatcher, "No matcher"));
            }

            if (!getTitle)
            {
                return(VideoUrlParseResult.CreateOk(url, PVService.Bilibili, id, VideoTitleParseResult.Empty));
            }

            var paramStr    = string.Format("appkey={0}&id={1}&type=xml{2}", AppConfig.BilibiliAppKey, id, AppConfig.BilibiliSecretKey);
            var paramStrMd5 = CryptoHelper.HashString(paramStr, CryptoHelper.MD5).ToLowerInvariant();

            var requestUrl = string.Format("https://api.bilibili.com/view?appkey={0}&id={1}&type=xml&sign={2}", AppConfig.BilibiliAppKey, id, paramStrMd5);

            XDocument doc;

            try {
                doc = await HtmlRequestHelper.GetStreamAsync(requestUrl, stream => XDocument.Load(stream), timeoutSec : 10, userAgent : "VocaDB/1.0 ([email protected])");
            } catch (WebException x) {
                log.Warn(x, "Unable to load Bilibili URL {0}", url);
                return(VideoUrlParseResult.CreateError(url, VideoUrlParseResultType.LoadError, new VideoParseException(string.Format("Unable to load Bilibili URL: {0}", x.Message), x)));
            } catch (XmlException x) {
                log.Warn(x, "Unable to load Bilibili URL {0}", url);
                return(VideoUrlParseResult.CreateError(url, VideoUrlParseResultType.LoadError, new VideoParseException(string.Format("Unable to load Bilibili URL: {0}", x.Message), x)));
            } catch (IOException x) {
                log.Warn(x, "Unable to load Bilibili URL {0}", url);
                return(VideoUrlParseResult.CreateError(url, VideoUrlParseResultType.LoadError, new VideoParseException(string.Format("Unable to load Bilibili URL: {0}", x.Message), x)));
            }

            var titleElem   = doc.XPathSelectElement("/info/title");
            var thumbElem   = doc.XPathSelectElement("/info/pic");
            var authorElem  = doc.XPathSelectElement("/info/author");
            var authorId    = GetValue(doc, "/info/mid");
            var createdElem = doc.XPathSelectElement("/info/created_at");

            int.TryParse(GetValue(doc, "/info/cid"), out var cid);             // Unsure what this is, but it's required for embedding

            if (titleElem == null)
            {
                return(VideoUrlParseResult.CreateError(url, VideoUrlParseResultType.LoadError, "No title element"));
            }

            var title   = HtmlEntity.DeEntitize(titleElem.Value);
            var thumb   = thumbElem?.Value ?? string.Empty;
            var author  = authorElem?.Value ?? string.Empty;
            var created = createdElem != null ? (DateTime?)DateTime.Parse(createdElem.Value) : null;
            var length  = await GetLength(id);

            var metadata = new PVExtendedMetadata(new BiliMetadata {
                Cid = cid
            });

            return(VideoUrlParseResult.CreateOk(url, PVService.Bilibili, id,
                                                VideoTitleParseResult.CreateSuccess(title, author, authorId, thumb, length: length, uploadDate: created, extendedMetadata: metadata)));
        }
Example #3
0
        protected virtual async Task <VideoUrlParseResult> ParseByIdAsync(string id, string url, bool getMeta)
        {
            var meta = (getMeta ? await GetVideoTitleAsync(id) : VideoTitleParseResult.Empty) ?? VideoTitleParseResult.Empty;

            // Note that even if meta lookup failed, we're returning Ok here, because for example NND API doesn't support all PVs.

            return(VideoUrlParseResult.CreateOk(url, Service, id, meta));
        }
        public async Task <VideoUrlParseResult> ParseBySoundCloudUrl(string url)
        {
            var apikey = AppConfig.SoundCloudClientId;
            var apiUrl = string.Format("https://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 = await JsonRequest.ReadObjectAsync <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 #5
0
        protected virtual async Task <VideoUrlParseResult> ParseByIdAsync(string id, string url, bool getMeta)
        {
            var meta = (getMeta ? await GetVideoTitleAsync(id) : VideoTitleParseResult.Empty) ?? VideoTitleParseResult.Empty;

            // Note that even if meta lookup failed, we're returning Ok here, because for example NND API doesn't support all PVs.
            // Metadata is optional. We should only return an error if the metadata is mandatory or there was a fatal unhandled error.

            return(VideoUrlParseResult.CreateOk(url, Service, id, meta));
        }
Example #6
0
        public override async Task <VideoUrlParseResult> ParseByUrlAsync(string url, bool getTitle)
        {
            var youtubeDl = new YoutubeDL {
                RetrieveAllInfo = true,
                YoutubeDlPath   = GetPath(AppConfig.YoutubeDLPath),
                PythonPath      = GetPath(AppConfig.PythonPath)
            };

            youtubeDl.StandardOutputEvent += StandardOutputEvent;
            youtubeDl.StandardErrorEvent  += StandardErrorEvent;

            DownloadInfo result;

            try {
                var task = youtubeDl.GetDownloadInfoAsync(url);
                result = await TimeoutAfter(task, 10000);
            } catch (TaskCanceledException) {
                var warnings = GetErrorString(youtubeDl.Info);
                _log.Error("Timeout. Error list: {0}", warnings);
                return(VideoUrlParseResult.CreateError(url, VideoUrlParseResultType.LoadError, "Timeout"));
            } catch (TimeoutException) {
                youtubeDl.CancelDownload();
                _log.Error("Timeout");
                return(VideoUrlParseResult.CreateError(url, VideoUrlParseResultType.LoadError, "Timeout"));
            }

            if (result == null)
            {
                var warnings = GetErrorString(youtubeDl.Info);
                _log.Error("Result from parser is empty. Error list: {0}", warnings);
                return(VideoUrlParseResult.CreateError(url, VideoUrlParseResultType.LoadError, "Result from parser is empty"));
            }

            if (!(result is VideoDownloadInfo info))
            {
                var warnings = GetErrorString(youtubeDl.Info);
                _log.Error("Unexpected result from parser. Error list: {0}. Result type is {1}. Title is {2}", warnings, result.GetType().Name, result.Title);
                return(VideoUrlParseResult.CreateError(url, VideoUrlParseResultType.LoadError, "Unexpected result from parser."));
            }

            DateTime?date = null;

            if (DateTime.TryParseExact(info.UploadDate, "yyyyMMdd", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal, out var parsedDate))
            {
                date = parsedDate;
            }

            var bandcampMetadata = new PVExtendedMetadata(new BandcampMetadata {
                Url = info.WebpageUrl
            });

            var meta = VideoTitleParseResult.CreateSuccess(info.Title, info.Uploader, info.UploaderId, info.Thumbnail, (int?)info.Duration, uploadDate: date, extendedMetadata: bandcampMetadata);

            return(VideoUrlParseResult.CreateOk(url, PVService.Bandcamp, info.Id, meta));
        }
Example #7
0
        public virtual Task <VideoUrlParseResult> ParseByUrlAsync(string url, bool getTitle)
        {
            var id = GetIdByUrl(url);

            if (id == null)
            {
                return(Task.FromResult(VideoUrlParseResult.CreateError(url, VideoUrlParseResultType.NoMatcher)));
            }

            return(ParseByIdAsync(id, url, getTitle));
        }
Example #8
0
        public static VideoUrlParseResult ParseByUrl(string url, bool getTitle, IUserPermissionContext permissionContext)
        {
            var service = services.FirstOrDefault(s => s.IsAuthorized(permissionContext) && s.IsValidFor(url));

            if (service == null)
            {
                return(VideoUrlParseResult.CreateError(url, VideoUrlParseResultType.NoMatcher));
            }

            return(service.ParseByUrl(url, getTitle));
        }
Example #9
0
        public static VideoUrlParseResult ParseByUrl(string url, bool getTitle)
        {
            var service = services.FirstOrDefault(s => s.IsValidFor(url));

            if (service == null)
            {
                return(VideoUrlParseResult.CreateError(url, VideoUrlParseResultType.NoMatcher));
            }

            return(service.ParseByUrl(url, getTitle));
        }
Example #10
0
        public static Task <VideoUrlParseResult> ParseByUrlAsync(string url, bool getTitle, IUserPermissionContext permissionContext, params VideoService[] testServices)
        {
            var service = testServices.FirstOrDefault(s => s.IsAuthorized(permissionContext) && s.IsValidFor(url));

            if (service == null)
            {
                return(Task.FromResult(VideoUrlParseResult.CreateError(url, VideoUrlParseResultType.NoMatcher)));
            }

            return(service.ParseByUrlAsync(url, getTitle));
        }
Example #11
0
        public override VideoUrlParseResult ParseByUrl(string url, bool getTitle)
        {
            var id = GetIdByUrl(url);

            if (string.IsNullOrEmpty(id))
            {
                return(VideoUrlParseResult.CreateError(url, VideoUrlParseResultType.NoMatcher, "No matcher"));
            }

            var paramStr    = string.Format("appkey={0}&id={1}&type=xml{2}", AppConfig.BilibiliAppKey, id, AppConfig.BilibiliSecretKey);
            var paramStrMd5 = CryptoHelper.HashString(paramStr, CryptoHelper.MD5).ToLowerInvariant();

            var requestUrl = string.Format("https://api.bilibili.com/view?appkey={0}&id={1}&type=xml&sign={2}", AppConfig.BilibiliAppKey, id, paramStrMd5);

            var request = (HttpWebRequest)WebRequest.Create(requestUrl);

            request.UserAgent = "VocaDB/1.0 ([email protected])";
            request.Timeout   = 10000;
            XDocument doc;

            try {
                using (var response = request.GetResponse())
                    using (var stream = response.GetResponseStream()) {
                        doc = XDocument.Load(stream);
                    }
            } catch (WebException x) {
                log.Warn(x, "Unable to load Bilibili URL {0}", url);
                return(VideoUrlParseResult.CreateError(url, VideoUrlParseResultType.LoadError, new VideoParseException(string.Format("Unable to load Bilibili URL: {0}", x.Message), x)));
            } catch (XmlException x) {
                log.Warn(x, "Unable to load Bilibili URL {0}", url);
                return(VideoUrlParseResult.CreateError(url, VideoUrlParseResultType.LoadError, new VideoParseException(string.Format("Unable to load Bilibili URL: {0}", x.Message), x)));
            } catch (IOException x) {
                log.Warn(x, "Unable to load Bilibili URL {0}", url);
                return(VideoUrlParseResult.CreateError(url, VideoUrlParseResultType.LoadError, new VideoParseException(string.Format("Unable to load Bilibili URL: {0}", x.Message), x)));
            }

            var titleElem   = doc.XPathSelectElement("/info/title");
            var thumbElem   = doc.XPathSelectElement("/info/pic");
            var authorElem  = doc.XPathSelectElement("/info/author");
            var createdElem = doc.XPathSelectElement("/info/created_at");

            if (titleElem == null)
            {
                return(VideoUrlParseResult.CreateError(url, VideoUrlParseResultType.LoadError, "No title element"));
            }

            var title   = HtmlEntity.DeEntitize(titleElem.Value);
            var thumb   = thumbElem != null ? thumbElem.Value : string.Empty;
            var author  = authorElem != null ? authorElem.Value : string.Empty;
            var created = createdElem != null ? (DateTime?)DateTime.Parse(createdElem.Value) : null;

            return(VideoUrlParseResult.CreateOk(url, PVService.Bilibili, id,
                                                VideoTitleParseResult.CreateSuccess(title, author, thumb, uploadDate: created)));
        }
Example #12
0
        public virtual VideoUrlParseResult ParseByUrl(string url, bool getTitle)
        {
            var id = GetIdByUrl(url);

            if (id == null)
            {
                return(VideoUrlParseResult.CreateError(url, VideoUrlParseResultType.NoMatcher));
            }

            return(ParseById(id, url, getTitle));
        }
Example #13
0
        public override async Task <VideoUrlParseResult> ParseByUrlAsync(string url, bool getTitle)
        {
            PostQueryResult result;

            try {
                result = await new PiaproClient.PiaproClient().ParseByUrlAsync(url);
            } catch (PiaproException x) {
                return(VideoUrlParseResult.CreateError(url, VideoUrlParseResultType.LoadError, new VideoParseException(x.Message, x)));
            }

            return(Parse(result, url));
        }
Example #14
0
        protected virtual VideoUrlParseResult ParseById(string id, string url, bool getMeta)
        {
            var meta = (getMeta ? GetVideoTitle(id) : VideoTitleParseResult.Empty) ?? VideoTitleParseResult.Empty;

            //if (!meta.Success) {
            //	return VideoUrlParseResult.CreateError(url, VideoUrlParseResultType.LoadError, meta.Error);
            //}

            // Note that even if meta lookup failed, we're returning Ok here, because for example NND API doesn't support all PVs.

            return(VideoUrlParseResult.CreateOk(url, Service, id, meta));
        }
Example #15
0
        public PVContract(VideoUrlParseResult parseResult, PVType type)
        {
            ParamIs.NotNull(() => parseResult);

            Author = parseResult.Author;
            Name = parseResult.Title;
            PVId = parseResult.Id;
            Service = parseResult.Service;
            ThumbUrl = parseResult.ThumbUrl;
            PVType = type;

            Url = PV.GetUrl(Service, PVId);
        }
Example #16
0
        public override async Task <VideoUrlParseResult> ParseByUrlAsync(string url, bool getTitle)
        {
            var id = GetIdByUrl(url);

            if (string.IsNullOrEmpty(id))
            {
                return(VideoUrlParseResult.CreateError(url, VideoUrlParseResultType.NoMatcher, "No matcher"));
            }

            var requestUrl = "https://api.bilibili.com/x/web-interface/view?" + (id.StartsWith("BV") ? $"bvid={id}" : $"aid={id}");

            BilibiliResponse response;

            try {
                response = await JsonRequest.ReadObjectAsync <BilibiliResponse>(requestUrl, timeout : TimeSpan.FromSeconds(10), userAgent : "VocaDB/1.0 ([email protected])");
            } catch (Exception x) when(x is HttpRequestException || x is WebException || x is JsonSerializationException || x is IOException)
            {
                log.Warn(x, "Unable to load Bilibili URL {0}", url);
                return(VideoUrlParseResult.CreateError(url, VideoUrlParseResultType.LoadError, new VideoParseException(string.Format("Unable to load Bilibili URL: {0}", x.Message), x)));
            }

            var authorId = response.Data.Owner.Mid.ToString();
            var aid      = response.Data.Aid;
            var bvid     = response.Data.Bvid;
            var cid      = response.Data.Cid;

            if (!getTitle)
            {
                return(VideoUrlParseResult.CreateOk(url, PVService.Bilibili, aid.ToString(), VideoTitleParseResult.Empty));
            }

            if (string.IsNullOrEmpty(response.Data.Title))
            {
                return(VideoUrlParseResult.CreateError(url, VideoUrlParseResultType.LoadError, "No title element"));
            }

            var title   = HtmlEntity.DeEntitize(response.Data.Title);
            var thumb   = response.Data.Pic ?? string.Empty;
            var author  = response.Data.Owner.Name ?? string.Empty;
            var created = response.Data.PubDate;
            var length  = response.Data.Duration;

            var metadata = new PVExtendedMetadata(new BiliMetadata {
                Aid  = aid,
                Bvid = bvid,
                Cid  = cid
            });

            return(VideoUrlParseResult.CreateOk(url, PVService.Bilibili, aid.ToString(),
                                                VideoTitleParseResult.CreateSuccess(title, author, authorId, thumb, length: length, uploadDate: created, extendedMetadata: metadata)));
        }
Example #17
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;

            try {
                result = JsonRequest.ReadObject <SoundCloudResult>(apiUrl, timeoutMs: 10000);
            } catch (WebException x) {
                var msg = string.Format("Unable to load SoundCloud URL '{0}'.", url);

                // Forbidden most likely means the artist has prevented API access to their tracks, http://stackoverflow.com/a/36529330
                if (((HttpWebResponse)x.Response).StatusCode == HttpStatusCode.Forbidden)
                {
                    msg += " This track cannot be embedded.";
                }

                log.Warn(x, msg);
                return(VideoUrlParseResult.CreateError(url, VideoUrlParseResultType.LoadError, new VideoParseException(msg, x)));
            } catch (JsonSerializationException x) {
                var msg = string.Format("Unable to load SoundCloud URL '{0}'.", url);
                log.Warn(x, msg);
                return(VideoUrlParseResult.CreateError(url, VideoUrlParseResultType.LoadError, new VideoParseException(msg, 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);

            return(VideoUrlParseResult.CreateOk(url, PVService.SoundCloud, id.ToString(), VideoTitleParseResult.CreateSuccess(title, author, thumbUrl, length, uploadDate: uploadDate)));
        }
        private VideoUrlParseResult Parse(PostQueryResult result, string url)
        {
            if (result.PostType != PostType.Audio)
            {
                return(VideoUrlParseResult.CreateError(url, VideoUrlParseResultType.LoadError, new VideoParseException("Content type indicates this isn't an audio post")));
            }

            var piaproMetadata = new PVExtendedMetadata(new PiaproMetadata {
                Timestamp = result.UploadTimestamp
            });

            return(VideoUrlParseResult.CreateOk(url, PVService.Piapro, result.Id,
                                                VideoTitleParseResult.CreateSuccess(result.Title, result.Author, result.AuthorId, result.ArtworkUrl, result.LengthSeconds, uploadDate: result.Date, extendedMetadata: piaproMetadata)));
        }
        public override async Task <VideoUrlParseResult> ParseByUrlAsync(string url, bool getTitle)
        {
            PostQueryResult result;
            var             client = new PiaproClient.PiaproClient {
                RequestTimeout = TimeSpan.FromMilliseconds(3900)                                                      /* Value chosen after careful consideration */
            };

            try {
                result = await client.ParseByUrlAsync(url);
            } catch (PiaproException x) {
                log.Warn(x, "Unable to load Piapro URL {0}", url);
                return(VideoUrlParseResult.CreateError(url, VideoUrlParseResultType.LoadError, new VideoParseException(x.Message, x)));
            }

            return(Parse(result, url));
        }
        public VideoUrlParseResult ParseBySoundCloudUrl(string url)
        {
            var apiUrl = string.Format("http://api.soundcloud.com/resolve?url=http://soundcloud.com/{0}&client_id=YOUR_CLIENT_ID", url);

            var request = WebRequest.Create(apiUrl);

            request.Timeout = 10000;
            SoundCloudResult result;

            try {
                using (var response = request.GetResponse())
                    using (var stream = response.GetResponseStream())
                        using (var streamReader = new StreamReader(stream))
                            using (var jsonReader = new JsonTextReader(streamReader)) {
                                var serializer = new JsonSerializer();
                                result = serializer.Deserialize <SoundCloudResult>(jsonReader);
                            }
            } catch (WebException x) {
                var msg = string.Format("Unable to load SoundCloud URL {0}", url);
                log.Warn(msg, x);
                return(VideoUrlParseResult.CreateError(url, VideoUrlParseResultType.LoadError, new VideoParseException(msg, 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 id = new SoundCloudId(trackId, url);

            return(VideoUrlParseResult.CreateOk(url, PVService.SoundCloud, id.ToString(), VideoTitleParseResult.CreateSuccess(title, author, thumbUrl, length)));
        }
Example #21
0
        public override VideoUrlParseResult ParseByUrl(string url, bool getTitle)
        {
            PostQueryResult result;

            try {
                result = new PiaproClient.PiaproClient().ParseByUrl(url);
            } catch (PiaproException x) {
                return(VideoUrlParseResult.CreateError(url, VideoUrlParseResultType.LoadError, new VideoParseException(x.Message, x)));
            }

            if (result.PostType != PostType.Audio)
            {
                return(VideoUrlParseResult.CreateError(url, VideoUrlParseResultType.LoadError, new VideoParseException("Content type indicates this isn't an audio post")));
            }

            return(VideoUrlParseResult.CreateOk(url, PVService.Piapro, result.Id,
                                                VideoTitleParseResult.CreateSuccess(result.Title, result.Author, string.Empty, result.LengthSeconds, uploadDate: result.Date)));
        }
        public override async Task <VideoUrlParseResult> ParseByUrlAsync(string url, bool getTitle)
        {
            url = UrlHelper.MakeLink(url);

            Uri parsedUri;

            try {
                parsedUri = new Uri(url, UriKind.Absolute);
            } catch (UriFormatException x) {
                var msg = string.Format("{0} could not be parsed as a valid URL.", url);
                log.Warn(x, msg);
                return(VideoUrlParseResult.CreateError(url, VideoUrlParseResultType.LoadError, new VideoParseException(msg, x)));
            }

            var request = new HttpRequestMessage(HttpMethod.Head, url);

            request.Headers.UserAgent.Add(new ProductInfoHeaderValue("VocaDB", "1.0"));

            try {
                using (var client = new HttpClient()) {
                    client.Timeout = TimeSpan.FromSeconds(10);

                    using (var response = await client.SendAsync(request)) {
                        response.EnsureSuccessStatusCode();

                        var mime = response.Content.Headers.ContentType?.MediaType;

                        if (!mimeTypes.Contains(mime))
                        {
                            return(VideoUrlParseResult.CreateError(url, VideoUrlParseResultType.LoadError, string.Format("Unsupported content type: {0}", mime)));
                        }
                    }
                }
            } catch (WebException x) {
                var msg = string.Format("Unable to load file URL {0}. The file might not be publicly accessible", url);
                log.Warn(x, msg);
                return(VideoUrlParseResult.CreateError(url, VideoUrlParseResultType.LoadError, new VideoParseException(msg, x)));
            }

            return(VideoUrlParseResult.CreateOk(url, PVService.File, url, await GetVideoTitleAsync(url)));
        }
Example #23
0
        public override async Task <VideoUrlParseResult> ParseByUrlAsync(string url, bool getTitle)
        {
            var extractor = new BandcampMetadataClient();
            var info      = await extractor.ExtractAsync(url);

            DateTime?date = null;

            if (DateTime.TryParseExact(info.UploadDate, "yyyyMMdd", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal, out var parsedDate))
            {
                date = parsedDate;
            }

            var bandcampMetadata = new PVExtendedMetadata(new BandcampMetadata
            {
                Url = info.WebpageUrl
            });

            var meta = VideoTitleParseResult.CreateSuccess(info.Title, info.Uploader, info.UploaderId, info.Thumbnail, (int?)info.Duration, uploadDate: date, extendedMetadata: bandcampMetadata);

            return(VideoUrlParseResult.CreateOk(url, PVService.Bandcamp, info.Id, meta));
        }
Example #24
0
        public override VideoUrlParseResult ParseByUrl(string url, bool getTitle)
        {
            var id = GetIdByUrl(url);

            if (string.IsNullOrEmpty(id))
            {
                return(VideoUrlParseResult.CreateError(url, VideoUrlParseResultType.NoMatcher, "No matcher"));
            }

            var requestUrl = string.Format("http://api.bilibili.tv/view?type=xml&appkey={0}&id={1}", AppConfig.BilibiliAppKey, id);

            var       request = WebRequest.Create(requestUrl);
            XDocument doc;

            try {
                using (var response = request.GetResponse())
                    using (var stream = response.GetResponseStream()) {
                        doc = XDocument.Load(stream);
                    }
            } catch (WebException x) {
                log.WarnException("Unable to load Bilibili URL " + url, x);
                return(VideoUrlParseResult.CreateError(url, VideoUrlParseResultType.LoadError, new VideoParseException("Unable to load Bilibili URL: " + x.Message, x)));
            }

            var titleElem  = doc.XPathSelectElement("/info/title");
            var thumbElem  = doc.XPathSelectElement("/info/pic");
            var authorElem = doc.XPathSelectElement("/info/author");

            if (titleElem == null)
            {
                return(VideoUrlParseResult.CreateError(url, VideoUrlParseResultType.LoadError, "No title element"));
            }

            var title  = HtmlEntity.DeEntitize(titleElem.Value);
            var thumb  = thumbElem != null ? thumbElem.Value : string.Empty;
            var author = authorElem != null ? authorElem.Value : string.Empty;

            return(VideoUrlParseResult.CreateOk(url, PVService.Bilibili, id,
                                                VideoTitleParseResult.CreateSuccess(title, author, thumb)));
        }
Example #25
0
        public override VideoUrlParseResult ParseByUrl(string url, bool getTitle)
        {
            url = UrlHelper.MakeLink(url);

            Uri parsedUri;

            try {
                parsedUri = new Uri(url, UriKind.Absolute);
            } catch (UriFormatException x) {
                var msg = string.Format("{0} could not be parsed as a valid URL.", url);
                log.Warn(x, msg);
                return(VideoUrlParseResult.CreateError(url, VideoUrlParseResultType.LoadError, new VideoParseException(msg, x)));
            }

            var request = WebRequest.CreateHttp(parsedUri);

            request.UserAgent = "VocaDB";
            request.Method    = "HEAD";
            request.Timeout   = 10000;

            try {
                using (var response = request.GetResponse()) {
                    var mime = response.ContentType;

                    if (!mimeTypes.Contains(mime))
                    {
                        return(VideoUrlParseResult.CreateError(url, VideoUrlParseResultType.LoadError, string.Format("Unsupported content type: {0}", mime)));
                    }
                }
            } catch (WebException x) {
                var msg = string.Format("Unable to load file URL {0}. The file might not be publicly accessible", url);
                log.Warn(x, msg);
                return(VideoUrlParseResult.CreateError(url, VideoUrlParseResultType.LoadError, new VideoParseException(msg, x)));
            }

            return(VideoUrlParseResult.CreateOk(url, PVService.File, url, GetVideoTitle(url)));
        }
Example #26
0
        /*public override string GetUrlById(string id) {
         *
         *      var compositeId = new CompositeId(id);
         *      var matcher = linkMatchers.First();
         *      return "http://" + matcher.MakeLinkFromId(compositeId.SoundCloudUrl);
         *
         * }*/

        private VideoUrlParseResult ParseByHtmlStream(Stream htmlStream, Encoding encoding, string url)
        {
            var doc = new HtmlDocument();

            doc.Load(htmlStream, encoding);

            var catLink = doc.DocumentNode.SelectSingleNode("//div[@class = 'dtl_data']/p[3]");

            if (catLink == null || !catLink.InnerHtml.Contains("/illust/?categoryId=1"))
            {
                return(VideoUrlParseResult.CreateError(url, VideoUrlParseResultType.LoadError, "Content type indicates this isn't an audio file."));
            }

            var idElem = doc.DocumentNode.SelectSingleNode("//input[@name = 'id']");

            if (idElem == null)
            {
                return(VideoUrlParseResult.CreateError(url, VideoUrlParseResultType.LoadError, "Could not find id element on page."));
            }

            var contentId = idElem.GetAttributeValue("value", string.Empty);

            var titleElem = doc.DocumentNode.SelectSingleNode("//h1[@class = 'dtl_title']");

            if (titleElem == null)
            {
                return(VideoUrlParseResult.CreateError(url, VideoUrlParseResultType.LoadError, "Could not find title element on page."));
            }

            var title = HtmlEntity.DeEntitize(titleElem.InnerText).Trim();

            var authorElem = doc.DocumentNode.SelectSingleNode("//div[@class = 'dtl_by_name']/a");
            var author     = (authorElem != null ? authorElem.InnerText : string.Empty);

            return(VideoUrlParseResult.CreateOk(url, PVService.Piapro, contentId, VideoTitleParseResult.CreateSuccess(title, author, string.Empty)));
        }
Example #27
0
        public virtual VideoUrlParseResult ParseById(string id, string url, bool getMeta)
        {
            var meta = (getMeta ? GetVideoTitle(id) : VideoTitleParseResult.Empty);

            return(VideoUrlParseResult.CreateOk(url, Service, id, meta));
        }