public PubSubClient( Config.BotConfiguration botConfig, ICommunication communication, IRedemptionSystem redemptionHandler, ErrorHandler errorHandler) { this.botConfig = botConfig; this.communication = communication; this.errorHandler = errorHandler; this.redemptionHandler = redemptionHandler; pingMessage = new BasicPubSubMessage("PING"); pongMessage = new BasicPubSubMessage("PONG"); }
private async void ReadMessages() { WebSocketReceiveResult webSocketReceiveResult = null; string lastMessage = null; try { readers.AddCount(); while (true) { await CheckConnectionOrWait(); bool readCompleted = false; try { webSocketReceiveResult = await clientWebSocket.ReceiveAsync(incomingData, readerTokenSource.Token); readCompleted = true; } catch (TaskCanceledException) { /* swallow */ } catch (ThreadAbortException) { /* swallow */ } catch (ObjectDisposedException) { /* swallow */ } catch (OperationCanceledException) { /* swallow */ } catch (WebSocketException) { communication.SendWarningMessage($"PubSub Websocket closed unexpectedly."); } catch (Exception ex) { communication.SendErrorMessage($"PubSub Exception: {ex.GetType().Name}"); errorHandler.LogMessageException(ex, ""); } if (generalTokenSource.IsCancellationRequested) { //We are quitting break; } if ((readerTokenSource?.IsCancellationRequested ?? true) || !readCompleted) { //We are just restarting reader, since it was intercepted with an exception or the reader token source was cancelled continue; } if (webSocketReceiveResult.Count < 1) { await Task.Delay(100, generalTokenSource.Token); continue; } lastMessage = Encoding.UTF8.GetString(incomingData, 0, webSocketReceiveResult.Count); while (!webSocketReceiveResult.EndOfMessage) { readCompleted = false; try { webSocketReceiveResult = await clientWebSocket.ReceiveAsync(incomingData, readerTokenSource.Token); readCompleted = true; } catch (TaskCanceledException) { /* swallow */ } catch (ThreadAbortException) { /* swallow */ } catch (ObjectDisposedException) { /* swallow */ } catch (OperationCanceledException) { /* swallow */ } catch (WebSocketException) { communication.SendWarningMessage($"PubSub Websocket closed unexpectedly."); } catch (Exception ex) { communication.SendErrorMessage($"PubSub Exception: {ex.GetType().Name}"); errorHandler.LogMessageException(ex, ""); } if (generalTokenSource.IsCancellationRequested) { //We are quitting break; } if ((readerTokenSource?.IsCancellationRequested ?? true) || !readCompleted) { //We are just restarting reader, since it was intercepted with an exception or the reader token source was cancelled break; } if (webSocketReceiveResult.Count < 1) { communication.SendWarningMessage($"WebSocketMessage returned no characters despite not being at end. {lastMessage}"); break; } lastMessage += Encoding.UTF8.GetString(incomingData, 0, webSocketReceiveResult.Count); } if (generalTokenSource.IsCancellationRequested) { //We are quitting break; } if ((readerTokenSource?.IsCancellationRequested ?? true) || !readCompleted) { //We are just restarting reader, since it was intercepted with an exception or the reader token source was cancelled continue; } BasicPubSubMessage message = JsonSerializer.Deserialize <BasicPubSubMessage>(lastMessage); switch (message.TypeString) { case "PONG": pongReceived = true; break; case "PING": await SendMessage(pongMessage); break; case "RECONNECT": communication.SendDebugMessage($"PubSub Reconnect Message Received"); breakConnection = true; break; case "RESPONSE": { PubSubResponseMessage response = JsonSerializer.Deserialize <PubSubResponseMessage>(lastMessage); PubSubMessage sentMessage = sentMessages.Where(x => x.Nonce == response.Nonce).FirstOrDefault(); if (!string.IsNullOrEmpty(response.ErrorString)) { if (sentMessage is not null) { communication.SendErrorMessage($"Error with message {JsonSerializer.Serialize(sentMessage)}: {response.ErrorString}"); } else { communication.SendErrorMessage($"Error with message <Unable To Locate>: {response.ErrorString}"); } } if (sentMessage is not null) { sentMessages.Remove(sentMessage); } } break; case "MESSAGE": { ListenResponse listenResponse = JsonSerializer.Deserialize <ListenResponse>(lastMessage); BaseMessageData messageData = JsonSerializer.Deserialize <BaseMessageData>(listenResponse.Data.Message); switch (messageData.TypeString) { case "reward-redeemed": ChannelPointMessageData channelPointMessageData = JsonSerializer.Deserialize <ChannelPointMessageData>(listenResponse.Data.Message); redemptionHandler.HandleRedemption(channelPointMessageData.Data); break; default: communication.SendErrorMessage($"Unsupported PubSub Message: {messageData.TypeString} - {listenResponse.Data.Message}"); break; } } break; default: communication.SendErrorMessage($"Unsupported PubSub Message Type: {message.TypeString} - {lastMessage}"); break; } } } catch (TaskCanceledException) { /* swallow */ } catch (ThreadAbortException) { /* swallow */ } catch (ObjectDisposedException) { /* swallow */ } catch (OperationCanceledException) { /* swallow */ } catch (Exception ex) { communication.SendErrorMessage($"PubSub Exception: {ex.GetType().Name}"); if (lastMessage is not null) { communication.SendErrorMessage($"Last PubSub Message: {lastMessage}"); } errorHandler.LogMessageException(ex, ""); } finally { readers.Signal(); } }