using Newtonsoft.Json.Linq; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Dynamic; using System.Linq; using System.Net.WebSockets; using System.Text; using System.Threading.Tasks; namespace PluralRichPresence.SimplyPlural { public class Socket : ApiType { public event EventHandler FronterChanged; ClientWebSocket wss = new ClientWebSocket(); Timer? keepAliveTimer = null; private void onFronterChanged(dynamic fronterChangedEventData) { if(FronterChanged is not null) { FronterChanged(this, new EventArgs()); } } private async Task receiveMessageText() { byte[] byteArray = await receiveMessageBytes(); return Encoding.UTF8.GetString(byteArray); } private async Task receiveMessageBytes() { List totalPayload = new List(); byte[] buffer = new byte[0x8000]; while (wss.State == WebSocketState.Open) { WebSocketReceiveResult result = await wss.ReceiveAsync(buffer, CancellationToken.None); for (int i = 0; i < result.Count; i++) totalPayload.Add(buffer[i]); if (result.EndOfMessage) return totalPayload.ToArray(); } return totalPayload.ToArray(); } private async Task doUpdate(dynamic jsonData) { string target = jsonData.target; switch (target) { case "frontHistory": onFronterChanged(jsonData); break; } } private async Task receiveTask() { while (wss.State == WebSocketState.Open) { string message = await receiveMessageText(); if (message == "pong") continue; Console.WriteLine("< " + message); try { dynamic? jsonData = JsonConvert.DeserializeObject(message); if (jsonData is null) continue; string type = jsonData.msg; if(type == "update") { await doUpdate(jsonData); } } catch (Exception) { }; } } private async Task connect() { await wss.ConnectAsync(new Uri("wss://api.apparyllis.com/v1/socket"), CancellationToken.None); _ = receiveTask(); keepAliveTimer = new Timer((TimerCallback) => { _ = sendKeepAlive(); }, null, 0, 10 * 1000); } private async Task sendText(string text) { if (wss.State != WebSocketState.Open) await connect(); Console.WriteLine("> " + text); await wss.SendAsync(Encoding.UTF8.GetBytes(text), WebSocketMessageType.Text, true, CancellationToken.None); } private async Task sendKeepAlive() { await sendText("ping"); } private async Task sendLogin() { dynamic data = new ExpandoObject(); data.op = "authenticate"; data.token = token; string authenticateJson = JsonConvert.SerializeObject(data); await sendText(authenticateJson); } public Socket(string token) : base(token) { _ = sendLogin(); } } }