// services/callTest/twiml.js
// Store entry steps + shared core steps for /calltest Twilio voice webhooks.
import {
buildVoiceWebhookUrl,
} from './config.js';
const CORE_STEPS = new Set(['intro', 'listen', 'outro', 'done']);
const STORE_ENTRY_STEPS = new Set(['greeting', 'dtmf', 'wait']);
function xmlEscape(text) {
return String(text || '')
.replace(/&/g, '&')
.replace(//g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
}
function redirect(testId, mode, step) {
const url = xmlEscape(buildVoiceWebhookUrl(testId, mode, step));
return `${url}`;
}
/**
* @param {object} opts
* @param {'store'|'dial'} opts.mode
* @param {string} opts.step
* @param {string} opts.testId
* @param {object} opts.config
*/
export function buildTwiml({ mode, step, testId, config }) {
const c = config;
let body = '';
if (mode === 'store' && STORE_ENTRY_STEPS.has(step)) {
switch (step) {
case 'greeting':
body = `\n${redirect(testId, mode, 'dtmf')}`;
break;
case 'dtmf': {
const digits = String(c.dtmf || '1').replace(/[^0-9*#w]/gi, '');
body = `\n${redirect(testId, mode, 'wait')}`;
break;
}
case 'wait':
body = `\n${redirect(testId, mode, 'intro')}`;
break;
default:
body = `Unknown entry step.\n`;
}
} else if (CORE_STEPS.has(step)) {
switch (step) {
case 'intro':
body = `${xmlEscape(c.introTts)}\n${redirect(testId, mode, 'listen')}`;
break;
case 'listen':
body = `\n${redirect(testId, mode, 'outro')}`;
break;
case 'outro':
body = `${xmlEscape(c.outroTts)}\n${redirect(testId, mode, 'done')}`;
break;
case 'done':
body = '';
break;
default:
body = '';
}
} else if (mode === 'dial' && step === 'intro') {
body = `${xmlEscape(c.introTts)}\n${redirect(testId, mode, 'listen')}`;
} else {
body = 'Invalid call test step.\n';
}
return `\n\n${body}\n`;
}
export function initialStepForMode(mode) {
return mode === 'store' ? 'greeting' : 'intro';
}
export function isCoreStep(step) {
return CORE_STEPS.has(step);
}
export function isStoreEntryStep(step) {
return STORE_ENTRY_STEPS.has(step);
}
export const STORE_ENTRY_STEP_ORDER = ['greeting', 'dtmf', 'wait'];
export const CORE_STEP_ORDER = ['intro', 'listen', 'outro', 'done'];