using Newtonsoft.Json; using PluralRichPresence.Api; using System.Dynamic; using System.Text; namespace PluralRichPresence.SimplyPlural { public class Socket : ApiType { private AWebSocket? wSock; public const int KEEPALIVE_INTERVAL = 10 * 1000; public const string DEFAULT_WEBSOCKET_SERVER_URI = "wss://api.apparyllis.com/v1/socket"; public event EventHandler? FronterChanged; Timer? keepAliveTimer = null; private void onFronterChanged(dynamic fronterChangedEventData) { if(FronterChanged is not null) { FronterChanged(this, new EventArgs()); } } private void doUpdate(dynamic jsonData) { string target = jsonData.target; switch (target) { case "frontHistory": onFronterChanged(jsonData); break; } } private async Task reconnect() { while (true) { try { try { if (wSock is not null) wSock.Dispose(); wSock = null; } catch (Exception) { }; await connect(); await sendLogin(); this.keepAliveTimer = new Timer((TimerCallback) => { _ = sendKeepAlive(); }, null, KEEPALIVE_INTERVAL, 0); } catch (Exception) { Logger.Debug("failed to connect."); continue; } break; } } private async Task connect() { wSock = new AWebSocket(Config.GetEntry("SIMPLY_PLURAL_WEBSOCKET_URI", DEFAULT_WEBSOCKET_SERVER_URI)); await wSock.Connect(); wSock.TextReceived += wSockTextReceived; wSock.Disconnected += wSockDisconnected; } private void wSockTextReceived(object? sender, TextReceivedEventArgs e) { string message = e.Text; if (message == "pong") return; try { dynamic? jsonData = JsonConvert.DeserializeObject(message); if (jsonData is null) return; string? type = jsonData.msg; switch (type) { case "update": doUpdate(jsonData); break; case null: default: break; } } catch (Exception) { }; } private void wSockDisconnected(object? sender, EventArgs e) { _ = reconnect(); } private async Task sendKeepAlive() { if (wSock is not null) { await wSock.SendText("ping"); } if (keepAliveTimer is not null) keepAliveTimer.Change(KEEPALIVE_INTERVAL, 0); } private async Task sendLogin() { dynamic data = new ExpandoObject(); data.op = "authenticate"; data.token = token; string authenticateJson = JsonConvert.SerializeObject(data); if(wSock is not null) await wSock.SendText(authenticateJson); } public Socket(string token) : base(token) { _ = reconnect(); } } }