import { Injectable } from '@angular/core'; import { DatePipe } from '@angular/common'; import { HermesSocketService } from './hermes-socket.service'; import EventService from './shared/services/EventService'; import { Observable } from 'rxjs'; export interface Message { d: object, t: object, o: object } @Injectable({ providedIn: 'root' }) export class HermesClientService { pipe = new DatePipe('en-US'); session_id: string|undefined; connected: boolean; logged_in: boolean; private subscriptions: { [key: number]: ((data: any) => void)[] } constructor(private socket: HermesSocketService, private events: EventService) { this.subscriptions = {}; this.connected = false; this.logged_in = false; this.events.listen('tts_login', (payload) => { this.login(payload); }); } public connect() { if (this.connected) return; this.socket.connect(); this.connected = true; return this.listen(); } public disconnect() { if (!this.connected) return; this.connected = false; this.logged_in = false; this.session_id = undefined; this.socket.close(); this.events.emit('tts_logoff', null); } public first(predicate: (data: any) => boolean): Observable | null { return this.socket.first(predicate); } private send(op: number, data: any) { if (op != 0) console.log("TX:", data); this.socket.sendMessage({ d: data, op }); } public login(api_key: string) { if (!this.connected) this.connect(); if (this.logged_in) return; this.send(1, { api_key, web_login: true, major_version: 0, minor_version: 1 }); } public createPolicy(groupId: string, path: string, usage: number, timespan: number) { if (!this.logged_in) return; this.send(3, { request_id: null, type: "create_policy", data: { groupId, path, count: usage, span: timespan }, }); } public createTTSFilter(search: string, replace: string) { if (!this.logged_in) return; this.send(3, { request_id: null, type: "create_tts_filter", data: { search, replace }, }); } public deletePolicy(id: string) { if (!this.logged_in) return; this.send(3, { request_id: null, type: "delete_policy", data: { id }, }); } public deleteTTSFilter(id: string) { if (!this.logged_in) return; this.send(3, { request_id: null, type: "delete_tts_filter", data: { id }, nounce: this.session_id, }); } public fetchFilters() { if (!this.logged_in) return; this.send(3, { request_id: null, type: "get_tts_word_filters", data: null, }); } public fetchPermissionsAndGroups() { if (!this.logged_in) return; this.send(3, { request_id: null, type: "get_permissions", data: null, }); } public fetchPolicies() { if (!this.logged_in) return; this.send(3, { request_id: null, type: "get_policies", data: null, }); } public heartbeat() { const date = new Date() this.send(0, { date_time: this.pipe.transform(date.getTime() + date.getUTCDate(), "yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'SSS'Z'") }); } public subscribe(code: number, action: (data: any) => void) { if (!(code in this.subscriptions)) { this.subscriptions[code] = [] } this.subscriptions[code].push(action); } public updatePolicy(id: string, groupId: string, path: string, usage: number, timespan: number) { if (!this.logged_in) return; this.send(3, { request_id: null, type: "update_policy", data: { id, groupId, path, count: usage, span: timespan }, }); } public updateTTSFilter(id: string, search: string, replace: string) { if (!this.logged_in) return; this.send(3, { request_id: null, type: "update_tts_filter", data: { id, search, replace }, nounce: this.session_id, }); } private listen() { return this.socket.subscribe({ next: (message: any) => { console.log("RX:", message); switch (message.op) { case 0: // Heartbeat console.log("Heartbeat received. Potential connection problem?"); break; case 2: // Login Ack console.log("Login successful.", message.d.session_id); this.logged_in = true; this.session_id = message.d.session_id; this.events.emit('tts_login_ack', null); break; case 4: // Request Ack console.log("Request ack received."); break; } if (message.op in this.subscriptions) { console.log('found #' + message.op + ' subscription for ' + message.op); for (let action of this.subscriptions[message.op]) action(message.d); } }, error: (err: any) => { console.error('Websocket error', err); if (err.type == 'close') { this.connected = false; this.logged_in = false; this.socket.close(); this.events.emit('tts_logoff', null); } }, complete: () => console.log('Websocket disconnected.') }); } }