function xmlEscape(value: string): string { return value .replace(/&/g, "&") .replace(//g, ">") .replace(/"/g, """) .replace(/'/g, "'"); } const STRATEGY_VALUES: Record = { LONGEST_IDLE_AGENT: "longest-idle-agent", ROUND_ROBIN: "round-robin", TOP_DOWN: "top-down", AGENT_WITH_LEAST_TALK_TIME: "agent-with-least-talk-time", AGENT_WITH_FEWEST_CALLS: "agent-with-fewest-calls", SEQUENTIALLY_BY_AGENT_ORDER: "sequentially-by-agent-order", RING_ALL: "ring-all", RING_PROGRESSIVELY: "ring-progressively", }; export interface QueueXmlParams { queueName: string; // ja no formato "@" strategy: keyof typeof STRATEGY_VALUES; mohSound?: string; announceSound?: string; announceFrequency: number; maxWaitTime: number; maxWaitTimeWithNoAgent: number; agentNoAnswerStatus?: string; tierRulesApply: boolean; tierRuleWaitSecond: number; discardAbandonedAfter: number; abandonedResumeAllowed: boolean; skipAgentsWithExternalCalls: boolean; recordingEnabled: boolean; } /** * XML de fila do mod_callcenter (agente.md secao 50-51). Escrito em * autoload_configs/callcenter_queues.conf.d/.xml (volume Docker * compartilhado, incluído via X-PRE-PROCESS no callcenter.conf.xml — * mesmo padrão dos gateways Sofia). Carregado com `callcenter_config queue * reload ` via ESL, não é resolvido dinamicamente por chamada como o * dialplan. */ export function buildQueueXml(params: QueueXmlParams): string { const lines: string[] = []; const param = (name: string, value: string | number | boolean | undefined) => { if (value === undefined || value === "") return; lines.push(` `); }; param("strategy", STRATEGY_VALUES[params.strategy]); param("moh-sound", params.mohSound); param("announce-sound", params.announceSound); param("announce-frequency", params.announceFrequency); param("time-base-score", "system"); param("max-wait-time", params.maxWaitTime); param("max-wait-time-with-no-agent", params.maxWaitTimeWithNoAgent); param("agent-no-answer-status", params.agentNoAnswerStatus); param("tier-rules-apply", params.tierRulesApply); param("tier-rule-wait-second", params.tierRuleWaitSecond); param("discard-abandoned-after", params.discardAbandonedAfter); param("abandoned-resume-allowed", params.abandonedResumeAllowed); param("skip-agents-with-external-calls", params.skipAgentsWithExternalCalls); if (params.recordingEnabled) { param( "record-template", "$${recordings_dir}/${strftime(%Y-%m-%d-%H-%M-%S)}.${destination_number}.${caller_id_number}.${uuid}.wav", ); } return ` ${lines.join("\n")} `; }