Beispiel #1
0
        public R <PlayResource, LocalStr> GetResourceById(ResolveContext ctx, AudioResource resource)
        {
            var result = ValidateFromString(ctx.Config, resource.ResourceId);

            if (!result)
            {
                return(result.Error);
            }

            var resData = result.Value;

            if (resData.IsIcyStream)
            {
                if (resource.ResourceTitle == null)
                {
                    resource = resource.WithTitle(StringNormalize.Normalize(resData.Title));
                }
                return(new MediaPlayResource(resData.FullUri, resource, null, true));
            }

            if (resource.ResourceTitle == null)
            {
                resource = resource.WithTitle(!string.IsNullOrWhiteSpace(resData.Title) ? StringNormalize.Normalize(resData.Title) : resource.ResourceId);
            }

            return(new MediaPlayResource(resData.FullUri, resource, resData.Image, false));
        }
Beispiel #2
0
 public PlayResource(string uri, AudioResource baseData, PlayInfo?playInfo = null, SongInfo?songInfo = null)
 {
     AudioResource = baseData;
     PlayUri       = uri;
     PlayInfo      = playInfo;
     SongInfo      = songInfo;
 }
        public RResultCode GetResourceById(string id, string name, out AudioResource resource)
        {
            string finalRequest = $"https://api.soundcloud.com/tracks/{id}/stream?client_id={SoundcloudClientID}";

            resource = new SoundcloudResource(id, name, finalRequest);
            return(RResultCode.Success);
        }
        private R <PlayResource, LocalStr> GetResourceById(AudioResource resource, bool allowNullName)
        {
            if (SoundcloudLink.IsMatch(resource.ResourceId))
            {
                return(GetResource(resource.ResourceId));
            }

            if (resource.ResourceTitle is null)
            {
                if (!allowNullName)
                {
                    return(new LocalStr(strings.error_media_internal_missing + " (title)"));
                }
                string link = RestoreLink(resource.ResourceId);
                if (link is null)
                {
                    return(new LocalStr(strings.error_media_internal_missing + " (link)"));
                }
                return(GetResource(link));
            }

            string finalRequest = $"https://api.soundcloud.com/tracks/{resource.ResourceId}/stream?client_id={SoundcloudClientId}";

            return(new PlayResource(finalRequest, resource));
        }
Beispiel #5
0
        public R <PlayResource, LocalStr> GetResourceById(ResolveContext _, AudioResource resource)
        {
            var result = DownloadEmbeddedSite(resource.ResourceId);

            if (!result.Ok)
            {
                return(result.Error);
            }
            var webSite = result.Value;

            if (resource.ResourceTitle == null)
            {
                var nameMatch = TrackNameRegex.Match(webSite);
                resource = resource.WithTitle(nameMatch.Success
                                        ? StringNormalize.Normalize(nameMatch.Groups[1].Value)
                                        : $"Bandcamp (id: {resource.ResourceId})");
            }

            var match = TrackLinkRegex.Match(webSite);

            if (!match.Success)
            {
                return(new LocalStr(strings.error_media_internal_missing + " (TrackLinkRegex)"));
            }

            return(new BandcampPlayResource(match.Groups[1].Value, resource, GetTrackArtId(webSite)));
        }
Beispiel #6
0
        public R <PlayResource, LocalStr> GetResource(ResolveContext ctx, string uriOrUrl)
        {
            string uri;

            // Convert if it is a URL.
            var uriResult = SpotifyApi.UrlToUri(uriOrUrl);

            if (uriResult.Ok)
            {
                uri = uriResult.Value;
            }
            else
            {
                uri = uriOrUrl;
            }

            var trackOption = api.UriToTrack(uri);

            if (!trackOption.Ok)
            {
                return(trackOption.Error);
            }

            var resource = new AudioResource(uri, SpotifyApi.TrackToName(trackOption.Value), ResolverFor);

            return(new PlayResource(resource.ResourceId, resource));
        }
        public R <PlayResource, LocalStr> GetResourceById(AudioResource resource)
        {
            var result = ValidateFromString(resource.ResourceId);

            if (!result)
            {
                return(result.Error);
            }

            var resData = result.Value;

            if (resData.IsIcyStream)
            {
                resource.ResourceTitle = resData.Title;
                return(new MediaPlayResource(resData.FullUri, resource, null, true));
            }

            if (resource.ResourceTitle == null)
            {
                if (!string.IsNullOrWhiteSpace(resData.Title))
                {
                    resource.ResourceTitle = resData.Title;
                }
                else
                {
                    resource.ResourceTitle = resource.ResourceId;
                }
            }
            return(new MediaPlayResource(resData.FullUri, resource, resData.Image, false));
        }
