import logger from "./logger.js"; import { getItem } from "./storage.js"; export const ConnectionEvent = { Open: 0, Closed: 1, Ready: 2, }; export default { ws: null, log: logger(["Connection"], ["log"]).log, messageLog: logger(["Connection", "Message"], ["log"]).log, url: getItem("server:gatewayBase"), isReady: false, reconnectTimeout: 0, handlers: new Map(), formatAuthString(password) { return `%auth%${btoa(password)}`; }, connect(password=getItem("auth:token")) { this.ws = new WebSocket(this.url); this.ws.onerror = (e) => this.log("Error", e); this.ws.onopen = () => { this.log("Open"); this.dispatch(ConnectionEvent.Open, 1); this.reconnectTimeout = 0; this.log("Sending authentication packet"); this.ws.send(`0${this.formatAuthString(password)}`); // send auth packet }; this.ws.onmessage = ({ data }) => { if (data === "1") { this.isReady = true; this.dispatch(ConnectionEvent.Ready, 1); this.log("Handshake complete"); } }; this.ws.onclose = ({ code }) => { this.dispatch(ConnectionEvent.Closed, code); if (code === 4001) {// code for bad auth this.log("Closed due to bad auth - skipping reconnect"); return; } this.isReady = false; this.reconnectTimeout += 400; if (this.reconnectTimeout >= 30000) this.reconnectTimeout = 30000; this.log(`Closed - will reconnect in ${this.reconnectTimeout}ms`); setTimeout(() => this.connect(password), this.reconnectTimeout); } }, sendMessage(code, params=[]) { let message = code; for (let i = 0; i < params.length; i++) { const param = params[i]; if (i == params.length - 1) message += param; else message += param + ";"; } this.ws.send(message); }, disconnect() { this.ws.close(); }, dispatch(event, data) { const eventHandlers = this.handlers.get(event); if (!eventHandlers) return; eventHandlers.forEach(e => e(data)); }, subscribe(event, handler) { if (!this.handlers.get(event)) { this.handlers.set(event, new Set()); } this.handlers.get(event).add(handler); return handler; // can later be used for unsubscribe() }, unsubscribe(event, handler) { const eventHandlers = this.handlers.get(event); if (!eventHandlers) return; eventHandlers.delete(handler); if (eventHandlers.size < 1) { this.handlers.delete(event); } }, };