diff --git a/src/commands/index.ts b/src/commands/index.ts index 603d187..c4c951d 100644 --- a/src/commands/index.ts +++ b/src/commands/index.ts @@ -33,6 +33,7 @@ export { default as pulldata } from './pulldata'; export { default as rank } from './rank'; export { default as roleinfo } from './roleinfo'; export { default as score } from './score'; +export { default as sip } from './sip'; export { default as site } from './site'; export { default as stats } from './stats'; export { default as storemessages } from './storemessages'; diff --git a/src/commands/sip.ts b/src/commands/sip.ts new file mode 100644 index 0000000..adb0c6f --- /dev/null +++ b/src/commands/sip.ts @@ -0,0 +1,81 @@ +/* eslint-disable consistent-return */ +import { Message } from 'eris'; +import type { Channel } from 'ari-client'; +import { Client, Command } from '../class'; +import { Misc } from '../pbx'; + +export default class SIP extends Command { + constructor(client: Client) { + super(client); + this.name = 'sip'; + this.description = 'Dials a SIP URI.'; + this.usage = `${this.client.config.prefix}sip `; + this.permissions = 1; + this.guildOnly = true; + this.enabled = true; + } + + public async run(message: Message, args: string[]) { + try { + const staff = await this.client.db.Staff.findOne({ userID: message.author.id }); + if (!staff || !staff?.extension) return this.error(message.channel, 'You must have an extension to complete this action.'); + this.success(message.channel, 'Queued call.'); + + const bridge = await this.client.pbx.ari.Bridge().create(); + let receiver: Channel = this.client.pbx.ari.Channel(); + const sender = await this.client.pbx.ari.channels.originate({ + endpoint: `PJSIP/${staff.extension}`, + extension: staff.extension, + callerId: 'LOC PBX AUTO OPERATOR ', + context: 'from-internal', + priority: 1, + app: 'cr-zero', + }); + + sender.once('StasisStart', async () => { + await Misc.play(this.client.pbx, sender, 'sound:pls-hold-while-try'); + await sender.ring(); + + try { + receiver = await receiver.originate({ + endpoint: `SIP/${args.join(' ')}`, + callerId: 'LOC PBX AUTO OPERATOR ', + context: 'from-internal', + priority: 1, + app: 'cr-zero', + }); + } catch { + await Misc.play(this.client.pbx, sender, 'sound:discon-or-out-of-service'); + await sender.hangup().catch(() => {}); + return false; + } + + // receiver.once('StasisStart', ) + }); + + receiver.once('StasisStart', async () => { + await sender.ringStop(); + await bridge.addChannel({ channel: [receiver.id, sender.id] }); + await bridge.play({ media: 'sound:beep' }); + }); + + receiver.once('ChannelDestroyed', async () => { + if (!sender.connected) return; + await Misc.play(this.client.pbx, sender, ['sound:the-number-u-dialed', 'sound:T-is-not-available', 'sound:please-try-again-later']); + await sender.hangup().catch(() => {}); + await bridge.destroy().catch(() => {}); + }); + + receiver.once('StasisEnd', async () => { + await sender.hangup().catch(() => {}); + await bridge.destroy().catch(() => {}); + }); + sender.once('StasisEnd', async () => { + await receiver.hangup().catch(() => {}); + await bridge.destroy().catch(() => {}); + }); + } catch (err) { + return this.client.util.handleError(err, message, this); + } + } +} diff --git a/src/pbx/actions/Misc.ts b/src/pbx/actions/Misc.ts index 83ead42..4193287 100644 --- a/src/pbx/actions/Misc.ts +++ b/src/pbx/actions/Misc.ts @@ -30,7 +30,7 @@ export default class Misc { return `sound:/tmp/${fileExtension}`; } - public static play(pbx: PBX, channel: ARI.Channel, sound: string): Promise { + public static play(pbx: PBX, channel: ARI.Channel, sound: string | string[]): Promise { const playback = pbx.ari.Playback(); return new Promise((resolve, reject) => {