Beispiel #8
0
        public R <PlayResource> GetResourceById(AudioResource resource)
        {
            var result = DownloadEmbeddedSite(resource.ResourceId);

            if (!result.Ok)
            {
                return(result.Error);
            }
            var webSite = result.Value;

            if (string.IsNullOrEmpty(resource.ResourceTitle))
            {
                var nameMatch = TrackNameRegex.Match(webSite);
                resource.ResourceTitle = nameMatch.Success
                                        ? nameMatch.Groups[1].Value
                                        : $"Bandcamp (id: {resource.ResourceId})";
            }

            var match = TrackLinkRegex.Match(webSite);

            if (!match.Success)
            {
                return("Could not extract track link");
            }

            return(new BandcampPlayResource(match.Groups[1].Value, resource, GetTrackArtId(webSite)));
        }
Beispiel #9
0
        public R <PlayResource> GetResourceById(AudioResource resource)
        {
            var result = ValidateUri(resource.ResourceId);

            if (!result)
            {
                return(result.Error);
            }
            else
            {
                var           resData = result.Value;
                AudioResource finalResource;
                if (resource.ResourceTitle != null)
                {
                    finalResource = resource;
                }
                else if (!string.IsNullOrWhiteSpace(resData.Title))
                {
                    finalResource = resource.WithName(resData.Title);
                }
                else
                {
                    finalResource = resource.WithName(resource.ResourceId);
                }
                return(new PlayResource(resData.FullUri, finalResource));
            }
        }
Beispiel #10
0
        private R <PlayResource> GetResourceById(AudioResource resource, bool allowNullName)
        {
            if (SoundcloudLink.IsMatch(resource.ResourceId))
            {
                return(GetResource(resource.ResourceId));
            }

            if (resource.ResourceTitle == null)
            {
                if (!allowNullName)
                {
                    return("Could not restore null title.");
                }
                string link = RestoreLink(resource.ResourceId);
                if (link == null)
                {
                    return("Could not restore link from id");
                }
                return(GetResource(link));
            }

            string finalRequest = $"https://api.soundcloud.com/tracks/{resource.ResourceId}/stream?client_id={SoundcloudClientId}";

            return(new PlayResource(finalRequest, resource));
        }
        private static R <PlayResource, LocalStr> ParseLiveData(AudioResource resource, JsonPlayerResponse parsed)
        {
            var webListResponse = WebWrapper.GetResponse(new Uri(parsed.streamingData.hlsManifestUrl), response =>
            {
                return(AudioTags.M3uReader.TryGetData(response.GetResponseStream()).OkOr(null));
            });

            if (webListResponse.Ok)
            {
                const string AacHe = "mp4a.40.5";
                const string AacLc = "mp4a.40.2";

                var webList    = webListResponse.Value;
                var streamPref = from item in webList
                                 let codecs = item.StreamMeta != null?StreamCodecMatch.Match(item.StreamMeta).Groups[1].Value : ""
                                              let codecPref = codecs.Contains(AacLc) ? 0
                                                                                                                                                                         : codecs.Contains(AacHe) ? 1
                                                                                                                                                                         : 2
                                                              let bitrate = item.StreamMeta != null?int.Parse(StreamBitrateMatch.Match(item.StreamMeta).Groups[1].Value) : int.MaxValue
                                                                            orderby codecPref, bitrate ascending
                select item;

                var streamSelect = streamPref.FirstOrDefault();
                if (streamSelect != null)
                {
                    if (resource.ResourceTitle == null)
                    {
                        resource.ResourceTitle = parsed.videoDetails.title;
                    }
                    return(new PlayResource(streamSelect.TrackUrl, resource));
                }
            }
            return(new LocalStr(strings.error_media_no_stream_extracted));
        }
        public R <PlayResource, LocalStr> GetResourceById(AudioResource resource)
        {
            var result = DownloadEmbeddedSite(resource.ResourceId);

            if (!result.Ok)
            {
                return(result.Error);
            }
            var webSite = result.Value;

            if (string.IsNullOrEmpty(resource.ResourceTitle))
            {
                var nameMatch = TrackNameRegex.Match(webSite);
                resource.ResourceTitle = nameMatch.Success
                                        ? nameMatch.Groups[1].Value
                                        : $"Bandcamp (id: {resource.ResourceId})";
            }

            var match = TrackLinkRegex.Match(webSite);

            if (!match.Success)
            {
                return(new LocalStr(strings.error_media_internal_missing + " (TrackLinkRegex)"));
            }

            return(new BandcampPlayResource(match.Groups[1].Value, resource, GetTrackArtId(webSite)));
        }
