mirror of
https://github.com/jambonz/jambonz-feature-server.git
synced 2025-12-19 04:17:44 +00:00
add tag task and varioius cleanup
This commit is contained in:
@@ -3,6 +3,7 @@ const uuidv4 = require('uuid/v4');
|
||||
const {CallStatus, CallDirection} = require('./utils/constants');
|
||||
const CallInfo = require('./session/call-info');
|
||||
const retrieveApp = require('./utils/retrieve-app');
|
||||
const parseUrl = require('parse-url');
|
||||
|
||||
module.exports = function(srf, logger) {
|
||||
const {lookupAppByPhoneNumber} = srf.locals.dbHelpers;
|
||||
@@ -44,8 +45,8 @@ module.exports = function(srf, logger) {
|
||||
const logger = req.locals.logger;
|
||||
try {
|
||||
const app = await lookupAppByPhoneNumber(req.locals.calledNumber);
|
||||
if (!app) {
|
||||
logger.info(`rejecting call to DID ${req.locals.calledNumber}: no application associated`);
|
||||
if (!app || !app.call_hook || !app.call_hook.url) {
|
||||
logger.info(`rejecting call to ${req.locals.calledNumber}: no application or webhook url`);
|
||||
return res.send(480, {
|
||||
headers: {
|
||||
'X-Reason': 'no configured application'
|
||||
@@ -53,22 +54,9 @@ module.exports = function(srf, logger) {
|
||||
});
|
||||
}
|
||||
|
||||
//TODO: temp hack pre-refactoring to latest db schema: bang the data into expected shape
|
||||
|
||||
req.locals.application = app;
|
||||
//end hack
|
||||
logger.debug(app, `retrieved application for ${req.locals.calledNumber}`);
|
||||
const from = req.getParsedHeader('From');
|
||||
req.locals.callInfo = new CallInfo({
|
||||
callSid: req.locals.callSid,
|
||||
accountSid: app.account_sid,
|
||||
applicationSid: app.application_sid,
|
||||
from: req.callingNumber,
|
||||
to: req.calledNumber,
|
||||
direction: CallDirection.Inbound,
|
||||
callerName: from.name || req.callingNumber,
|
||||
callId: req.get('Call-ID')
|
||||
});
|
||||
req.locals.callInfo = new CallInfo({req, app, direction: CallDirection.Inbound});
|
||||
next();
|
||||
} catch (err) {
|
||||
logger.error(err, `${req.get('Call-ID')} Error looking up application for ${req.calledNumber}`);
|
||||
@@ -82,20 +70,25 @@ module.exports = function(srf, logger) {
|
||||
async function invokeWebCallback(req, res, next) {
|
||||
const logger = req.locals.logger;
|
||||
const app = req.locals.application;
|
||||
const method = (app.hook_http_method || 'POST').toUpperCase();
|
||||
const qs = Object.assign({}, req.locals.callInfo, {
|
||||
sipStatus: 100,
|
||||
callStatus: CallStatus.Trying,
|
||||
originatingSipIP: req.get('X-Forwarded-For'),
|
||||
originatingSipTrunkName: req.get('X-Originating-Carrier')
|
||||
});
|
||||
const call_hook = app.call_hook;
|
||||
const method = (call_hook.method || 'POST').toUpperCase();
|
||||
let auth;
|
||||
if (app.hook_basic_auth_user && app.hook_basic_auth_password) {
|
||||
logger.debug(`using basic auth with ${app.hook_basic_auth_user}:${app.hook_basic_auth_password}`);
|
||||
auth = Object.assign({}, {user: app.hook_basic_auth_user, password: app.hook_basic_auth_password});
|
||||
if (call_hook.username && call_hook.password) {
|
||||
auth = {username: call_hook.username, password: call_hook.password};
|
||||
}
|
||||
try {
|
||||
app.tasks = await retrieveApp(logger, app.call_hook, method, auth, qs, method === 'POST' ? req.msg : null);
|
||||
const u = parseUrl(call_hook.url);
|
||||
const myPort = u.port ? `:${u.port}` : '';
|
||||
app.originalRequest = {
|
||||
baseUrl: `${u.protocol}://${u.resource}${myPort}`,
|
||||
auth
|
||||
};
|
||||
logger.debug({originalRequest: app.originalRequest}, 'invokeWebCallback');
|
||||
const obj = req.locals.callInfo;
|
||||
|
||||
// if the call hook is a POST add the entire SIP message to the payload
|
||||
if (method === 'POST') Object.assign(obj, {sip: req.msg});
|
||||
app.tasks = await retrieveApp(logger, app.call_hook, method, auth, obj);
|
||||
next();
|
||||
} catch (err) {
|
||||
logger.error(err, 'Error retrieving or parsing application');
|
||||
|
||||
@@ -1,22 +1,69 @@
|
||||
const {CallDirection, CallStatus} = require('../lib/constants');
|
||||
const uuidv4 = require('uuid/v4');
|
||||
|
||||
class CallInfo {
|
||||
constructor(opts) {
|
||||
this.callSid = opts.callSid;
|
||||
this.parentCallSid = opts.parentCallSid;
|
||||
this.direction = opts.direction;
|
||||
this.from = opts.from;
|
||||
this.to = opts.to;
|
||||
this.callId = opts.callId;
|
||||
this.sipStatus = opts.sipStatus;
|
||||
this.callStatus = opts.callStatus;
|
||||
this.callerId = opts.callerId;
|
||||
this.accountSid = opts.accountSid;
|
||||
this.applicationSid = opts.applicationSid;
|
||||
if (this.direction === CallDirection.Inbound) {
|
||||
const {app, req} = opts;
|
||||
this.callSid = req.locals.callSid,
|
||||
this.accountSid = app.account_sid,
|
||||
this.applicationSid = app.application_sid;
|
||||
this.from = req.callingNumber;
|
||||
this.to = req.calledNumber;
|
||||
this.callerName = this.from.name || req.callingNumber;
|
||||
this.callId = req.get('Call-ID');
|
||||
this.sipStatus = 100;
|
||||
this.callStatus = CallStatus.Trying;
|
||||
this.originatingSipIP = req.get('X-Forwarded-For');
|
||||
this.originatingSipTrunkName = req.get('X-Originating-Carrier');
|
||||
}
|
||||
else if (opts.parentCallInfo instanceof CallInfo) {
|
||||
const {req, parentCallInfo} = opts;
|
||||
this.callSid = uuidv4();
|
||||
this.parentCallSid = parentCallInfo.callSid;
|
||||
this.accountSid = parentCallInfo.accountSid;
|
||||
this.applicationSid = parentCallInfo.applicationSid;
|
||||
this.from = req.callingNumber;
|
||||
this.to = req.calledNumber;
|
||||
this.callerName = this.from.name || req.callingNumber;
|
||||
this.callId = req.get('Call-ID');
|
||||
this.callStatus = CallStatus.Trying,
|
||||
this.sipStatus = 100;
|
||||
}
|
||||
}
|
||||
|
||||
updateCallStatus(callStatus, sipStatus) {
|
||||
this.callStatus = callStatus;
|
||||
if (sipStatus) this.sipStatus = sipStatus;
|
||||
}
|
||||
|
||||
set customerData(obj) {
|
||||
this._customerData = obj;
|
||||
}
|
||||
|
||||
toJSON() {
|
||||
const obj = {
|
||||
callSid: this.callSid,
|
||||
direction: this.direction,
|
||||
from: this.from,
|
||||
to: this.to,
|
||||
callId: this.callId,
|
||||
sipStatus: this.sipStatus,
|
||||
callStatus: this.callStatus,
|
||||
callerId: this.callId,
|
||||
accountSid: this.accountSid,
|
||||
applicationSid: this.applicationSid
|
||||
};
|
||||
['parentCallSid', 'originatingSipIP', 'originatingSipTrunkName'].forEach((prop) => {
|
||||
if (this[prop]) obj[prop] = this[prop];
|
||||
});
|
||||
|
||||
if (this._customerData && Object.keys(this._customerData).length) {
|
||||
obj.customerData = this._customerData;
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = CallInfo;
|
||||
|
||||
@@ -1,24 +1,44 @@
|
||||
const Emitter = require('events');
|
||||
const config = require('config');
|
||||
const {CallDirection, TaskPreconditions, CallStatus} = require('../utils/constants');
|
||||
const hooks = require('../utils/notifiers');
|
||||
const moment = require('moment');
|
||||
const assert = require('assert');
|
||||
const BADPRECONDITIONS = 'preconditions not met';
|
||||
|
||||
class CallSession extends Emitter {
|
||||
constructor({logger, application, srf, tasks, callSid}) {
|
||||
constructor({logger, application, srf, tasks, callInfo}) {
|
||||
super();
|
||||
this.logger = logger;
|
||||
this.application = application;
|
||||
this.srf = srf;
|
||||
this.callSid = callSid;
|
||||
this.callInfo = callInfo;
|
||||
this.tasks = tasks;
|
||||
|
||||
const {notifyHook} = hooks(this.logger, this.callInfo);
|
||||
this.notifyHook = notifyHook;
|
||||
|
||||
this.taskIdx = 0;
|
||||
this.stackIdx = 0;
|
||||
this.callGone = false;
|
||||
}
|
||||
|
||||
get callSid() {
|
||||
return this.callInfo.callSid;
|
||||
}
|
||||
|
||||
get originalRequest() {
|
||||
return this.application.originalRequest;
|
||||
}
|
||||
|
||||
get direction() {
|
||||
return this.callInfo.direction;
|
||||
}
|
||||
|
||||
get callId() {
|
||||
return this.callInfo.direction;
|
||||
}
|
||||
|
||||
async exec() {
|
||||
this.logger.info(`CallSession:exec starting task list with ${this.tasks.length} tasks`);
|
||||
while (this.tasks.length && !this.callGone) {
|
||||
@@ -176,19 +196,13 @@ class CallSession extends Emitter {
|
||||
}
|
||||
return {ms: this.ms, ep: this.ep};
|
||||
}
|
||||
_notifyCallStatusChange(callStatus) {
|
||||
this.logger.debug({app: this.application}, `CallSession:_notifyCallStatusChange: ${JSON.stringify(callStatus)}`);
|
||||
_notifyCallStatusChange({callStatus, sipStatus}) {
|
||||
this.logger.debug(`CallSession:_notifyCallStatusChange: ${callStatus} ${sipStatus}`);
|
||||
this.callInfo.updateStatus(callStatus, sipStatus);
|
||||
try {
|
||||
const auth = {};
|
||||
if (this.application.hook_basic_auth_user && this.application.hook_basic_auth_password) {
|
||||
Object.assign(auth, {user: this.application.hook_basic_auth_user, password: this.hook_basic_auth_password});
|
||||
}
|
||||
this.notifyHook(this.application.call_status_hook,
|
||||
this.application.hook_http_method,
|
||||
auth,
|
||||
callStatus);
|
||||
this.notifyHook(this.application.call_status_hook);
|
||||
} catch (err) {
|
||||
this.logger.info(err, `CallSession:_notifyCallStatusChange error sending ${JSON.stringify(callStatus)}`);
|
||||
this.logger.info(err, `CallSession:_notifyCallStatusChange error sending ${callStatus} ${sipStatus}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
const CallSession = require('./call-session');
|
||||
const {CallDirection, CallStatus} = require('../utils/constants');
|
||||
const hooks = require('../utils/notifiers');
|
||||
const {CallStatus} = require('../utils/constants');
|
||||
const moment = require('moment');
|
||||
const assert = require('assert');
|
||||
|
||||
@@ -10,17 +9,11 @@ class InboundCallSession extends CallSession {
|
||||
logger: req.locals.logger,
|
||||
srf: req.srf,
|
||||
application: req.locals.application,
|
||||
callSid: req.locals.callInfo.callSid,
|
||||
callInfo: req.locals.callInfo,
|
||||
tasks: req.locals.application.tasks
|
||||
});
|
||||
this.req = req;
|
||||
this.res = res;
|
||||
this.srf = req.srf;
|
||||
this.logger = req.locals.logger;
|
||||
this.callInfo = req.locals.callInfo;
|
||||
this.direction = CallDirection.Inbound;
|
||||
const {notifyHook} = hooks(this.logger, this.callInfo);
|
||||
this.notifyHook = notifyHook;
|
||||
|
||||
req.on('cancel', this._callReleased.bind(this));
|
||||
|
||||
|
||||
@@ -145,7 +145,7 @@ class TaskDial extends Task {
|
||||
this.target.forEach((t) => {
|
||||
try {
|
||||
t.url = t.url || this.confirmUrl;
|
||||
t.method = t.method || this.confirmMethod;
|
||||
t.method = t.method || this.confirmMethod || 'POST';
|
||||
const sd = placeCall({
|
||||
logger: this.logger,
|
||||
application: cs.application,
|
||||
|
||||
@@ -62,7 +62,7 @@ class TaskGather extends Task {
|
||||
this._startTranscribing(ep);
|
||||
}
|
||||
|
||||
if (this.input.includes('dtmf')) {
|
||||
if (this.input.includes('digits')) {
|
||||
ep.on('dtmf', this._onDtmf.bind(this, ep));
|
||||
}
|
||||
|
||||
@@ -129,8 +129,14 @@ class TaskGather extends Task {
|
||||
}
|
||||
|
||||
_killAudio() {
|
||||
if (this.sayTask && !this.sayTask.killed) this.sayTask.kill();
|
||||
if (this.playTask && !this.playTask.killed) this.playTask.kill();
|
||||
if (this.sayTask && !this.sayTask.killed) {
|
||||
this.sayTask.removeAllListeners('playDone');
|
||||
this.sayTask.kill();
|
||||
}
|
||||
if (this.playTask && !this.playTask.killed) {
|
||||
this.playTask.removeAllListeners('playDone');
|
||||
this.playTask.kill();
|
||||
}
|
||||
}
|
||||
|
||||
_onTranscription(ep, evt) {
|
||||
|
||||
@@ -42,6 +42,9 @@ function makeTask(logger, obj) {
|
||||
case TaskName.Redirect:
|
||||
const TaskRedirect = require('./redirect');
|
||||
return new TaskRedirect(logger, data);
|
||||
case TaskName.Tag:
|
||||
const TaskTag = require('./tag');
|
||||
return new TaskTag(logger, data);
|
||||
}
|
||||
|
||||
// should never reach
|
||||
|
||||
@@ -10,6 +10,7 @@ class TaskRedirect extends Task {
|
||||
|
||||
this.action = this.data.action;
|
||||
this.method = this.data.method || 'POST';
|
||||
this.auth = this.data.auth;
|
||||
}
|
||||
|
||||
get name() { return TaskName.Redirect; }
|
||||
|
||||
@@ -115,6 +115,14 @@
|
||||
"action"
|
||||
]
|
||||
},
|
||||
"tag": {
|
||||
"properties": {
|
||||
"data": "object"
|
||||
},
|
||||
"required": [
|
||||
"data"
|
||||
]
|
||||
},
|
||||
"transcribe": {
|
||||
"properties": {
|
||||
"transcriptionCallback": "string",
|
||||
|
||||
19
lib/tasks/tag.js
Normal file
19
lib/tasks/tag.js
Normal file
@@ -0,0 +1,19 @@
|
||||
const Task = require('./task');
|
||||
const {TaskName} = require('../utils/constants');
|
||||
|
||||
class TaskTag extends Task {
|
||||
constructor(logger, opts) {
|
||||
super(logger, opts);
|
||||
this.data = this.data.data;
|
||||
}
|
||||
|
||||
get name() { return TaskName.Tag; }
|
||||
|
||||
async exec(cs) {
|
||||
super.exec(cs);
|
||||
cs.callInfo.customerData = this.data;
|
||||
this.logger.debug({customerData: cs.callInfo.customerData}, 'TaskTag:exec set customer data');
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = TaskTag;
|
||||
@@ -58,7 +58,14 @@ class Task extends Emitter {
|
||||
|
||||
async performAction(method, auth, results) {
|
||||
if (this.action) {
|
||||
const tasks = await this.actionHook(this.action, method, auth, results);
|
||||
let action = this.action;
|
||||
if (action.startsWith('/')) {
|
||||
const or = this.callSession.originalRequest;
|
||||
action = `${or.baseUrl}${this.action}`;
|
||||
this.logger.debug({originalUrl: this.action, normalizedUrl: action}, 'Task:performAction normalized url');
|
||||
if (!auth && or.auth) auth = or.auth;
|
||||
}
|
||||
const tasks = await this.actionHook(action, method, auth, results);
|
||||
if (tasks && Array.isArray(tasks)) {
|
||||
this.logger.debug({tasks: tasks}, `${this.name} replacing application with ${tasks.length} tasks`);
|
||||
this.callSession.replaceApplication(tasks);
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
"SipNotify": "sip:notify",
|
||||
"SipRedirect": "sip:redirect",
|
||||
"Say": "say",
|
||||
"Tag": "tag",
|
||||
"Transcribe": "transcribe"
|
||||
},
|
||||
"CallStatus": {
|
||||
|
||||
@@ -1,23 +1,36 @@
|
||||
const request = require('request');
|
||||
require('request-debug')(request);
|
||||
const retrieveApp = require('./retrieve-app');
|
||||
|
||||
function hooks(logger, callAttributes) {
|
||||
function actionHook(url, method, auth, opts, expectResponse = true) {
|
||||
const params = Object.assign({}, callAttributes, opts);
|
||||
let basicauth, qs, body;
|
||||
if (auth && typeof auth === 'object' && Object.keys(auth) === 2) basicauth = auth;
|
||||
if ('GET' === method.toUpperCase()) qs = params;
|
||||
else body = params;
|
||||
const obj = {url, method, auth: basicauth, json: expectResponse || !!body, qs, body};
|
||||
logger.debug({opts: obj}, 'actionHook');
|
||||
function hooks(logger, callInfo) {
|
||||
function actionHook(hook, obj, expectResponse = true) {
|
||||
const method = hook.method.toUpperCase();
|
||||
const auth = (hook.username && hook.password) ?
|
||||
{username: hook.username, password: hook.password} :
|
||||
null;
|
||||
|
||||
const data = Object.assign({}, obj, callInfo);
|
||||
if ('GET' === method) {
|
||||
// remove customer data - only for POSTs since it might be quite complex
|
||||
delete data.customerData;
|
||||
}
|
||||
const opts = {
|
||||
url: hook.url,
|
||||
method,
|
||||
json: 'POST' === method || expectResponse
|
||||
};
|
||||
if (auth) obj.auth = auth;
|
||||
if ('POST' === method) obj.body = data;
|
||||
else obj.qs = data;
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
request(obj, (err, response, body) => {
|
||||
request(opts, (err, response, body) => {
|
||||
if (err) {
|
||||
logger.info(`actionHook error ${method} ${url}: ${err.message}`);
|
||||
logger.info(`actionHook error ${method} ${hook.url}: ${err.message}`);
|
||||
return reject(err);
|
||||
}
|
||||
if (body && expectResponse) {
|
||||
logger.debug(body, `actionHook response ${method} ${url}`);
|
||||
logger.debug(body, `actionHook response ${method} ${hook.url}`);
|
||||
return resolve(retrieveApp(logger, body));
|
||||
}
|
||||
resolve(body);
|
||||
@@ -25,7 +38,7 @@ function hooks(logger, callAttributes) {
|
||||
});
|
||||
}
|
||||
|
||||
function notifyHook(url, method, auth, opts) {
|
||||
function notifyHook(url, method, auth, opts = {}) {
|
||||
return actionHook(url, method, auth, opts, false);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
const Emitter = require('events');
|
||||
const {CallStatus} = require('./constants');
|
||||
const uuidv4 = require('uuid/v4');
|
||||
const SipError = require('drachtio-srf').SipError;
|
||||
const {TaskPreconditions} = require('../utils/constants');
|
||||
const {TaskPreconditions, CallDirection} = require('../utils/constants');
|
||||
const CallInfo = require('../session/call-info');
|
||||
const assert = require('assert');
|
||||
const ConfirmCallSession = require('../session/confirm-call-session');
|
||||
const hooks = require('./notifiers');
|
||||
const moment = require('moment');
|
||||
const parseUrl = require('parse-url');
|
||||
|
||||
class SingleDialer extends Emitter {
|
||||
constructor({logger, sbcAddress, target, opts, application, callInfo}) {
|
||||
@@ -18,13 +19,21 @@ class SingleDialer extends Emitter {
|
||||
this.sbcAddress = sbcAddress;
|
||||
this.opts = opts;
|
||||
this.application = application;
|
||||
this.url = opts.url;
|
||||
this.method = opts.method;
|
||||
this.url = target.url;
|
||||
this.method = target.method;
|
||||
|
||||
this._callSid = uuidv4();
|
||||
this.bindings = logger.bindings();
|
||||
this.callInfo = Object.assign({}, callInfo, {callSid: this._callSid});
|
||||
this.sipStatus;
|
||||
|
||||
this.parentCallInfo = callInfo;
|
||||
/*
|
||||
this.callInfo = Object.assign({}, callInfo, {
|
||||
callSid: this._callSid,
|
||||
parentCallSid: callInfo.callSid,
|
||||
direction: CallDirection.Outbound,
|
||||
callStatus: CallStatus.Trying,
|
||||
sipStatus: 100
|
||||
});
|
||||
*/
|
||||
this.callGone = false;
|
||||
|
||||
this.on('callStatusChange', this._notifyCallStatusChange.bind(this));
|
||||
@@ -86,18 +95,21 @@ class SingleDialer extends Emitter {
|
||||
* (a) create a logger for this call
|
||||
* (b) augment this.callInfo with additional call info
|
||||
*/
|
||||
this.callInfo = new CallInfo({
|
||||
direction: CallDirection.Outbound,
|
||||
parentCallInfo: this.parentCallInfo,
|
||||
req
|
||||
});
|
||||
this.logger = srf.locals.parentLogger.child({
|
||||
callSid: this.callSid,
|
||||
parentCallSid: this.bindings.callSid,
|
||||
callId: req.get('Call-ID')
|
||||
callSid: this.callInfo.callSid,
|
||||
parentCallSid: this.parentCallInfo.callSid,
|
||||
callId: this.callInfo.callId
|
||||
});
|
||||
this.inviteInProgress = req;
|
||||
const status = {callStatus: CallStatus.Trying, sipStatus: 100};
|
||||
Object.assign(this.callInfo, {callId: req.get('Call-ID'), from: req.callingNumber, to});
|
||||
const {actionHook, notifyHook} = hooks(this.logger, this.callInfo);
|
||||
this.actionHook = actionHook;
|
||||
this.notifyHook = notifyHook;
|
||||
this.emit('callStatusChange', status);
|
||||
this.emit('callStatusChange', {callStatus: CallStatus.Trying, sipStatus: 100});
|
||||
},
|
||||
cbProvisional: (prov) => {
|
||||
const status = {sipStatus: prov.status};
|
||||
@@ -168,7 +180,24 @@ class SingleDialer extends Emitter {
|
||||
async _executeApp(url) {
|
||||
this.logger.debug(`SingleDialer:_executeApp: executing ${url} after connect`);
|
||||
try {
|
||||
const tasks = await this.actionHook(this.url, this.method);
|
||||
let auth;
|
||||
const app = Object.assign({}, this.application);
|
||||
if (url.startsWith('/')) {
|
||||
const savedUrl = url;
|
||||
const or = app.originalRequest;
|
||||
url = `${or.baseUrl}${url}`;
|
||||
auth = or.auth;
|
||||
this.logger.debug({originalUrl: savedUrl, normalizedUrl: url}, 'SingleDialer:_executeApp normalized url');
|
||||
}
|
||||
else {
|
||||
const u = parseUrl(url);
|
||||
const myPort = u.port ? `:${u.port}` : '';
|
||||
app.originalRequest = {
|
||||
baseUrl: `${u.protocol}://${u.resource}${myPort}`
|
||||
};
|
||||
}
|
||||
|
||||
const tasks = await this.actionHook(url, this.method, auth);
|
||||
const allowedTasks = tasks.filter((task) => {
|
||||
return [
|
||||
TaskPreconditions.StableCall,
|
||||
@@ -180,7 +209,7 @@ class SingleDialer extends Emitter {
|
||||
}
|
||||
|
||||
this.logger.debug(`SingleDialer:_executeApp: executing ${tasks.length} tasks`);
|
||||
const cs = new ConfirmCallSession(this.logger, this.application, this.dlg, this.ep, tasks);
|
||||
const cs = new ConfirmCallSession({logger: this.logger, application: app, dlg: this.dlg, ep: this.ep, tasks});
|
||||
await cs.exec();
|
||||
this.emit(this.dlg.connected ? 'accept' : 'decline');
|
||||
} catch (err) {
|
||||
@@ -190,18 +219,13 @@ class SingleDialer extends Emitter {
|
||||
}
|
||||
}
|
||||
|
||||
_notifyCallStatusChange(callStatus) {
|
||||
_notifyCallStatusChange({callStatus, sipStatus}) {
|
||||
this.logger.debug(`SingleDialer:_notifyCallStatusChange: ${callStatus} ${sipStatus}`);
|
||||
this.callInfo.updateStatus(callStatus, sipStatus);
|
||||
try {
|
||||
const auth = {};
|
||||
if (this.application.hook_basic_auth_user && this.application.hook_basic_auth_password) {
|
||||
Object.assign(auth, {user: this.application.hook_basic_auth_user, password: this.hook_basic_auth_password});
|
||||
}
|
||||
this.notifyHook(this.application.call_status_hook,
|
||||
this.application.hook_http_method,
|
||||
auth,
|
||||
callStatus);
|
||||
this.notifyHook(this.application.call_status_hook);
|
||||
} catch (err) {
|
||||
this.logger.info(err, `SingleDialer:_notifyCallStatusChange: error sending ${JSON.stringify(callStatus)}`);
|
||||
this.logger.info(err, `SingleDialer:_notifyCallStatusChange error sending ${callStatus} ${sipStatus}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,26 +4,25 @@ const makeTask = require('../tasks/make_task');
|
||||
const normalizeJamones = require('./normalize-jamones');
|
||||
|
||||
|
||||
function retrieveUrl(logger, url, method, auth, qs, body) {
|
||||
logger.debug(`body: ${body}`);
|
||||
const opts = {url, method, auth, qs, json: true};
|
||||
if (body) {
|
||||
logger.debug('adding body');
|
||||
Object.assign(opts, {body});
|
||||
}
|
||||
function retrieveUrl(logger, url, method, auth, obj) {
|
||||
const opts = {url, method, auth, json: true};
|
||||
if (method === 'GET') Object.assign(opts, {qs: obj});
|
||||
else Object.assign(opts, {body: obj});
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
request(opts, (err, response, body) => {
|
||||
if (err) throw err;
|
||||
if (body) logger.debug({body}, 'retrieveUrl: customer returned an application');
|
||||
resolve(body);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function retrieveApp(logger, url, method, auth, qs, body) {
|
||||
async function retrieveApp(logger, url, method, auth, obj) {
|
||||
let json;
|
||||
|
||||
if (typeof url === 'object') json = url;
|
||||
else json = await retrieveUrl(logger, url, method, auth, qs, body);
|
||||
else json = await retrieveUrl(logger, url, method, auth, obj);
|
||||
return normalizeJamones(logger, json).map((tdata) => makeTask(logger, tdata));
|
||||
}
|
||||
|
||||
|
||||
38
package-lock.json
generated
38
package-lock.json
generated
@@ -1561,6 +1561,14 @@
|
||||
"has": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"is-ssh": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.3.1.tgz",
|
||||
"integrity": "sha512-0eRIASHZt1E68/ixClI8bp2YK2wmBPVWEismTs6M+M099jKgrzl/3E976zIbImSIob48N2/XGe9y7ZiYdImSlg==",
|
||||
"requires": {
|
||||
"protocols": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"is-stream": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
|
||||
@@ -2198,6 +2206,11 @@
|
||||
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
|
||||
"dev": true
|
||||
},
|
||||
"normalize-url": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-3.3.0.tgz",
|
||||
"integrity": "sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg=="
|
||||
},
|
||||
"number-is-nan": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
|
||||
@@ -2417,6 +2430,26 @@
|
||||
"integrity": "sha1-VjRtR0nXjyNDDKDHE4UK75GqNh0=",
|
||||
"dev": true
|
||||
},
|
||||
"parse-path": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/parse-path/-/parse-path-4.0.1.tgz",
|
||||
"integrity": "sha512-d7yhga0Oc+PwNXDvQ0Jv1BuWkLVPXcAoQ/WREgd6vNNoKYaW52KI+RdOFjI63wjkmps9yUE8VS4veP+AgpQ/hA==",
|
||||
"requires": {
|
||||
"is-ssh": "^1.3.0",
|
||||
"protocols": "^1.4.0"
|
||||
}
|
||||
},
|
||||
"parse-url": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/parse-url/-/parse-url-5.0.1.tgz",
|
||||
"integrity": "sha512-flNUPP27r3vJpROi0/R3/2efgKkyXqnXwyP1KQ2U0SfFRgdizOdWfvrrvJg1LuOoxs7GQhmxJlq23IpQ/BkByg==",
|
||||
"requires": {
|
||||
"is-ssh": "^1.3.0",
|
||||
"normalize-url": "^3.3.0",
|
||||
"parse-path": "^4.0.0",
|
||||
"protocols": "^1.4.0"
|
||||
}
|
||||
},
|
||||
"path-exists": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
|
||||
@@ -2557,6 +2590,11 @@
|
||||
"react-is": "^16.8.1"
|
||||
}
|
||||
},
|
||||
"protocols": {
|
||||
"version": "1.4.7",
|
||||
"resolved": "https://registry.npmjs.org/protocols/-/protocols-1.4.7.tgz",
|
||||
"integrity": "sha512-Fx65lf9/YDn3hUX08XUc0J8rSux36rEsyiv21ZGUC1mOyeM3lTRpZLcrm8aAolzS4itwVfm7TAPyxC2E5zd6xg=="
|
||||
},
|
||||
"pseudomap": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
"drachtio-srf": "^4.4.27",
|
||||
"jambonz-db-helpers": "^0.1.8",
|
||||
"moment": "^2.24.0",
|
||||
"parse-url": "^5.0.1",
|
||||
"pino": "^5.14.0",
|
||||
"request": "^2.88.0",
|
||||
"request-debug": "^0.2.0"
|
||||
|
||||
Reference in New Issue
Block a user