fixes
parent
15bd296d67
commit
affb9fbde3
|
@ -1,4 +1,7 @@
|
||||||
/* eslint-disable no-continue */
|
/* eslint-disable no-continue */
|
||||||
|
import ARIClient from 'ari-client';
|
||||||
|
import AMIClient from 'asterisk-manager';
|
||||||
|
import GoogleTTS, { TextToSpeechClient } from '@google-cloud/text-to-speech';
|
||||||
import { Client, Collection, Handler } from '.';
|
import { Client, Collection, Handler } from '.';
|
||||||
|
|
||||||
export default class PBX {
|
export default class PBX {
|
||||||
|
@ -6,27 +9,43 @@ export default class PBX {
|
||||||
|
|
||||||
public handlers: Collection<Handler>;
|
public handlers: Collection<Handler>;
|
||||||
|
|
||||||
|
public ari: ARIClient.Client;
|
||||||
|
|
||||||
|
public ami: any;
|
||||||
|
|
||||||
|
public tts: TextToSpeechClient;
|
||||||
|
|
||||||
constructor(client: Client) {
|
constructor(client: Client) {
|
||||||
this.client = client;
|
this.client = client;
|
||||||
|
|
||||||
this.handlers = new Collection<Handler>();
|
this.handlers = new Collection<Handler>();
|
||||||
|
|
||||||
this.start();
|
this.load();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async load() {
|
||||||
|
this.ari = await ARIClient.connect('http://10.8.0.1:8088/ari', 'cr0', this.client.config.ariClientKey);
|
||||||
|
this.ari.start(['cr-zero', 'page-dtmf']);
|
||||||
|
|
||||||
|
this.ami = new AMIClient(5038, '10.8.0.1', 'cr', this.client.config.amiClientKey);
|
||||||
|
|
||||||
|
process.env.GOOGLE_APPLICATION_CREDENTIALS = `${__dirname}/../../google.json`;
|
||||||
|
this.tts = new GoogleTTS.TextToSpeechClient();
|
||||||
|
this.load();
|
||||||
}
|
}
|
||||||
|
|
||||||
public start() {
|
public start() {
|
||||||
this.client.util.ari.on('ChannelHangupRequest', (_, channel) => channel.hangup());
|
|
||||||
const handlers = Object.values<typeof Handler>(require(`${__dirname}/../pbx`));
|
const handlers = Object.values<typeof Handler>(require(`${__dirname}/../pbx`));
|
||||||
for (const HandlerFile of handlers) {
|
for (const HandlerFile of handlers) {
|
||||||
const handler = new HandlerFile(this);
|
const handler = new HandlerFile(this);
|
||||||
if (!handler.app) continue;
|
if (!handler.app) continue;
|
||||||
if (!handler.options?.available) {
|
if (!handler.options?.available) {
|
||||||
this.client.util.ari.on('StasisStart', async (event, channel) => {
|
this.ari.on('StasisStart', async (event, channel) => {
|
||||||
if (event.application !== handler.app) return;
|
if (event.application !== handler.app) return;
|
||||||
await handler.unavailable(event, channel);
|
await handler.unavailable(event, channel);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
this.client.util.ari.on('StasisStart', async (event, channel) => {
|
this.ari.on('StasisStart', async (event, channel) => {
|
||||||
if (event.application !== handler.app) return;
|
if (event.application !== handler.app) return;
|
||||||
try {
|
try {
|
||||||
await handler.run(event, channel);
|
await handler.run(event, channel);
|
||||||
|
|
|
@ -1,10 +1,7 @@
|
||||||
/* eslint-disable no-bitwise */
|
/* eslint-disable no-bitwise */
|
||||||
import nodemailer from 'nodemailer';
|
import nodemailer from 'nodemailer';
|
||||||
import GoogleTTS, { TextToSpeechClient } from '@google-cloud/text-to-speech';
|
|
||||||
import childProcess from 'child_process';
|
import childProcess from 'child_process';
|
||||||
import { promisify } from 'util';
|
import { promisify } from 'util';
|
||||||
import ARIClient from 'ari-client';
|
|
||||||
import AMIClient from 'asterisk-manager';
|
|
||||||
import signale from 'signale';
|
import signale from 'signale';
|
||||||
import { Member, Message, Guild, PrivateChannel, GroupChannel, Role, AnyGuildChannel, WebhookPayload } from 'eris';
|
import { Member, Message, Guild, PrivateChannel, GroupChannel, Role, AnyGuildChannel, WebhookPayload } from 'eris';
|
||||||
import { Client, Command, Moderation, PBX, RichEmbed } from '.';
|
import { Client, Command, Moderation, PBX, RichEmbed } from '.';
|
||||||
|
@ -21,12 +18,6 @@ export default class Util {
|
||||||
|
|
||||||
public pbx: PBX;
|
public pbx: PBX;
|
||||||
|
|
||||||
public ari: ARIClient.Client;
|
|
||||||
|
|
||||||
public ami: any;
|
|
||||||
|
|
||||||
public tts: TextToSpeechClient;
|
|
||||||
|
|
||||||
constructor(client: Client) {
|
constructor(client: Client) {
|
||||||
this.client = client;
|
this.client = client;
|
||||||
this.moderation = new Moderation(this.client);
|
this.moderation = new Moderation(this.client);
|
||||||
|
@ -41,19 +32,6 @@ export default class Util {
|
||||||
port: 587,
|
port: 587,
|
||||||
auth: { user: 'internal', pass: this.client.config.emailPass },
|
auth: { user: 'internal', pass: this.client.config.emailPass },
|
||||||
});
|
});
|
||||||
|
|
||||||
this.load();
|
|
||||||
}
|
|
||||||
|
|
||||||
private async load() {
|
|
||||||
this.ari = await ARIClient.connect('http://10.8.0.1:8088/ari', 'cr0', this.client.config.ariClientKey);
|
|
||||||
this.ari.start(['cr-zero', 'page-dtmf']);
|
|
||||||
|
|
||||||
this.ami = new AMIClient(5038, '10.8.0.1', 'cr', this.client.config.amiClientKey);
|
|
||||||
|
|
||||||
process.env.GOOGLE_APPLICATION_CREDENTIALS = `${__dirname}/../../google.json`;
|
|
||||||
this.tts = new GoogleTTS.TextToSpeechClient();
|
|
||||||
|
|
||||||
this.pbx = new PBX(this.client);
|
this.pbx = new PBX(this.client);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ export default class Intercom extends Command {
|
||||||
|
|
||||||
const recordingLocation = await MiscPBXActions.TTS(this.client.util.pbx, `Hello, this is the Library of Code Private Branch Exchange dialing you at the request of ${message.author.username} to deliver you a message. Playing message: ${args.slice(1).join(' ')}`, 'MALE');
|
const recordingLocation = await MiscPBXActions.TTS(this.client.util.pbx, `Hello, this is the Library of Code Private Branch Exchange dialing you at the request of ${message.author.username} to deliver you a message. Playing message: ${args.slice(1).join(' ')}`, 'MALE');
|
||||||
await loading.edit(`***${this.client.util.emojis.LOADING} Preparing to dial...***`);
|
await loading.edit(`***${this.client.util.emojis.LOADING} Preparing to dial...***`);
|
||||||
this.client.util.ami.action({
|
this.client.util.pbx.ami.action({
|
||||||
action: 'originate',
|
action: 'originate',
|
||||||
channel: `PJSIP/${args[0]}`,
|
channel: `PJSIP/${args[0]}`,
|
||||||
exten: args[0],
|
exten: args[0],
|
||||||
|
@ -34,7 +34,7 @@ export default class Intercom extends Command {
|
||||||
'PJSIP_HEADER(add,Alert-Info)': 'Ring Answer',
|
'PJSIP_HEADER(add,Alert-Info)': 'Ring Answer',
|
||||||
},
|
},
|
||||||
}, async (err: Error) => {
|
}, async (err: Error) => {
|
||||||
if (err) return loading.edit(`***${this.client.util.emojis.ERROR} Failed to dial extension. | ${err}`);
|
if (err) return loading.edit(`***${this.client.util.emojis.ERROR} Failed to dial extension.***`);
|
||||||
return loading.edit(`***${this.client.util.emojis.SUCCESS} Successfully queued intercom message to EXT \`${args[0]}\`.***`);
|
return loading.edit(`***${this.client.util.emojis.SUCCESS} Successfully queued intercom message to EXT \`${args[0]}\`.***`);
|
||||||
});
|
});
|
||||||
return undefined;
|
return undefined;
|
||||||
|
|
|
@ -193,7 +193,7 @@ export default class Page extends Command {
|
||||||
|
|
||||||
const fileExtension = `${randomBytes(10).toString('hex')}`;
|
const fileExtension = `${randomBytes(10).toString('hex')}`;
|
||||||
|
|
||||||
const [response] = await this.client.util.tts.synthesizeSpeech({
|
const [response] = await this.client.util.pbx.tts.synthesizeSpeech({
|
||||||
input: { text: `Hello, this call was automatically dialed by the Library of Code Private Branch Exchange. You have received a page from Pager Number, ${senderNumber}. The Pager Code is ${code}. Please check your Direct Messages on Discord for further information.` },
|
input: { text: `Hello, this call was automatically dialed by the Library of Code Private Branch Exchange. You have received a page from Pager Number, ${senderNumber}. The Pager Code is ${code}. Please check your Direct Messages on Discord for further information.` },
|
||||||
voice: { languageCode: 'en-US', ssmlGender: 'MALE' },
|
voice: { languageCode: 'en-US', ssmlGender: 'MALE' },
|
||||||
audioConfig: { audioEncoding: 'OGG_OPUS' },
|
audioConfig: { audioEncoding: 'OGG_OPUS' },
|
||||||
|
@ -202,7 +202,7 @@ export default class Page extends Command {
|
||||||
await this.client.util.exec(`ffmpeg -i /tmp/${fileExtension}.ogg -af "highpass=f=300, lowpass=f=3400" -ar 8000 -ac 1 -ab 64k -f mulaw /tmp/${fileExtension}.ulaw`);
|
await this.client.util.exec(`ffmpeg -i /tmp/${fileExtension}.ogg -af "highpass=f=300, lowpass=f=3400" -ar 8000 -ac 1 -ab 64k -f mulaw /tmp/${fileExtension}.ulaw`);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const chan = await this.client.util.ari.channels.originate({
|
const chan = await this.client.util.pbx.ari.channels.originate({
|
||||||
endpoint: `PJSIP/${member.extension}`,
|
endpoint: `PJSIP/${member.extension}`,
|
||||||
extension: `${member.extension}`,
|
extension: `${member.extension}`,
|
||||||
callerId: `LOC PBX - PAGE FRM ${senderNumber} <00>`,
|
callerId: `LOC PBX - PAGE FRM ${senderNumber} <00>`,
|
||||||
|
|
|
@ -14,7 +14,7 @@ export default class Misc {
|
||||||
public static async TTS(pbx: PBX, text: string, gender: string | any): Promise<string> {
|
public static async TTS(pbx: PBX, text: string, gender: string | any): Promise<string> {
|
||||||
const fileExtension = `${randomBytes(10).toString('hex')}`;
|
const fileExtension = `${randomBytes(10).toString('hex')}`;
|
||||||
|
|
||||||
const [response] = await pbx.client.util.tts.synthesizeSpeech({
|
const [response] = await pbx.tts.synthesizeSpeech({
|
||||||
input: { text },
|
input: { text },
|
||||||
voice: { languageCode: 'en-US', ssmlGender: gender },
|
voice: { languageCode: 'en-US', ssmlGender: gender },
|
||||||
audioConfig: { audioEncoding: 'OGG_OPUS' },
|
audioConfig: { audioEncoding: 'OGG_OPUS' },
|
||||||
|
@ -23,4 +23,16 @@ export default class Misc {
|
||||||
await pbx.client.util.exec(`ffmpeg -i /tmp/${fileExtension}.ogg -af "highpass=f=300, lowpass=f=3400" -ar 8000 -ac 1 -ab 64k -f mulaw /tmp/${fileExtension}.ulaw`);
|
await pbx.client.util.exec(`ffmpeg -i /tmp/${fileExtension}.ogg -af "highpass=f=300, lowpass=f=3400" -ar 8000 -ac 1 -ab 64k -f mulaw /tmp/${fileExtension}.ulaw`);
|
||||||
return `sound:/tmp/${fileExtension}`;
|
return `sound:/tmp/${fileExtension}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static play(pbx: PBX, channel: ARI.Channel, sound: string): Promise<ARI.Playback> {
|
||||||
|
const playback = pbx.ari.Playback();
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
playback.once('PlaybackFinished', (_, pl: ARI.Playback) => {
|
||||||
|
resolve(pl);
|
||||||
|
});
|
||||||
|
|
||||||
|
channel.play({ media: sound }, playback).catch((err) => reject(err));
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,9 +28,10 @@ export default class PageDTMF extends Handler {
|
||||||
media: 'sound:please-enter-the-pn',
|
media: 'sound:please-enter-the-pn',
|
||||||
}, undefined);
|
}, undefined);
|
||||||
channel.on('ChannelDtmfReceived', async (ev) => {
|
channel.on('ChannelDtmfReceived', async (ev) => {
|
||||||
|
if (!channel.connected) return;
|
||||||
if (status === 0) {
|
if (status === 0) {
|
||||||
if (ev.digit === '#') {
|
if (ev.digit === '#') {
|
||||||
pnPlayback.stop();
|
await pnPlayback.stop();
|
||||||
await channel.play({
|
await channel.play({
|
||||||
media: 'sound:please-enter-the-pc',
|
media: 'sound:please-enter-the-pc',
|
||||||
}, undefined);
|
}, undefined);
|
||||||
|
@ -39,7 +40,7 @@ export default class PageDTMF extends Handler {
|
||||||
}
|
}
|
||||||
pagerNumber.push(ev.digit);
|
pagerNumber.push(ev.digit);
|
||||||
} else if (status === 1) {
|
} else if (status === 1) {
|
||||||
const processingPlayback = this.client.util.ari.Playback();
|
const processingPlayback = this.pbx.ari.Playback();
|
||||||
if (ev.digit === '#') {
|
if (ev.digit === '#') {
|
||||||
await channel.play({
|
await channel.play({
|
||||||
media: 'sound:pls-hold-process-tx',
|
media: 'sound:pls-hold-process-tx',
|
||||||
|
@ -49,10 +50,8 @@ export default class PageDTMF extends Handler {
|
||||||
const page = await Page.page(pagerNumber.join(''), pager.num, pagerCode.join(''), message);
|
const page = await Page.page(pagerNumber.join(''), pager.num, pagerCode.join(''), message);
|
||||||
if (page.status === true) {
|
if (page.status === true) {
|
||||||
processingPlayback.stop();
|
processingPlayback.stop();
|
||||||
const playback = await channel.play({
|
await Misc.play(this.pbx, channel, 'sound:page-delivered');
|
||||||
media: 'sound:page-delivered',
|
channel.hangup();
|
||||||
}, undefined);
|
|
||||||
playback.on('PlaybackFinished', () => channel.hangup());
|
|
||||||
} else if (page.status === false) {
|
} else if (page.status === false) {
|
||||||
try {
|
try {
|
||||||
const ch = await this.client.getDMChannel(member.userID);
|
const ch = await this.client.getDMChannel(member.userID);
|
||||||
|
@ -63,10 +62,8 @@ export default class PageDTMF extends Handler {
|
||||||
this.client.util.handleError(new Error(page.message));
|
this.client.util.handleError(new Error(page.message));
|
||||||
}
|
}
|
||||||
processingPlayback.stop();
|
processingPlayback.stop();
|
||||||
const errorPlayback = await channel.play({
|
await Misc.play(this.pbx, channel, 'sound:request-error');
|
||||||
media: 'sound:request-error',
|
channel.hangup();
|
||||||
}, undefined);
|
|
||||||
errorPlayback.on('PlaybackFinished', () => channel.hangup());
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue