Ejemplo n.º 1
0
 protected virtual async Task <string> GetMetadata(CookieContainer cc, string url, string data)
 {
     return(await _server.PostAsync(new HttpOptions
     {
         Url = url,
         Cc = cc,
         UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36",
     }, new StringContent(data, Encoding.UTF8, "application/x-www-form-urlencoded")));
 }
Ejemplo n.º 2
0
 protected virtual async Task <string> GetMetadata(CookieContainer cc, string url, string data)
 {
     return(await _server.PostAsync(new HttpOptions
     {
         Url = url,
         Cc = cc,
         UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:60.0) Gecko/20100101 Firefox/60.0",
     }, new StringContent(data, Encoding.UTF8, "application/x-www-form-urlencoded")));
 }
Ejemplo n.º 3
0
        public async Task <bool> PostCommentAsync(string text)
        {
            var ret = false;

            if (CanPostComment)
            {
                try
                {
                    var clientMessageId = PostCommentContext.ClientIdPrefix + _commentPostCount;
                    var s            = "{\"text_segments\":[{\"text\":\"" + text + "\"}]}";
                    var sej          = PostCommentContext.Sej.Replace("\r\n", "").Replace("\t", "").Replace(" ", "");
                    var sessionToken = PostCommentContext.SessionToken;
                    var data         = new Dictionary <string, string>
                    {
                        { "client_message_id", clientMessageId },
                        { "rich_message", s },
                        { "sej", sej },
                        { "session_token", sessionToken },
                    };
                    var url = "https://www.youtube.com/service_ajax?name=sendLiveChatMessageEndpoint";
                    var res = await _server.PostAsync(url, data, _cc);

                    Debug.WriteLine(res);
                    var json = DynamicJson.Parse(res);
                    //if (json.IsDefined("errors"))
                    //{
                    //    var k = string.Join("&", data.Select(kv => kv.Key + "=" + kv.Value));
                    //    throw new PostingCommentFailedException("コメント投稿に失敗しました(" + json.errors[0] + ")",$"data={k}, res={res}");
                    //}
                    if (json.IsDefined("code") && json.code == "SUCCESS")
                    {
                        if (json.IsDefined("data") && json.data.IsDefined("errorMessage"))
                        {
                            var k         = string.Join("&", data.Select(kv => kv.Key + "=" + kv.Value));
                            var errorText = json.data.errorMessage.liveChatTextActionsErrorMessageRenderer.errorText.simpleText;
                            throw new PostingCommentFailedException("コメント投稿に失敗しました(" + errorText + ")", $"data={k}, res={res}");
                        }
                        else if (json.IsDefined("data") && json.data.IsDefined("actions"))
                        {
                            //多分成功
                            _commentPostCount++;
                            ret = true;
                            goto CommentPostsucceeded;
                        }
                    }
                    var k0 = string.Join("&", data.Select(kv => kv.Key + "=" + kv.Value));
                    throw new UnknownResponseReceivedException($"data={k0}, res={res}");
                }
                catch (UnknownResponseReceivedException ex)
                {
                    _logger.LogException(ex);
                    SendInfo(ex.Message, InfoType.Error);
                }
                catch (PostingCommentFailedException ex)
                {
                    _logger.LogException(ex);
                    SendInfo(ex.Message, InfoType.Error);
                }
                //catch (HttpException ex)
                //{
                //    //{\"errors\":[\"検証中にエラーが発生しました。\"]} statuscodeは分からないけど200以外
                //    _logger.LogException(ex, "", $"text={text},statuscode={ex.StatusCode}");
                //    SendInfo("コメント投稿時にエラーが発生", InfoType.Error);
                //}
                catch (HttpRequestException ex)
                {
                    if (ex.InnerException is WebException webEx)
                    {
                        string response;
                        using (var sr = new System.IO.StreamReader(webEx.Response.GetResponseStream()))
                        {
                            response = sr.ReadToEnd();
                        }
                        var statuscode = (int)((HttpWebResponse)webEx.Response).StatusCode;
                        //{\"errors\":[\"検証中にエラーが発生しました。\"]} statuscodeは分からないけど200以外
                        _logger.LogException(ex, "", $"text={text},statuscode={statuscode}");
                        SendInfo("コメント投稿時にエラーが発生", InfoType.Error);
                    }
                    else
                    {
                        _logger.LogException(ex, "", $"text={text}");
                        SendInfo("コメント投稿時にエラーが発生", InfoType.Error);
                    }
                }
                catch (Exception ex)
                {
                    _logger.LogException(ex);
                    SendInfo("コメント投稿時にエラーが発生", InfoType.Error);
                }
            }
CommentPostsucceeded:
            return(ret);
        }