Beispiel #13
0
        public bool ReallyEquals(AudioResource other)
        {
            if (ReferenceEquals(null, other))
            {
                return(false);
            }

            if (ReferenceEquals(this, other))
            {
                return(true);
            }

            if (!Equals(other) || Gain != other.Gain || TitleIsUserSet != other.TitleIsUserSet)
            {
                return(false);
            }

            if (AdditionalData == null && other.AdditionalData != null)
            {
                return(false);
            }

            if (AdditionalData != null && other.AdditionalData == null)
            {
                return(false);
            }

            // Both are null (see checks above). If I use &&, static code analysis is unhappy for some weird reason.
            if (AdditionalData == null || other.AdditionalData == null)
            {
                return(true);
            }

            if (AdditionalData.Count != other.AdditionalData.Count)
            {
                return(false);
            }

            if (new HashSet <string>(AdditionalData.Keys).Equals(new HashSet <string>(other.AdditionalData.Keys)))
            {
                // Key sets are not the same.
                return(false);
            }

            foreach (var key in AdditionalData.Keys)
            {
                if (AdditionalData[key] != other.AdditionalData[key])
                {
                    // There is a key-value-pair that does not match.
                    return(false);
                }
            }

            // No need to compare values in the other direction as the key sets are the same.
            return(true);
        }
Beispiel #14
0
		public RResultCode GetResource(string url, out AudioResource resource)
		{
			var match = twitchMatch.Match(url);
			if (!match.Success)
			{
				resource = null;
				return RResultCode.TwitchInvalidUrl;
			}
			return GetResourceById(match.Groups[3].Value, null, out resource);
		}
		public RResultCode GetResource(string ytLink, out AudioResource result)
		{
			Match matchYtId = idMatch.Match(ytLink);
			if (!matchYtId.Success)
			{
				result = null;
				return RResultCode.YtIdNotFound;
			}
			return GetResourceById(matchYtId.Groups[3].Value, null, out result);
		}
Beispiel #16
0
        public R <PlayResource> GetResourceById(AudioResource resource)
        {
            var result = ResolveResourceInternal(resource);

            if (result.Ok)
            {
                return(result);
            }

            return(YoutubeDlWrapped(resource));
        }
Beispiel #17
0
        public RResultCode GetResource(string url, out AudioResource resource)
        {
            var match = twitchMatch.Match(url);

            if (!match.Success)
            {
                resource = null;
                return(RResultCode.TwitchInvalidUrl);
            }
            return(GetResourceById(match.Groups[3].Value, null, out resource));
        }
