add dmtf verb

This commit is contained in:
Dave Horton
2020-10-12 09:59:50 -04:00
parent 9d3c9accb9
commit 91f507bf3f
9 changed files with 141 additions and 52 deletions

View File

@@ -340,8 +340,8 @@ class CallSession extends Emitter {
// this whole thing requires us to be in a Dial verb // this whole thing requires us to be in a Dial verb
const task = this.currentTask; const task = this.currentTask;
if (!task || TaskName.Dial !== task.name) { if (!task || ![TaskName.Dial, TaskName.Listen].includes(task.name)) {
return this.logger.info('CallSession:_lccWhisper - invalid command since we are not in a dial'); return this.logger.info('CallSession:_lccWhisper - invalid command since we are not in a dial or listen');
} }
// allow user to provide a url object, a url string, an array of tasks, or a single task // allow user to provide a url object, a url string, an array of tasks, or a single task

41
lib/tasks/dtmf.js Normal file
View File

@@ -0,0 +1,41 @@
const Task = require('./task');
const {TaskName, TaskPreconditions} = require('../utils/constants');
class TaskDtmf extends Task {
constructor(logger, opts) {
super(logger, opts);
this.preconditions = TaskPreconditions.Endpoint;
this.dtmf = this.data.dtmf;
this.duration = this.data.duration || 500;
}
get name() { return TaskName.Dtmf; }
async exec(cs, ep) {
await super.exec(cs);
this.ep = ep;
try {
this.logger.info({data: this.data}, `sending dtmf ${this.dtmf}`);
await this.ep.execute('send_dtmf', `${this.dtmf}@${this.duration}`);
this.timer = setTimeout(this.notifyTaskDone.bind(this), this.dtmf.length * (this.duration + 250) + 750);
await this.awaitTaskDone();
this.logger.info({data: this.data}, `done sending dtmf ${this.dtmf}`);
} catch (err) {
this.logger.info(err, `TaskDtmf:exec - error playing ${this.dtmf}`);
}
this.emit('playDone');
}
async kill(cs) {
super.kill(cs);
if (this.ep.connected && !this.playComplete) {
this.logger.debug('TaskDtmf:kill - killing audio');
await this.ep.api('uuid_break', this.ep.uuid).catch((err) => this.logger.info(err, 'Error killing audio'));
}
clearTimeout(this.timer);
this.notifyTaskDone();
}
}
module.exports = TaskDtmf;

View File

@@ -159,6 +159,24 @@ class TaskListen extends Task {
this.notifyTaskDone(); this.notifyTaskDone();
} }
/**
* play or say something during the call
* @param {*} tasks - array of play/say tasks to execute
*/
async whisper(tasks, callSid) {
try {
const cs = this.callSession;
this.logger.debug('Listen:whisper tasks starting');
while (tasks.length && !cs.callGone) {
const task = tasks.shift();
await task.exec(cs, this.ep);
}
this.logger.debug('Listen:whisper tasks complete');
} catch (err) {
this.logger.error(err, 'Listen:whisper error');
}
}
} }
module.exports = TaskListen; module.exports = TaskListen;

View File

