private async Task Receive(ClientWebSocket webSocket, CancellationToken cancellationToken) { if (webSocket.State != WebSocketState.Open) { throw new InvalidOperationException($"Twitch socket {webSocket.State.ToString()}"); } var encoder = new UTF8Encoding(); var partial = string.Empty; while (webSocket.State == WebSocketState.Open && !cancellationToken.IsCancellationRequested && await twitchService.IsEnabled()) { var buffer = new byte[receiveChunkSize]; var result = await ReceiveAsync(webSocket, cancellationToken, buffer); if (result.MessageType == WebSocketMessageType.Close) { await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, cancellationToken); } else if (result.MessageType == WebSocketMessageType.Text) { var text = partial + encoder.GetString(buffer).Replace("\0", ""); partial = string.Empty; if (string.IsNullOrEmpty(text)) { continue; } var lines = (text.Substring(0, text.LastIndexOf('\r'))).Split('\r'); foreach (var line in lines) { logger.LogDebug($"Twitch Chat < {line}"); if (line.Contains("PING")) { var host = line.Substring(line.IndexOf(':')); await Send(webSocket, cancellationToken, $"PONG :{host}"); await dashboardService.UpdateStatus(ApiSource.Twitch, BackgroundServiceStatus.Connected, cancellationToken); continue; } await twitchService.ProcessMessage(line); } partial = text.Substring(text.LastIndexOf('\r')); } await Task.Delay(delay, cancellationToken); } }
private async Task Receive(ClientWebSocket webSocket, CancellationToken cancellationToken, TwitchService twitchService, TwitchManager twitchManager, AccessToken accessToken) { if (webSocket.State != WebSocketState.Open) { throw new InvalidOperationException($"[TwitchBackgroundService] Twitch socket {webSocket.State.ToString()}"); } var user = await twitchManager.GetUser(); var encoder = new UTF8Encoding(); var partial = string.Empty; while (webSocket.State == WebSocketState.Open && !cancellationToken.IsCancellationRequested && await twitchService.IsEnabled() && accessToken.Status == AccessTokenStatus.Ok) { var buffer = new byte[receiveChunkSize]; logger.LogDebug($"[TwitchBackgroundService] Listening to socket"); var result = await webSocket.ReceiveAsync(new ArraySegment <byte>(buffer), cancellationToken); logger.LogDebug($"[TwitchBackgroundService] Receive status {result.MessageType}"); if (result.MessageType == WebSocketMessageType.Close) { await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, cancellationToken); } else if (result.MessageType == WebSocketMessageType.Text) { var text = partial + encoder.GetString(buffer).Replace("\0", ""); partial = string.Empty; if (string.IsNullOrEmpty(text)) { continue; } var lines = (text.Substring(0, text.LastIndexOf('\r'))).Split('\r'); foreach (var line in lines) { //logger.LogDebug($"[TwitchBackgroundService] Twitch Chat < {line}"); if (line.Contains("PING")) { var host = line.Substring(line.IndexOf(':')); Send($"PONG :{host}"); await UpdateDashboardStatus(IntegrationStatus.Connected, cancellationToken); continue; } await twitchService.ProcessMessage(line); } partial = text.Substring(text.LastIndexOf('\r')); } await Task.Delay(delay, cancellationToken); } }
protected override async Task ExecuteAsync(CancellationToken cancellationToken) { cancellationToken.Register(() => { logger.LogDebug($"TwitchBackgroundService background task is stopping."); }); delay = defaultDelay; using (var scope = serviceScopeFactory.CreateScope()) { twitchService = scope.ServiceProvider.GetRequiredService <TwitchService>(); dashboardService = scope.ServiceProvider.GetRequiredService <DashboardService>(); while (!cancellationToken.IsCancellationRequested) { try { if (!await twitchService.IsEnabled()) { await dashboardService.UpdateStatus(ApiSource.Twitch, BackgroundServiceStatus.Disabled, cancellationToken); await Task.Delay(delay, cancellationToken); continue; } if (!twitchService.IsConfigured()) { await dashboardService.UpdateStatus(ApiSource.Twitch, BackgroundServiceStatus.NotConfigured, cancellationToken); await Task.Delay(delay, cancellationToken); continue; } var webSocket = new ClientWebSocket(); if (webSocket.State != WebSocketState.Open) { await webSocket.ConnectAsync(new Uri("wss://irc-ws.chat.twitch.tv:443"), cancellationToken); var timeout = 0; while (webSocket.State == WebSocketState.Connecting && timeout < connectionTimeout && !cancellationToken.IsCancellationRequested) { await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken); timeout++; } if (webSocket.State == WebSocketState.Open) { await TwitchHandshake(webSocket, cancellationToken); } } while (!cancellationToken.IsCancellationRequested && await twitchService.IsEnabled()) { await dashboardService.UpdateStatus(ApiSource.Twitch, BackgroundServiceStatus.Connected, cancellationToken); await Send(webSocket, cancellationToken, "JOIN :#machacoder"); await Receive(webSocket, cancellationToken); } } catch (Exception ex) { logger.LogError(ex.GetBaseException(), ex.GetBaseException().Message); await dashboardService.UpdateStatus(ApiSource.Twitch, "Error", cancellationToken); } await Task.Delay(delay, cancellationToken); } } }