Ejemplo n.º 4
0
 protected virtual async Task <string> GetMetadata(CookieContainer cc, string url, string payload)
 {
     return(await _server.PostAsync(new HttpOptions { Url = url, Cc = cc }, new StringContent(payload, Encoding.UTF8, "application/json")));
 }
Ejemplo n.º 5
0
        public override async Task ReceiveAsync(string ytCfg, string vid, CookieContainer cc)
        {
            _cts = new CancellationTokenSource();

            string innerTubeKey;

            try
            {
                var ytCfgJson = DynamicJson.Parse(ytCfg);
                innerTubeKey = ytCfgJson.INNERTUBE_API_KEY;
            }catch (Exception ex)
            {
                throw new FatalException("", ex);
            }
            var url     = "https://www.youtube.com/youtubei/v1/updated_metadata?alt=json&key=" + innerTubeKey;
            var payload = "{\"context\":{\"client\":{\"hl\":\"ja\",\"gl\":\"JP\",\"clientName\":1,\"clientVersion\":\"1.20180224\",\"screenDensityFloat\":\"1.25\"}},\"videoId\":\"" + vid + "\"}";

            //var payloadBytes = Encoding.UTF8.GetBytes(payload);

            //var wc = new MyWebClient(cc);

            while (!_cts.IsCancellationRequested)
            {
                int timeoutMs = 0;
                //wc.Headers["origin"] = "https://www.youtube.com";
                //wc.Headers[HttpRequestHeader.ContentType] = "application/json";
                //wc.Headers[HttpRequestHeader.Accept] = "*/*";

                try
                {
                    //var bytes = await wc.UploadDataTaskAsync(url, payloadBytes);
                    //var res = Encoding.UTF8.GetString(bytes);
                    var res = await _server.PostAsync(new HttpOptions { Url = url, Cc = cc }, new StringContent(payload, Encoding.UTF8, "application/json"));

                    var json = DynamicJson.Parse(res);
                    if (json.continuation.IsDefined("invalidationContinuationData"))
                    {
                        throw new ParseException(res);
                    }
                    else
                    {
                        timeoutMs = (int)json.continuation.timedContinuationData.timeoutMs;
                    }
                    var metadata = ActionsToMetadata(json.actions);
                    metaReceived?.Invoke(this, metadata);
                }
                catch (TaskCanceledException)
                {
                    break;
                }
                catch (WebException ex) when(ex.Status == WebExceptionStatus.ProtocolError)
                {
                    var httpRes = (HttpWebResponse)ex.Response;
                    var code    = httpRes.StatusCode;

                    _logger.LogException(ex, "", $"url={url}");
                    SendInfo($"メタデータの取得でエラーが発生 ({code})", InfoType.Notice);
                }
                catch (WebException ex)
                {
                    SendInfo($"メタデータの取得でエラーが発生 ({ex.Status})", InfoType.Notice);
                    Debug.WriteLine(ex.Message);
                }
                catch (ParseException ex)
                {
                    _logger.LogException(ex);
                }
                catch (Exception ex)
                {
                    var parseEx = new ParseException("", ex);
                    _logger.LogException(parseEx);
                }
                timeoutMs = timeoutMs == 0 ? 1000 : timeoutMs;
                try
                {
                    await Task.Delay(timeoutMs, _cts.Token);
                }
                catch (TaskCanceledException)
                {
                    break;
                }
            }
            _cts = null;
        }
