private void WebSocket_Received(object sender, IPacket e) { try { if (e is PacketMessageEventMessageChat chat) { var comment = Tools.Parse(chat.Comment); var commentData = Tools.CreateCommentData(comment, _startAt, _siteOptions); var messageContext = CreateMessageContext(comment, commentData, false); if (messageContext != null) { MessageReceived?.Invoke(this, messageContext); } } else if (e is PacketMessageEventMessageAudienceCount audienceCount) { var ac = audienceCount.AudienceCount; MetadataUpdated?.Invoke(this, new Metadata { CurrentViewers = ac.live_viewers.ToString(), TotalViewers = ac.viewers.ToString(), }); } else if (e is PacketMessageEventMessageLiveEnd liveEnd) { Disconnect(); } } catch (Exception ex) { _logger.LogException(ex); } }
//protected virtual Extract() private async Task ConnectInternalAsync(string input, IBrowserProfile browserProfile) { if (_ws != null) { throw new InvalidOperationException(""); } var cookies = GetCookies(browserProfile); _cc = CreateCookieContainer(cookies); _context = Tools.GetContext(cookies); string liveId; try { liveId = await GetLiveId(input); _liveId = liveId; } catch (InvalidInputException ex) { _logger.LogException(ex, "無効な入力値", $"input={input}"); SendSystemInfo("無効な入力値です", InfoType.Error); AfterDisconnected(); return; } var movieContext2 = await GetMovieInfo(liveId); var movieId = movieContext2.MovieId; if (movieId == 0) { SendSystemInfo("存在しないURLまたはIDです", InfoType.Error); AfterDisconnected(); return; } if (movieContext2.OnairStatus == 2) { SendSystemInfo("この放送は終了しています", InfoType.Error); AfterDisconnected(); return; } MetadataUpdated?.Invoke(this, new Metadata { Title = movieContext2.Title }); _startAt = movieContext2.StartedAt.DateTime; _500msTimer.Enabled = true; var(chats, raw) = await GetChats(movieContext2); try { foreach (var item in chats) { var comment = Tools.Parse(item); var commentData = Tools.CreateCommentData(comment, _startAt, _siteOptions); var messageContext = CreateMessageContext(comment, commentData, true); if (messageContext != null) { MessageReceived?.Invoke(this, messageContext); } } } catch (Exception ex) { _logger.LogException(ex, "", "raw=" + raw); } foreach (var user in _userStoreManager.GetAllUsers(SiteType.Openrec)) { if (!(user is IUser2 user2)) { continue; } _userDict.AddOrUpdate(user2.UserId, user2, (id, u) => u); } Reconnect: _ws = CreateOpenrecWebsocket(); _ws.Received += WebSocket_Received; var userAgent = GetUserAgent(browserProfile.Type); var wsTask = _ws.ReceiveAsync(movieId.ToString(), userAgent, cookies); var blackListProvider = CreateBlacklistProvider(); blackListProvider.Received += BlackListProvider_Received; var blackTask = blackListProvider.ReceiveAsync(movieId.ToString(), _context); var tasks = new List <Task> { wsTask, blackTask }; while (tasks.Count > 0) { var t = await Task.WhenAny(tasks); if (t == blackTask) { try { await blackTask; } catch (Exception ex) { _logger.LogException(ex); } tasks.Remove(blackTask); } else { blackListProvider.Disconnect(); try { await blackTask; } catch (Exception ex) { _logger.LogException(ex); } tasks.Remove(blackTask); SendSystemInfo("ブラックリストタスク終了", InfoType.Debug); try { await wsTask; } catch (Exception ex) { _logger.LogException(ex); } tasks.Remove(wsTask); SendSystemInfo("wsタスク終了", InfoType.Debug); } } _ws.Received -= WebSocket_Received; blackListProvider.Received -= BlackListProvider_Received; //意図的な切断では無い場合、配信がまだ続いているか確認して、配信中だったら再接続する。 //2019/03/12 heartbeatを送っているのにも関わらずwebsocketが切断されてしまう場合を確認。ブラウザでも配信中に切断されて再接続するのを確認済み。 if (!_isExpectedDisconnect) { var movieInfo = await GetMovieInfo(liveId); if (movieInfo.OnairStatus == 1) { goto Reconnect; } } }