initial commit of distributor before upgrades and optimizations.
This commit is contained in:
parent
d9934cd2ad
commit
db05f06137
File diff suppressed because one or more lines are too long
@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"nlu": {
|
||||||
|
"apiBaseURL": "http://ivas-router.prd1",
|
||||||
|
"modelName": "MVP",
|
||||||
|
"settings": {
|
||||||
|
"intentConfidenceThreshold": 0.4
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"suffix": "6647ad7b84df93835bbb4346",
|
||||||
|
"waitHoldTimeout": "8s",
|
||||||
|
"waitHoldQueueStatus": "20",
|
||||||
|
"responses": {
|
||||||
|
"welcome": "Hello, I'm a virtual assistant. How can I help you?",
|
||||||
|
"unrecognized": "I did not understand what you said. Can you please say it again?",
|
||||||
|
"unanswered": "I understand what you said, but I have not been taught how to answer your question... yet.",
|
||||||
|
"noinput": "If you said something, I did not hear it. Can you please repeat that?",
|
||||||
|
"speechtimeout": "We may be having noise issues with our call, Can you repeat that?",
|
||||||
|
"transferCall": "Forwarding to a live operator",
|
||||||
|
"pleaseContinueToHold": "Please continue to wait for the next available representative.",
|
||||||
|
"safetynet": "There was a problem processing your request. How else can I help?"
|
||||||
|
},
|
||||||
|
"ivr": {
|
||||||
|
"hostname": "https://router.ivastudio.verint.live",
|
||||||
|
"applicationName": "SC Distr"
|
||||||
|
},
|
||||||
|
"transfer": {
|
||||||
|
"destination": ""
|
||||||
|
},
|
||||||
|
"integrations": {
|
||||||
|
"CAInterface": {
|
||||||
|
"enabled": false,
|
||||||
|
"suffix": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,17 @@
|
|||||||
|
console.log(req.body); // <- Post request body
|
||||||
|
console.log(res.query); // <- Query strings
|
||||||
|
const vxmlResponse = `<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<vxml version="2.1" xmlns="http://www.w3.org/2001/vxml"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://www.w3.org/2001/vxml http://www.w3.org/TR/2007/REC-voicexml21-20070619/vxml.xsd">
|
||||||
|
<form>
|
||||||
|
<block>
|
||||||
|
<prompt>An error has occurred</prompt>
|
||||||
|
<exit />
|
||||||
|
</block>
|
||||||
|
</form>
|
||||||
|
</vxml>`;
|
||||||
|
res.setHeader('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0');
|
||||||
|
res.setHeader('etag', nanoid());
|
||||||
|
res.type('text/xml');
|
||||||
|
res.send(vxmlResponse);
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
console.log({
|
||||||
|
frontdoor: "1.0",
|
||||||
|
body: req.body,
|
||||||
|
query: req.query,
|
||||||
|
params: req.params
|
||||||
|
});
|
||||||
|
const brand = req.query.brand;
|
||||||
|
(async () => {
|
||||||
|
const vxmlResponse = vxmlgen_gvf_6647ad7b84df93835bbb4346().frontDoor({
|
||||||
|
hostname: voiceSettings_6647ad7b84df93835bbb4346.ivr.hostname,
|
||||||
|
workspaceId: req.params.workspaceId,
|
||||||
|
branch: req.params.branch,
|
||||||
|
suffix: voiceSettings_6647ad7b84df93835bbb4346.suffix,
|
||||||
|
brand
|
||||||
|
});
|
||||||
|
res.setHeader('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0');
|
||||||
|
res.setHeader('etag', nanoid());
|
||||||
|
res.type('text/xml');
|
||||||
|
res.send(vxmlResponse);
|
||||||
|
})();
|
||||||
@ -0,0 +1,431 @@
|
|||||||
|
const utterance = req.body.utterance;
|
||||||
|
const sessionId = req.body.sessionId;
|
||||||
|
console.log({
|
||||||
|
loop: "1.6",
|
||||||
|
utterance,
|
||||||
|
sessionId
|
||||||
|
});
|
||||||
|
const getNested = (obj, ...args) => {
|
||||||
|
return args.reduce((obj, level) => {
|
||||||
|
return obj && obj[level];
|
||||||
|
}, obj);
|
||||||
|
};
|
||||||
|
if (req.body.body && req.body.query) {
|
||||||
|
const tmpBody = JSON.parse(JSON.stringify(req.body.body));
|
||||||
|
const tmpQuery = JSON.parse(JSON.stringify(req.body.query));
|
||||||
|
req.query = tmpQuery;
|
||||||
|
req.body = tmpBody;
|
||||||
|
}
|
||||||
|
if (req.body.sessionJSON) {
|
||||||
|
try {
|
||||||
|
req.body.sessionJSON = JSON.parse(req.body.sessionJSON);
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const verbose = voiceSettings_6647ad7b84df93835bbb4346.verbose || false;
|
||||||
|
const useDomain = req.body.useDomain;
|
||||||
|
const route = req.params && req.params[0] && req.params[0].split('/').slice(-1)[0];
|
||||||
|
const requestId = uuidv4();
|
||||||
|
const safetyNet = voiceSettings_6647ad7b84df93835bbb4346.responses.safetynet;
|
||||||
|
const waitHoldTimeout = voiceSettings_6647ad7b84df93835bbb4346.waitHoldTimeout;
|
||||||
|
let promptText = voiceSettings_6647ad7b84df93835bbb4346.responses.welcome;
|
||||||
|
let disconnect;
|
||||||
|
let waveform;
|
||||||
|
let gcsUri;
|
||||||
|
let fileName;
|
||||||
|
let recognizedData;
|
||||||
|
if (req.body.waveform) {
|
||||||
|
try {
|
||||||
|
waveform = url.parse(req.body.waveform, true).query.googleUri;
|
||||||
|
fileName = url.parse(waveform, true);
|
||||||
|
if (fileName && fileName.pathName) gcsUri = `gs:/${fileName.pathname}`;
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const isCA = () => {
|
||||||
|
return voiceSettings_6647ad7b84df93835bbb4346?.integrations?.CAInterface?.enabled || false;
|
||||||
|
};
|
||||||
|
const getCA = () => {
|
||||||
|
if (isCA()) {
|
||||||
|
let ca = "CAInterface";
|
||||||
|
if (voiceSettings_6647ad7b84df93835bbb4346.integrations.CAInterface.suffix) {
|
||||||
|
ca += voiceSettings_6647ad7b84df93835bbb4346.integrations.CAInterface.suffix;
|
||||||
|
}
|
||||||
|
ca += "()";
|
||||||
|
return eval(ca);
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
};
|
||||||
|
const getInteractionId = async (ani, dnis, xSpVerintId) => {
|
||||||
|
const suffix = voiceSettings_6647ad7b84df93835bbb4346.suffix && `_${voiceSettings_6647ad7b84df93835bbb4346.suffix}` || "";
|
||||||
|
const callback = `${voiceSettings_6647ad7b84df93835bbb4346.ivr.hostname}/ProxyScript/run/${req.params.workspaceId}/${req.params.branch}/vxml_transfer${suffix}?sessionId=${sessionId}`;
|
||||||
|
let tisId;
|
||||||
|
const CA = getCA();
|
||||||
|
if (CA) {
|
||||||
|
try {
|
||||||
|
const OIDC = await CA.getOIDC();
|
||||||
|
if (OIDC.access_token) {
|
||||||
|
tisId = await CA.createTelephonyInteraction(OIDC, ani, dnis, xSpVerintId, callback);
|
||||||
|
} else {
|
||||||
|
console.log("getInteractionId failed: Bad OIDC credentials");
|
||||||
|
console.log(OIDC);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(`getInteractionId failed. error: ${error.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tisId;
|
||||||
|
};
|
||||||
|
const blockWaitLiveOperator = async (smStr, sessionMap, CA) => {
|
||||||
|
const start = Date.now();
|
||||||
|
let rd;
|
||||||
|
const loopWait = 100;
|
||||||
|
const total = voiceSettings_6647ad7b84df93835bbb4346.waitHoldQueueStatus * 1000 / loopWait;
|
||||||
|
for (let i = 0; i < total; i++) {
|
||||||
|
const sessionMap = await redis.hGetAll(smStr);
|
||||||
|
if (sessionMap.transferCall) {
|
||||||
|
console.log("Loop: transfer call");
|
||||||
|
rd = {
|
||||||
|
answers: [voiceSettings_6647ad7b84df93835bbb4346.responses.transferCall],
|
||||||
|
endCall: true
|
||||||
|
};
|
||||||
|
return rd;
|
||||||
|
}
|
||||||
|
await new Promise(r => setTimeout(r, loopWait));
|
||||||
|
}
|
||||||
|
if (CA) {
|
||||||
|
try {
|
||||||
|
const OIDC = await CA.getOIDC();
|
||||||
|
// fallthrough, provide a queue status update
|
||||||
|
const predictions = await CA.getWaitTime(OIDC, sessionMap.interactionId);
|
||||||
|
rd = await run_app_event(sessionMap, smStr, "VXML Queue Status Event", "vxmlqueuestatus", voiceSettings_6647ad7b84df93835bbb4346.responses.pleaseContinueToHold, {
|
||||||
|
predictions
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.log("/predictions failed" + error.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!rd) {
|
||||||
|
rd = {
|
||||||
|
answers: [voiceSettings_6647ad7b84df93835bbb4346.responses.pleaseContinueToHold]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
console.log({
|
||||||
|
blockWaitElapsed: Date.now() - start
|
||||||
|
});
|
||||||
|
return rd;
|
||||||
|
};
|
||||||
|
const sequenceApiCalls = async (smStr, interactionId, apiCalls) => {
|
||||||
|
const CA = getCA();
|
||||||
|
if (CA) {
|
||||||
|
await redis.hSet(smStr, {
|
||||||
|
waitForApi: "true"
|
||||||
|
});
|
||||||
|
const OIDC = await CA.getOIDC();
|
||||||
|
for (let api of apiCalls) {
|
||||||
|
try {
|
||||||
|
if (api.api == "patchCallInfo") {
|
||||||
|
await CA.patchCallInfo(OIDC, interactionId, api.params);
|
||||||
|
} else if (api.api = "connectWithLiveOperator") {
|
||||||
|
const isVirtualHold = api.params.isVirtualHold;
|
||||||
|
const callReason = api.params.callReason;
|
||||||
|
if (isVirtualHold || callReason) {
|
||||||
|
await CA.patchCallInfo(OIDC, interactionId, {
|
||||||
|
isVirtualHold,
|
||||||
|
callReason
|
||||||
|
});
|
||||||
|
}
|
||||||
|
await CA.connectWithLiveOperator(OIDC, interactionId);
|
||||||
|
redis.hSet(smStr, {
|
||||||
|
waitForLiveOperator: "true",
|
||||||
|
lastQueueStatus: JSON.stringify(Date.now())
|
||||||
|
});
|
||||||
|
redis.hDel(smStr, "pendingAPIs");
|
||||||
|
} else {
|
||||||
|
console.log({
|
||||||
|
badapi: api
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.log(`Error: ${api.api} failed. ${err.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
redis.hDel(smStr, "waitForApi");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const run_app_event = async (sessionMap, smStr, intent, input, defaultAnswer, metadata = {}) => {
|
||||||
|
const configuration = {
|
||||||
|
directIntentHit: intent
|
||||||
|
};
|
||||||
|
return await run_model_and_report(sessionMap, smStr, input, defaultAnswer, configuration, metadata);
|
||||||
|
};
|
||||||
|
const run_model_and_report = async (sessionMap, smStr, input, defaultAnswer, configuration, metadata = {}) => {
|
||||||
|
let privateData = voiceSettings_6647ad7b84df93835bbb4346.ivr.privateData || false;
|
||||||
|
let interactionId = sessionMap.interactionId;
|
||||||
|
let {
|
||||||
|
data: recognizedData
|
||||||
|
} = await axios.post(`${voiceSettings_6647ad7b84df93835bbb4346.nlu.apiBaseURL}/Model/run/${req.params.workspaceId}/${req.params.branch}/${voiceSettings_6647ad7b84df93835bbb4346.nlu.modelName}`, {
|
||||||
|
input,
|
||||||
|
configuration,
|
||||||
|
conversationId: sessionMap.conversationId,
|
||||||
|
settings: voiceSettings_6647ad7b84df93835bbb4346.nlu.settings,
|
||||||
|
channel: "voice",
|
||||||
|
// for old multi-channel widgets
|
||||||
|
metadata: {
|
||||||
|
channel: 'voice',
|
||||||
|
gcsUriAudio: waveform,
|
||||||
|
ani: sessionMap.ani,
|
||||||
|
dnis: sessionMap.dnis,
|
||||||
|
callid: sessionMap.callid,
|
||||||
|
xSpVerintId: sessionMap.xSpVerintId,
|
||||||
|
interactionId,
|
||||||
|
sessionId,
|
||||||
|
syntheticAudio: true,
|
||||||
|
utteranceFileName: `${fileName?.pathname?.replace('/asr-archive/', '') || ""}`,
|
||||||
|
...metadata
|
||||||
|
}
|
||||||
|
});
|
||||||
|
privateData = recognizedData.ivrSettings?.privateData || privateData;
|
||||||
|
if (!privateData && recognizedData.conversationId && sessionMap.conversationId === undefined) {
|
||||||
|
db.analytics.addConversation({
|
||||||
|
id: recognizedData.conversationId
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (recognizedData.conversationId) {
|
||||||
|
await redis.hSet(smStr, {
|
||||||
|
conversationId: recognizedData.conversationId
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (defaultAnswer && recognizedData.answers.length === 0) {
|
||||||
|
recognizedData.answers = [defaultAnswer];
|
||||||
|
} else if (recognizedData.classificationResults.length === 0 && recognizedData.answers.length === 0) {
|
||||||
|
recognizedData.answers = [voiceSettings_6647ad7b84df93835bbb4346.responses.unrecognized];
|
||||||
|
} else if (recognizedData.answers.length === 0) {
|
||||||
|
recognizedData.answers = [voiceSettings_6647ad7b84df93835bbb4346.responses.unanswered];
|
||||||
|
}
|
||||||
|
if (!recognizedData.ivrSettings) {
|
||||||
|
recognizedData.ivrSettings = {};
|
||||||
|
}
|
||||||
|
let timeout;
|
||||||
|
// look for the wait-hold event from the flow
|
||||||
|
|
||||||
|
if (recognizedData.vxmlCAApis) {
|
||||||
|
timeout = waitHoldTimeout;
|
||||||
|
// async
|
||||||
|
if (recognizedData.vxmlCAApis.find(api => api.api == "connectWithLiveOperator")) {
|
||||||
|
// defer api until after the current prompt finishes. next loop
|
||||||
|
console.log("Deferring VC Apis");
|
||||||
|
await redis.hSet(smStr, {
|
||||||
|
waitForLiveOperator: "true",
|
||||||
|
pendingAPIs: JSON.stringify(recognizedData.vxmlCAApis)
|
||||||
|
});
|
||||||
|
sessionMap.waitForLiveOperator = true;
|
||||||
|
} else {
|
||||||
|
sequenceApiCalls(smStr, interactionId, recognizedData.vxmlCAApis);
|
||||||
|
}
|
||||||
|
} else if (sessionMap.waitForLiveOperator) {
|
||||||
|
timeout = waitHoldTimeout;
|
||||||
|
}
|
||||||
|
if (timeout && !recognizedData.ivrSettings.timeout) {
|
||||||
|
recognizedData.ivrSettings.timeout = timeout;
|
||||||
|
}
|
||||||
|
// add dialogName hueristically
|
||||||
|
if (!recognizedData.ivrSettings.dialogName) {
|
||||||
|
let dialogName = "";
|
||||||
|
if (recognizedData.classificationResults.length) {
|
||||||
|
dialogName = recognizedData.classificationResults[0].label.split(/\s+/).join('_');
|
||||||
|
}
|
||||||
|
if (recognizedData.answers.length) {
|
||||||
|
let words = recognizedData.answers[0].split(/\s+/).map(word => {
|
||||||
|
return word.replace(/[^a-z0-9]/gi, '');
|
||||||
|
}).filter(word => word.length > 0);
|
||||||
|
for (let i = 0; i < Math.min(6, words.length); i++) {
|
||||||
|
dialogName += "_" + words[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (dialogName.length) {
|
||||||
|
recognizedData.ivrSettings.dialogName = dialogName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!privateData && input !== "vxmlqueuestatus") {
|
||||||
|
db.analytics.addTransaction(recognizedData);
|
||||||
|
}
|
||||||
|
return recognizedData;
|
||||||
|
};
|
||||||
|
// DEMO DISTRIBUTOR CODE
|
||||||
|
console.log("req.body.interpretation");
|
||||||
|
console.log(req.body.interpretation);
|
||||||
|
const selectedWorkspaceOption = req.body.interpretation;
|
||||||
|
console.log("Selected Option:");
|
||||||
|
console.log(selectedWorkspaceOption);
|
||||||
|
|
||||||
|
let vxmlResponse;
|
||||||
|
|
||||||
|
const generateVXML = async () => {
|
||||||
|
try {
|
||||||
|
// Common properties used in all cases, unless specified in the case block
|
||||||
|
const commonProperties = {
|
||||||
|
hostname: "https://router.ivastudio.verint.live",
|
||||||
|
branch: "current",
|
||||||
|
requestId,
|
||||||
|
promptText,
|
||||||
|
disconnect,
|
||||||
|
recognizedData,
|
||||||
|
...voiceSettings_6647ad7b84df93835bbb4346.ivr,
|
||||||
|
};
|
||||||
|
|
||||||
|
switch (selectedWorkspaceOption) {
|
||||||
|
case "1":
|
||||||
|
// Peter's Workspace
|
||||||
|
vxmlResponse = vxmlgen_gvf_6647ad7b84df93835bbb4346().frontDoor({
|
||||||
|
workspaceId: "67bca862210071627d32ef12",
|
||||||
|
suffix: "6647ad7b84df93835bbb4346",
|
||||||
|
...commonProperties,
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case "2":
|
||||||
|
// David's Workspace
|
||||||
|
vxmlResponse = vxmlgen_gvf_6647ad7b84df93835bbb4346().frontDoor({
|
||||||
|
workspaceId: "67c9ddd765e40fd3d60ef441",
|
||||||
|
suffix: "6647ad7b84df93835bbb4346",
|
||||||
|
...commonProperties,
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case "3":
|
||||||
|
// Ramzi's Workspace
|
||||||
|
vxmlResponse = vxmlgen_gvf_6647ad7b84df93835bbb4346().frontDoor({
|
||||||
|
workspaceId: "67c758bf8e90ca81122106a5",
|
||||||
|
suffix: "6647ad7b84df93835bbb4346",
|
||||||
|
...commonProperties,
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case "4":
|
||||||
|
// Amber's Workspace
|
||||||
|
vxmlResponse = vxmlgen_gvf_6647ad7b84df93835bbb4346().frontDoor({
|
||||||
|
workspaceId: "67c9dde765e40fd3d60ef446",
|
||||||
|
suffix: "6647ad7b84df93835bbb4346",
|
||||||
|
...commonProperties,
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case "5":
|
||||||
|
// Ring Central Workspace
|
||||||
|
vxmlResponse = vxmlgen_gvf_6647ad7b84df93835bbb4346().frontDoor({
|
||||||
|
workspaceId: "68098e35ad4260eaf807cff2",
|
||||||
|
suffix: "6647ad7b84df93835bbb4346",
|
||||||
|
...commonProperties,
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
vxmlResponse = vxmlgen_gvf_6647ad7b84df93835bbb4346().loop({
|
||||||
|
hostname: voiceSettings_6647ad7b84df93835bbb4346.ivr.hostname,
|
||||||
|
workspaceId: req.params.workspaceId,
|
||||||
|
suffix: voiceSettings_6647ad7b84df93835bbb4346.suffix,
|
||||||
|
branch: req.params.branch,
|
||||||
|
sessionId,
|
||||||
|
...commonProperties,
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// END OF DEMO DISTRIBUTOR CODE
|
||||||
|
res.setHeader('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0');
|
||||||
|
res.setHeader('etag', nanoid());
|
||||||
|
res.type('text/xml');
|
||||||
|
if (verbose) {
|
||||||
|
console.log('============================');
|
||||||
|
console.log(vxmlResponse);
|
||||||
|
console.log('++++++++++++++++++++++++++++');
|
||||||
|
}
|
||||||
|
res.send(vxmlResponse);
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e.message);
|
||||||
|
if (e.toJSON) console.log(e.toJSON());
|
||||||
|
res.status(500);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (sessionId) {
|
||||||
|
const smStr = `session-map-${sessionId}`;
|
||||||
|
(async () => {
|
||||||
|
if (req.body.sessionJSON && req.body.sessionJSON) {
|
||||||
|
const ani = getNested(req.body, 'sessionJSON', 'telephone', 'ani').split('@')[0];
|
||||||
|
const dnis = getNested(req.body, 'sessionJSON', 'connection', 'protocol', 'sip', 'requesturi').split('@')[0];
|
||||||
|
const callid = getNested(req.body, 'sessionJSON', 'connection', 'protocol', 'sip', 'headers', 'call-id').split('_')[0];
|
||||||
|
let xSpVerintId = getNested(req.body, 'sessionJSON', 'connection', 'protocol', 'sip', 'headers', 'x-sp-verintid') || callid;
|
||||||
|
if (utterance == undefined) {
|
||||||
|
getInteractionId(ani, dnis, callid).then(interactionId => {
|
||||||
|
if (interactionId) {
|
||||||
|
redis.hSet(smStr, {
|
||||||
|
interactionId
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
await redis.hSet(smStr, {
|
||||||
|
ani,
|
||||||
|
dnis,
|
||||||
|
callid,
|
||||||
|
xSpVerintId
|
||||||
|
});
|
||||||
|
await redis.expire(smStr, 60 * 60 * 24);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const sessionMap = await redis.hGetAll(smStr);
|
||||||
|
Object.keys(sessionMap).forEach((key, i) => {
|
||||||
|
try {
|
||||||
|
sessionMap[key] = JSON.parse(sessionMap[key]);
|
||||||
|
} catch (e) {}
|
||||||
|
});
|
||||||
|
console.log(sessionMap);
|
||||||
|
if (sessionMap.waitForApi) {
|
||||||
|
promptText = undefined;
|
||||||
|
recognizedData = {
|
||||||
|
answers: [""],
|
||||||
|
ivrSettings: {
|
||||||
|
timeout: waitHoldTimeout
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} else if (sessionMap.endCall) {
|
||||||
|
promptText = undefined;
|
||||||
|
recognizedData = {
|
||||||
|
answers: [""],
|
||||||
|
endCall: true
|
||||||
|
};
|
||||||
|
} else if (sessionMap.transferCall) {
|
||||||
|
recognizedData = await run_app_event(sessionMap, smStr, 'VXML Transfer Call Event', 'vxmltransfercall', voiceSettings_6647ad7b84df93835bbb4346.responses.transferCall);
|
||||||
|
recognizedData.endCall = true;
|
||||||
|
} else if (sessionMap.waitForLiveOperator) {
|
||||||
|
if (sessionMap.pendingAPIs) {
|
||||||
|
// async. success will delete sessionMap.pendingApis
|
||||||
|
sequenceApiCalls(smStr, sessionMap.interactionId, sessionMap.pendingAPIs);
|
||||||
|
}
|
||||||
|
recognizedData = await blockWaitLiveOperator(smStr, sessionMap, getCA());
|
||||||
|
} else if (route === 'noinput') {
|
||||||
|
recognizedData = await run_app_event(sessionMap, smStr, 'VXML Noinput Event', 'vxmlnoinput', voiceSettings_6647ad7b84df93835bbb4346.responses.noinput);
|
||||||
|
} else if (route === 'nomatch') {
|
||||||
|
recognizedData = await run_app_event(sessionMap, smStr, 'VXML Unrecognized Event', 'vxmlunrecognized', voiceSettings_6647ad7b84df93835bbb4346.responses.unrecognized);
|
||||||
|
} else if (route === 'maxspeechtimeout') {
|
||||||
|
recognizedData = await run_app_event(sessionMap, smStr, 'VXML Max Speech Timeout', 'vxmlmaxspeechtimeout', voiceSettings_6647ad7b84df93835bbb4346.responses.speechtimeout);
|
||||||
|
} else if (utterance) {
|
||||||
|
recognizedData = await run_model_and_report(sessionMap, smStr, utterance);
|
||||||
|
} else {
|
||||||
|
recognizedData = await run_app_event(sessionMap, smStr, 'VXML Welcome Event', 'vxmlwelcome', voiceSettings_6647ad7b84df93835bbb4346.responses.welcome);
|
||||||
|
}
|
||||||
|
if (recognizedData && recognizedData.transferCall) {
|
||||||
|
recognizedData.endCall = true;
|
||||||
|
await redis.hSet(smStr, {
|
||||||
|
transferCall: "true",
|
||||||
|
transferTo: recognizedData.transferTo || voiceSettings_6647ad7b84df93835bbb4346.transfer.destination
|
||||||
|
});
|
||||||
|
}
|
||||||
|
promptText = recognizedData && recognizedData.answers && recognizedData.answers.join(' ') || promptText;
|
||||||
|
disconnect = recognizedData && recognizedData.endCall || false;
|
||||||
|
generateVXML(sessionMap);
|
||||||
|
})().catch(e => {
|
||||||
|
console.log(e.message);
|
||||||
|
promptText = safetyNet;
|
||||||
|
generateVXML();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
generateVXML();
|
||||||
|
}
|
||||||
@ -0,0 +1,57 @@
|
|||||||
|
console.log({
|
||||||
|
stop: "1.5",
|
||||||
|
body: req.body,
|
||||||
|
query: req.query,
|
||||||
|
params: req.params
|
||||||
|
});
|
||||||
|
const getCA = () => {
|
||||||
|
if (voiceSettings_6647ad7b84df93835bbb4346?.integrations?.CAInterface?.enabled) {
|
||||||
|
let ca = "CAInterface";
|
||||||
|
if (voiceSettings_6647ad7b84df93835bbb4346.integrations.CAInterface.suffix) {
|
||||||
|
ca += voiceSettings_6647ad7b84df93835bbb4346.integrations.CAInterface.suffix;
|
||||||
|
}
|
||||||
|
ca += "()";
|
||||||
|
return eval(ca);
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
};
|
||||||
|
const sessionId = req.body.sessionId;
|
||||||
|
(async () => {
|
||||||
|
const smStr = `session-map-${sessionId}`;
|
||||||
|
const sessionMap = await redis.hGetAll(smStr);
|
||||||
|
const terminationObject = {
|
||||||
|
type: 'RETURN'
|
||||||
|
};
|
||||||
|
const transferCall = sessionMap.transferCall || req.headers["transfer-call-tester"];
|
||||||
|
if (transferCall) {
|
||||||
|
terminationObject.type = 'TRANSFER';
|
||||||
|
let dest = sessionMap.transferTo || voiceSettings_6647ad7b84df93835bbb4346.transfer.destination;
|
||||||
|
const params = [];
|
||||||
|
if (sessionMap.xSpVerintId) params.push("X-SP-VerintID=" + encodeURIComponent(sessionMap.xSpVerintId));
|
||||||
|
for (let [index, value] of params.entries()) {
|
||||||
|
if (index == 0) {
|
||||||
|
dest += "?";
|
||||||
|
} else {
|
||||||
|
dest += "&";
|
||||||
|
}
|
||||||
|
dest += value;
|
||||||
|
}
|
||||||
|
terminationObject.destination = dest;
|
||||||
|
console.log({
|
||||||
|
terminationObject
|
||||||
|
});
|
||||||
|
} else if (sessionMap.waitForLiveOperator === "true" && sessionMap.interactionId) {
|
||||||
|
const CA = getCA();
|
||||||
|
if (CA) {
|
||||||
|
CA.endTelephonyInteraction(await CA.getOIDC(), sessionMap.interactionId, "abandoned-in-queue");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const vxmlResponse = vxmlgen_gvf_6647ad7b84df93835bbb4346().stop({
|
||||||
|
terminationObject
|
||||||
|
});
|
||||||
|
console.log(vxmlResponse);
|
||||||
|
res.setHeader('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0');
|
||||||
|
res.setHeader('etag', nanoid());
|
||||||
|
res.type('text/xml');
|
||||||
|
res.send(vxmlResponse);
|
||||||
|
})();
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
console.log({
|
||||||
|
transfer: "1.2",
|
||||||
|
query: req.query
|
||||||
|
});
|
||||||
|
const sessionId = req.query.sessionId;
|
||||||
|
console.log("Transfer", sessionId);
|
||||||
|
if (sessionId) {
|
||||||
|
const smStr = `session-map-${sessionId}`;
|
||||||
|
(async () => {
|
||||||
|
await redis.hSet(smStr, {
|
||||||
|
transferCall: "true",
|
||||||
|
waitForLiveOperator: "false"
|
||||||
|
});
|
||||||
|
res.send(200);
|
||||||
|
})().catch(e => {
|
||||||
|
console.log("error");
|
||||||
|
console.log(e.message);
|
||||||
|
res.send(500);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
res.send(400);
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user