mirror of
https://github.com/jambonz/jambonz-feature-server.git
synced 2025-12-20 08:40:38 +00:00
wip: implemented listen, transcribe, play
This commit is contained in:
@@ -9,6 +9,7 @@ const makeTask = require('./tasks/make_task');
|
||||
const resourcesMixin = require('./utils/resources');
|
||||
const moment = require('moment');
|
||||
const assert = require('assert');
|
||||
const Dialog = require('drachtio-srf').Dialog;
|
||||
const BADPRECONDITIONS = 'preconditions not met';
|
||||
|
||||
class CallSession extends Emitter {
|
||||
@@ -34,27 +35,34 @@ class CallSession extends Emitter {
|
||||
|
||||
this.hooks = notifiers(this.logger, this.callAttributes);
|
||||
|
||||
req.on('cancel', this._onCallerHangup.bind(this));
|
||||
this.callGone = false;
|
||||
|
||||
req.on('cancel', this._onCallerHangup.bind(this, req));
|
||||
this.on('callStatusChange', this._onCallStatusChange.bind(this));
|
||||
}
|
||||
|
||||
get callSid() { return this.callAttributes.CallSid; }
|
||||
get parentCallSid() { return this.callAttributes.CallSid; }
|
||||
get actionHook() { return this.hooks.actionHook; }
|
||||
get callingNumber() { return this.req.callingNumber; }
|
||||
get calledNumber() { return this.req.calledNumber; }
|
||||
|
||||
async exec() {
|
||||
let idx = 0;
|
||||
while (this._executionStack.length) {
|
||||
const taskList = this.currentTaskList = this._executionStack.shift();
|
||||
this.logger.debug(`CallSession:exec starting task list with ${taskList.tasks.length} tasks`);
|
||||
while (taskList.length) {
|
||||
while (taskList.length && !this.callGone) {
|
||||
const {task, callSid} = taskList.shift();
|
||||
this.logger.debug(`CallSession:exec starting task #${++idx}: ${task.name}`);
|
||||
try {
|
||||
const resources = await this._evaluatePreconditions(task, callSid);
|
||||
this.currentTask = task;
|
||||
await task.exec(this, resources);
|
||||
this.currentTask = null;
|
||||
this.logger.debug(`CallSession:exec completed task #${idx}: ${task.name}`);
|
||||
} catch (err) {
|
||||
this.currentTask = null;
|
||||
if (err.message.includes(BADPRECONDITIONS)) {
|
||||
this.logger.info(`CallSession:exec task #${idx}: ${task.name}: ${err.message}`);
|
||||
}
|
||||
@@ -92,6 +100,7 @@ class CallSession extends Emitter {
|
||||
}
|
||||
|
||||
async _evalEndpointPrecondition(task, callSid) {
|
||||
if (this.callGone) new Error(`${BADPRECONDITIONS}: call gone`);
|
||||
const resources = this.calls.get(callSid);
|
||||
if (!resources) throw new Error(`task ${task.name} attempting to operate on unknown CallSid ${callSid}`);
|
||||
if (resources.ep) return resources.ep;
|
||||
@@ -105,6 +114,7 @@ class CallSession extends Emitter {
|
||||
this.addResource('ms', ms);
|
||||
}
|
||||
const ep = await ms.createEndpoint({remoteSdp: this.req.body});
|
||||
ep.cs = this;
|
||||
resources.ep = ep;
|
||||
if (task.earlyMedia && callSid === this.parentCallSid && this.req && !this.req.finalResponseSent) {
|
||||
this.res.send(183, {body: ep.local.sdp});
|
||||
@@ -112,7 +122,10 @@ class CallSession extends Emitter {
|
||||
return ep;
|
||||
}
|
||||
const uas = await this.srf.createUAS(this.req, this.res, {localSdp: ep.local.sdp});
|
||||
uas.on('destroy', this._onCallerHangup.bind(this, uas));
|
||||
uas.callSid = callSid;
|
||||
resources.dlg = uas;
|
||||
this.logger.debug(`CallSession:_evalEndpointPrecondition - call was answered with callSid ${callSid}`);
|
||||
this.calls.set(callSid, resources);
|
||||
return ep;
|
||||
} catch (err) {
|
||||
@@ -122,13 +135,15 @@ class CallSession extends Emitter {
|
||||
}
|
||||
|
||||
_evalStableCallPrecondition(task, callSid) {
|
||||
if (this.callGone) throw new Error(`${BADPRECONDITIONS}: call gone`);
|
||||
const resources = this.calls.get(callSid);
|
||||
if (!resources) throw new Error(`task ${task.name} attempting to operate on unknown callSid ${callSid}`);
|
||||
if (resources.dlg) throw new Error(`${BADPRECONDITIONS}: call was not answered - callSid ${callSid}`);
|
||||
if (!resources.dlg) throw new Error(`${BADPRECONDITIONS}: call was not answered - callSid ${callSid}`);
|
||||
return resources.dlg;
|
||||
}
|
||||
|
||||
_evalUnansweredCallPrecondition(task, callSid) {
|
||||
if (this.callGone) new Error(`${BADPRECONDITIONS}: call gone`);
|
||||
if (callSid !== this.parentCallSid || !this.req) {
|
||||
throw new Error(`${BADPRECONDITIONS}: no inbound call - callSid ${callSid}`);
|
||||
}
|
||||
@@ -152,6 +167,11 @@ class CallSession extends Emitter {
|
||||
this.calls.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* These below methods are needed mainly by the dial verb, which
|
||||
* deals with a variety of scenarios that can't simply be
|
||||
* described by the precondition concept as other verbs can
|
||||
*/
|
||||
|
||||
/**
|
||||
* retrieve the media server and endpoint for this call, allocate them if needed
|
||||
@@ -208,6 +228,7 @@ class CallSession extends Emitter {
|
||||
return {ep, ms, res: this.res};
|
||||
}
|
||||
const dlg = await this.srf.createUAS(this.req, this.res, {localSdp: ep.local.sdp});
|
||||
this.logger.debug(`CallSession:connectInboundCallToIvr - answered callSid ${this.parentCallSid}`);
|
||||
this.calls.set(this.parentCallSid, {ep, dlg});
|
||||
return {ep, ms, dlg};
|
||||
} catch (err) {
|
||||
@@ -265,10 +286,25 @@ class CallSession extends Emitter {
|
||||
}
|
||||
|
||||
/**
|
||||
* got CANCEL from inbound leg
|
||||
* got CANCEL or BYE from inbound leg
|
||||
*/
|
||||
_onCallerHangup(evt) {
|
||||
this.logger.debug('CallSession: caller hung before connection');
|
||||
_onCallerHangup(obj, evt) {
|
||||
this.callGone = true;
|
||||
if (obj instanceof Dialog) {
|
||||
this.logger.debug('CallSession: caller hung up');
|
||||
/* cant destroy endpoint as current task may need to get final transcription
|
||||
const resources = this.calls.get(obj.callSid);
|
||||
if (resources.ep && resources.ep.connected) {
|
||||
resources.ep.destroy();
|
||||
resources.ep = null;
|
||||
this.calls.set(obj.callSid, resources);
|
||||
}
|
||||
*/
|
||||
}
|
||||
else {
|
||||
this.logger.debug('CallSession: caller hung before answer');
|
||||
}
|
||||
if (this.currentTask) this.currentTask.kill();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user