示例#1
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);
        }
示例#2
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;
		}