Beispiel #18
0
        public RResultCode GetResource(string ytLink, out AudioResource result)
        {
            Match matchYtId = idMatch.Match(ytLink);

            if (!matchYtId.Success)
            {
                result = null;
                return(RResultCode.YtIdNotFound);
            }
            return(GetResourceById(matchYtId.Groups[3].Value, null, out result));
        }
Beispiel #19
0
        public R <PlayResource, LocalStr> GetResourceById(ResolveContext ctx, AudioResource resource)
        {
            // Check if the track is available on the market of the bots spotify account.
            var trackOption = api.UriToTrack(resource.ResourceId);

            if (!trackOption.Ok)
            {
                return(trackOption.Error);
            }

            return(new PlayResource(resource.ResourceId, resource));
        }
Beispiel #20
0
        public string RestoreLink(ResolveContext _, AudioResource resource)
        {
            var artistName = resource.Get(AddArtist);
            var trackName  = resource.Get(AddTrack);

            if (artistName != null && trackName != null)
            {
                return($"https://soundcloud.com/{artistName}/{trackName}");
            }

            return("https://soundcloud.com");
        }
Beispiel #21
0
        public string RestoreLink(ResolveContext _, AudioResource resource)
        {
            var artistName = resource.Get(AddArtist);
            var trackName  = resource.Get(AddTrack);

            if (artistName != null && trackName != null)
            {
                return($"https://{artistName}.bandcamp.com/track/{trackName}");
            }

            // backup when something's wrong with the website
            return($"https://bandcamp.com/EmbeddedPlayer/v=2/track={resource.ResourceId}");
        }
		public RResultCode GetResource(string link, out AudioResource resource)
		{
			string jsonResponse;
			var uri = new Uri($"https://api.soundcloud.com/resolve.json?url={Uri.EscapeUriString(link)}&client_id={SoundcloudClientID}");
			if (!WebWrapper.DownloadString(out jsonResponse, uri))
			{
				resource = null;
				return RResultCode.ScInvalidLink;
			}
			var parsedDict = ParseJson(jsonResponse);
			int id = (int)parsedDict["id"];
			string title = (string)parsedDict["title"];
			return GetResourceById(id.ToString(), title, out resource);
		}
Beispiel #23
0
        public RResultCode GetResourceById(string id, string name, out AudioResource resource)
        {
            var result = ValidateUri(id, ref name, id);

            if (result == RResultCode.MediaNoWebResponse)
            {
                resource = null;
                return(result);
            }
            else
            {
                resource = new MediaResource(id, name, id, result);
                return(RResultCode.Success);
            }
        }
Beispiel #24
0
		public RResultCode GetResourceById(string id, string name, out AudioResource resource)
		{
			var result = ValidateUri(id, ref name, id);

			if (result == RResultCode.MediaNoWebResponse)
			{
				resource = null;
				return result;
			}
			else
			{
				resource = new MediaResource(id, name, id, result);
				return RResultCode.Success;
			}
		}
        public RResultCode GetResource(string link, out AudioResource resource)
        {
            string jsonResponse;
            var    uri = new Uri($"https://api.soundcloud.com/resolve.json?url={Uri.EscapeUriString(link)}&client_id={SoundcloudClientID}");

            if (!WebWrapper.DownloadString(out jsonResponse, uri))
            {
                resource = null;
                return(RResultCode.ScInvalidLink);
            }
            var    parsedDict = ParseJson(jsonResponse);
            int    id         = (int)parsedDict["id"];
            string title      = (string)parsedDict["title"];

            return(GetResourceById(id.ToString(), title, out resource));
        }
