mirror of
https://github.com/chuot/rdio-scanner.git
synced 2026-08-14 08:53:03 -06:00
210 lines
7.2 KiB
JavaScript
210 lines
7.2 KiB
JavaScript
/*
|
|
* *****************************************************************************
|
|
* Copyright (C) 2019-2021 Chrystian Huot <chrystian.huot@saubeo.solutions>
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
* ****************************************************************************
|
|
*/
|
|
|
|
'use strict';
|
|
|
|
import EventEmitter from 'events';
|
|
import FormData from 'form-data';
|
|
import { URL } from 'url';
|
|
|
|
import { Log } from './log.js';
|
|
|
|
export class Downstream {
|
|
constructor(ctx) {
|
|
this.config = ctx.config;
|
|
|
|
this.log = ctx.log;
|
|
|
|
this.config.downstreams.forEach((downstream) => {
|
|
if (typeof downstream.apiKey !== 'string' || !downstream.apiKey.length) {
|
|
this.log.write(Log.error, 'Config: no dirWatch.apiKey defined');
|
|
}
|
|
|
|
if (typeof downstream.disabled !== 'boolean') {
|
|
downstream.disabled = false;
|
|
}
|
|
|
|
if (downstream.systems === undefined) {
|
|
downstream.systems = '*';
|
|
}
|
|
|
|
if (typeof downstream.url !== 'string' || !downstream.url.length) {
|
|
this.log.write(Log.error, 'Config: no dirWatch.url defined');
|
|
}
|
|
});
|
|
|
|
if (ctx.controller instanceof EventEmitter) {
|
|
ctx.controller.on('call', (call) => this.exportCall(call));
|
|
}
|
|
}
|
|
|
|
exportCall(call) {
|
|
const parseSystem = (system) => {
|
|
const parseTalkgroup = (talkgroup) => {
|
|
if (Array.isArray(talkgroup)) {
|
|
return talkgroup.some((tg) => parseTalkgroup(tg));
|
|
|
|
} else if (talkgroup !== null && typeof talkgroup === 'object') {
|
|
return talkgroup.id === call.talkgroup;
|
|
|
|
} else if (typeof talkgroup === 'number') {
|
|
return talkgroup === call.talkgroup;
|
|
|
|
} else {
|
|
return talkgroup === undefined || talkgroup === '*';
|
|
}
|
|
};
|
|
|
|
if (Array.isArray(system)) {
|
|
return system.some((sys) => parseSystem(sys));
|
|
|
|
} else if (system !== null && typeof system === 'object' && system.id === call.system) {
|
|
return parseTalkgroup(system.talkgroups);
|
|
|
|
} else if (typeof system === 'number') {
|
|
return system === call.system;
|
|
|
|
} else if (typeof system === 'string') {
|
|
return system === '*';
|
|
|
|
} else {
|
|
return false;
|
|
}
|
|
};
|
|
|
|
this.config.downstreams.forEach((downstream) => {
|
|
if (typeof downstream.disabled === 'boolean' && downstream.disabled) {
|
|
return;
|
|
}
|
|
|
|
if (typeof downstream.apiKey !== 'string' || !downstream.apiKey.length) {
|
|
return;
|
|
}
|
|
|
|
if (typeof downstream.url !== 'string' || !downstream.url.length) {
|
|
return;
|
|
}
|
|
|
|
if (parseSystem(downstream.systems)) {
|
|
switch (downstream.type) {
|
|
default:
|
|
this.exportCallToRdioScanner(call, downstream);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
exportCallToRdioScanner(call, downstream) {
|
|
const apiUrl = new URL('/api/call-upload', downstream.url);
|
|
|
|
const form = new FormData();
|
|
|
|
form.append('key', downstream.apiKey);
|
|
form.append('audio', call.audio, {
|
|
contentType: call.audioType,
|
|
filename: call.audioName,
|
|
knownLength: call.audio.length,
|
|
});
|
|
form.append('dateTime', call.dateTime.toJSON());
|
|
form.append('frequencies', JSON.stringify(call.frequencies));
|
|
|
|
if (typeof call.frequency === 'number') {
|
|
form.append('frequency', call.frequency);
|
|
}
|
|
|
|
if (typeof call.source === 'number') {
|
|
form.append('source', call.source);
|
|
}
|
|
|
|
form.append('sources', JSON.stringify(call.sources));
|
|
form.append('system', this.getSystemId(call, downstream));
|
|
form.append('talkgroup', this.getTalkgroupId(call, downstream));
|
|
|
|
form.submit({
|
|
host: apiUrl.hostname,
|
|
path: apiUrl.pathname,
|
|
port: apiUrl.port,
|
|
protocol: apiUrl.protocol,
|
|
rejectUnauthorized: false,
|
|
}, (error, response) => {
|
|
const message = `system=${call.system} talkgroup=${call.talkgroup} file=${call.audioName} to=${downstream.url}`;
|
|
|
|
if (error) {
|
|
this.log.write(Log.error, `Downstream: ${message} ${error.message}`);
|
|
|
|
} else if (response.statusCode !== 200) {
|
|
this.log.write(Log.warn, `Downstream: ${message} ${response.statusMessage}`);
|
|
|
|
} else {
|
|
this.log.write(Log.info, `Downstream: ${message} Success`);
|
|
}
|
|
});
|
|
}
|
|
|
|
getSystemId(call, downstream) {
|
|
const parseSystem = (system) => {
|
|
if (Array.isArray(system)) {
|
|
system = system.find((sys) => sys !== null && typeof sys === 'object' && sys.id === call.system);
|
|
|
|
return system ? parseSystem(system) : call.system;
|
|
|
|
} else if (system !== null && typeof system === 'object') {
|
|
return typeof system.id_as === 'number' && system.id === call.system ? system.id_as : call.system;
|
|
|
|
} else {
|
|
return call.system;
|
|
}
|
|
};
|
|
|
|
return parseSystem(downstream.systems);
|
|
}
|
|
|
|
getTalkgroupId(call, downstream) {
|
|
const parseSystem = (system) => {
|
|
const parseTalkgroup = (talkgroup) => {
|
|
if (Array.isArray(talkgroup)) {
|
|
talkgroup = talkgroup.find((tg) => tg !== null && typeof tg === 'object' && tg.id === call.talkgroup);
|
|
|
|
return talkgroup ? parseTalkgroup(talkgroup) : call.talkgroup;
|
|
|
|
} else if (talkgroup !== null && typeof talkgroup === 'object') {
|
|
return typeof talkgroup.id_as === 'number' && talkgroup.id === call.talkgroup ? talkgroup.id_as : talkgroup.id;
|
|
|
|
} else {
|
|
return call.talkgroup;
|
|
}
|
|
};
|
|
|
|
if (Array.isArray(system)) {
|
|
system = system.find((sys) => sys !== null && typeof sys === 'object' && sys.id === call.system);
|
|
|
|
return system ? parseSystem(system) : call.talkgroup;
|
|
|
|
} else if (system !== null && typeof system === 'object') {
|
|
return system.id === call.system ? parseTalkgroup(system.talkgroups) : call.talkgroup;
|
|
|
|
} else {
|
|
return call.talkgroup;
|
|
}
|
|
};
|
|
|
|
return parseSystem(downstream.systems);
|
|
}
|
|
}
|