// 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'];