mirror of
https://github.com/jambonz/jambonz-feature-server.git
synced 2025-12-20 16:50:39 +00:00
feat actionHook delay action (#470)
* feat actionHook delay action * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip
This commit is contained in:
@@ -27,7 +27,7 @@ class TaskGather extends SttTask {
|
||||
[
|
||||
'finishOnKey', 'input', 'numDigits', 'minDigits', 'maxDigits',
|
||||
'interDigitTimeout', 'partialResultHook', 'bargein', 'dtmfBargein',
|
||||
'speechTimeout', 'timeout', 'say', 'play'
|
||||
'speechTimeout', 'timeout', 'say', 'play', 'actionHookDelayAction'
|
||||
].forEach((k) => this[k] = this.data[k]);
|
||||
|
||||
// gather default input is digits
|
||||
@@ -138,6 +138,30 @@ class TaskGather extends SttTask {
|
||||
this.interim = true;
|
||||
this.logger.debug('Gather:exec - early hints match enabled');
|
||||
}
|
||||
// actionHook delay
|
||||
this._actionHookDelayEnabled = cs.actionHookDelayEnabled || !!this.actionHookDelayAction;
|
||||
this._actionHookDelayActions = this.actionHookDelayAction && this.actionHookDelayAction.actions ?
|
||||
this.actionHookDelayAction.actions : cs.actionHookDelayActions || [];
|
||||
if (this._actionHookDelayEnabled && this._actionHookDelayActions.length > 0) {
|
||||
this._actionHookNoResponseTimeout = (this.actionHookDelayAction && this.actionHookDelayAction.noResponseTimeout ?
|
||||
this.actionHookDelayAction.noResponseTimeout : cs.actionHookNoResponseTimeout || 0) * 1000;
|
||||
|
||||
this._actionHookNoResponseGiveUpTimeout = (this.actionHookDelayAction &&
|
||||
this.actionHookDelayAction.noResponseGiveUpTimeout ?
|
||||
this.actionHookDelayAction.noResponseGiveUpTimeout : cs.actionHookNoResponseGiveUpTimeout || 0) * 1000;
|
||||
|
||||
this._actionHookDelayRetries = this.actionHookDelayAction && this.actionHookDelayAction.retries ?
|
||||
this.actionHookDelayAction.retries : cs.actionHookDelayRetries || 1;
|
||||
this._actionHookDelayTryCount = 0;
|
||||
this.actionHookDelayActionOptions = {
|
||||
enabled: this._actionHookDelayEnabled,
|
||||
actions: this._actionHookDelayActions,
|
||||
noResponseTimeoutMs: this._actionHookNoResponseTimeout,
|
||||
noResponseGiveUpTimeoutMs: this._actionHookNoResponseGiveUpTimeout,
|
||||
retries: this._actionHookDelayRetries
|
||||
};
|
||||
}
|
||||
|
||||
const startListening = async(cs, ep) => {
|
||||
this._startTimer();
|
||||
if (this.isContinuousAsr && 0 === this.timeout) this._startAsrTimer();
|
||||
@@ -231,6 +255,7 @@ class TaskGather extends SttTask {
|
||||
kill(cs) {
|
||||
super.kill(cs);
|
||||
this._killAudio(cs);
|
||||
this._killActionHookDelayAction();
|
||||
this.ep.removeAllListeners('dtmf');
|
||||
clearTimeout(this.interDigitTimer);
|
||||
this._clearAsrTimer();
|
||||
@@ -521,6 +546,104 @@ class TaskGather extends SttTask {
|
||||
this._asrTimer = null;
|
||||
}
|
||||
|
||||
_hangupCall() {
|
||||
this.logger.debug('_hangupCall');
|
||||
this.cs.hangup();
|
||||
}
|
||||
|
||||
_actionHookDelaySayAction(verb) {
|
||||
delete verb.verb;
|
||||
this.logger.debug(`_actionHookDelaySayAction ${verb}`);
|
||||
this._actionHookDelaySayTask = makeTask(this.logger, {say: verb}, this);
|
||||
const {span, ctx} = this.startChildSpan(`actionHookDelayAction:${this._actionHookDelaySayTask.summary}`);
|
||||
this._actionHookDelaySayTask.span = span;
|
||||
this._actionHookDelaySayTask.ctx = ctx;
|
||||
this._actionHookDelaySayTask.exec(this.cs, {ep: this.ep});
|
||||
this._actionHookDelaySayTask.on('playDone', (err) => {
|
||||
this._actionHookDelaySayTask = null;
|
||||
span.end();
|
||||
if (err) this.logger.error({err}, 'Gather:actionHookDelay Error playing tts');
|
||||
});
|
||||
}
|
||||
|
||||
_killActionHookDelayAction() {
|
||||
this.logger.debug('_killActionHookDelayAction');
|
||||
if (this._actionHookDelaySayTask && !this._actionHookDelaySayTask.killed) {
|
||||
this._actionHookDelaySayTask.removeAllListeners('playDone');
|
||||
this._actionHookDelaySayTask.kill(this.cs);
|
||||
this._actionHookDelaySayTask.span.end();
|
||||
this._actionHookDelaySayTask = null;
|
||||
}
|
||||
|
||||
if (this._actionHookDelayPlayTask && !this._actionHookDelayPlayTask.killed) {
|
||||
this._actionHookDelayPlayTask.removeAllListeners('playDone');
|
||||
this._actionHookDelayPlayTask.kill(this.cs);
|
||||
this._actionHookDelayPlayTask.span.end();
|
||||
this._actionHookDelayPlayTask = null;
|
||||
}
|
||||
}
|
||||
|
||||
_actionHookDelayPlayAction(verb) {
|
||||
delete verb.verb;
|
||||
this.logger.debug(`_actionHookDelayPlayAction ${verb}`);
|
||||
this._actionHookDelayPlayTask = makeTask(this.logger, {play: verb}, this);
|
||||
const {span, ctx} = this.startChildSpan(`actionHookDelayAction:${this._actionHookDelayPlayTask.summary}`);
|
||||
this._actionHookDelayPlayTask.span = span;
|
||||
this._actionHookDelayPlayTask.ctx = ctx;
|
||||
this._actionHookDelayPlayTask.exec(this.cs, {ep: this.ep});
|
||||
this._actionHookDelayPlayTask.on('playDone', (err) => {
|
||||
this._actionHookDelayPlayTask = null;
|
||||
span.end();
|
||||
if (err) this.logger.error({err}, 'Gather:actionHookDelay Error playing tts');
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
_startActionHookNoResponseTimer() {
|
||||
assert(this._actionHookNoResponseTimeout > 0);
|
||||
this._clearActionHookNoResponseTimer();
|
||||
this.logger.debug('startActionHookNoResponseTimer');
|
||||
this._actionHookNoResponseTimer = setTimeout(() => {
|
||||
if (this._actionHookDelayTryCount >= this._actionHookDelayRetries) {
|
||||
this._hangupCall();
|
||||
return;
|
||||
}
|
||||
const verb = this._actionHookDelayActions[this._actionHookDelayTryCount % this._actionHookDelayActions.length];
|
||||
if (verb.verb === 'say') {
|
||||
this._actionHookDelaySayAction(verb);
|
||||
} else if (verb.verb === 'play') {
|
||||
this._actionHookDelayPlayAction(verb);
|
||||
}
|
||||
this._actionHookDelayTryCount++;
|
||||
this._startActionHookNoResponseTimer();
|
||||
|
||||
}, this._actionHookNoResponseTimeout);
|
||||
|
||||
}
|
||||
|
||||
_clearActionHookNoResponseTimer() {
|
||||
if (this._actionHookNoResponseTimer) {
|
||||
clearTimeout(this._actionHookNoResponseTimer);
|
||||
}
|
||||
this._actionHookNoResponseTimer = null;
|
||||
}
|
||||
|
||||
_startActionHookNoResponseGiveUpTimer() {
|
||||
assert(this._actionHookNoResponseGiveUpTimeout > 0);
|
||||
this._clearActionHookNoResponseGiveUpTimer();
|
||||
this.logger.debug('startActionHookNoResponseGiveUpTimer');
|
||||
this._actionHookNoResponseGiveUpTimer = setTimeout(() => {
|
||||
this._hangupCall();
|
||||
}, this._actionHookNoResponseGiveUpTimeout);
|
||||
}
|
||||
|
||||
_clearActionHookNoResponseGiveUpTimer() {
|
||||
if (this._actionHookNoResponseGiveUpTimer) {
|
||||
clearTimeout(this._actionHookNoResponseGiveUpTimer);
|
||||
}
|
||||
this._actionHookNoResponseGiveUpTimer = null;
|
||||
}
|
||||
|
||||
_startFastRecognitionTimer(evt) {
|
||||
assert(this.fastRecognitionTimeout > 0);
|
||||
this._clearFastRecognitionTimer();
|
||||
@@ -865,6 +988,15 @@ class TaskGather extends SttTask {
|
||||
return;
|
||||
}
|
||||
|
||||
// Enabled action Hook delay timer to applied actions
|
||||
if (this._actionHookNoResponseTimeout > 0) {
|
||||
this._startActionHookNoResponseTimer();
|
||||
}
|
||||
|
||||
if (this._actionHookNoResponseGiveUpTimeout > 0) {
|
||||
this._startActionHookNoResponseGiveUpTimer();
|
||||
}
|
||||
|
||||
try {
|
||||
if (reason.startsWith('dtmf')) {
|
||||
if (this.parentTask) this.parentTask.emit('dtmf', evt);
|
||||
@@ -895,6 +1027,11 @@ class TaskGather extends SttTask {
|
||||
}
|
||||
}
|
||||
} catch (err) { /*already logged error*/ }
|
||||
|
||||
// Gather got response from hook, cancel all delay timers if there is any
|
||||
this._clearActionHookNoResponseTimer();
|
||||
this._clearActionHookNoResponseGiveUpTimer();
|
||||
|
||||
this.notifyTaskDone();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user