class EventEmitter { constructor() { this.events = {}; } on(event, listener) { if (!this.events[event]) { this.events[event] = []; } this.events[event].push(listener); } emit(event, ...args) { if (this.events[event]) { this.events[event].forEach(listener => listener(...args)); } } removeAllListeners() { this.events = {}; } } // Convert Node.js module system to ES6 module system export class NotConnectedError extends Error { constructor(client) { super("Client not connected"); this.client = client; } } export const Polarity = { Negative: 0, Positive: 1, }; export const Region = { Unknown: 0, Europe: 1, Oceania: 2, NorthAmerica: 3, Asia: 4, SouthAmerica: 5, }; export class Client extends EventEmitter { constructor(socketFactory) { super(); this.socketFactory = socketFactory; } getSocket() { return this.socket; } connect(url = this.generateRandomConnectionUrl()) { const socket = (this.socket = this.socketFactory.make(url)); socket.onmessage = (event) => { const rawData = this.decode(event.data); this.emit("data", this.buildStrikeData(JSON.parse(rawData))); }; socket.onopen = () => { this.sendJSON({ a: 111 }); this.emit("connect", socket); }; socket.onerror = (err) => this.emit("error", err); } close() { if (!this.socket) { throw new NotConnectedError(this); } this.socket.close(); this.removeAllListeners(); } processRawLocation(location) { return { latitude: location.lat, longitude: location.lon, altitude: location.alt, }; } buildStrikeData(strike) { return { location: this.processRawLocation(strike), deviation: strike.mds, delay: strike.delay, time: new Date(Math.floor(strike.time / 1e6)), detectors: strike.sig.map((rawDec) => ({ id: rawDec.sta, location: this.processRawLocation(rawDec), status: rawDec.status, delay: rawDec.time, })), polarity: strike.pol > 0 ? Polarity.Positive : Polarity.Negative, maxDeviation: strike.mds, maxCircularGap: strike.mcg, region: 1 <= strike.region && strike.region <= 5 ? strike.region : Region.Unknown, }; } decode(b) { let a, e = {}, d = b.split(""), c = d[0], f = c, g = [c], h = 256, o = h; for (let i = 1; i < d.length; i++) { let charCode = d[i].charCodeAt(0); a = h > charCode ? d[i] : e[charCode] ? e[charCode] : f + c; g.push(a); c = a.charAt(0); e[o] = f + c; o++; f = a; } return g.join(""); } sendJSON(data) { this.socket.send(JSON.stringify(data)); } generateRandomConnectionUrl() { const knownServerIds = [1, 7, 8]; return `wss://ws${knownServerIds[Math.floor(Math.random() * knownServerIds.length)]}.blitzortung.org:443/`; } } export class BrowserSocketFactory { make(url) { return new WebSocket(url); } }