@@ -30,6 +30,9 @@ function makeTask(logger, obj, parent) {
case TaskName.Dequeue: case TaskName.Dequeue:
const TaskDequeue = require('./dequeue'); const TaskDequeue = require('./dequeue');
return new TaskDequeue(logger, data, parent); return new TaskDequeue(logger, data, parent);
case TaskName.Dtmf:
const TaskDtmf = require('./dtmf');
return new TaskDtmf(logger, data, parent);
case TaskName.Enqueue: case TaskName.Enqueue:
const TaskEnqueue = require('./enqueue'); const TaskEnqueue = require('./enqueue');
return new TaskEnqueue(logger, data, parent); return new TaskEnqueue(logger, data, parent);

View File

@@ -141,6 +141,15 @@
"lang" "lang"
] ]
}, },
"dtmf": {
"properties": {
"dtmf": "string",
"duration": "number"
},
"required": [
"dtmf"
]
},
"lex": { "lex": {
"properties": { "properties": {
"bot": "string", "bot": "string",

View File

@@ -4,6 +4,7 @@
"Dequeue": "dequeue", "Dequeue": "dequeue",
"Dial": "dial", "Dial": "dial",
"Dialogflow": "dialogflow", "Dialogflow": "dialogflow",
"Dtmf": "dtmf",
"Enqueue": "enqueue", "Enqueue": "enqueue",
"Gather": "gather", "Gather": "gather",
"Hangup": "hangup", "Hangup": "hangup",

View File

@@ -108,11 +108,12 @@ class SingleDialer extends Emitter {
this.ep = await ms.createEndpoint(); this.ep = await ms.createEndpoint();
this.logger.debug(`SingleDialer:exec - created endpoint ${this.ep.uuid}`); this.logger.debug(`SingleDialer:exec - created endpoint ${this.ep.uuid}`);
let promiseStreamConnected;
let lastSdp;
const connectStream = async(remoteSdp) => { const connectStream = async(remoteSdp) => {
// wait for previous re-invite to complete, if any if (remoteSdp === lastSdp) return;
if (promiseStreamConnected) await promiseStreamConnected.catch((err) => {}); lastSdp = remoteSdp;
return promiseStreamConnected = this.ep.modify(remoteSdp); return this.ep.modify(remoteSdp);
}; };
Object.assign(opts, { Object.assign(opts, {

96
package-lock.json generated
View File

@@ -515,9 +515,9 @@
} }
}, },
"ajv": { "ajv": {
"version": "6.12.5", "version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.5.tgz", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
"integrity": "sha512-lRF8RORchjpKG50/WFf8xmg7sgCLFiYNNnqdKflk63whMQcWR5ngGjiSXkL9bjxy6B2npOK2HSMN49jEBMSkag==", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"dev": true, "dev": true,
"requires": { "requires": {
"fast-deep-equal": "^3.1.1", "fast-deep-equal": "^3.1.1",
@@ -655,9 +655,9 @@
"integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g=="
}, },
"bent": { "bent": {
"version": "7.3.9", "version": "7.3.12",
"resolved": "https://registry.npmjs.org/bent/-/bent-7.3.9.tgz", "resolved": "https://registry.npmjs.org/bent/-/bent-7.3.12.tgz",
"integrity": "sha512-CyuIXgoO6UWJaoMtPHkq6JlzNRjCGQqZQeYuO4W5MxY+P0sO1jM3CMYLf16eoga2ozyhVPzXVUxkPw9rz5VNgA==", "integrity": "sha512-T3yrKnVGB63zRuoco/7Ybl7BwwGZR0lceoVG5XmQyMIH9s19SV5m+a8qam4if0zQuAmOQTyPTPmsQBdAorGK3w==",
"requires": { "requires": {
"bytesish": "^0.4.1", "bytesish": "^0.4.1",
"caseless": "~0.12.0", "caseless": "~0.12.0",
@@ -766,9 +766,9 @@
"integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg=="
}, },
"bytesish": { "bytesish": {
"version": "0.4.2", "version": "0.4.4",
"resolved": "https://registry.npmjs.org/bytesish/-/bytesish-0.4.2.tgz", "resolved": "https://registry.npmjs.org/bytesish/-/bytesish-0.4.4.tgz",
"integrity": "sha512-ym4cXhq28K7uhYZUEOl17LuqsqKSphDsZcfAKmEa/HcCsCqHMQXOiFuWx1OnbktJux/qKK1W9Xt9uU5kLIKypQ==" "integrity": "sha512-i4uu6M4zuMUiyfZN4RU2+i9+peJh//pXhd9x1oSe1LBkZ3LEbCoygu8W0bXTukU1Jme2txKuotpCZRaC3FLxcQ=="
}, },
"caching-transform": { "caching-transform": {
"version": "4.0.0", "version": "4.0.0",
@@ -984,11 +984,11 @@
} }
}, },
"debug": { "debug": {
"version": "4.1.1", "version": "4.2.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz",
"integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==",
"requires": { "requires": {
"ms": "^2.1.1" "ms": "2.1.2"
} }
}, },
"decamelize": { "decamelize": {
@@ -1151,9 +1151,9 @@
"integrity": "sha1-Bmlv43Wvt/68AI8oaCJWukEHWAE=" "integrity": "sha1-Bmlv43Wvt/68AI8oaCJWukEHWAE="
}, },
"drachtio-sip": { "drachtio-sip": {
"version": "0.4.0", "version": "0.4.1",
"resolved": "https://registry.npmjs.org/drachtio-sip/-/drachtio-sip-0.4.0.tgz", "resolved": "https://registry.npmjs.org/drachtio-sip/-/drachtio-sip-0.4.1.tgz",
"integrity": "sha512-/HHK0KH8sfQxUuVrYwaaRxdCq7j6sAQMxzegqzGQeOULx2TNeYb9Bf2SF5AO59DpmYkQRc+ezuHX58EpN/SR7A==", "integrity": "sha512-XjrsVb4O5bjgAr/hWogFk8TLoSp2bbOKYhFAFRayiMs/w7PkYep5z5IOW+erbR8LgVDjZVfdGxjA0RPkI4QMvA==",
"requires": { "requires": {
"debug": "^4.1.1", "debug": "^4.1.1",
"merge": ">=1.2.1", "merge": ">=1.2.1",
@@ -1163,16 +1163,16 @@
} }
}, },
"drachtio-srf": { "drachtio-srf": {
"version": "4.4.37", "version": "4.4.39",
"resolved": "https://registry.npmjs.org/drachtio-srf/-/drachtio-srf-4.4.37.tgz", "resolved": "https://registry.npmjs.org/drachtio-srf/-/drachtio-srf-4.4.39.tgz",
"integrity": "sha512-Z7MpHzee8z6gYVFgLRCqTC2Tt7d0v+EjDLhpZDLpEX0gMTs2Qey+VZ6QxO4CGyMrysZsLBZG5ZBNEifC2gBkHg==", "integrity": "sha512-wqiCe3nM8C9OJwllYVTMoYpVIjtWgX1TcyYy4y0b8jII9uhyB6CaK8aRfgzesZLJ6NTVlioS3a2Ic3e3Cmrkng==",
"requires": { "requires": {
"async": "^1.4.2", "async": "^1.4.2",
"debug": "^3.2.6", "debug": "^3.2.6",
"delegates": "^0.1.0", "delegates": "^0.1.0",
"deprecate": "^1.1.1", "deprecate": "^1.1.1",
"drachtio-mw-registration-parser": "0.0.2", "drachtio-mw-registration-parser": "0.0.2",
"drachtio-sip": "^0.4.0", "drachtio-sip": "^0.4.1",
"lodash": "^4.17.20", "lodash": "^4.17.20",
"node-noop": "0.0.1", "node-noop": "0.0.1",
"only": "0.0.2", "only": "0.0.2",
@@ -1319,9 +1319,9 @@
"dev": true "dev": true
}, },
"eslint": { "eslint": {
"version": "7.10.0", "version": "7.11.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-7.10.0.tgz", "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.11.0.tgz",
"integrity": "sha512-BDVffmqWl7JJXqCjAK6lWtcQThZB/aP1HXSH1JKwGwv0LQEdvpR7qzNrUT487RM39B5goWuboFad5ovMBmD8yA==", "integrity": "sha512-G9+qtYVCHaDi1ZuWzBsOWo2wSwd70TXnU6UHA3cTYHp7gCTXZcpggWFoUVAMRarg68qtPoNfFbzPh+VdOgmwmw==",
"dev": true, "dev": true,
"requires": { "requires": {
"@babel/code-frame": "^7.0.0", "@babel/code-frame": "^7.0.0",
@@ -1334,7 +1334,7 @@
"enquirer": "^2.3.5", "enquirer": "^2.3.5",
"eslint-scope": "^5.1.1", "eslint-scope": "^5.1.1",
"eslint-utils": "^2.1.0", "eslint-utils": "^2.1.0",
"eslint-visitor-keys": "^1.3.0", "eslint-visitor-keys": "^2.0.0",
"espree": "^7.3.0", "espree": "^7.3.0",
"esquery": "^1.2.0", "esquery": "^1.2.0",
"esutils": "^2.0.2", "esutils": "^2.0.2",
@@ -1400,12 +1400,20 @@
"dev": true, "dev": true,
"requires": { "requires": {
"eslint-visitor-keys": "^1.1.0" "eslint-visitor-keys": "^1.1.0"
},
"dependencies": {
"eslint-visitor-keys": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
"integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
"dev": true
}
} }
}, },
"eslint-visitor-keys": { "eslint-visitor-keys": {
"version": "1.3.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz",
"integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", "integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==",
"dev": true "dev": true
}, },
"espree": { "espree": {
@@ -1417,6 +1425,14 @@
"acorn": "^7.4.0", "acorn": "^7.4.0",
"acorn-jsx": "^5.2.0", "acorn-jsx": "^5.2.0",
"eslint-visitor-keys": "^1.3.0" "eslint-visitor-keys": "^1.3.0"
},
"dependencies": {
"eslint-visitor-keys": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
"integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
"dev": true
}
} }
}, },
"esprima": { "esprima": {
@@ -1587,9 +1603,9 @@
"dev": true "dev": true
}, },
"fast-redact": { "fast-redact": {
"version": "2.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-2.0.0.tgz", "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.0.0.tgz",
"integrity": "sha512-zxpkULI9W9MNTK2sJ3BpPQrTEXFNESd2X6O1tXMFpK/XM0G5c5Rll2EVYZH2TqI3xRGK/VaJ+eEOt7pnENJpeA==" "integrity": "sha512-a/S/Hp6aoIjx7EmugtzLqXmcNsyFszqbt6qQ99BdG61QjBZF6shNis0BYR6TsZOQ1twYc0FN2Xdhwwbv6+KD0w=="
}, },
"fast-safe-stringify": { "fast-safe-stringify": {
"version": "2.0.7", "version": "2.0.7",
@@ -2529,9 +2545,9 @@
} }
}, },
"moment": { "moment": {
"version": "2.27.0", "version": "2.29.1",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.27.0.tgz", "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz",
"integrity": "sha512-al0MUK7cpIcglMv3YF13qSgdAIqxHTO7brRtaz3DlSULbqfazqkc5kEjNrLDOM7fsjshoFIihnU8snrP7zUvhQ==" "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ=="
}, },
"ms": { "ms": {
"version": "2.1.2", "version": "2.1.2",
@@ -2861,11 +2877,11 @@
"integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
}, },
"pino": { "pino": {
"version": "6.5.1", "version": "6.7.0",
"resolved": "https://registry.npmjs.org/pino/-/pino-6.5.1.tgz", "resolved": "https://registry.npmjs.org/pino/-/pino-6.7.0.tgz",
"integrity": "sha512-76+RUhQkqjUD4AtQcSfEzh6vlsjXmoWZK5gg+2d70aCLXZTbo4/5js4I9rN1Xk6z1h2/7pnOFX10G4c2T4qNiA==", "integrity": "sha512-vPXJ4P9rWCwzlTJt+f0Ni4THc3DWyt8iDDCO4edQ8narTu6hnpzdXu8FqeSJCGndl1W6lfbYQUQihUO54y66Lw==",
"requires": { "requires": {
"fast-redact": "^2.0.0", "fast-redact": "^3.0.0",
"fast-safe-stringify": "^2.0.7", "fast-safe-stringify": "^2.0.7",
"flatstr": "^1.0.12", "flatstr": "^1.0.12",
"pino-std-serializers": "^2.4.2", "pino-std-serializers": "^2.4.2",
@@ -3289,9 +3305,9 @@
} }
}, },
"sonic-boom": { "sonic-boom": {
"version": "1.1.0", "version": "1.3.0",
"resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-1.1.0.tgz", "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-1.3.0.tgz",
"integrity": "sha512-JyOf+Xt7GBN4tAic/DD1Bitw6OMgSHAnswhPeOiLpfRoSjPNjEIi73UF3OxHzhSNn9WavxGuCZzprFCGFSNwog==", "integrity": "sha512-4nX6OYvOYr6R76xfQKi6cZpTO3YSWe/vd+QdIfoH0lBy0MnPkeAbb2rRWgmgADkXUeCKPwO1FZAKlAVWAadELw==",
"requires": { "requires": {
"atomic-sleep": "^1.0.0", "atomic-sleep": "^1.0.0",
"flatstr": "^1.0.12" "flatstr": "^1.0.12"

View File

@@ -29,25 +29,25 @@
"@jambonz/db-helpers": "^0.5.1", "@jambonz/db-helpers": "^0.5.1",
"@jambonz/realtimedb-helpers": "^0.2.17", "@jambonz/realtimedb-helpers": "^0.2.17",
"@jambonz/stats-collector": "^0.0.4", "@jambonz/stats-collector": "^0.0.4",
"bent": "^7.3.9", "bent": "^7.3.12",
"cidr-matcher": "^2.1.1", "cidr-matcher": "^2.1.1",
"debug": "^4.1.1", "debug": "^4.2.0",
"deepcopy": "^2.1.0", "deepcopy": "^2.1.0",
"drachtio-fsmrf": "^2.0.2", "drachtio-fsmrf": "^2.0.2",
"drachtio-srf": "^4.4.37", "drachtio-srf": "^4.4.39",
"express": "^4.17.1", "express": "^4.17.1",
"ip": "^1.1.5", "ip": "^1.1.5",
"jambonz-mw-registrar": "^0.1.3", "jambonz-mw-registrar": "^0.1.3",
"moment": "^2.27.0", "moment": "^2.29.1",
"parse-url": "^5.0.2", "parse-url": "^5.0.2",
"pino": "^6.5.1", "pino": "^6.7.0",
"verify-aws-sns-signature": "^0.0.6", "verify-aws-sns-signature": "^0.0.6",
"xml2js": "^0.4.23" "xml2js": "^0.4.23"
}, },
"devDependencies": { "devDependencies": {
"blue-tape": "^1.0.0", "blue-tape": "^1.0.0",
"clear-module": "^4.1.1", "clear-module": "^4.1.1",
"eslint": "^7.10.0", "eslint": "^7.11.0",
"eslint-plugin-promise": "^4.2.1", "eslint-plugin-promise": "^4.2.1",
"nyc": "^15.1.0", "nyc": "^15.1.0",
"tap-dot": "^2.0.0", "tap-dot": "^2.0.0",