Beispiel #26
0
        // Load lookup stages
        // PlayResource != null    => ret PlayResource
        // ResourceData != null    => call RF.RestoreFromId
        // TextMessage != null     => call RF.GetResoruce
        // else                    => ret Error

        /// <summary>Generates a new <see cref="PlayResource"/> which can be played.</summary>
        /// <param name="resource">An <see cref="AudioResource"/> with at least
        /// <see cref="AudioResource.AudioType"/> and<see cref="AudioResource.ResourceId"/> set.</param>
        /// <returns>The playable resource if successful, or an error message otherwise.</returns>
        public R <PlayResource> Load(AudioResource resource)
        {
            if (resource == null)
            {
                throw new ArgumentNullException(nameof(resource));
            }

            IResourceFactory factory = GetFactoryFor(resource.AudioType);

            var result = factory.GetResourceById(resource);

            if (!result)
            {
                return($"Could not load ({result.Message})");
            }
            return(result);
        }
        private R <PlayResource> YoutubeDlWrapped(AudioResource resource)
        {
            string title = null;
            string url   = null;

            Log.Write(Log.Level.Debug, "YT Ruined!");

            var result = YoutubeDlHelper.FindAndRunYoutubeDl(resource.ResourceId);

            if (!result.Ok)
            {
                return(result.Message);
            }

            var response = result.Value;

            title = response.Item1;
            var urlOptions = response.Item2;

            if (urlOptions.Count == 1)
            {
                url = urlOptions[0];
            }
            else if (urlOptions.Count >= 1)
            {
                Uri[] uriList   = urlOptions.Select(s => new Uri(s)).ToArray();
                Uri   bestMatch = uriList
                                  .FirstOrDefault(u => HttpUtility.ParseQueryString(u.Query)
                                                  .GetValues("mime")
                                                  .Any(x => x.StartsWith("audio", StringComparison.OrdinalIgnoreCase)));
                url = (bestMatch ?? uriList[0]).OriginalString;
            }

            if (string.IsNullOrEmpty(title) || string.IsNullOrEmpty(url))
            {
                return("No youtube-dl response");
            }

            Log.Write(Log.Level.Debug, "YT Saved!");
            return(new PlayResource(url, resource.WithName(title)));
        }
Beispiel #28
0
        public async Task <PlayResource> GetResourceById(ResolveContext _, AudioResource resource)
        {
            var webSite = await DownloadEmbeddedSite(resource.ResourceId);

            if (string.IsNullOrEmpty(resource.ResourceTitle))
            {
                var nameMatch = TrackNameRegex.Match(webSite);
                resource.ResourceTitle = nameMatch.Success
                                        ? nameMatch.Groups[1].Value
                                        : $"Bandcamp (id: {resource.ResourceId})";
            }

            var match = TrackLinkRegex.Match(webSite);

            if (!match.Success)
            {
                throw Error.LocalStr(strings.error_media_internal_missing + " (TrackLinkRegex)");
            }

            return(new BandcampPlayResource(match.Groups[1].Value, resource, GetTrackArtId(webSite)));
        }
        private static R <PlayResource, LocalStr> YoutubeDlWrapped(AudioResource resource)
        {
            Log.Debug("Falling back to youtube-dl!");

            var result = YoutubeDlHelper.FindAndRunYoutubeDl(resource.ResourceId);

            if (!result.Ok)
            {
                return(result.Error);
            }

            var response   = result.Value;
            var title      = response.title;
            var urlOptions = response.links;

            string url = null;

            if (urlOptions.Count == 1)
            {
                url = urlOptions[0];
            }
            else if (urlOptions.Count >= 1)
            {
                Uri[] uriList   = urlOptions.Select(s => new Uri(s)).ToArray();
                Uri   bestMatch = uriList
                                  .FirstOrDefault(u => ParseQueryString(u.Query).TryGetValue("mime", out var mimes) &&
                                                  mimes.Any(x => x.StartsWith("audio", StringComparison.OrdinalIgnoreCase)));
                url = (bestMatch ?? uriList[0]).OriginalString;
            }

            if (string.IsNullOrEmpty(title) || string.IsNullOrEmpty(url))
            {
                return(new LocalStr(strings.error_ytdl_empty_response));
            }

            resource.ResourceTitle = title;

            Log.Debug("youtube-dl succeeded!");
            return(new PlayResource(url, resource));
        }