Ejemplo n.º 6
0
        public override async Task ReceiveAsync(string ytCfg, string vid, CookieContainer cc)
        {
            _cts = new CancellationTokenSource();
            string token;

            try
            {
                var ytCfgJson = DynamicJson.Parse(ytCfg);
                token = ytCfgJson.XSRF_TOKEN;
            }
            catch (Exception ex)
            {
                //TODO:metadataが一切取れない致命的なエラーだということを表したい
                throw new FatalException("", ex);
            }
            //このAPIを呼び出すとき、Cookieに"YSC"と"VISITOR_INFO1_LIVE"が必須。
            //2つとも配信ページか $"https://www.youtube.com/live_chat?v={vid}&is_popout=1"にアクセスした時にCookieをセットしなければもらえる。
            //コメビュではtokenとかを取得するために"/live_chat"に必ずアクセスする必要があるため、未ログイン時にはそれで取得した値を使えば良い。
            var url = "https://www.youtube.com/service_ajax?name=updatedMetadataEndpoint";
            //この値接続毎に固定っぽい。continuationも変わらない気がする。
            var sej  = "{\"clickTrackingParams\":\"CIQBEMyrARgAIhMIrdnBx6fm2wIVQ5VYCh14dQoMKPgd\",\"commandMetadata\":{\"webCommandMetadata\":{\"url\":\"/service_ajax\",\"sendPost\":true}},\"updatedMetadataEndpoint\":{\"videoId\":\"" + vid + "\"}}";
            var data = new Dictionary <string, string>
            {
                { "sej", sej },
                //{"csn", "E90sW4DVBdaP4ALlho8Q" },
                { "session_token", token },
            };
            var    encodedData         = string.Join("&", data.Select(kv => kv.Key + "=" + HttpUtility.UrlEncode(kv.Value))); //HttpUtility.UrlEncode()の戻り値は小文字だけど問題ない。
            string encodedContinuation = "";
            bool   isFatalError        = false;                                                                               //続行不能なエラーが出た場合にtrueにする。

            while (!_cts.IsCancellationRequested)
            {
                int timeoutMs = 0;
                try
                {
                    var res = await _server.PostAsync(new HttpOptions
                    {
                        Url       = url,
                        Cc        = cc,
                        UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:60.0) Gecko/20100101 Firefox/60.0",
                    }, new StringContent(encodedContinuation + encodedData, Encoding.UTF8, "application/x-www-form-urlencoded"));

                    var    d = DynamicJson.Parse(res);
                    string continuation;

                    if (!d.IsDefined("code") || d.code != "SUCCESS")
                    {
                        if (res == "{\"errors\":[\"Invalid Request\"]}")
                        {
                            isFatalError = true;
                        }
                        var v = string.Join("&", data.Select(kv => kv.Key + "=" + kv.Value));
                        //{"code":"ERROR","error":"不明なエラーです。"}
                        //{"code":"ERROR","error":"この機能は現在利用できません。しばらくしてからもう一度お試しください。"}
                        throw new ParseException($"res={res},ytCfg={ytCfg},encoded={v}");
                    }
                    if (d.data.continuation.IsDefined("invalidationContinuationData"))
                    {
                        throw new ParseException(res);
                    }
                    else
                    {
                        continuation = d.data.continuation.timedContinuationData.continuation;
                        //if (!data.ContainsKey("continuation"))
                        //{
                        //    data.Add("continuation", continuation);
                        //}
                        //else
                        //{
                        //    data["continuation"] = continuation;
                        //}
                        encodedContinuation = "continuation=" + HttpUtility.UrlEncode(continuation) + "&";
                        timeoutMs           = (int)d.data.continuation.timedContinuationData.timeoutMs;
                    }
                    try
                    {
                        var metadata = ActionsToMetadata(d.data.actions);
                        metaReceived?.Invoke(this, metadata);
                    }
                    catch (Exception ex)
                    {
                        throw new ParseException(res, ex);
                    }
                }
                catch (HttpRequestException ex)
                {
                    SendInfo($"メタデータの取得でエラーが発生 ({ex.Message})", InfoType.Notice);
                }
                catch (HttpException ex)
                {
                    SendInfo($"メタデータの取得でエラーが発生 ({ex.Message})", InfoType.Notice);
                    break;
                }
                catch (ParseException ex)
                {
                    _logger.LogException(ex);
                    if (isFatalError)
                    {
                        SendInfo("メタデータの取得がキャンセルされました(Invalid Request)", InfoType.Notice);
                        break;
                    }
                }
                catch (TaskCanceledException ex)
                {
                    SendInfo("メタデータの取得がキャンセルされました(" + ex.Message + ")", InfoType.Notice);
                    break;
                }
                catch (Exception ex)
                {
                    var parseEx = new ParseException("", ex);
                    _logger.LogException(parseEx);
                }
                timeoutMs = timeoutMs == 0 ? 1000 : timeoutMs;
                try
                {
                    await Task.Delay(timeoutMs, _cts.Token);
                }
                catch (TaskCanceledException)
                {
                    break;
                }
            }
            _cts = null;
            return;
        }