internal async Task check(CasterHub hub) { if (httpErrorCode >= 400 && httpErrorCode < 500) { log.e($"httpErrorCode={httpErrorCode}"); return; } // 最低限3分は待つ var now = UnixTime.now; if (now < lastCheckTime + UnixTime.minute1 * 3) { return; } lastCheckTime = now; log.d("check start."); var csrfToken = ""; var liveId = ""; var hasLive = false; var castTotal = 0; while (!isDisposed) { try { ConcurrentDictionary <Int32, Int32> giftMap; String pageUrl; Int64 timePageOpen; if (!hasLive) { // 初回は部屋のHTMLを読む pageUrl = $"{Config.URL_TOP}{roomName}"; var request = new HttpRequestMessage(HttpMethod.Get, pageUrl); request.Headers.Add("Cookie", hub.cookie); request.Headers.Add("Accept", "text/html"); var response = await Config.httpClient.SendAsync(request, canceller.Token).ConfigureAwait(false); timePageOpen = UnixTime.now; var code = response.codeInt(); if (!response.IsSuccessStatusCode) { log.d($"HTTP {code} {response.ReasonPhrase} {pageUrl}"); httpErrorCode = code; httpError = $"HTTP {code} {response.ReasonPhrase}"; hub.showStatus(); if (code >= 400 && code < 500) { log.d($"don't retry for error {code}."); break; } await delayEx(UnixTime.second1 * 10L); continue; } httpErrorCode = 0; httpError = ""; var content = await response.Content.ReadAsStringAsync().ConfigureAwait(false); var json = reInitialData.matchOrNull(content)?.Groups[1].Value.decodeEntity(); if (json == null) { log.e("missing jsinitialData. (maybe not in live)."); break; } var jsinitialData = JToken.Parse(json); csrfToken = jsinitialData.Value <String>("csrfToken") ?? ""; liveId = jsinitialData.Value <String>("liveId") ?? ""; if (csrfToken == "" || liveId == "") { log.e("missing csrfToken or liveId in jsinitialData. (maybe not in live)."); break; } // json = reLiveData.matchOrNull(content)?.Groups[1].Value.decodeEntity(); if (json == null) { log.d("missing jsLiveData. (maybe not in live)."); break; } try { giftMap = JToken.Parse(json).Value <JArray>("gift_list").parseGiftCount(); } catch (Exception ex) { log.e(ex, "gift list is null. (parse error)"); break; } } else { // 2回目以降は current_user APIを読む pageUrl = $"{Config.URL_TOP}api/live/current_user?room_id={ roomId }&_={UnixTime.now / 1000L}"; var request = new HttpRequestMessage(HttpMethod.Get, pageUrl); request.Headers.Add("Accept", "application/json"); request.Headers.Add("Cookie", hub.cookie); var response = await Config.httpClient.SendAsync(request, canceller.Token).ConfigureAwait(false); timePageOpen = UnixTime.now; var code = response.codeInt(); if (!response.IsSuccessStatusCode) { log.d($"HTTP {code} {response.ReasonPhrase} {pageUrl}"); httpErrorCode = code; httpError = $"HTTP {code} {response.ReasonPhrase}"; hub.showStatus(); if (code >= 400 && code < 500) { log.d($"don't retry for error {code}."); break; } await delayEx(UnixTime.second1 * 10L); continue; } httpErrorCode = 0; httpError = ""; // レスポンスを受け取った時刻 timePageOpen = UnixTime.now; var content = await response.Content.ReadAsStringAsync().ConfigureAwait(false); MyResourceRequestHandler.responceLog(UnixTime.now, url, content); try { giftMap = JToken.Parse(content).Value <JObject>("gift_list").Value <JArray>("normal").parseGiftCount(); } catch (Exception ex) { log.e(ex, "gift list is null. (parse error)"); break; } } if (giftMap.Count == 0) { // 配信してなかった… log.d("gift list is empty. (not in live)"); break; } if (!hasLive) { var dontWait = Task.Run(() => count(hub, liveId, csrfToken, timePageOpen)); } hasLive = true; var giftIds = giftMap.Keys.ToArray(); Array.Sort(giftIds); isCasting = true; hub.showStatus(); hub.mainWindow.onGiftCount(UnixTime.now, giftMap, pageUrl); while (true) { var castCount = 0; foreach (var giftId in giftIds) { var freeNum = giftMap.getOrDefault(giftId, -1); if (giftId < 0 || freeNum <= 0) { continue; } if (!Config.starIds.Contains(giftId) && !Config.seedIds.Contains(giftId)) { continue; } var step = Math.Min(10, freeNum); log.d($"gifting giftId={giftId}, num={step}"); var parameters = new Dictionary <String, String>() { { "gift_id", giftId.ToString() }, { "live_id", liveId }, { "num", step.ToString() }, { "csrf_token", csrfToken } }; var url = $"{Config.URL_TOP}api/live/gifting_free"; var request = new HttpRequestMessage(HttpMethod.Post, url); request.Headers.Add("Cookie", hub.cookie); request.Headers.Add("Accept", "application/json"); request.Content = new FormUrlEncodedContent(parameters); // var response = await Config.httpClient.SendAsync(request, canceller.Token).ConfigureAwait(false); var code = response.codeInt(); if (!response.IsSuccessStatusCode) { log.d($"HTTP {code} {response.ReasonPhrase} {url}"); break; } castCount += step; freeNum -= step; giftMap[giftId] = freeNum; } if (castCount == 0) { break; } castTotal += castCount; log.d($"castCount={castCount}, total={castTotal}"); hub.mainWindow.onGiftCount(UnixTime.now, giftMap, pageUrl); await delayEx(UnixTime.second1 * 2L); } // ページを開いてから31秒は待つ // (自動取得と足並みを揃える) var remain = UnixTime.second1 * 31 + timePageOpen - UnixTime.now; if (remain > 0L) { log.d($"wait {remain}ms"); await delayEx(remain); } } catch (TaskCanceledException ex) { log.e(ex, "task was cancelled."); break; } catch (Exception ex) { log.e(ex, "check() failed."); await delayEx(UnixTime.second1 * 60L); } } isCasting = false; hub.showStatus(); if (hasLive) { log.d("check() end."); } }
async void count(CasterHub hub, String liveId, String csrfToken, Int64 lastPageOpen) { if (lastPageOpen - lastCountStart < UnixTime.hour1) { countStr = "カウント(前回から1時間経過してない)"; hub.showStatus(); log.d("dont count due to rapidly open pages."); return; } lastCountStart = lastPageOpen; countStr = "カウント開始"; hub.showStatus(); for (var count = 0; count <= 50; ++count) { for (var nTry = 4; nTry >= 1; --nTry) { try { if (isDisposed) { log.d("count cancelled."); return; } var parameters = new Dictionary <String, String>() { { "live_id", liveId }, { "comment", count.ToString() }, { "is_delay", "0" }, { "csrf_token", csrfToken } }; var url = $"{Config.URL_TOP}api/live/post_live_comment"; var request = new HttpRequestMessage(HttpMethod.Post, url); request.Headers.Add("Cookie", hub.cookie); request.Headers.Add("Accept", "application/json"); request.Content = new FormUrlEncodedContent(parameters); // var response = await Config.httpClient.SendAsync(request, canceller.Token).ConfigureAwait(false); var code = response.codeInt(); log.d($"count {count} HTTP {code} {response.ReasonPhrase}"); await delayEx(UnixTime.second1 * 2); if (response.IsSuccessStatusCode) { countStr = $"カウント{count} 成功"; hub.showStatus(); break; } if (nTry == 1) { log.d($"count {count} too many retry. stop counting…"); countStr = $"カウント{count} 中断 HTTP {response.ReasonPhrase}"; hub.showStatus(); return; } } catch (Exception ex) { countStr = $"カウント{count} {ex}"; hub.showStatus(); return; } } } }