atc24-client
Version:
A Javascript wrapper for the 24data API
133 lines (113 loc) • 4.16 kB
JavaScript
const axios = require('axios');
const WebSocket = require('ws');
const BASE_URL = 'https://24data.ptfs.app';
const WS_URL = 'wss://24data.ptfs.app/wss';
/**
* @typedef {'connected' | 'disconnected' | 'error' | 'ACFT_DATA' | 'CONTROLLERS' | 'FLIGHT_PLAN' | 'EVENT_FLIGHT_PLAN' | 'EVENT_ACFT_DATA'} Data24Event
*/
/**
* @callback Data24Listener
* @param {any} data
*/
class Data24 {
/**
* @param {Object} [options]
* @param {boolean} [options.cache=false] CACHING ; TODO: COMPLETE FUNCTIONALITY, FIX AA
* @param {number} [options.cacheDuration=5000] TODO: INTRODUCE WORKING CACHE HANDLING, PAST CACHEING
* @param {boolean} [options.autoReconnect=false] ARC FBDF
* @param {number} [options.reconnectInterval=5000] IF ARC TRUE, RI DEF 5000
*/
constructor({ cache = false, cacheDuration = 5000, autoReconnect = false, reconnectInterval = 5000 } = {}) {
this.ws = null;
this.listeners = {};
this.cacheEnabled = cache;
this.cacheDuration = cacheDuration;
this.autoReconnect = autoReconnect;
this.reconnectInterval = reconnectInterval;
this.cache = {
aircraft: { timestamp: 0, data: null },
eventAircraft: { timestamp: 0, data: null },
controllers: { timestamp: 0, data: null },
};
}
/**
* @returns {Promise<Object>} aircraft data, rest or cache it
*/
async getAircraftData() {
if (this._isCacheValid('aircraft')) return this.cache.aircraft.data;
const response = await axios.get(`${BASE_URL}/acft-data`);
this._updateCache('aircraft', response.data);
return response.data;
}
/**
* @returns {Promise<Object>} e ac data, rest or cache it
*/
async getEventAircraftData() {
if (this._isCacheValid('eventAircraft')) return this.cache.eventAircraft.data;
const response = await axios.get(`${BASE_URL}/acft-data/event`);
this._updateCache('eventAircraft', response.data);
return response.data;
}
/**
* @returns {Promise<Object>} controller data, rest or cache it
*/
async getControllers() {
if (this._isCacheValid('controllers')) return this.cache.controllers.data;
const response = await axios.get(`${BASE_URL}/controllers`);
this._updateCache('controllers', response.data);
return response.data;
}
connectWebSocket() {
if (this.ws) return;
this.ws = new WebSocket(WS_URL, { headers: { Origin: '' } });
this.ws.on('open', () => this._emit('connected'));
this.ws.on('message', (data) => {
const parsed = JSON.parse(data);
this._emit(parsed.t, parsed.d);
});
this.ws.on('close', () => {
this._emit('disconnected');
this.ws = null;
if (this.autoReconnect) setTimeout(() => this.connectWebSocket(), this.reconnectInterval);
});
this.ws.on('error', (err) => this._emit('error', err));
}
disconnectWebSocket() {
if (this.ws) {
this.ws.close();
this.ws = null;
}
}
destroy() {
this.disconnectWebSocket();
this.listeners = {};
this.cache = {
aircraft: { timestamp: 0, data: null },
eventAircraft: { timestamp: 0, data: null },
controllers: { timestamp: 0, data: null },
};
}
/**
* @param {Data24Event} event name of event.
* @param {Data24Listener} callback fbca
*/
on(event, callback) {
if (!this.listeners[event]) this.listeners[event] = [];
this.listeners[event].push(callback);
}
_emit(event, data) {
if (this.listeners[event]) {
for (const cb of this.listeners[event]) cb(data);
}
}
_isCacheValid(type) {
if (!this.cacheEnabled) return false;
return (Date.now() - this.cache[type].timestamp) < this.cacheDuration;
}
_updateCache(type, data) {
if (this.cacheEnabled) {
this.cache[type] = { timestamp: Date.now(), data };
}
}
}
module.exports = Data24;