Beispiel #30
0
        public async Task <PlayResource> GetResourceById(ResolveContext ctx, AudioResource resource)
        {
            var resData = await ValidateFromString(ctx.Config, resource.ResourceId);

            if (resData.IsIcyStream)
            {
                resource.ResourceTitle = resData.Title;
                return(new MediaPlayResource(resData.FullUri, resource, null, true));
            }

            if (resource.ResourceTitle is null)
            {
                if (!string.IsNullOrWhiteSpace(resData.Title))
                {
                    resource.ResourceTitle = resData.Title;
                }
                else
                {
                    resource.ResourceTitle = resource.ResourceId;
                }
            }
            return(new MediaPlayResource(resData.FullUri, resource, resData.Image, false));
        }
Beispiel #31
0
		public RResultCode GetResource(string uri, out AudioResource resource)
		{
			return GetResourceById(uri, null, out resource);
		}
 public BandcampPlayResource(string uri, AudioResource baseData, string artId) : base(uri, baseData)
 {
     ArtId = artId;
 }
		public void AddResource(AudioResource resource)
		{
			if (!resourceSet.Contains(resource))
			{

				Length++;
			}
		}
Beispiel #34
0
 public string RestoreLink(ResolveContext ctx, AudioResource resource)
 {
     return(SpotifyApi.UriToUrl(resource.ResourceId).OkOr(null));
 }
		public void RemoveResource(AudioResource resource)
		{
			if (!resourceSet.Contains(resource))
			{

			}
		}
Beispiel #36
0
		public RResultCode GetResourceById(string id, string name, out AudioResource resource)
		{
			var channel = id;

			// request api token
			string jsonResponse;
			if (!WebWrapper.DownloadString(out jsonResponse, new Uri($"http://api.twitch.tv/api/channels/{channel}/access_token")))
			{
				resource = null;
				return RResultCode.NoConnection;
			}

			var jsonDict = (Dictionary<string, object>)jsonParser.DeserializeObject(jsonResponse);

			// request m3u8 file
			var token = Uri.EscapeUriString(jsonDict["token"].ToString());
			var sig = jsonDict["sig"];
			// guaranteed to be random, chosen by fair dice roll.
			var random = 4;
			string m3u8;
			if (!WebWrapper.DownloadString(out m3u8, new Uri($"http://usher.twitch.tv/api/channel/hls/{channel}.m3u8?player=twitchweb&&token={token}&sig={sig}&allow_audio_only=true&allow_source=true&type=any&p={random}")))
			{
				resource = null;
				return RResultCode.NoConnection;
			}

			// parse m3u8 file
			var dataList = new List<StreamData>();
			using (var reader = new System.IO.StringReader(m3u8))
			{
				var header = reader.ReadLine();
				if (string.IsNullOrEmpty(header) || header != "#EXTM3U")
				{
					resource = null;
					return RResultCode.TwitchMalformedM3u8File;
				}

				while (true)
				{
					var blockInfo = reader.ReadLine();
					if (string.IsNullOrEmpty(blockInfo))
						break;

					var match = m3u8ExtMatch.Match(blockInfo);
					if (!match.Success)
						continue;

					switch (match.Groups[1].Value)
					{
					case "EXT-X-TWITCH-INFO": break; // Ignore twitch info line
					case "EXT-X-MEDIA":
						string streamInfo = reader.ReadLine();
						Match infoMatch;
						if (string.IsNullOrEmpty(streamInfo) ||
							 !(infoMatch = m3u8ExtMatch.Match(streamInfo)).Success ||
							 infoMatch.Groups[1].Value != "EXT-X-STREAM-INF")
						{
							resource = null;
							return RResultCode.TwitchMalformedM3u8File;
						}

						var streamData = new StreamData();
						// #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=128000,CODECS="mp4a.40.2",VIDEO="audio_only"
						for (int i = 0; i < infoMatch.Groups[3].Captures.Count; i++)
						{
							string key = infoMatch.Groups[4].Captures[i].Value.ToUpper();
							string value = infoMatch.Groups[5].Captures[i].Value;

							switch (key)
							{
							case "BANDWIDTH": streamData.Bandwidth = int.Parse(value); break;
							case "CODECS": streamData.Codec = TextUtil.StripQuotes(value); break;
							case "VIDEO":
								StreamQuality quality;
								if (Enum.TryParse(TextUtil.StripQuotes(value), out quality))
									streamData.QualityType = quality;
								else
									streamData.QualityType = StreamQuality.unknown;
								break;
							}
						}

						streamData.Url = reader.ReadLine();
						dataList.Add(streamData);
						break;
					default: break;
					}
				}
			}

			resource = new TwitchResource(channel, name ?? $"Twitch channel: {channel}", dataList);
			return dataList.Count > 0 ? RResultCode.Success : RResultCode.TwitchNoStreamsExtracted;
		}
		public RResultCode GetResourceById(string id, string name, out AudioResource resource)
		{
			string finalRequest = $"https://api.soundcloud.com/tracks/{id}/stream?client_id={SoundcloudClientID}";
			resource = new SoundcloudResource(id, name, finalRequest);
			return RResultCode.Success;
		}
 public R <PlayResource, LocalStr> GetResourceById(AudioResource resource) => GetResourceById(resource, true);
		public string RestoreLink(AudioResource res)
		{
			IResourceFactory factory = GetFactoryFor(res.AudioType);
			return factory.RestoreLink(res.ResourceId);
		}
Beispiel #40
0
 public string?RestoreLink(AudioResource res) => Resolver.RestoreLink(this, res);
		public RResultCode GetResourceById(string ytID, string name, out AudioResource result)
		{
			string resulthtml;
			if (!WebWrapper.DownloadString(out resulthtml, new Uri($"http://www.youtube.com/get_video_info?video_id={ytID}&el=info")))
			{
				result = null;
				return RResultCode.NoConnection;
			}

			var videoTypes = new List<VideoData>();
			NameValueCollection dataParse = HttpUtility.ParseQueryString(resulthtml);

			string videoDataUnsplit = dataParse["url_encoded_fmt_stream_map"];
			if (videoDataUnsplit != null)
			{
				string[] videoData = videoDataUnsplit.Split(',');

				foreach (string vdat in videoData)
				{
					NameValueCollection videoparse = HttpUtility.ParseQueryString(vdat);

					string vLink = videoparse["url"];
					if (vLink == null)
						continue;

					string vType = videoparse["type"];
					if (vType == null)
						continue;

					string vQuality = videoparse["quality"];
					if (vQuality == null)
						continue;

					var vt = new VideoData();
					vt.link = vLink;
					vt.codec = GetCodec(vType);
					vt.qualitydesciption = vQuality;
					videoTypes.Add(vt);
				}
			}

			videoDataUnsplit = dataParse["adaptive_fmts"];
			if (videoDataUnsplit != null)
			{
				string[] videoData = videoDataUnsplit.Split(',');

				foreach (string vdat in videoData)
				{
					NameValueCollection videoparse = HttpUtility.ParseQueryString(vdat);

					string vType = videoparse["type"];
					if (vType == null)
						continue;

					bool audioOnly = false;
					if (vType.StartsWith("video/"))
						continue;
					else if (vType.StartsWith("audio/"))
						audioOnly = true;

					string vLink = videoparse["url"];
					if (vLink == null)
						continue;

					var vt = new VideoData();
					vt.codec = GetCodec(vType);
					vt.qualitydesciption = vType;
					vt.link = vLink;
					if (audioOnly)
						vt.audioOnly = true;
					else
						vt.videoOnly = true;
					videoTypes.Add(vt);
				}
			}

			string finalName = name ?? dataParse["title"] ?? $"<YT - no title : {ytID}>";
			var ytResult = new YoutubeResource(ytID, finalName, videoTypes);
			result = ytResult;
			return ytResult.AvailableTypes.Count > 0 ? RResultCode.Success : RResultCode.YtNoVideosExtracted;
		}