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