/// <summary> /// コメントを取得する(エントリー・ポイント) /// </summary> /// <returns></returns> public async Task <List <ComApi.CommentBody.Json.JsonComment> > GetComment(WatchPage::BaseJson data, NicoContext context, bool kako = false) { var logger = NicoLogger.GetLogger(); logger.Debug($"過去ログ: {kako}", moduleName); //threadkeyを取得 (crInfo.Threadkey, crInfo.Force184) = await GetThreadKey(data.video.dmcInfo.thread.thread_id.ToString(), context); //最古コメントを取得 logger.Log("現行コメントをダウンロード中..."); var comments = new CommentList(); comments.Add(await GetCommentData(data)); ComApi::CommentBody.Json.Chat firstComment = comments.GetFirstComment(); if (kako) { crInfo.WayBackKey = await GetWayBackKey(data.video.dmcInfo.thread.thread_id, context); //初期whenデータを作成 int _when = comments.GetFirstComment().date; int i = 1; do { var kacomments = new CommentList(); logger.Log($"過去ログをダウンロード中...({i}件目、no.{firstComment.no}まで取得完了)"); kacomments.Add(await GetCommentData(data, _when)); try { firstComment = kacomments.GetFirstComment(); } catch { break; } _when = firstComment.GetPrevDate(); comments.Merge(kacomments); ++i; if (comments.IsMax(i)) { break; } }while (firstComment.no > 1); } logger.Log("ダウンロードしたコメントの整合性をチェックしています。"); comments.FormatComments(); return(comments.Comments); }
/// <summary> /// 視聴ページのJSONをデシリアライズする /// </summary> /// <param name="html"></param> /// <returns></returns> private WatchPage::BaseJson LoadHTML(string html) { var logger = NicoLogger.GetLogger(); logger.Debug("htmlの解析を開始", moduleName); var htmlParser = new HtmlParser(); var document = htmlParser.ParseDocument(html); WatchPage::BaseJson data = JsonSerializer.Deserialize <WatchPage::BaseJson>(document.QuerySelector("#js-initial-watch-data").GetAttribute("data-api-data")); logger.Debug("htmlの解析が完了", moduleName); return(data); }
/// <summary> /// Leafを取得(過去ログ) /// </summary> private ComApi.RequestItems GetLeaf(WatchPage::CommentCompositeItems.Thread thread, WatchPage::BaseJson data, int _when) { var command = new ComApi.RequestItems(); command.thread_leaves = new ComApi.CommentItems.Leaf(); command.thread_leaves.thread = $"{thread.id}"; command.thread_leaves.user_id = $"{data.video.dmcInfo.user.user_id}"; int minute = (int)Math.Ceiling(data.video.duration / 60); command.thread_leaves.content = $"0-{minute}:100,1000,nicoru:100"; if (thread.isThreadkeyRequired) { command.thread_leaves.threadkey = crInfo.Threadkey; command.thread_leaves.force_184 = crInfo.Force184; } else { //command.thread_leaves.userkey = data.context.userkey; } command.thread_leaves.waybackkey = crInfo.WayBackKey; command.thread_leaves.whencom = _when; return(command); }
/// <summary> /// threadを取得(過去ログ) /// </summary> private ComApi.RequestItems GetThread(WatchPage::CommentCompositeItems.Thread thread, WatchPage::BaseJson data, int _when) { var command = new ComApi.RequestItems(); command.thread = new ComApi.CommentItems.Thread(); command.thread.thread = $"{thread.id}"; command.thread.fork = thread.fork; command.thread.user_id = $"{data.video.dmcInfo.user.user_id}"; //公式動画・ユーザー動画で分岐 if (thread.isThreadkeyRequired) { command.thread.threadkey = crInfo.Threadkey; command.thread.force_184 = crInfo.Force184; } else { //command.thread.userkey = data.context.userkey; } command.thread.waybackkey = crInfo.WayBackKey; command.thread.whencom = _when; return(command); }
/// <summary> /// リクエストデータを取得する /// </summary> private List <ComApi.RequestItems> GetCommentRequest(WatchPage::BaseJson data, int?_when) { var logger = NicoLogger.GetLogger(); logger.Debug("コメントリクエストデータの作成を開始", moduleName); var request = new List <ComApi.RequestItems>(); void insertStart(string type = "ps") { var s = new ComApi.RequestItems(); s.ping = new ComApi.CommentItems.Ping(); switch (type) { case "ps": s.ping.content = $"ps:{crInfo.ComCommandCount}"; break; case "rs": s.ping.content = $"rs:{crInfo.ComRequestCount}"; break; } request.Add(s); } void insertEnd(string type = "pf") { var e = new ComApi.RequestItems(); e.ping = new ComApi.CommentItems.Ping(); switch (type) { case "pf": e.ping.content = $"pf:{crInfo.ComCommandCount}"; ++crInfo.ComCommandCount; break; case "rf": e.ping.content = $"rf:{crInfo.ComRequestCount}"; ++crInfo.ComRequestCount; break; } request.Add(e); } //rs insertStart("rs"); foreach (var thread in data.commentComposite.threads) { if (!thread.isActive) { continue; } insertStart(); if (_when == null) { request.Add(GetThread(thread, data)); } else { request.Add(GetThread(thread, data, (int)_when)); } insertEnd(); if (thread.isLeafRequired) { insertStart(); if (_when == null) { request.Add(GetLeaf(thread, data)); } else { request.Add(GetLeaf(thread, data, (int)_when)); } insertEnd(); } } //rf insertEnd("rf"); logger.Debug("コメントリクエストデータの作成が完了", moduleName); return(request); }
/// <summary> /// コメントデータを取得する /// </summary> private async Task <List <ComApi.CommentBody.Json.JsonComment> > GetCommentData(WatchPage::BaseJson data, int?_when = null) { var logger = NicoLogger.GetLogger(); var serializer = new CommentSerializer(); var chandler = new CommentHandller(); List <ComApi.RequestItems> comRequest = GetCommentRequest(data, _when); //コメントを取得する logger.Debug("コメントの取得を開始", moduleName); HttpClient client = context.NicoClient.Client; var comBody = await client.PostAsync(new Uri(@"http://nmsg.nicovideo.jp/api.json/"), new StringContent(serializer.SerializeJson(comRequest))); //エラーハンドリング if (!comBody.IsSuccessStatusCode) { throw new Exception($"コメントの取得に失敗しました。 (status_code: {(int)comBody.StatusCode})"); } else { logger.Debug($"コメントデータの取得が完了", moduleName); } //取得したコメントをデシリアライズ string comJson = await comBody.Content.ReadAsStringAsync(); return(serializer.DeserializeJson <List <ComApi.CommentBody.Json.JsonComment> >(comJson)); }