altervoice-asterisk-callbot
Version:
Jovo plugin for Altervoice asterisk integration
261 lines (217 loc) • 10.1 kB
text/typescript
import { Plugin, BaseApp, SpeechBuilder, Log} from '../../jovo-core';
import { Config } from '../../jovo-platform-dialogflow/dist/src/DialogflowCore';
import { Dialogflow , DialogflowConfig} from '../../jovo-platform-dialogflow';
import { DialogflowAgent} from '../../jovo-platform-dialogflow/dist/src/DialogflowAgent';
import { DialogflowRequest } from '../../jovo-platform-dialogflow/dist/src/core/DialogflowRequest';
import { DialogflowResponse } from '../../jovo-platform-dialogflow/dist/src/core/DialogflowResponse';
import { EntityOverrideMode, SessionEntity, SessionEntityType } from '../../jovo-platform-dialogflow';
import _get = require('lodash.get');
import _set = require('lodash.set');
const _sample = require('lodash.sample');
import _unionWith = require('lodash.unionwith');
import { TelephonyActions } from './Interfaces';
import { AltervoiceAsteriskCallbotUser } from './altervoice-asterisk-callbot-user';
type reprompt = string | SpeechBuilder;
//const idPlatform = 'telephony';
const idPlatform = 'phone_gateway';
const idSource = 'phone_gateway';
declare module '../../jovo-platform-dialogflow/dist/src/DialogflowAgent' {
export interface DialogflowAgent {
isCallbot(): boolean;
addActions(action : TelephonyActions) : void;
getDtmf(): string;
getResult(): any;
addOutputContext(name: string, parameters: { [key: string]: any }, lifespanCount:number): void;
getOutputContext(name: string): void;
addSessionEntityTypes(sessionEntityTypes: SessionEntityType[] ) : this;
addSessionEntityType(sessionEntityTypes: SessionEntityType ) : this;
addSessionEntity(name: string,value: string,synonyms: string[], entityOverrideMode?: EntityOverrideMode): this;
actions : (TelephonyActions| any)[];
$request : DialogflowRequest;
}
}
export * from '../../jovo-platform-dialogflow';
export class AltervoiceAsteriskCallbot implements Plugin {
config = {
enabled: true,
};
constructor(config?: Config) { }
install(dialogFlow: Dialogflow): void {
dialogFlow.middleware('$output')!.use(this.output.bind(this));
dialogFlow.middleware('$type')!.use(this.type.bind(this));
DialogflowAgent.prototype.isCallbot = function () {
return _get(this.$request, 'originalDetectIntentRequest.payload.source') === idSource;
};
DialogflowAgent.prototype.addActions = function (action : TelephonyActions) {
action.platform = idPlatform;
if(action.telephonyMaxCall && action.telephonyMaxCall.prompt)
action.telephonyMaxCall.prompt = action.telephonyMaxCall.prompt.toString();
if(action.telephonyInact && action.telephonyInact.prompt)
action.telephonyInact.prompt = action.telephonyInact.prompt.toString();
if(!this.actions)
this.actions = [];
this.actions!.push(action);
};
DialogflowAgent.prototype.ask = function(
speech: string | SpeechBuilder | string[],
reprompt: string | SpeechBuilder | string[],
...reprompts: reprompt[]
) {
delete this.$output.tell;
if (Array.isArray(speech)) {
speech = _sample(speech);
}
if (Array.isArray(reprompt)) {
reprompt = _sample(reprompt);
}
if (!reprompt) {
reprompt = [];
}
this.$output.ask = {
speech: speech.toString(),
reprompt: [reprompt.toString()],
};
if (reprompts) {
this.$output.ask.reprompt = [reprompt.toString()];
reprompts.forEach((repr: string | SpeechBuilder) => {
(this.$output.ask!.reprompt as string[]).push(repr.toString());
});
}
return this;
}
DialogflowAgent.prototype.getDtmf = function () {
let reg = /\/telephony_dtmf$/g;
let outputContext = _get(this.$request, 'queryResult.outputContexts');
let data = outputContext ? outputContext.find((x :any) => reg.exec(x.name)) : {};
return data.parameters;
};
DialogflowAgent.prototype.getResult = function () {
let reg = /\/telephony_result$/g;
let outputContext = _get(this.$request, 'queryResult.outputContexts');
let data = outputContext ? outputContext.find((x :any) => reg.exec(x.name)) : {};
return data.parameters;
};
DialogflowAgent.prototype.addOutputContext = function(name: string, parameters: { [key: string]: any }, lifespanCount = 1) {
let output = _get(this.$output, "Dialogflow.OutputContexts") || [];
output.push({name,parameters,lifespanCount});
_set(this.$output, 'Dialogflow.OutputContexts',output);
}
DialogflowAgent.prototype.getOutputContext = function(name: string) {
return _get(this.$request, 'queryResult.outputContexts', []).find((context: any) => {
return context.name.indexOf(`/contexts/${name}`) > -1;
});
}
DialogflowAgent.prototype.addSessionEntityTypes = function ( sessionEntityTypes: SessionEntityType[] ) {
if (! _get(this.$output,'Dialogflow.SessionEntityTypes')) {
_set(this.$output, 'Dialogflow.SessionEntityTypes',[]);
}
sessionEntityTypes.forEach((el: SessionEntityType) => {
// Place session id in front of session entity name to accomodate to proper format
const sessionId = this.$request!.getSessionId();
const entityName = el.name;
el.name = `${sessionId}/entityTypes/${entityName}`;
// Set default override mode
if (!el.entityOverrideMode) {
el.entityOverrideMode = 'ENTITY_OVERRIDE_MODE_SUPPLEMENT';
}
});
// Merge existing entities with new ones provided as arguments with _.unionWith.
_set(this.$output, 'Dialogflow.SessionEntityTypes', _unionWith(
_get( this.$output, 'Dialogflow.SessionEntityTypes'),
sessionEntityTypes,
(newEntry: SessionEntityType, original: SessionEntityType) => {
// If the new session entity does not yet exist by its name, just add it to the new array.
if (newEntry.name !== original.name) {
return false;
}
// If the session entity already exists by its name, check if its entity values already exist.
const entities = _unionWith(
newEntry.entities,
original.entities,
(n: SessionEntity, o: SessionEntity) => {
// If the current value is not yet present, just add it with a new entry.
if (n.value !== o.value) {
return false;
}
// Else merge the respective synonyms and unify them.
o.synonyms = _unionWith(o.synonyms, n.synonyms);
return true;
}
);
// Replace old entries with new, merged ones.
original.entities = entities;
return true;
})
);
return this;
};
DialogflowAgent.prototype.addSessionEntityType = function (sessionEntityType: SessionEntityType) {
return this.addSessionEntityTypes([sessionEntityType]);
};
}
uninstall(app: BaseApp) : void { }
type(dialogflowAgent: DialogflowAgent) {
if (dialogflowAgent.isCallbot()) {
dialogflowAgent.$user = new AltervoiceAsteriskCallbotUser(dialogflowAgent);
if (!dialogflowAgent.$response)
dialogflowAgent.$response = new DialogflowResponse();
}
}
output(dialogflowAgent: DialogflowAgent) : void {
if (dialogflowAgent.isCallbot()) {
const output = dialogflowAgent.$output;
if (!dialogflowAgent.$response) {
dialogflowAgent.$response = new DialogflowResponse();
}
const response = dialogflowAgent.$response as DialogflowResponse;
if(dialogflowAgent.actions === undefined)
dialogflowAgent.actions = [];
if( dialogflowAgent.$output.Dialogflow){
response.sessionEntityTypes = _get(dialogflowAgent.$output.Dialogflow, 'SessionEntityTypes') ;
}
if( dialogflowAgent.$output.ask ){
// _set(response, 'fulfillmentText', dialogflowAgent.$output.ask.speech);
dialogflowAgent.actions.push({ simpleResponse:{ssml: dialogflowAgent.$output.ask.speech}} );
if((dialogflowAgent.$output.ask!.reprompt as string[]).length)
_set(response, 'payload.'+idPlatform+'.noInputPrompts', (dialogflowAgent.$output.ask!.reprompt as string[]).map((x: string | SpeechBuilder) => {return {ssml: x};} ));
_set(response, 'payload.'+idPlatform+'.expectUserResponse',true);
response.end_interaction = false;
// delete dialogflowAgent.$output.ask;
}
else if( dialogflowAgent.$output.tell ){
// _set(response, 'fulfillmentText', dialogflowAgent.$output.tell.speech);
dialogflowAgent.actions.push({simpleResponse:{ssml: dialogflowAgent.$output.tell.speech}} );
_set(response, 'payload.'+idPlatform+'.expectUserResponse',false);
response.end_interaction = true;
// delete dialogflowAgent.$output.tell;
}
if (response.fulfillmentText && SpeechBuilder.isSSML(response.fulfillmentText)) {
const ssml = response.fulfillmentText;
if (!response.fulfillmentMessages) {
response.fulfillmentMessages = [];
}
response.fulfillmentMessages.push({
platform: idSource,
telephonySynthesizeSpeech: {
ssml,
},
});
response.fulfillmentText = SpeechBuilder.removeSSML(response.fulfillmentText);
}
else {
Log.debug('Response does not contain SSML');
}
if(dialogflowAgent.actions){
_set(response, 'payload.'+idPlatform+'.richResponse.items',dialogflowAgent.actions );
dialogflowAgent.actions = [];
}
/*
let user = _get(dialogflowAgent.$request, 'originalDetectIntentRequest.payload.user');
console.log('user=',user);
_set(response, 'payload.'+idPlatform+'.user.',user);
*/
// _set(response, 'userStorage.user', user);
// console.log("response", Object.keys(response));
}
}
}