typescript-agi-ipcom 0.0.10-beta.1 → 0.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/index.ts", "../../src/AGIServer.ts", "../../src/Channel.ts", "../../src/ResponseArguments.ts"],
4
- "sourcesContent": ["// Copyright (c) 2020, Brandon Lehmann\n//\n// Please see the included LICENSE file for more information.\n\nexport {AGIServer} from './AGIServer';\nexport {Channel, ChannelState, DialStatus, PlaybackStatus} from './Channel';\n", "// Copyright (c) 2020, Brandon Lehmann\n//\n// Please see the included LICENSE file for more information.\n\nimport * as net from 'net';\nimport {EventEmitter} from 'events';\nimport {Channel} from './Channel';\nimport {format} from 'util';\n\n/**\n * Represents an AGI server instance\n */\nexport class AGIServer extends EventEmitter {\n private readonly m_port: number;\n private readonly m_ip: string;\n private readonly m_server: net.Server = net.createServer();\n\n /**\n * Constructs a new instance of the object\n * @param port\n * @param ip\n */\n constructor(port: number = 3000, ip: string = '0.0.0.0') {\n super();\n this.setMaxListeners(10);\n\n this.m_port = port;\n this.m_ip = ip;\n\n this.m_server.on('connection', (socket: net.Socket) => {\n const channel = new Channel(socket);\n\n channel.on('ready', () => this.emit('channel', channel));\n });\n }\n\n /**\n * Event that is emitted when a new AGI channel has been established and is ready for interation\n * @param event\n * @param listener\n */\n public on(event: 'channel', listener: (channel: Channel) => void): this;\n\n /**\n * Event that is emitted when the AGI server is started and in a listening state\n * @param event\n * @param listener\n */\n public on(event: 'listening', listener: (port: number, ip: string) => void): this;\n\n /**\n * Event that is emitted when the server encounters and error\n * @param event\n * @param listener\n */\n public on(event: 'error', listener: (error: any) => void): this;\n\n /**\n * Event that emitted when the server is closed and stopped\n * @param event\n * @param listener\n */\n public on(event: 'close', listener: () => void): this;\n\n public on(event: any, listener: (...args: any[]) => void): this {\n return super.on(event, listener);\n }\n\n /**\n * Starts the AGI server\n */\n public async start(): Promise<void> {\n this.m_server.on('error', (error) =>\n this.emit('error', new Error(\n format('Internal TCP server error: %s', error.toString()),\n )),\n );\n\n this.m_server.on('close', () => this.emit('close'));\n\n this.m_server.listen(this.m_port, this.m_ip, () => {\n this.emit('listening', this.m_port, this.m_ip);\n });\n }\n\n /**\n * Stops the AGI server\n */\n public async stop(): Promise<void> {\n return new Promise((resolve, reject) => {\n this.m_server.close((error) => {\n if (error) {\n return reject(error);\n }\n return resolve();\n });\n });\n }\n}\n", "// Copyright (c) 2020, Brandon Lehmann\n//\n// Please see the included LICENSE file for more information.\n\nimport { EventEmitter } from 'node:events';\nimport type { Socket } from 'node:net';\nimport { format } from 'node:util';\nimport { ResponseArguments } from './ResponseArguments';\n\n/** @ignore */\nenum ContextState {\n INIT = 0,\n WAITING = 2,\n}\n\n/**\n * Represents the current channel state\n */\nexport enum ChannelState {\n DOWN_AVAILABLE = 0,\n DOWN_RESERVED,\n OFF_HOOK,\n DIGITS_DIALED,\n RINGING,\n REMOTE_RINGING,\n UP,\n BUSY,\n}\n\n/**\n * Represents the result of a Dial() attempt\n */\nexport enum DialStatus {\n ANSWER,\n BUSY,\n NOANSWER,\n CANCEL,\n CONGESTION,\n CHANUNAVAIL,\n DONTCALL,\n TORTURE,\n INVALIDARGS,\n}\n\n/**\n * Represents the playback status\n */\nexport enum PlaybackStatus {\n SUCCESS,\n USER_STOPPED,\n REMOTE_STOPPED,\n ERROR,\n}\n\n/** @ignore */\ninterface IResponse {\n code: number;\n result: number;\n arguments: ResponseArguments;\n}\n\n/** @ignore */\ninterface IQueuedCommand {\n command: string;\n resolve: (value: IResponse) => void;\n reject: (reason: any) => void;\n timeout?: number;\n timestamp: number;\n}\n\n/**\n * Represents an AGI Channel\n */\nexport class Channel extends EventEmitter {\n private readonly m_connection: Socket;\n private m_state: ContextState;\n private m_message: string = '';\n private m_network: string = '';\n private m_network_script: string = '';\n private m_request: string = '';\n private m_channel: string = '';\n private m_language: string = '';\n private m_type: string = '';\n private m_uniqueid: string = '';\n private m_version: string = '';\n private m_callerid: string = '';\n private m_calleridname: string = '';\n private m_callingpres: string = '';\n private m_callingani2: string = '';\n private m_callington: string = '';\n private m_callingtns: string = '';\n private m_dnid: string = '';\n private m_rdnis: string = '';\n private m_context: string = '';\n private m_extension: string = '';\n private m_priority: string = '';\n private m_enhanced: string = '';\n private m_accountcode: string = '';\n private m_threadid: string = '';\n private commandQueue: IQueuedCommand[] = [];\n private isProcessingCommand = false;\n private channelAlive = true;\n private readonly maxQueueSize = 100;\n private readonly defaultCommandTimeout = 10000;\n private readonly maxCallDuration = 21600000; // 6 horas (360 minutos)\n\n /**\n * Creates a new instance of a channel object\n * @param connection the AGI socket connection\n */\n constructor(connection: Socket) {\n super();\n this.setMaxListeners(10);\n\n this.m_connection = connection;\n this.m_state = ContextState.INIT;\n\n this.m_connection.on('data', (data: Buffer) => this.read(data));\n this.m_connection.on('close', () => {\n this.handleChannelClose();\n this.emit('close');\n });\n this.m_connection.on('error', (error) => this.emit('error', error));\n this.m_connection.on('timeout', () => this.emit('timeout'));\n this.on('hangup', () => {\n this.handleHangup();\n this.close();\n });\n }\n\n /**\n * Event that is emitted when the underlying socket encounters an error\n * @param event\n * @param listener\n */\n public on(event: 'error', listener: (error: any) => void): this;\n\n /**\n * Event that is emitted when the underlying socket is closed\n * @param event\n * @param listener\n */\n public on(event: 'close', listener: () => void): this;\n\n /**\n * Event that emitted when the underlying socket times out\n * @param event\n * @param listener\n */\n public on(event: 'timeout', listener: () => void): this;\n\n /**\n * Event that is emitted when the channel is ready\n * @param event\n * @param listener\n */\n public on(event: 'ready', listener: () => void): this;\n\n /**\n * Event that is emitted when a response is received from the Asterisk server\n * @param event\n * @param listener\n */\n public on(event: 'recv', listener: (response: string) => void): this;\n\n /**\n * Event that emitted when the channel is hung up\n * @param event\n * @param listener\n */\n public on(event: 'hangup', listener: () => void): this;\n\n /**\n * Event that emitted when the response from the Asterisk server is processed into a structured response\n * @param event\n * @param listener\n */\n public on(event: 'response', listener: (response: IResponse) => void): this;\n\n /**\n * Event that is emitted when data is sent to the Asterisk server\n * @param event\n * @param listener\n */\n public on(event: 'send', listener: (data: string) => void): this;\n\n public on(event: any, listener: (...args: any[]) => void): this {\n return super.on(event, listener);\n }\n\n /**\n * Whether this AGI request is over the network\n */\n public get network(): boolean {\n return this.m_network.toLowerCase() === 'yes';\n }\n\n /**\n * The network path included in the AGI request\n * ie. agi://127.0.0.1:3000/test\n * This value would return 'test'\n */\n public get network_script(): string {\n return this.m_network_script;\n }\n\n /**\n * The version of Asterisk\n */\n public get version(): string {\n return this.m_version;\n }\n\n /**\n * The filename of your script\n * ie. agi\n */\n public get request(): string {\n return this.m_request;\n }\n\n /**\n * The originating channel (your phone)\n */\n public get channel(): string {\n return this.m_channel;\n }\n\n /**\n * The language code (e.g. \u201Cen\u201D)\n */\n public get language(): string {\n return this.m_language;\n }\n\n /**\n * The originating channel type (e.g. \u201CSIP\u201D or \u201CZAP\u201D)\n */\n public get type(): string {\n return this.m_type;\n }\n\n /**\n * A unique ID for the call\n */\n public get uniqueid(): string {\n return this.m_uniqueid;\n }\n\n /**\n * The caller ID number (or \u201Cunknown\u201D)\n */\n public get callerid(): string {\n return this.m_callerid;\n }\n\n /**\n * The caller ID name (or \u201Cunknown\u201D)\n */\n public get calleridname(): string {\n return this.m_calleridname;\n }\n\n /**\n * The presentation for the callerid in a ZAP channel\n */\n public get callingpres(): string {\n return this.m_callingpres;\n }\n\n /**\n * The number which is defined in ANI2 see Asterisk Detailed Variable List (only for PRI Channels)\n */\n public get callingani2(): string {\n return this.m_callingani2;\n }\n\n /**\n * The type of number used in PRI Channels see Asterisk Detailed Variable List\n */\n public get callington(): string {\n return this.m_callington;\n }\n\n /**\n * An optional 4 digit number (Transit Network Selector) used in PRI Channels see Asterisk Detailed Variable List\n */\n public get callingtns(): string {\n return this.m_callingtns;\n }\n\n /**\n * The dialed number id (or \u201Cunknown\u201D)\n */\n public get dnid(): string {\n return this.m_dnid;\n }\n\n /**\n * The referring DNIS number (or \u201Cunknown\u201D)\n */\n public get rdnis(): string {\n return this.m_rdnis;\n }\n\n /**\n * Origin context in extensions.conf\n */\n public get context(): string {\n return this.m_context;\n }\n\n /**\n * The called number\n */\n public get extension(): string {\n return this.m_extension;\n }\n\n /**\n * The priority it was executed as in the dial plan\n */\n public get priority(): string {\n return this.m_priority;\n }\n\n /**\n * The flag value is 1.0 if started as an EAGI script, 0.0 otherwise\n */\n public get enhanced(): string {\n return this.m_enhanced;\n }\n\n /**\n * Account code of the origin channel\n */\n public get accountcode(): string {\n return this.m_accountcode;\n }\n\n /**\n * Thread ID of the AGI script\n */\n public get threadid(): string {\n return this.m_threadid;\n }\n\n /**\n * Answers channel if not already in answer state.\n */\n public async answer(): Promise<void> {\n const response = await this.sendCommand('ANSWER');\n\n if (response.code !== 200 || response.result !== 0) {\n throw new Error('Could not answer call');\n }\n }\n\n /**\n * Interrupts expected flow of Async AGI commands and returns control to\n * previous source (typically, the PBX dialplan).\n */\n public async break(): Promise<void> {\n const response = await this.sendCommand('ASYNCAGI BREAK');\n\n if (response.code !== 200 || response.result !== 0) {\n throw new Error('Could not interrupt processing');\n }\n\n return this.close();\n }\n\n /**\n * Returns status of the connected channel.\n * @param channel\n */\n public async channelStatus(channel?: string): Promise<ChannelState> {\n const response = await this.sendCommand(\n format('CHANNEL STATUS %s', channel || '')\n );\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not get channel status');\n }\n\n return response.result;\n }\n\n /**\n * Sends audio file on channel and allows the listener to control the stream.\n * @param filename\n * @param escapeDigits\n * @param skipms\n * @param fastForwardCharacter\n * @param rewindCharacter\n * @param pauseCharacter\n */\n public async controlStreamFile(\n filename: string,\n escapeDigits: string = '',\n skipms?: number,\n fastForwardCharacter?: string,\n rewindCharacter?: string,\n pauseCharacter?: string\n ): Promise<{\n digit: string;\n playbackStatus: PlaybackStatus;\n playbackOffset: number;\n }> {\n const response = await this.sendCommand(\n format(\n 'CONTROL STREAM FILE %s \"%s\" %s %s %s %s',\n filename,\n escapeDigits,\n skipms || '',\n fastForwardCharacter || '',\n rewindCharacter || '',\n pauseCharacter || ''\n )\n );\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not control stream file');\n }\n\n const playbackStatus = await this.getVariable('CPLAYBACKSTATUS ');\n\n const playbackOffset = await this.getVariable('CPLAYBACKOFFSET ');\n\n let status: PlaybackStatus = PlaybackStatus.ERROR;\n\n switch (playbackStatus.toUpperCase()) {\n case 'SUCCESS':\n status = PlaybackStatus.SUCCESS;\n break;\n case 'USERSTOPPED':\n status = PlaybackStatus.USER_STOPPED;\n break;\n case 'REMOTESTOPPED':\n status = PlaybackStatus.REMOTE_STOPPED;\n break;\n }\n\n return {\n digit: response.arguments.char('result'),\n playbackStatus: status,\n playbackOffset: parseInt(playbackOffset, 10),\n };\n }\n\n /**\n * Attempts to establish a new outgoing connection on a channel, and then link it to the calling input channel.\n *\n * **Important:** This method is blocking. It only returns when the call ends completely:\n * - If answered: returns after either party hangs up\n * - If not answered: returns after timeout expires\n * - If busy/unavailable: returns immediately\n *\n * @param target - The dial target (e.g., \"PJSIP/1000\", \"PJSIP/alice&PJSIP/bob\")\n * @param timeout - Ring timeout in seconds (default: 30)\n * @param params - Optional Dial parameters (e.g., \"m\" for music on hold, \"t\" for transfer)\n * @returns The dial status indicating how the call ended\n * @throws Error if an unknown dial status is returned\n *\n * @example\n * ```typescript\n * const status = await channel.dial('PJSIP/1000', 30, 'm');\n * if (status === DialStatus.ANSWER) {\n * console.log('Call was answered and has now ended');\n * } else if (status === DialStatus.BUSY) {\n * console.log('Destination was busy');\n * }\n * ```\n *\n * @see https://docs.asterisk.org/Asterisk_22_Documentation/API_Documentation/Dialplan_Applications/Dial\n */\n public async dial(\n target: string,\n timeout: number = 30,\n params?: string\n ): Promise<DialStatus> {\n // Note: exec('Dial') blocks until the call ends (bridge is destroyed or dial fails)\n await this.exec('Dial', format('%s,%s,%s', target, timeout, params || ''));\n\n const dialstatus = await this.getVariable('DIALSTATUS');\n\n switch (dialstatus.toUpperCase()) {\n case 'ANSWER':\n return DialStatus.ANSWER;\n case 'BUSY':\n return DialStatus.BUSY;\n case 'NOANSWER':\n return DialStatus.NOANSWER;\n case 'CANCEL':\n return DialStatus.CANCEL;\n case 'CONGESTION':\n return DialStatus.CONGESTION;\n case 'CHANUNAVAIL':\n return DialStatus.CHANUNAVAIL;\n case 'DONTCALL':\n return DialStatus.DONTCALL;\n case 'TORTURE':\n return DialStatus.TORTURE;\n case 'INVALIDARGS':\n return DialStatus.INVALIDARGS;\n default:\n throw new Error('Unknown dial status');\n }\n }\n\n /**\n * Deletes an entry in the Asterisk database for a given family and key.\n * @param family\n * @param key\n */\n public async databaseDel(family: string, key: string): Promise<void> {\n const response = await this.sendCommand(\n format('DATABASE DEL %s %s', family, key)\n );\n\n if (response.code !== 200 || response.result === 0) {\n throw new Error('Could not delete from the database');\n }\n }\n\n /**\n * Deletes a family or specific keytree within a family in the Asterisk database.\n * @param family\n * @param keyTree\n */\n public async databaseDelTree(\n family: string,\n keyTree?: string\n ): Promise<boolean> {\n const response = await this.sendCommand(\n format('DATABASE DELTREE %s %s', family, keyTree || '')\n );\n\n if (response.code !== 200) {\n throw new Error('Could not delete tree from database');\n }\n\n return response.result === 0;\n }\n\n /**\n * Retrieves an entry in the Asterisk database for a given family and key.\n * @param family\n * @param key\n */\n public async databaseGet(family: string, key: string): Promise<string> {\n const response = await this.sendCommand(\n format('DATABASE GET %s %s', family, key)\n );\n\n if (response.code !== 200 || response.result === 0) {\n throw new Error('Database key not set');\n }\n\n return response.arguments.nokey();\n }\n\n /**\n * Adds or updates an entry in the Asterisk database for a given family, key, and value.\n * @param family\n * @param key\n * @param value\n */\n public async databasePut(\n family: string,\n key: string,\n value: string\n ): Promise<string> {\n const response = await this.sendCommand(\n format('DATABASE PUT %s %s %s', family, key, value)\n );\n\n if (response.code !== 200 || response.result === 0) {\n throw new Error('Database key not set');\n }\n\n return response.arguments.string('value');\n }\n\n /**\n * Executes application with given options\n * @param application The application to execute (e.g., 'Dial', 'Playback')\n * @param args Application arguments\n * @param commandTimeout Optional timeout in milliseconds (default: 6 hours for EXEC, use Infinity for no timeout)\n */\n public async exec(\n application: string,\n args: string,\n commandTimeout?: number\n ): Promise<number> {\n const response = await this.sendCommand(\n format('EXEC %s %s', application, args),\n commandTimeout\n );\n\n if (response.code !== 200 || response.result === -2) {\n throw new Error('Could not execute application');\n }\n\n return response.result;\n }\n\n /**\n * Stream the given file, and receive DTMF data with inter-digit timeout support.\n * @param soundFile The audio file to play\n * @param timeout Total timeout in milliseconds for digit collection AFTER audio finishes (default: 5000ms)\n * @param maxDigits Maximum number of digits to collect\n * @param interDigitTimeout Timeout between digits in milliseconds. If provided, enables digit-by-digit collection with inter-digit timeout.\n */\n public async getData(\n soundFile: string,\n timeout: number = 5000,\n maxDigits?: number,\n interDigitTimeout?: number\n ): Promise<{ digits: string; timeout: boolean }> {\n // If maxDigits is specified and interDigitTimeout is provided, use digit-by-digit collection\n if (maxDigits && maxDigits > 1 && interDigitTimeout) {\n return this.getDataWithInterDigitTimeout(soundFile, timeout, maxDigits, interDigitTimeout);\n }\n\n // Use standard GET DATA for simple cases\n const command = maxDigits !== undefined\n ? format('GET DATA %s %s %s', soundFile, timeout, maxDigits)\n : format('GET DATA %s %s', soundFile, timeout);\n\n const response = await this.sendCommand(command);\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not get data from channel');\n }\n\n return {\n digits: response.arguments.string('result'),\n timeout: response.arguments.string('value') === '(timeout)',\n };\n }\n\n /**\n * Internal method to collect digits with inter-digit timeout support\n * @param soundFile The audio file to play\n * @param totalTimeout Total timeout in milliseconds\n * @param maxDigits Maximum number of digits to collect\n * @param interDigitTimeout Timeout between digits in milliseconds\n */\n private async getDataWithInterDigitTimeout(\n soundFile: string,\n totalTimeout: number,\n maxDigits: number,\n interDigitTimeout: number\n ): Promise<{ digits: string; timeout: boolean }> {\n let collectedDigits = '';\n\n // Play the sound file first, allowing any digit to interrupt\n try {\n // Use STREAM FILE directly instead of streamFile() to avoid PLAYBACKSTATUS check\n const response = await this.sendCommand(\n format('STREAM FILE %s \"%s\"', soundFile, '0123456789*#')\n );\n\n if (response.code === 200 && response.result !== -1) {\n const digit = response.arguments.char('result');\n\n // If user pressed a digit during playback, collect it\n if (digit) {\n collectedDigits += digit;\n\n // If we already have max digits, return immediately\n if (collectedDigits.length === maxDigits) {\n return { digits: collectedDigits, timeout: false };\n }\n }\n }\n } catch (error) {\n // Continue even if file fails to play\n }\n\n // Start timing AFTER audio finishes - totalTimeout only applies to digit collection\n const startTime = Date.now();\n\n // Collect remaining digits one by one with inter-digit timeout\n while (collectedDigits.length < maxDigits) {\n const elapsedTime = Date.now() - startTime;\n const remainingTotalTimeout = totalTimeout - elapsedTime;\n\n if (remainingTotalTimeout <= 0) {\n return { digits: collectedDigits, timeout: collectedDigits.length === 0 };\n }\n\n // For the first digit, use totalTimeout. For subsequent digits, use interDigitTimeout\n const timeoutToUse = collectedDigits.length === 0\n ? remainingTotalTimeout\n : Math.min(interDigitTimeout, remainingTotalTimeout);\n\n try {\n // Convert milliseconds to seconds for waitForDigit\n const digit = await this.waitForDigit(timeoutToUse / 1000);\n\n if (!digit) {\n // Timeout waiting for digit\n return { digits: collectedDigits, timeout: collectedDigits.length === 0 };\n }\n\n collectedDigits += digit;\n\n if (collectedDigits.length === maxDigits) {\n return { digits: collectedDigits, timeout: false };\n }\n } catch (error) {\n return { digits: collectedDigits, timeout: true };\n }\n }\n\n return { digits: collectedDigits, timeout: false };\n }\n\n /**\n * Evaluates a channel expression\n * Understands complex variable names and builtin variables, unlike GET VARIABLE.\n * @param key\n * @param channel\n */\n public async getFullVariable(key: string, channel?: string): Promise<string> {\n const response = await this.sendCommand(\n format('GET FULL VARIABLE %s %s', key.toUpperCase(), channel || '')\n );\n\n if (response.code !== 200 || response.result === 0) {\n throw new Error('Variable not set');\n }\n\n return response.arguments.nokey();\n }\n\n /**\n * Stream file, prompt for DTMF, with timeout.\n * Behaves similar to STREAM FILE but used with a timeout option.\n * @param soundFile\n * @param escapeDigits\n * @param timeout\n */\n public async getOption(\n soundFile: string,\n escapeDigits: string = '#',\n timeout: number = 5\n ): Promise<{ digit: string; endpos: number }> {\n const response = await this.sendCommand(\n format('GET OPTION %s \"%s\" %s', soundFile, escapeDigits, timeout * 1000)\n );\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not get option');\n }\n\n if (response.arguments.number('endpos') === 0) {\n throw new Error('Could Not play file');\n }\n\n return {\n digit: response.arguments.char('result'),\n endpos: response.arguments.number('endpos'),\n };\n }\n\n /**\n * Gets a channel variable.\n * @param key\n */\n public async getVariable(key: string): Promise<string> {\n const response = await this.sendCommand(\n format('GET VARIABLE %s', key.toUpperCase())\n );\n\n if (response.code !== 200 || response.result === 0) {\n throw new Error('Variable not set');\n }\n\n return response.arguments.nokey();\n }\n\n /**\n * Cause the channel to execute the specified dialplan subroutine.\n * @param context\n * @param extension\n * @param priority\n * @param argument\n */\n public async goSub(\n context: string,\n extension: string,\n priority: number,\n argument?: string\n ): Promise<void> {\n const response = await this.sendCommand(\n format('GOSUB %s %s %s %s', context, extension, priority, argument || '')\n );\n\n if (response.code !== 200 || response.result !== 0) {\n throw new Error('Could not execute gosub');\n }\n }\n\n /**\n * Hangs up the specified channel. If no channel name is given, hangs up the current channel\n * @param channel\n */\n public async hangup(channel?: string): Promise<void> {\n const response = await this.sendCommand(format('HANGUP %s', channel || ''));\n\n if (response.code !== 200 || response.result !== 1) {\n throw new Error('Could not hang up call');\n }\n }\n\n /**\n * Does nothing\n */\n public async noop(): Promise<void> {\n const response = await this.sendCommand('NOOP');\n\n if (response.code !== 200 || response.result !== 0) {\n throw new Error('Could not NOOP');\n }\n }\n\n /**\n * Receives one character from channels supporting it.\n * @param timeout\n */\n public async receiveChar(\n timeout: number = 5\n ): Promise<{ char: string; timeout: boolean }> {\n const response = await this.sendCommand(\n format('RECEIVE CHAR %s', timeout * 1000)\n );\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not get data from channel');\n }\n\n return {\n char: response.arguments.char('result'),\n timeout: response.arguments.boolean('timeout'),\n };\n }\n\n /**\n * Receives text from channels supporting it.\n * @param timeout\n */\n public async receiveText(timeout: number = 5): Promise<string> {\n const response = await this.sendCommand(\n format('RECEIVE TEXT %s', timeout * 1000)\n );\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not get data from channel');\n }\n\n return response.arguments.string('result');\n }\n\n /**\n * Records to a given file.\n * @param filename\n * @param fileFormat\n * @param escapeDigits\n * @param timeout\n * @param beep\n * @param silence\n * @param offsetSamples\n */\n public async recordFile(\n filename: string,\n fileFormat: string = 'gsm',\n escapeDigits: string = '#',\n timeout: number = 10,\n beep?: boolean,\n silence?: number,\n offsetSamples?: number\n ): Promise<{ digit: string; endpos: number; timeout: boolean }> {\n const response = await this.sendCommand(\n format(\n 'RECORD FILE %s %s \"%s\" %s %s %s %s',\n filename,\n fileFormat,\n escapeDigits,\n timeout * 1000,\n offsetSamples || '',\n beep ? 'BEEP' : '',\n silence ? format('s=%s', silence) : ''\n )\n );\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not record file');\n }\n\n return {\n digit: response.arguments.char('result'),\n endpos: response.arguments.number('endpos'),\n timeout: response.arguments.boolean('timeout'),\n };\n }\n\n /**\n * Says a given character string.\n * @param value\n * @param escapeDigits\n */\n public async sayAlpha(\n value: string,\n escapeDigits: string = '#'\n ): Promise<string> {\n const response = await this.sendCommand(\n format('SAY ALPHA %s \"%s\"', value, escapeDigits)\n );\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not say alpha');\n }\n\n return response.arguments.char('result');\n }\n\n /**\n * Says a given date.\n * @param value\n * @param escapeDigits\n */\n public async sayDate(\n value: Date | number,\n escapeDigits: string = '#'\n ): Promise<string> {\n const response = await this.sendCommand(\n format(\n 'SAY DATE %s \"%s\"',\n typeof value === 'number' ? value : Math.floor(value.getTime() / 1000),\n escapeDigits\n )\n );\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not say date');\n }\n\n return response.arguments.char('result');\n }\n\n /**\n * Says a given time as specified by the format given.\n * @param value\n * @param escapeDigits\n * @param dateFormat\n * @param timezone\n */\n public async sayDateTime(\n value: Date | number,\n escapeDigits: string = '#',\n dateFormat?: string,\n timezone?: string\n ): Promise<string> {\n const response = await this.sendCommand(\n format(\n 'SAY DATETIME %s \"%s\" %s %s',\n typeof value === 'number' ? value : Math.floor(value.getTime() / 1000),\n escapeDigits,\n dateFormat || '',\n timezone || ''\n )\n );\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not say date time');\n }\n\n return response.arguments.char('result');\n }\n\n /**\n * Says a given digit string.\n * @param value\n * @param escapeDigits\n */\n public async sayDigits(\n value: string,\n escapeDigits: string = '#'\n ): Promise<string> {\n const response = await this.sendCommand(\n format('SAY DIGITS %s \"%s\"', value, escapeDigits)\n );\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not say digits');\n }\n\n return response.arguments.char('result');\n }\n\n /**\n * Says a given number.\n * @param value\n * @param escapeDigits\n */\n public async sayNumber(\n value: number,\n escapeDigits: string = '#'\n ): Promise<string> {\n const response = await this.sendCommand(\n format('SAY NUMBER %s \"%s\"', value, escapeDigits)\n );\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not say number');\n }\n\n return response.arguments.char('result');\n }\n\n /**\n * Says a given character string with phonetics.\n * @param value\n * @param escapeDigits\n */\n public async sayPhonetic(\n value: string,\n escapeDigits: string = '#'\n ): Promise<string> {\n const response = await this.sendCommand(\n format('SAY PHONETIC %s \"%s\"', value, escapeDigits)\n );\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not say phonetic');\n }\n\n return response.arguments.char('result');\n }\n\n /**\n * Says a given time.\n * @param value\n * @param escapeDigits\n */\n public async sayTime(\n value: Date | number,\n escapeDigits: string = '#'\n ): Promise<string> {\n const response = await this.sendCommand(\n format(\n 'SAY TIME %s \"%s\"',\n typeof value === 'number' ? value : Math.floor(value.getTime() / 1000),\n escapeDigits\n )\n );\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not say time');\n }\n\n return response.arguments.char('result');\n }\n\n /**\n * Sends images to channels supporting it.\n * @param image\n */\n public async sendImage(image: string): Promise<void> {\n const response = await this.sendCommand(format('SEND IMAGE %s', image));\n\n if (response.code !== 200 || response.result !== 0) {\n throw new Error('Could not send image');\n }\n }\n\n /**\n * Sends text to channels supporting it.\n * @param text\n */\n public async sendText(text: string): Promise<void> {\n const response = await this.sendCommand(format('SEND TEXT \"%s\"', text));\n\n if (response.code !== 200 || response.result !== 0) {\n throw new Error('Could not send text');\n }\n }\n\n /**\n * Autohangup channel in some time.\n * @param timeout\n */\n public async setAutoHangup(timeout: number = 60): Promise<void> {\n const response = await this.sendCommand(\n format('SET AUTOHANGUP %s', timeout)\n );\n\n if (response.code !== 200 || response.result !== 0) {\n throw new Error('Could not set auto hangup');\n }\n }\n\n /**\n * Sets callerid for the current channel.\n * @param callerNumber\n * @param callerName\n */\n public async setCallerID(\n callerNumber: number,\n callerName?: string\n ): Promise<void> {\n const callerid = callerName\n ? format('\"%s\"<%s>', callerName, callerNumber)\n : callerNumber;\n\n const response = await this.sendCommand(\n format('SET CALLERID %s', callerid)\n );\n\n if (response.code !== 200 || response.result !== 1) {\n throw new Error('Could not set caller id');\n }\n }\n\n /**\n * Sets channel context.\n * @param context\n */\n public async setContext(context: string): Promise<void> {\n const response = await this.sendCommand(format('SET CONTEXT %s', context));\n\n if (response.code !== 200 || response.result !== 0) {\n throw new Error('Could not set context');\n }\n }\n\n /**\n * Changes channel extension.\n * @param extension\n */\n public async setExtension(extension: string): Promise<void> {\n const response = await this.sendCommand(\n format('SET EXTENSION %s', extension)\n );\n\n if (response.code !== 200 || response.result !== 0) {\n throw new Error('Could not set extension');\n }\n }\n\n /**\n * Enable/Disable Music on hold generator\n * @param status\n * @param musicClass\n */\n public async setMusic(\n status: boolean = true,\n musicClass?: string\n ): Promise<void> {\n const response = await this.sendCommand(\n format('SET MUSIC %s %s', status ? 'ON' : 'OFF', musicClass || '')\n );\n\n if (response.code !== 200 || response.result !== 0) {\n throw new Error('Could not set priority');\n }\n }\n\n /**\n * Set channel dialplan priority.\n * @param priority\n */\n public async setPriority(priority: number): Promise<void> {\n const response = await this.sendCommand(\n format('SET PRIORITY %s', priority)\n );\n\n if (response.code !== 200 || response.result !== 0) {\n throw new Error('Could not set priority');\n }\n }\n\n /**\n * Sets a channel variable.\n * @param key - The variable name\n * @param value - The variable value\n * @throws Error if the variable could not be set\n */\n public async setVariable(key: string, value: string): Promise<void> {\n const response = await this.sendCommand(\n format('SET VARIABLE %s \"%s\"', key.toUpperCase(), value)\n );\n\n if (response.code !== 200 || response.result !== 1) {\n throw new Error('Could not set variable');\n }\n }\n\n public async speechActivateGrammar(grammar: string): Promise<IResponse> {\n // TODO: Handle the response\n return this.sendCommand(format('SPEECH ACTIVATE GRAMMAR %s', grammar));\n }\n\n public async speechCreate(engine: string): Promise<IResponse> {\n // TODO: Handle the response\n return this.sendCommand(format('SPEECH CREATE ENGINE %s', engine));\n }\n\n public async speechDeactivateGrammar(grammar: string): Promise<IResponse> {\n // TODO: Handle the response\n return this.sendCommand(format('SPEECH DEACTIVATE GRAMMAR %s', grammar));\n }\n\n public async speechDestroy(): Promise<IResponse> {\n // TODO: Handle the response\n return this.sendCommand('SPEECH DESTROY');\n }\n\n public async speechLoadGrammar(\n grammar: string,\n path: string\n ): Promise<IResponse> {\n // TODO: Handle the response\n return this.sendCommand(format('SPEECH LOAD GRAMMAR %s %s', grammar, path));\n }\n\n public async speechRecognize(\n soundFile: string,\n timeout: number = 5,\n offset: number\n ): Promise<IResponse> {\n // TODO: Handle the response\n return this.sendCommand(\n format('SPEECH RECOGNIZE %s %s %s', soundFile, timeout * 1000, offset)\n );\n }\n\n public async speechSet(key: string, value: string): Promise<IResponse> {\n // TODO: Handle the response\n return this.sendCommand(format('SPEECH SET %s %s', key, value));\n }\n\n public async speedUnloadGrammar(grammar: string): Promise<IResponse> {\n // TODO: Handle the response\n return this.sendCommand(format('SPEECH UNLOAD GRAMMAR %s', grammar));\n }\n\n /**\n * Streams an audio file to the channel, allowing playback to be interrupted by DTMF digits.\n *\n * The file extension should not be included in the filename - Asterisk will automatically\n * select the best available format based on the channel's codec.\n *\n * @param filename - The audio file to play (without extension, e.g., \"welcome\" not \"welcome.wav\")\n * @param escapeDigits - DTMF digits that will interrupt playback (default: \"#\"). Use \"\" for none.\n * @param offset - Sample offset to start playback from (optional)\n * @returns Object containing:\n * - `digit`: The DTMF digit pressed to interrupt, or empty string if played to completion\n * - `endpos`: The sample position where playback stopped\n * @throws Error if the file could not be played or PLAYBACKSTATUS is not SUCCESS\n *\n * @example\n * ```typescript\n * // Play a file, allowing any digit to interrupt\n * const result = await channel.streamFile('welcome', '0123456789*#');\n * if (result.digit) {\n * console.log(`User pressed: ${result.digit}`);\n * }\n *\n * // Play a file without allowing interruption\n * await channel.streamFile('announcement', '');\n * ```\n *\n * @see https://docs.asterisk.org/Asterisk_22_Documentation/API_Documentation/AGI_Commands/stream_file\n */\n public async streamFile(\n filename: string,\n escapeDigits: string = '#',\n offset?: number\n ): Promise<{ digit: string; endpos: number }> {\n const response = await this.sendCommand(\n format('STREAM FILE %s \"%s\" %s', filename, escapeDigits, offset || '')\n );\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not stream file');\n }\n\n const status = await this.getVariable('PLAYBACKSTATUS');\n\n if (status !== 'SUCCESS') {\n throw new Error('Could not stream file');\n }\n\n return {\n digit: response.arguments.char('result'),\n endpos: response.arguments.number('endpos'),\n };\n }\n\n /**\n * Toggles TDD mode (for the deaf).\n * @param status\n */\n public async tddMode(status: boolean): Promise<void> {\n const response = await this.sendCommand(\n format('TDD MODE %s', status ? 'ON' : 'OFF')\n );\n\n if (response.code !== 200 || response.result !== 1) {\n throw new Error('Could not set TDD mode');\n }\n }\n\n /**\n * Logs a message to the asterisk verbose log.\n * @param message\n * @param level\n */\n public async verbose(message: string, level?: number): Promise<void> {\n const response = await this.sendCommand(\n format('VERBOSE \"%s\" %s', message, level || '')\n );\n\n if (response.code !== 200 || response.result !== 1) {\n throw new Error('Could not send logging message');\n }\n }\n\n /**\n * Waits for a digit to be pressed.\n * @param timeout Timeout in seconds\n */\n public async waitForDigit(timeout: number = 5): Promise<string> {\n // Convert timeout from seconds to milliseconds and add 2s safety margin for network/processing latency\n const commandTimeout = (timeout * 1000) + 2000;\n\n const response = await this.sendCommand(\n format('WAIT FOR DIGIT %s', timeout * 1000),\n commandTimeout\n );\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not wait for digit');\n }\n\n return response.arguments.char('result');\n }\n\n /* Internal Methods */\n\n private close() {\n this.m_connection.destroy();\n }\n\n private read(data: Buffer): void {\n if (data.length === 0) {\n return;\n }\n\n this.m_message += data.toString();\n\n if (this.m_state === ContextState.INIT) {\n if (this.m_message.indexOf('\\n\\n') === -1) {\n return;\n }\n\n this.readVariables(this.m_message);\n } else if (this.m_state === ContextState.WAITING) {\n if (this.m_message.indexOf('\\n') === -1) {\n return;\n }\n\n this.readResponse(this.m_message);\n }\n\n this.m_message = '';\n }\n\n private readVariables(message: string) {\n const lines = message.split('\\n');\n\n lines.map((line) => {\n const split = line.split(':');\n const name: string = (split[0] || '').trim();\n const value: string = (split[1] || '').trim();\n\n const id = name.substring(4);\n\n switch (id) {\n case 'network':\n return (this.m_network = value);\n case 'network_script':\n return (this.m_network_script = value);\n case 'request':\n return (this.m_request = value);\n case 'channel':\n return (this.m_channel = value);\n case 'language':\n return (this.m_language = value);\n case 'type':\n return (this.m_type = value);\n case 'uniqueid':\n return (this.m_uniqueid = value);\n case 'version':\n return (this.m_version = value);\n case 'callerid':\n return (this.m_callerid = value);\n case 'calleridname':\n return (this.m_calleridname = value);\n case 'callingpres':\n return (this.m_callingpres = value);\n case 'callingani2':\n return (this.m_callingani2 = value);\n case 'callington':\n return (this.m_callington = value);\n case 'callingtns':\n return (this.m_callingtns = value);\n case 'dnid':\n return (this.m_dnid = value);\n case 'rdnis':\n return (this.m_rdnis = value);\n case 'context':\n return (this.m_context = value);\n case 'extension':\n return (this.m_extension = value);\n case 'priority':\n return (this.m_priority = value);\n case 'enhanced':\n return (this.m_enhanced = value);\n case 'accountcode':\n return (this.m_accountcode = value);\n case 'threadid':\n return (this.m_threadid = value);\n }\n });\n\n this.m_state = ContextState.WAITING;\n\n this.emit('ready');\n }\n\n private readResponse(message: string) {\n const lines = message.split('\\n');\n\n lines.map((line) => this.readResponseLine(line));\n }\n\n private readResponseLine(line: string) {\n if (!line) {\n return;\n }\n\n this.emit('recv', line);\n\n const parsed = line.split(' ');\n\n if (!parsed || parsed[0] === 'HANGUP') {\n return this.emit('hangup');\n }\n\n const code = parseInt(parsed[0], 10);\n parsed.shift();\n\n const args: ResponseArguments = new ResponseArguments();\n\n for (const value of parsed) {\n if (value.indexOf('=') !== -1) {\n const parts = value.split('=', 2);\n const key = parts[0].trim();\n const val = parts[1].trim();\n args.addArgument(key, val);\n } else if (value.indexOf('(') !== -1) {\n const name = value.substring(1, value.length - 1);\n args.addArgument(name, true);\n } else {\n args.addArgument('value', value);\n }\n }\n\n const response: IResponse = {\n code: code,\n result: args.number('result'),\n arguments: args,\n };\n\n this.emit('response', response);\n }\n\n private async send(message: string): Promise<void> {\n return new Promise((resolve, reject) => {\n if (!this.m_connection || this.m_connection.destroyed) {\n return reject(new Error('Stream has been destroyed'));\n }\n this.emit('send', message);\n this.m_connection.write(message, (error) => {\n if (error) {\n return reject(error);\n }\n resolve();\n });\n });\n }\n\n /**\n * Sends an AGI command and waits for response using a FIFO queue\n * @param command AGI command to send\n * @param timeout Optional timeout in milliseconds (default: 10000ms)\n */\n private async sendCommand(\n command: string,\n timeout?: number\n ): Promise<IResponse> {\n return new Promise((resolve, reject) => {\n // Check if channel is still alive\n if (!this.channelAlive) {\n return reject(new Error('Channel is no longer alive'));\n }\n\n // Check queue size limit (backpressure)\n if (this.commandQueue.length >= this.maxQueueSize) {\n return reject(\n new Error(\n `Command queue full (${this.maxQueueSize}). Command rejected: ${command}`\n )\n );\n }\n\n // Add command to queue\n const queuedCommand: IQueuedCommand = {\n command,\n resolve,\n reject,\n timeout: timeout ?? this.getCommandTimeout(command),\n timestamp: Date.now(),\n };\n\n this.commandQueue.push(queuedCommand);\n\n // Emit event for monitoring\n this.emit('commandQueued', {\n command,\n queueSize: this.commandQueue.length,\n });\n\n // Start processing if not active\n if (!this.isProcessingCommand) {\n this.processCommandQueue();\n }\n });\n }\n\n /**\n * Gets the appropriate timeout for a given command\n * @param command The AGI command string\n * @returns Timeout in milliseconds (or Infinity for no timeout)\n */\n private getCommandTimeout(command: string): number {\n // Comandos r\u00E1pidos (devem responder em segundos)\n if (\n command.startsWith('ANSWER') ||\n command.startsWith('HANGUP') ||\n command.startsWith('CHANNEL STATUS') ||\n command.startsWith('GET VARIABLE') ||\n command.startsWith('SET VARIABLE') ||\n command.startsWith('DATABASE')\n ) {\n return 10000; // 10 segundos\n }\n\n // Comandos m\u00E9dios (audio playback, prompts)\n if (\n command.startsWith('STREAM FILE') ||\n command.startsWith('SAY ') ||\n command.startsWith('GET DATA') ||\n command.startsWith('GET OPTION')\n ) {\n return 60000; // 1 minuto\n }\n\n // Comandos de grava\u00E7\u00E3o\n if (command.startsWith('RECORD FILE')) {\n return 600000; // 10 minutos\n }\n\n // EXEC: pode incluir Dial, Queue, VoiceMail (podem durar horas)\n if (command.startsWith('EXEC')) {\n return this.maxCallDuration; // 6 horas padr\u00E3o\n }\n\n // Outros comandos\n return this.defaultCommandTimeout; // 10 segundos\n }\n\n /**\n * Processes the command queue sequentially (FIFO)\n */\n private async processCommandQueue(): Promise<void> {\n if (this.commandQueue.length === 0) {\n this.isProcessingCommand = false;\n this.emit('queueEmpty');\n return;\n }\n\n this.isProcessingCommand = true;\n const queuedCommand = this.commandQueue.shift()!;\n\n try {\n const response = await this.sendCommandInternal(\n queuedCommand.command,\n queuedCommand.timeout!\n );\n\n // Emit success event\n this.emit('commandProcessed', {\n command: queuedCommand.command,\n duration: Date.now() - queuedCommand.timestamp,\n });\n\n queuedCommand.resolve(response);\n } catch (err) {\n // Emit error event\n this.emit('commandFailed', {\n command: queuedCommand.command,\n error: err,\n });\n\n queuedCommand.reject(err);\n } finally {\n // Process next command (continues even with error)\n setImmediate(() => this.processCommandQueue());\n }\n }\n\n /**\n * Internal implementation of command sending\n * @param command The AGI command to send\n * @param timeout Timeout in milliseconds, or Infinity for no timeout\n */\n private sendCommandInternal(\n command: string,\n timeout: number\n ): Promise<IResponse> {\n return new Promise((resolve, reject) => {\n // Check connection state and channel status\n if (\n !this.channelAlive ||\n !this.m_connection ||\n this.m_connection.destroyed\n ) {\n return reject(new Error('Channel is no longer alive'));\n }\n\n let timeoutId: NodeJS.Timeout | null = null;\n\n const responseHandler = (response: IResponse) => {\n cleanup();\n resolve(response);\n };\n\n const cleanup = () => {\n this.removeListener('response', responseHandler);\n if (timeoutId) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n };\n\n // Register listener\n this.once('response', responseHandler);\n\n // Configurable timeout (supports Infinity for no timeout)\n if (timeout > 0 && timeout !== Infinity) {\n timeoutId = setTimeout(() => {\n cleanup();\n reject(new Error(`Command timeout after ${timeout}ms: ${command}`));\n }, timeout);\n }\n // If timeout is Infinity or <= 0, no timeout is set (relies on channelAlive)\n\n // Send command\n this.send(format('%s\\n', command.trim())).catch((err) => {\n cleanup();\n reject(err);\n });\n });\n }\n\n /**\n * Handles channel closure with pending commands\n */\n private handleChannelClose(): void {\n this.channelAlive = false;\n const pendingCount = this.commandQueue.length;\n\n if (pendingCount > 0) {\n this.emit('queueCleared', {\n reason: 'channel_closed',\n commandsCleared: pendingCount,\n });\n\n // Reject all pending commands\n while (this.commandQueue.length > 0) {\n const cmd = this.commandQueue.shift()!;\n cmd.reject(new Error('Channel closed before command could be sent'));\n }\n }\n\n this.isProcessingCommand = false;\n }\n\n /**\n * Handles HANGUP from Asterisk\n */\n private handleHangup(): void {\n this.channelAlive = false;\n const pendingCount = this.commandQueue.length;\n\n if (pendingCount > 0) {\n this.emit('queueCleared', {\n reason: 'hangup',\n commandsCleared: pendingCount,\n });\n\n // Reject pending commands\n while (this.commandQueue.length > 0) {\n const cmd = this.commandQueue.shift()!;\n cmd.reject(new Error('Call hung up before command could be executed'));\n }\n }\n\n this.isProcessingCommand = false;\n }\n\n /**\n * Manually clears the command queue (for emergency cases)\n */\n public clearCommandQueue(): number {\n const clearedCount = this.commandQueue.length;\n\n while (this.commandQueue.length > 0) {\n const cmd = this.commandQueue.shift()!;\n cmd.reject(new Error('Command queue manually cleared'));\n }\n\n this.isProcessingCommand = false;\n\n this.emit('queueCleared', {\n reason: 'manual',\n commandsCleared: clearedCount,\n });\n\n return clearedCount;\n }\n\n /**\n * Returns queue statistics\n */\n public getQueueStats(): {\n size: number;\n isProcessing: boolean;\n oldestCommandAge: number | null;\n } {\n const oldest = this.commandQueue[0];\n\n return {\n size: this.commandQueue.length,\n isProcessing: this.isProcessingCommand,\n oldestCommandAge: oldest ? Date.now() - oldest.timestamp : null,\n };\n }\n}\n", "// Copyright (c) 2020, Brandon Lehmann\n//\n// Please see the included LICENSE file for more information.\n\n/** @ignore */\nexport interface IResponseArguments {\n key: string;\n value: string | number | boolean;\n}\n\n/**\n * Represents a set of AGI response arguments\n * @ignore\n */\nexport class ResponseArguments {\n private m_args: IResponseArguments[] = [];\n\n /**\n * Adds a new argument to the set\n * @param key\n * @param value\n */\n public addArgument(key: string, value: string | number | boolean) {\n this.m_args.push({key, value});\n }\n\n /**\n * Retrieves the requested key as a string\n * @param key\n */\n public string(key: string): string {\n for (const arg of this.m_args) {\n if (arg.key === key) {\n return (arg.value as string);\n }\n }\n\n return '';\n }\n\n /**\n * Retrieves the requested key as a number\n * @param key\n */\n public number(key: string): number {\n for (const arg of this.m_args) {\n if (arg.key === key) {\n return parseInt((arg.value as string), 10);\n }\n }\n\n return 0;\n }\n\n /**\n * Retrieves the request key as a boolean\n * @param key\n */\n public boolean(key: string): boolean {\n for (const arg of this.m_args) {\n if (arg.key === key) {\n return (arg.value as boolean);\n }\n }\n\n return false;\n }\n\n /**\n * Retrieves the requested key from a character code\n * @param key\n */\n public char(key: string): string {\n const num = this.number(key);\n\n return (num !== 0) ? String.fromCharCode(num) : '';\n }\n\n /**\n * Retrieves the value from the arguments that has no key, if it exists\n */\n public nokey(): string {\n for (const arg of this.m_args) {\n if (arg.key !== 'result' && arg.value) {\n return arg.key;\n }\n }\n\n return '';\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["// Copyright (c) 2020, Brandon Lehmann\n//\n// Please see the included LICENSE file for more information.\n\nexport {AGIServer} from './AGIServer';\nexport {Channel, ChannelState, DialStatus, PlaybackStatus} from './Channel';\n", "// Copyright (c) 2020, Brandon Lehmann\n//\n// Please see the included LICENSE file for more information.\n\nimport * as net from 'net';\nimport {EventEmitter} from 'events';\nimport {Channel} from './Channel';\nimport {format} from 'util';\n\n/**\n * Represents an AGI server instance\n */\nexport class AGIServer extends EventEmitter {\n private readonly m_port: number;\n private readonly m_ip: string;\n private readonly m_server: net.Server = net.createServer();\n\n /**\n * Constructs a new instance of the object\n * @param port\n * @param ip\n */\n constructor(port: number = 3000, ip: string = '0.0.0.0') {\n super();\n this.setMaxListeners(10);\n\n this.m_port = port;\n this.m_ip = ip;\n\n this.m_server.on('connection', (socket: net.Socket) => {\n const channel = new Channel(socket);\n\n channel.on('ready', () => this.emit('channel', channel));\n });\n }\n\n /**\n * Event that is emitted when a new AGI channel has been established and is ready for interation\n * @param event\n * @param listener\n */\n public on(event: 'channel', listener: (channel: Channel) => void): this;\n\n /**\n * Event that is emitted when the AGI server is started and in a listening state\n * @param event\n * @param listener\n */\n public on(event: 'listening', listener: (port: number, ip: string) => void): this;\n\n /**\n * Event that is emitted when the server encounters and error\n * @param event\n * @param listener\n */\n public on(event: 'error', listener: (error: any) => void): this;\n\n /**\n * Event that emitted when the server is closed and stopped\n * @param event\n * @param listener\n */\n public on(event: 'close', listener: () => void): this;\n\n public on(event: any, listener: (...args: any[]) => void): this {\n return super.on(event, listener);\n }\n\n /**\n * Starts the AGI server\n */\n public async start(): Promise<void> {\n this.m_server.on('error', (error) =>\n this.emit('error', new Error(\n format('Internal TCP server error: %s', error.toString()),\n )),\n );\n\n this.m_server.on('close', () => this.emit('close'));\n\n this.m_server.listen(this.m_port, this.m_ip, () => {\n this.emit('listening', this.m_port, this.m_ip);\n });\n }\n\n /**\n * Stops the AGI server\n */\n public async stop(): Promise<void> {\n return new Promise((resolve, reject) => {\n this.m_server.close((error) => {\n if (error) {\n return reject(error);\n }\n return resolve();\n });\n });\n }\n}\n", "// Copyright (c) 2020, Brandon Lehmann\n//\n// Please see the included LICENSE file for more information.\n\nimport { EventEmitter } from 'node:events';\nimport type { Socket } from 'node:net';\nimport { format } from 'node:util';\nimport { ResponseArguments } from './ResponseArguments';\n\n/** @ignore */\nenum ContextState {\n INIT = 0,\n WAITING = 2,\n}\n\n/**\n * Represents the current channel state\n */\nexport enum ChannelState {\n DOWN_AVAILABLE = 0,\n DOWN_RESERVED,\n OFF_HOOK,\n DIGITS_DIALED,\n RINGING,\n REMOTE_RINGING,\n UP,\n BUSY,\n}\n\n/**\n * Represents the result of a Dial() attempt\n */\nexport enum DialStatus {\n ANSWER,\n BUSY,\n NOANSWER,\n CANCEL,\n CONGESTION,\n CHANUNAVAIL,\n DONTCALL,\n TORTURE,\n INVALIDARGS,\n}\n\n/**\n * Represents the playback status\n */\nexport enum PlaybackStatus {\n SUCCESS,\n USER_STOPPED,\n REMOTE_STOPPED,\n ERROR,\n}\n\n/** @ignore */\ninterface IResponse {\n code: number;\n result: number;\n arguments: ResponseArguments;\n}\n\n/** @ignore */\ninterface IQueuedCommand {\n command: string;\n resolve: (value: IResponse) => void;\n reject: (reason: any) => void;\n timeout?: number;\n timestamp: number;\n}\n\n/**\n * Represents an AGI Channel\n */\nexport class Channel extends EventEmitter {\n private readonly m_connection: Socket;\n private m_state: ContextState;\n private m_message: string = '';\n private m_network: string = '';\n private m_network_script: string = '';\n private m_request: string = '';\n private m_channel: string = '';\n private m_language: string = '';\n private m_type: string = '';\n private m_uniqueid: string = '';\n private m_version: string = '';\n private m_callerid: string = '';\n private m_calleridname: string = '';\n private m_callingpres: string = '';\n private m_callingani2: string = '';\n private m_callington: string = '';\n private m_callingtns: string = '';\n private m_dnid: string = '';\n private m_rdnis: string = '';\n private m_context: string = '';\n private m_extension: string = '';\n private m_priority: string = '';\n private m_enhanced: string = '';\n private m_accountcode: string = '';\n private m_threadid: string = '';\n private commandQueue: IQueuedCommand[] = [];\n private isProcessingCommand = false;\n private channelAlive = true;\n private readonly maxQueueSize = 100;\n private readonly defaultCommandTimeout = 10000;\n private readonly maxCallDuration = 21600000; // 6 horas (360 minutos)\n\n /**\n * Creates a new instance of a channel object\n * @param connection the AGI socket connection\n */\n constructor(connection: Socket) {\n super();\n this.setMaxListeners(10);\n\n this.m_connection = connection;\n this.m_state = ContextState.INIT;\n\n this.m_connection.on('data', (data: Buffer) => this.read(data));\n this.m_connection.on('close', () => {\n this.handleChannelClose();\n this.emit('close');\n });\n this.m_connection.on('error', (error) => this.emit('error', error));\n this.m_connection.on('timeout', () => this.emit('timeout'));\n this.on('hangup', () => {\n this.handleHangup();\n this.close();\n });\n }\n\n /**\n * Event that is emitted when the underlying socket encounters an error\n * @param event\n * @param listener\n */\n public on(event: 'error', listener: (error: any) => void): this;\n\n /**\n * Event that is emitted when the underlying socket is closed\n * @param event\n * @param listener\n */\n public on(event: 'close', listener: () => void): this;\n\n /**\n * Event that emitted when the underlying socket times out\n * @param event\n * @param listener\n */\n public on(event: 'timeout', listener: () => void): this;\n\n /**\n * Event that is emitted when the channel is ready\n * @param event\n * @param listener\n */\n public on(event: 'ready', listener: () => void): this;\n\n /**\n * Event that is emitted when a response is received from the Asterisk server\n * @param event\n * @param listener\n */\n public on(event: 'recv', listener: (response: string) => void): this;\n\n /**\n * Event that emitted when the channel is hung up\n * @param event\n * @param listener\n */\n public on(event: 'hangup', listener: () => void): this;\n\n /**\n * Event that emitted when the response from the Asterisk server is processed into a structured response\n * @param event\n * @param listener\n */\n public on(event: 'response', listener: (response: IResponse) => void): this;\n\n /**\n * Event that is emitted when data is sent to the Asterisk server\n * @param event\n * @param listener\n */\n public on(event: 'send', listener: (data: string) => void): this;\n\n public on(event: any, listener: (...args: any[]) => void): this {\n return super.on(event, listener);\n }\n\n /**\n * Whether this AGI request is over the network\n */\n public get network(): boolean {\n return this.m_network.toLowerCase() === 'yes';\n }\n\n /**\n * The network path included in the AGI request\n * ie. agi://127.0.0.1:3000/test\n * This value would return 'test'\n */\n public get network_script(): string {\n return this.m_network_script;\n }\n\n /**\n * The version of Asterisk\n */\n public get version(): string {\n return this.m_version;\n }\n\n /**\n * The filename of your script\n * ie. agi\n */\n public get request(): string {\n return this.m_request;\n }\n\n /**\n * The originating channel (your phone)\n */\n public get channel(): string {\n return this.m_channel;\n }\n\n /**\n * The language code (e.g. \u201Cen\u201D)\n */\n public get language(): string {\n return this.m_language;\n }\n\n /**\n * The originating channel type (e.g. \u201CSIP\u201D or \u201CZAP\u201D)\n */\n public get type(): string {\n return this.m_type;\n }\n\n /**\n * A unique ID for the call\n */\n public get uniqueid(): string {\n return this.m_uniqueid;\n }\n\n /**\n * The caller ID number (or \u201Cunknown\u201D)\n */\n public get callerid(): string {\n return this.m_callerid;\n }\n\n /**\n * The caller ID name (or \u201Cunknown\u201D)\n */\n public get calleridname(): string {\n return this.m_calleridname;\n }\n\n /**\n * The presentation for the callerid in a ZAP channel\n */\n public get callingpres(): string {\n return this.m_callingpres;\n }\n\n /**\n * The number which is defined in ANI2 see Asterisk Detailed Variable List (only for PRI Channels)\n */\n public get callingani2(): string {\n return this.m_callingani2;\n }\n\n /**\n * The type of number used in PRI Channels see Asterisk Detailed Variable List\n */\n public get callington(): string {\n return this.m_callington;\n }\n\n /**\n * An optional 4 digit number (Transit Network Selector) used in PRI Channels see Asterisk Detailed Variable List\n */\n public get callingtns(): string {\n return this.m_callingtns;\n }\n\n /**\n * The dialed number id (or \u201Cunknown\u201D)\n */\n public get dnid(): string {\n return this.m_dnid;\n }\n\n /**\n * The referring DNIS number (or \u201Cunknown\u201D)\n */\n public get rdnis(): string {\n return this.m_rdnis;\n }\n\n /**\n * Origin context in extensions.conf\n */\n public get context(): string {\n return this.m_context;\n }\n\n /**\n * The called number\n */\n public get extension(): string {\n return this.m_extension;\n }\n\n /**\n * The priority it was executed as in the dial plan\n */\n public get priority(): string {\n return this.m_priority;\n }\n\n /**\n * The flag value is 1.0 if started as an EAGI script, 0.0 otherwise\n */\n public get enhanced(): string {\n return this.m_enhanced;\n }\n\n /**\n * Account code of the origin channel\n */\n public get accountcode(): string {\n return this.m_accountcode;\n }\n\n /**\n * Thread ID of the AGI script\n */\n public get threadid(): string {\n return this.m_threadid;\n }\n\n /**\n * Answers channel if not already in answer state.\n */\n public async answer(): Promise<void> {\n const response = await this.sendCommand('ANSWER');\n\n if (response.code !== 200 || response.result !== 0) {\n throw new Error('Could not answer call');\n }\n }\n\n /**\n * Interrupts expected flow of Async AGI commands and returns control to\n * previous source (typically, the PBX dialplan).\n */\n public async break(): Promise<void> {\n const response = await this.sendCommand('ASYNCAGI BREAK');\n\n if (response.code !== 200 || response.result !== 0) {\n throw new Error('Could not interrupt processing');\n }\n\n return this.close();\n }\n\n /**\n * Returns status of the connected channel.\n * @param channel\n */\n public async channelStatus(channel?: string): Promise<ChannelState> {\n const response = await this.sendCommand(\n format('CHANNEL STATUS %s', channel || '')\n );\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not get channel status');\n }\n\n return response.result;\n }\n\n /**\n * Sends audio file on channel and allows the listener to control the stream.\n * @param filename\n * @param escapeDigits\n * @param skipms\n * @param fastForwardCharacter\n * @param rewindCharacter\n * @param pauseCharacter\n */\n public async controlStreamFile(\n filename: string,\n escapeDigits: string = '',\n skipms?: number,\n fastForwardCharacter?: string,\n rewindCharacter?: string,\n pauseCharacter?: string\n ): Promise<{\n digit: string;\n playbackStatus: PlaybackStatus;\n playbackOffset: number;\n }> {\n const response = await this.sendCommand(\n format(\n 'CONTROL STREAM FILE %s \"%s\" %s %s %s %s',\n filename,\n escapeDigits,\n skipms || '',\n fastForwardCharacter || '',\n rewindCharacter || '',\n pauseCharacter || ''\n )\n );\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not control stream file');\n }\n\n const playbackStatus = await this.getVariable('CPLAYBACKSTATUS ');\n\n const playbackOffset = await this.getVariable('CPLAYBACKOFFSET ');\n\n let status: PlaybackStatus = PlaybackStatus.ERROR;\n\n switch (playbackStatus.toUpperCase()) {\n case 'SUCCESS':\n status = PlaybackStatus.SUCCESS;\n break;\n case 'USERSTOPPED':\n status = PlaybackStatus.USER_STOPPED;\n break;\n case 'REMOTESTOPPED':\n status = PlaybackStatus.REMOTE_STOPPED;\n break;\n }\n\n return {\n digit: response.arguments.char('result'),\n playbackStatus: status,\n playbackOffset: parseInt(playbackOffset, 10),\n };\n }\n\n /**\n * Attempts to establish a new outgoing connection on a channel, and then link it to the calling input channel.\n *\n * **Important:** This method is blocking. It only returns when the call ends completely:\n * - If answered: returns after either party hangs up\n * - If not answered: returns after timeout expires\n * - If busy/unavailable: returns immediately\n *\n * @param target - The dial target (e.g., \"PJSIP/1000\", \"PJSIP/alice&PJSIP/bob\")\n * @param timeout - Ring timeout in seconds (default: 30)\n * @param params - Optional Dial parameters (e.g., \"m\" for music on hold, \"t\" for transfer)\n * @returns The dial status indicating how the call ended\n * @throws Error if an unknown dial status is returned\n *\n * @example\n * ```typescript\n * const status = await channel.dial('PJSIP/1000', 30, 'm');\n * if (status === DialStatus.ANSWER) {\n * console.log('Call was answered and has now ended');\n * } else if (status === DialStatus.BUSY) {\n * console.log('Destination was busy');\n * }\n * ```\n *\n * @see https://docs.asterisk.org/Asterisk_22_Documentation/API_Documentation/Dialplan_Applications/Dial\n */\n public async dial(\n target: string,\n timeout: number = 30,\n params?: string\n ): Promise<DialStatus> {\n // Note: exec('Dial') blocks until the call ends (bridge is destroyed or dial fails)\n await this.exec('Dial', format('%s,%s,%s', target, timeout, params || ''));\n\n const dialstatus = await this.getVariable('DIALSTATUS');\n\n switch (dialstatus.toUpperCase()) {\n case 'ANSWER':\n return DialStatus.ANSWER;\n case 'BUSY':\n return DialStatus.BUSY;\n case 'NOANSWER':\n return DialStatus.NOANSWER;\n case 'CANCEL':\n return DialStatus.CANCEL;\n case 'CONGESTION':\n return DialStatus.CONGESTION;\n case 'CHANUNAVAIL':\n return DialStatus.CHANUNAVAIL;\n case 'DONTCALL':\n return DialStatus.DONTCALL;\n case 'TORTURE':\n return DialStatus.TORTURE;\n case 'INVALIDARGS':\n return DialStatus.INVALIDARGS;\n default:\n throw new Error('Unknown dial status');\n }\n }\n\n /**\n * Deletes an entry in the Asterisk database for a given family and key.\n * @param family\n * @param key\n */\n public async databaseDel(family: string, key: string): Promise<void> {\n const response = await this.sendCommand(\n format('DATABASE DEL %s %s', family, key)\n );\n\n if (response.code !== 200 || response.result === 0) {\n throw new Error('Could not delete from the database');\n }\n }\n\n /**\n * Deletes a family or specific keytree within a family in the Asterisk database.\n * @param family\n * @param keyTree\n */\n public async databaseDelTree(\n family: string,\n keyTree?: string\n ): Promise<boolean> {\n const response = await this.sendCommand(\n format('DATABASE DELTREE %s %s', family, keyTree || '')\n );\n\n if (response.code !== 200) {\n throw new Error('Could not delete tree from database');\n }\n\n return response.result === 0;\n }\n\n /**\n * Retrieves an entry in the Asterisk database for a given family and key.\n * @param family\n * @param key\n */\n public async databaseGet(family: string, key: string): Promise<string> {\n const response = await this.sendCommand(\n format('DATABASE GET %s %s', family, key)\n );\n\n if (response.code !== 200 || response.result === 0) {\n throw new Error('Database key not set');\n }\n\n return response.arguments.nokey();\n }\n\n /**\n * Adds or updates an entry in the Asterisk database for a given family, key, and value.\n * @param family\n * @param key\n * @param value\n */\n public async databasePut(\n family: string,\n key: string,\n value: string\n ): Promise<string> {\n const response = await this.sendCommand(\n format('DATABASE PUT %s %s %s', family, key, value)\n );\n\n if (response.code !== 200 || response.result === 0) {\n throw new Error('Database key not set');\n }\n\n return response.arguments.string('value');\n }\n\n /**\n * Executes application with given options\n * @param application The application to execute (e.g., 'Dial', 'Playback')\n * @param args Application arguments\n * @param commandTimeout Optional timeout in milliseconds (default: 6 hours for EXEC, use Infinity for no timeout)\n */\n public async exec(\n application: string,\n args: string,\n commandTimeout?: number\n ): Promise<number> {\n const response = await this.sendCommand(\n format('EXEC %s %s', application, args),\n commandTimeout\n );\n\n if (response.code !== 200 || response.result === -2) {\n throw new Error('Could not execute application');\n }\n\n return response.result;\n }\n\n /**\n * Streams an audio file and collects DTMF digits from the channel.\n *\n * This method plays the specified audio file and waits for the user to enter DTMF digits.\n * The audio can be interrupted by pressing any digit. Collection ends when:\n * - The user presses `#` (terminator)\n * - `maxDigits` is reached\n * - Timeout expires\n *\n * **Standard mode** (without `interDigitTimeout`):\n * Uses the native AGI GET DATA command. The `timeout` parameter controls both the\n * first digit timeout and inter-digit timeout (Asterisk defaults: 6000ms/2000ms).\n *\n * **Inter-digit timeout mode** (with `interDigitTimeout`):\n * Uses a custom implementation that provides separate control over:\n * - `timeout`: Maximum time to wait for the first digit after audio ends\n * - `interDigitTimeout`: Maximum time to wait between subsequent digits\n *\n * @param soundFile - The audio file to play (without extension)\n * @param timeout - Timeout in milliseconds (default: 5000ms). In standard mode, this is\n * used for both first digit and inter-digit timeout.\n * @param maxDigits - Maximum number of digits to collect (default: 1024)\n * @param interDigitTimeout - Optional. If provided, enables custom inter-digit timeout mode\n * with separate timeout between digits in milliseconds.\n * @returns Object containing:\n * - `digits`: The collected DTMF digits (without the # terminator)\n * - `timeout`: True if collection ended due to timeout, false otherwise\n * @throws Error if the channel encounters an error during collection\n *\n * @example\n * ```typescript\n * // Standard mode: collect up to 4 digits with 10 second timeout\n * const result = await channel.getData('enter-pin', 10000, 4);\n * console.log(`User entered: ${result.digits}`);\n *\n * // Inter-digit timeout mode: 10s for first digit, 3s between digits\n * const result = await channel.getData('enter-account', 10000, 10, 3000);\n * if (result.timeout) {\n * console.log('User timed out');\n * }\n * ```\n *\n * @see https://docs.asterisk.org/Asterisk_22_Documentation/API_Documentation/AGI_Commands/get_data\n */\n public async getData(\n soundFile: string,\n timeout: number = 5000,\n maxDigits?: number,\n interDigitTimeout?: number\n ): Promise<{ digits: string; timeout: boolean }> {\n // If maxDigits is specified and interDigitTimeout is provided, use digit-by-digit collection\n if (maxDigits && maxDigits > 1 && interDigitTimeout) {\n return this.getDataWithInterDigitTimeout(soundFile, timeout, maxDigits, interDigitTimeout);\n }\n\n // Use standard GET DATA for simple cases\n const command = maxDigits !== undefined\n ? format('GET DATA %s %s %s', soundFile, timeout, maxDigits)\n : format('GET DATA %s %s', soundFile, timeout);\n\n const response = await this.sendCommand(command);\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not get data from channel');\n }\n\n return {\n digits: response.arguments.string('result'),\n timeout: response.arguments.string('value') === '(timeout)',\n };\n }\n\n /**\n * Internal method to collect digits with separate inter-digit timeout control.\n *\n * This method provides more granular control over digit collection than the standard\n * AGI GET DATA command by implementing custom timeout logic:\n *\n * 1. Plays the audio file (interruptible by any digit)\n * 2. Waits up to `totalTimeout` for the first digit\n * 3. For each subsequent digit, waits up to `interDigitTimeout`\n * 4. Returns when `maxDigits` is reached, `#` is pressed, or timeout occurs\n *\n * @param soundFile - The audio file to play (without extension)\n * @param totalTimeout - Maximum time in milliseconds to wait for the first digit after audio\n * @param maxDigits - Maximum number of digits to collect\n * @param interDigitTimeout - Maximum time in milliseconds to wait between subsequent digits\n * @returns Object with collected digits and timeout flag\n * @internal\n */\n private async getDataWithInterDigitTimeout(\n soundFile: string,\n totalTimeout: number,\n maxDigits: number,\n interDigitTimeout: number\n ): Promise<{ digits: string; timeout: boolean }> {\n let collectedDigits = '';\n\n // Play the sound file first, allowing any digit to interrupt\n try {\n // Use STREAM FILE directly instead of streamFile() to avoid PLAYBACKSTATUS check\n const response = await this.sendCommand(\n format('STREAM FILE %s \"%s\"', soundFile, '0123456789*#')\n );\n\n if (response.code === 200 && response.result !== -1) {\n const digit = response.arguments.char('result');\n\n // If user pressed a digit during playback, collect it\n if (digit) {\n collectedDigits += digit;\n\n // If we already have max digits, return immediately\n if (collectedDigits.length === maxDigits) {\n return { digits: collectedDigits, timeout: false };\n }\n }\n }\n } catch (error) {\n // Continue even if file fails to play\n }\n\n // Start timing AFTER audio finishes - totalTimeout only applies to digit collection\n const startTime = Date.now();\n\n // Collect remaining digits one by one with inter-digit timeout\n while (collectedDigits.length < maxDigits) {\n const elapsedTime = Date.now() - startTime;\n const remainingTotalTimeout = totalTimeout - elapsedTime;\n\n if (remainingTotalTimeout <= 0) {\n return { digits: collectedDigits, timeout: collectedDigits.length === 0 };\n }\n\n // For the first digit, use totalTimeout. For subsequent digits, use interDigitTimeout\n const timeoutToUse = collectedDigits.length === 0\n ? remainingTotalTimeout\n : Math.min(interDigitTimeout, remainingTotalTimeout);\n\n try {\n // Convert milliseconds to seconds for waitForDigit\n const digit = await this.waitForDigit(timeoutToUse / 1000);\n\n if (!digit) {\n // Timeout waiting for digit\n return { digits: collectedDigits, timeout: collectedDigits.length === 0 };\n }\n\n collectedDigits += digit;\n\n if (collectedDigits.length === maxDigits) {\n return { digits: collectedDigits, timeout: false };\n }\n } catch (error) {\n return { digits: collectedDigits, timeout: true };\n }\n }\n\n return { digits: collectedDigits, timeout: false };\n }\n\n /**\n * Evaluates a channel expression\n * Understands complex variable names and builtin variables, unlike GET VARIABLE.\n * @param key\n * @param channel\n */\n public async getFullVariable(key: string, channel?: string): Promise<string> {\n const response = await this.sendCommand(\n format('GET FULL VARIABLE %s %s', key.toUpperCase(), channel || '')\n );\n\n if (response.code !== 200 || response.result === 0) {\n throw new Error('Variable not set');\n }\n\n return response.arguments.nokey();\n }\n\n /**\n * Stream file, prompt for DTMF, with timeout.\n * Behaves similar to STREAM FILE but used with a timeout option.\n * @param soundFile\n * @param escapeDigits\n * @param timeout\n */\n public async getOption(\n soundFile: string,\n escapeDigits: string = '#',\n timeout: number = 5\n ): Promise<{ digit: string; endpos: number }> {\n const response = await this.sendCommand(\n format('GET OPTION %s \"%s\" %s', soundFile, escapeDigits, timeout * 1000)\n );\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not get option');\n }\n\n if (response.arguments.number('endpos') === 0) {\n throw new Error('Could Not play file');\n }\n\n return {\n digit: response.arguments.char('result'),\n endpos: response.arguments.number('endpos'),\n };\n }\n\n /**\n * Gets a channel variable.\n * @param key\n */\n public async getVariable(key: string): Promise<string> {\n const response = await this.sendCommand(\n format('GET VARIABLE %s', key.toUpperCase())\n );\n\n if (response.code !== 200 || response.result === 0) {\n throw new Error('Variable not set');\n }\n\n return response.arguments.nokey();\n }\n\n /**\n * Cause the channel to execute the specified dialplan subroutine.\n * @param context\n * @param extension\n * @param priority\n * @param argument\n */\n public async goSub(\n context: string,\n extension: string,\n priority: number,\n argument?: string\n ): Promise<void> {\n const response = await this.sendCommand(\n format('GOSUB %s %s %s %s', context, extension, priority, argument || '')\n );\n\n if (response.code !== 200 || response.result !== 0) {\n throw new Error('Could not execute gosub');\n }\n }\n\n /**\n * Hangs up the specified channel. If no channel name is given, hangs up the current channel\n * @param channel\n */\n public async hangup(channel?: string): Promise<void> {\n const response = await this.sendCommand(format('HANGUP %s', channel || ''));\n\n if (response.code !== 200 || response.result !== 1) {\n throw new Error('Could not hang up call');\n }\n }\n\n /**\n * Does nothing\n */\n public async noop(): Promise<void> {\n const response = await this.sendCommand('NOOP');\n\n if (response.code !== 200 || response.result !== 0) {\n throw new Error('Could not NOOP');\n }\n }\n\n /**\n * Receives one character from channels supporting it.\n * @param timeout\n */\n public async receiveChar(\n timeout: number = 5\n ): Promise<{ char: string; timeout: boolean }> {\n const response = await this.sendCommand(\n format('RECEIVE CHAR %s', timeout * 1000)\n );\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not get data from channel');\n }\n\n return {\n char: response.arguments.char('result'),\n timeout: response.arguments.boolean('timeout'),\n };\n }\n\n /**\n * Receives text from channels supporting it.\n * @param timeout\n */\n public async receiveText(timeout: number = 5): Promise<string> {\n const response = await this.sendCommand(\n format('RECEIVE TEXT %s', timeout * 1000)\n );\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not get data from channel');\n }\n\n return response.arguments.string('result');\n }\n\n /**\n * Records to a given file.\n * @param filename\n * @param fileFormat\n * @param escapeDigits\n * @param timeout\n * @param beep\n * @param silence\n * @param offsetSamples\n */\n public async recordFile(\n filename: string,\n fileFormat: string = 'gsm',\n escapeDigits: string = '#',\n timeout: number = 10,\n beep?: boolean,\n silence?: number,\n offsetSamples?: number\n ): Promise<{ digit: string; endpos: number; timeout: boolean }> {\n const response = await this.sendCommand(\n format(\n 'RECORD FILE %s %s \"%s\" %s %s %s %s',\n filename,\n fileFormat,\n escapeDigits,\n timeout * 1000,\n offsetSamples || '',\n beep ? 'BEEP' : '',\n silence ? format('s=%s', silence) : ''\n )\n );\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not record file');\n }\n\n return {\n digit: response.arguments.char('result'),\n endpos: response.arguments.number('endpos'),\n timeout: response.arguments.boolean('timeout'),\n };\n }\n\n /**\n * Says a given character string.\n * @param value\n * @param escapeDigits\n */\n public async sayAlpha(\n value: string,\n escapeDigits: string = '#'\n ): Promise<string> {\n const response = await this.sendCommand(\n format('SAY ALPHA %s \"%s\"', value, escapeDigits)\n );\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not say alpha');\n }\n\n return response.arguments.char('result');\n }\n\n /**\n * Says a given date.\n * @param value\n * @param escapeDigits\n */\n public async sayDate(\n value: Date | number,\n escapeDigits: string = '#'\n ): Promise<string> {\n const response = await this.sendCommand(\n format(\n 'SAY DATE %s \"%s\"',\n typeof value === 'number' ? value : Math.floor(value.getTime() / 1000),\n escapeDigits\n )\n );\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not say date');\n }\n\n return response.arguments.char('result');\n }\n\n /**\n * Says a given time as specified by the format given.\n * @param value\n * @param escapeDigits\n * @param dateFormat\n * @param timezone\n */\n public async sayDateTime(\n value: Date | number,\n escapeDigits: string = '#',\n dateFormat?: string,\n timezone?: string\n ): Promise<string> {\n const response = await this.sendCommand(\n format(\n 'SAY DATETIME %s \"%s\" %s %s',\n typeof value === 'number' ? value : Math.floor(value.getTime() / 1000),\n escapeDigits,\n dateFormat || '',\n timezone || ''\n )\n );\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not say date time');\n }\n\n return response.arguments.char('result');\n }\n\n /**\n * Says a given digit string.\n * @param value\n * @param escapeDigits\n */\n public async sayDigits(\n value: string,\n escapeDigits: string = '#'\n ): Promise<string> {\n const response = await this.sendCommand(\n format('SAY DIGITS %s \"%s\"', value, escapeDigits)\n );\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not say digits');\n }\n\n return response.arguments.char('result');\n }\n\n /**\n * Says a given number.\n * @param value\n * @param escapeDigits\n */\n public async sayNumber(\n value: number,\n escapeDigits: string = '#'\n ): Promise<string> {\n const response = await this.sendCommand(\n format('SAY NUMBER %s \"%s\"', value, escapeDigits)\n );\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not say number');\n }\n\n return response.arguments.char('result');\n }\n\n /**\n * Says a given character string with phonetics.\n * @param value\n * @param escapeDigits\n */\n public async sayPhonetic(\n value: string,\n escapeDigits: string = '#'\n ): Promise<string> {\n const response = await this.sendCommand(\n format('SAY PHONETIC %s \"%s\"', value, escapeDigits)\n );\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not say phonetic');\n }\n\n return response.arguments.char('result');\n }\n\n /**\n * Says a given time.\n * @param value\n * @param escapeDigits\n */\n public async sayTime(\n value: Date | number,\n escapeDigits: string = '#'\n ): Promise<string> {\n const response = await this.sendCommand(\n format(\n 'SAY TIME %s \"%s\"',\n typeof value === 'number' ? value : Math.floor(value.getTime() / 1000),\n escapeDigits\n )\n );\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not say time');\n }\n\n return response.arguments.char('result');\n }\n\n /**\n * Sends images to channels supporting it.\n * @param image\n */\n public async sendImage(image: string): Promise<void> {\n const response = await this.sendCommand(format('SEND IMAGE %s', image));\n\n if (response.code !== 200 || response.result !== 0) {\n throw new Error('Could not send image');\n }\n }\n\n /**\n * Sends text to channels supporting it.\n * @param text\n */\n public async sendText(text: string): Promise<void> {\n const response = await this.sendCommand(format('SEND TEXT \"%s\"', text));\n\n if (response.code !== 200 || response.result !== 0) {\n throw new Error('Could not send text');\n }\n }\n\n /**\n * Autohangup channel in some time.\n * @param timeout\n */\n public async setAutoHangup(timeout: number = 60): Promise<void> {\n const response = await this.sendCommand(\n format('SET AUTOHANGUP %s', timeout)\n );\n\n if (response.code !== 200 || response.result !== 0) {\n throw new Error('Could not set auto hangup');\n }\n }\n\n /**\n * Sets callerid for the current channel.\n * @param callerNumber\n * @param callerName\n */\n public async setCallerID(\n callerNumber: number,\n callerName?: string\n ): Promise<void> {\n const callerid = callerName\n ? format('\"%s\"<%s>', callerName, callerNumber)\n : callerNumber;\n\n const response = await this.sendCommand(\n format('SET CALLERID %s', callerid)\n );\n\n if (response.code !== 200 || response.result !== 1) {\n throw new Error('Could not set caller id');\n }\n }\n\n /**\n * Sets channel context.\n * @param context\n */\n public async setContext(context: string): Promise<void> {\n const response = await this.sendCommand(format('SET CONTEXT %s', context));\n\n if (response.code !== 200 || response.result !== 0) {\n throw new Error('Could not set context');\n }\n }\n\n /**\n * Changes channel extension.\n * @param extension\n */\n public async setExtension(extension: string): Promise<void> {\n const response = await this.sendCommand(\n format('SET EXTENSION %s', extension)\n );\n\n if (response.code !== 200 || response.result !== 0) {\n throw new Error('Could not set extension');\n }\n }\n\n /**\n * Enable/Disable Music on hold generator\n * @param status\n * @param musicClass\n */\n public async setMusic(\n status: boolean = true,\n musicClass?: string\n ): Promise<void> {\n const response = await this.sendCommand(\n format('SET MUSIC %s %s', status ? 'ON' : 'OFF', musicClass || '')\n );\n\n if (response.code !== 200 || response.result !== 0) {\n throw new Error('Could not set priority');\n }\n }\n\n /**\n * Set channel dialplan priority.\n * @param priority\n */\n public async setPriority(priority: number): Promise<void> {\n const response = await this.sendCommand(\n format('SET PRIORITY %s', priority)\n );\n\n if (response.code !== 200 || response.result !== 0) {\n throw new Error('Could not set priority');\n }\n }\n\n /**\n * Sets a channel variable.\n * @param key - The variable name\n * @param value - The variable value\n * @throws Error if the variable could not be set\n */\n public async setVariable(key: string, value: string): Promise<void> {\n const response = await this.sendCommand(\n format('SET VARIABLE %s \"%s\"', key.toUpperCase(), value)\n );\n\n if (response.code !== 200 || response.result !== 1) {\n throw new Error('Could not set variable');\n }\n }\n\n public async speechActivateGrammar(grammar: string): Promise<IResponse> {\n // TODO: Handle the response\n return this.sendCommand(format('SPEECH ACTIVATE GRAMMAR %s', grammar));\n }\n\n public async speechCreate(engine: string): Promise<IResponse> {\n // TODO: Handle the response\n return this.sendCommand(format('SPEECH CREATE ENGINE %s', engine));\n }\n\n public async speechDeactivateGrammar(grammar: string): Promise<IResponse> {\n // TODO: Handle the response\n return this.sendCommand(format('SPEECH DEACTIVATE GRAMMAR %s', grammar));\n }\n\n public async speechDestroy(): Promise<IResponse> {\n // TODO: Handle the response\n return this.sendCommand('SPEECH DESTROY');\n }\n\n public async speechLoadGrammar(\n grammar: string,\n path: string\n ): Promise<IResponse> {\n // TODO: Handle the response\n return this.sendCommand(format('SPEECH LOAD GRAMMAR %s %s', grammar, path));\n }\n\n public async speechRecognize(\n soundFile: string,\n timeout: number = 5,\n offset: number\n ): Promise<IResponse> {\n // TODO: Handle the response\n return this.sendCommand(\n format('SPEECH RECOGNIZE %s %s %s', soundFile, timeout * 1000, offset)\n );\n }\n\n public async speechSet(key: string, value: string): Promise<IResponse> {\n // TODO: Handle the response\n return this.sendCommand(format('SPEECH SET %s %s', key, value));\n }\n\n public async speedUnloadGrammar(grammar: string): Promise<IResponse> {\n // TODO: Handle the response\n return this.sendCommand(format('SPEECH UNLOAD GRAMMAR %s', grammar));\n }\n\n /**\n * Streams an audio file to the channel, allowing playback to be interrupted by DTMF digits.\n *\n * The file extension should not be included in the filename - Asterisk will automatically\n * select the best available format based on the channel's codec.\n *\n * @param filename - The audio file to play (without extension, e.g., \"welcome\" not \"welcome.wav\")\n * @param escapeDigits - DTMF digits that will interrupt playback (default: \"#\"). Use \"\" for none.\n * @param offset - Sample offset to start playback from (optional)\n * @returns Object containing:\n * - `digit`: The DTMF digit pressed to interrupt, or empty string if played to completion\n * - `endpos`: The sample position where playback stopped\n * @throws Error if the file could not be played or PLAYBACKSTATUS is not SUCCESS\n *\n * @example\n * ```typescript\n * // Play a file, allowing any digit to interrupt\n * const result = await channel.streamFile('welcome', '0123456789*#');\n * if (result.digit) {\n * console.log(`User pressed: ${result.digit}`);\n * }\n *\n * // Play a file without allowing interruption\n * await channel.streamFile('announcement', '');\n * ```\n *\n * @see https://docs.asterisk.org/Asterisk_22_Documentation/API_Documentation/AGI_Commands/stream_file\n */\n public async streamFile(\n filename: string,\n escapeDigits: string = '#',\n offset?: number\n ): Promise<{ digit: string; endpos: number }> {\n const response = await this.sendCommand(\n format('STREAM FILE %s \"%s\" %s', filename, escapeDigits, offset || '')\n );\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not stream file');\n }\n\n const status = await this.getVariable('PLAYBACKSTATUS');\n\n if (status !== 'SUCCESS') {\n throw new Error('Could not stream file');\n }\n\n return {\n digit: response.arguments.char('result'),\n endpos: response.arguments.number('endpos'),\n };\n }\n\n /**\n * Toggles TDD mode (for the deaf).\n * @param status\n */\n public async tddMode(status: boolean): Promise<void> {\n const response = await this.sendCommand(\n format('TDD MODE %s', status ? 'ON' : 'OFF')\n );\n\n if (response.code !== 200 || response.result !== 1) {\n throw new Error('Could not set TDD mode');\n }\n }\n\n /**\n * Logs a message to the asterisk verbose log.\n * @param message\n * @param level\n */\n public async verbose(message: string, level?: number): Promise<void> {\n const response = await this.sendCommand(\n format('VERBOSE \"%s\" %s', message, level || '')\n );\n\n if (response.code !== 200 || response.result !== 1) {\n throw new Error('Could not send logging message');\n }\n }\n\n /**\n * Waits for a digit to be pressed.\n * @param timeout Timeout in seconds\n */\n public async waitForDigit(timeout: number = 5): Promise<string> {\n // Convert timeout from seconds to milliseconds and add 2s safety margin for network/processing latency\n const commandTimeout = (timeout * 1000) + 2000;\n\n const response = await this.sendCommand(\n format('WAIT FOR DIGIT %s', timeout * 1000),\n commandTimeout\n );\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not wait for digit');\n }\n\n return response.arguments.char('result');\n }\n\n /* Internal Methods */\n\n private close() {\n this.m_connection.destroy();\n }\n\n private read(data: Buffer): void {\n if (data.length === 0) {\n return;\n }\n\n this.m_message += data.toString();\n\n if (this.m_state === ContextState.INIT) {\n if (this.m_message.indexOf('\\n\\n') === -1) {\n return;\n }\n\n this.readVariables(this.m_message);\n } else if (this.m_state === ContextState.WAITING) {\n if (this.m_message.indexOf('\\n') === -1) {\n return;\n }\n\n this.readResponse(this.m_message);\n }\n\n this.m_message = '';\n }\n\n private readVariables(message: string) {\n const lines = message.split('\\n');\n\n lines.map((line) => {\n const split = line.split(':');\n const name: string = (split[0] || '').trim();\n const value: string = (split[1] || '').trim();\n\n const id = name.substring(4);\n\n switch (id) {\n case 'network':\n return (this.m_network = value);\n case 'network_script':\n return (this.m_network_script = value);\n case 'request':\n return (this.m_request = value);\n case 'channel':\n return (this.m_channel = value);\n case 'language':\n return (this.m_language = value);\n case 'type':\n return (this.m_type = value);\n case 'uniqueid':\n return (this.m_uniqueid = value);\n case 'version':\n return (this.m_version = value);\n case 'callerid':\n return (this.m_callerid = value);\n case 'calleridname':\n return (this.m_calleridname = value);\n case 'callingpres':\n return (this.m_callingpres = value);\n case 'callingani2':\n return (this.m_callingani2 = value);\n case 'callington':\n return (this.m_callington = value);\n case 'callingtns':\n return (this.m_callingtns = value);\n case 'dnid':\n return (this.m_dnid = value);\n case 'rdnis':\n return (this.m_rdnis = value);\n case 'context':\n return (this.m_context = value);\n case 'extension':\n return (this.m_extension = value);\n case 'priority':\n return (this.m_priority = value);\n case 'enhanced':\n return (this.m_enhanced = value);\n case 'accountcode':\n return (this.m_accountcode = value);\n case 'threadid':\n return (this.m_threadid = value);\n }\n });\n\n this.m_state = ContextState.WAITING;\n\n this.emit('ready');\n }\n\n private readResponse(message: string) {\n const lines = message.split('\\n');\n\n lines.map((line) => this.readResponseLine(line));\n }\n\n private readResponseLine(line: string) {\n if (!line) {\n return;\n }\n\n this.emit('recv', line);\n\n const parsed = line.split(' ');\n\n if (!parsed || parsed[0] === 'HANGUP') {\n return this.emit('hangup');\n }\n\n const code = parseInt(parsed[0], 10);\n parsed.shift();\n\n const args: ResponseArguments = new ResponseArguments();\n\n for (const value of parsed) {\n if (value.indexOf('=') !== -1) {\n const parts = value.split('=', 2);\n const key = parts[0].trim();\n const val = parts[1].trim();\n args.addArgument(key, val);\n } else if (value.indexOf('(') !== -1) {\n const name = value.substring(1, value.length - 1);\n args.addArgument(name, true);\n } else {\n args.addArgument('value', value);\n }\n }\n\n const response: IResponse = {\n code: code,\n result: args.number('result'),\n arguments: args,\n };\n\n this.emit('response', response);\n }\n\n private async send(message: string): Promise<void> {\n return new Promise((resolve, reject) => {\n if (!this.m_connection || this.m_connection.destroyed) {\n return reject(new Error('Stream has been destroyed'));\n }\n this.emit('send', message);\n this.m_connection.write(message, (error) => {\n if (error) {\n return reject(error);\n }\n resolve();\n });\n });\n }\n\n /**\n * Sends an AGI command and waits for response using a FIFO queue\n * @param command AGI command to send\n * @param timeout Optional timeout in milliseconds (default: 10000ms)\n */\n private async sendCommand(\n command: string,\n timeout?: number\n ): Promise<IResponse> {\n return new Promise((resolve, reject) => {\n // Check if channel is still alive\n if (!this.channelAlive) {\n return reject(new Error('Channel is no longer alive'));\n }\n\n // Check queue size limit (backpressure)\n if (this.commandQueue.length >= this.maxQueueSize) {\n return reject(\n new Error(\n `Command queue full (${this.maxQueueSize}). Command rejected: ${command}`\n )\n );\n }\n\n // Add command to queue\n const queuedCommand: IQueuedCommand = {\n command,\n resolve,\n reject,\n timeout: timeout ?? this.getCommandTimeout(command),\n timestamp: Date.now(),\n };\n\n this.commandQueue.push(queuedCommand);\n\n // Emit event for monitoring\n this.emit('commandQueued', {\n command,\n queueSize: this.commandQueue.length,\n });\n\n // Start processing if not active\n if (!this.isProcessingCommand) {\n this.processCommandQueue();\n }\n });\n }\n\n /**\n * Gets the appropriate timeout for a given command\n * @param command The AGI command string\n * @returns Timeout in milliseconds (or Infinity for no timeout)\n */\n private getCommandTimeout(command: string): number {\n // Comandos r\u00E1pidos (devem responder em segundos)\n if (\n command.startsWith('ANSWER') ||\n command.startsWith('HANGUP') ||\n command.startsWith('CHANNEL STATUS') ||\n command.startsWith('GET VARIABLE') ||\n command.startsWith('SET VARIABLE') ||\n command.startsWith('DATABASE')\n ) {\n return 10000; // 10 segundos\n }\n\n // Comandos m\u00E9dios (audio playback, prompts)\n if (\n command.startsWith('STREAM FILE') ||\n command.startsWith('SAY ') ||\n command.startsWith('GET DATA') ||\n command.startsWith('GET OPTION')\n ) {\n return 60000; // 1 minuto\n }\n\n // Comandos de grava\u00E7\u00E3o\n if (command.startsWith('RECORD FILE')) {\n return 600000; // 10 minutos\n }\n\n // EXEC: pode incluir Dial, Queue, VoiceMail (podem durar horas)\n if (command.startsWith('EXEC')) {\n return this.maxCallDuration; // 6 horas padr\u00E3o\n }\n\n // Outros comandos\n return this.defaultCommandTimeout; // 10 segundos\n }\n\n /**\n * Processes the command queue sequentially (FIFO)\n */\n private async processCommandQueue(): Promise<void> {\n if (this.commandQueue.length === 0) {\n this.isProcessingCommand = false;\n this.emit('queueEmpty');\n return;\n }\n\n this.isProcessingCommand = true;\n const queuedCommand = this.commandQueue.shift()!;\n\n try {\n const response = await this.sendCommandInternal(\n queuedCommand.command,\n queuedCommand.timeout!\n );\n\n // Emit success event\n this.emit('commandProcessed', {\n command: queuedCommand.command,\n duration: Date.now() - queuedCommand.timestamp,\n });\n\n queuedCommand.resolve(response);\n } catch (err) {\n // Emit error event\n this.emit('commandFailed', {\n command: queuedCommand.command,\n error: err,\n });\n\n queuedCommand.reject(err);\n } finally {\n // Process next command (continues even with error)\n setImmediate(() => this.processCommandQueue());\n }\n }\n\n /**\n * Internal implementation of command sending\n * @param command The AGI command to send\n * @param timeout Timeout in milliseconds, or Infinity for no timeout\n */\n private sendCommandInternal(\n command: string,\n timeout: number\n ): Promise<IResponse> {\n return new Promise((resolve, reject) => {\n // Check connection state and channel status\n if (\n !this.channelAlive ||\n !this.m_connection ||\n this.m_connection.destroyed\n ) {\n return reject(new Error('Channel is no longer alive'));\n }\n\n let timeoutId: NodeJS.Timeout | null = null;\n\n const responseHandler = (response: IResponse) => {\n cleanup();\n resolve(response);\n };\n\n const cleanup = () => {\n this.removeListener('response', responseHandler);\n if (timeoutId) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n };\n\n // Register listener\n this.once('response', responseHandler);\n\n // Configurable timeout (supports Infinity for no timeout)\n if (timeout > 0 && timeout !== Infinity) {\n timeoutId = setTimeout(() => {\n cleanup();\n reject(new Error(`Command timeout after ${timeout}ms: ${command}`));\n }, timeout);\n }\n // If timeout is Infinity or <= 0, no timeout is set (relies on channelAlive)\n\n // Send command\n this.send(format('%s\\n', command.trim())).catch((err) => {\n cleanup();\n reject(err);\n });\n });\n }\n\n /**\n * Handles channel closure with pending commands\n */\n private handleChannelClose(): void {\n this.channelAlive = false;\n const pendingCount = this.commandQueue.length;\n\n if (pendingCount > 0) {\n this.emit('queueCleared', {\n reason: 'channel_closed',\n commandsCleared: pendingCount,\n });\n\n // Reject all pending commands\n while (this.commandQueue.length > 0) {\n const cmd = this.commandQueue.shift()!;\n cmd.reject(new Error('Channel closed before command could be sent'));\n }\n }\n\n this.isProcessingCommand = false;\n }\n\n /**\n * Handles HANGUP from Asterisk\n */\n private handleHangup(): void {\n this.channelAlive = false;\n const pendingCount = this.commandQueue.length;\n\n if (pendingCount > 0) {\n this.emit('queueCleared', {\n reason: 'hangup',\n commandsCleared: pendingCount,\n });\n\n // Reject pending commands\n while (this.commandQueue.length > 0) {\n const cmd = this.commandQueue.shift()!;\n cmd.reject(new Error('Call hung up before command could be executed'));\n }\n }\n\n this.isProcessingCommand = false;\n }\n\n /**\n * Manually clears the command queue (for emergency cases)\n */\n public clearCommandQueue(): number {\n const clearedCount = this.commandQueue.length;\n\n while (this.commandQueue.length > 0) {\n const cmd = this.commandQueue.shift()!;\n cmd.reject(new Error('Command queue manually cleared'));\n }\n\n this.isProcessingCommand = false;\n\n this.emit('queueCleared', {\n reason: 'manual',\n commandsCleared: clearedCount,\n });\n\n return clearedCount;\n }\n\n /**\n * Returns queue statistics\n */\n public getQueueStats(): {\n size: number;\n isProcessing: boolean;\n oldestCommandAge: number | null;\n } {\n const oldest = this.commandQueue[0];\n\n return {\n size: this.commandQueue.length,\n isProcessing: this.isProcessingCommand,\n oldestCommandAge: oldest ? Date.now() - oldest.timestamp : null,\n };\n }\n}\n", "// Copyright (c) 2020, Brandon Lehmann\n//\n// Please see the included LICENSE file for more information.\n\n/** @ignore */\nexport interface IResponseArguments {\n key: string;\n value: string | number | boolean;\n}\n\n/**\n * Represents a set of AGI response arguments\n * @ignore\n */\nexport class ResponseArguments {\n private m_args: IResponseArguments[] = [];\n\n /**\n * Adds a new argument to the set\n * @param key\n * @param value\n */\n public addArgument(key: string, value: string | number | boolean) {\n this.m_args.push({key, value});\n }\n\n /**\n * Retrieves the requested key as a string\n * @param key\n */\n public string(key: string): string {\n for (const arg of this.m_args) {\n if (arg.key === key) {\n return (arg.value as string);\n }\n }\n\n return '';\n }\n\n /**\n * Retrieves the requested key as a number\n * @param key\n */\n public number(key: string): number {\n for (const arg of this.m_args) {\n if (arg.key === key) {\n return parseInt((arg.value as string), 10);\n }\n }\n\n return 0;\n }\n\n /**\n * Retrieves the request key as a boolean\n * @param key\n */\n public boolean(key: string): boolean {\n for (const arg of this.m_args) {\n if (arg.key === key) {\n return (arg.value as boolean);\n }\n }\n\n return false;\n }\n\n /**\n * Retrieves the requested key from a character code\n * @param key\n */\n public char(key: string): string {\n const num = this.number(key);\n\n return (num !== 0) ? String.fromCharCode(num) : '';\n }\n\n /**\n * Retrieves the value from the arguments that has no key, if it exists\n */\n public nokey(): string {\n for (const arg of this.m_args) {\n if (arg.key !== 'result' && arg.value) {\n return arg.key;\n }\n }\n\n return '';\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["index_exports", "__export", "AGIServer", "Channel", "ChannelState", "DialStatus", "PlaybackStatus", "__toCommonJS", "net", "import_events", "import_node_events", "import_node_util", "ResponseArguments", "key", "value", "arg", "num", "ChannelState", "DialStatus", "PlaybackStatus", "Channel", "connection", "data", "error", "event", "listener", "response", "channel", "filename", "escapeDigits", "skipms", "fastForwardCharacter", "rewindCharacter", "pauseCharacter", "playbackStatus", "playbackOffset", "status", "target", "timeout", "params", "family", "key", "keyTree", "value", "application", "args", "commandTimeout", "soundFile", "maxDigits", "interDigitTimeout", "command", "totalTimeout", "collectedDigits", "digit", "startTime", "elapsedTime", "remainingTotalTimeout", "timeoutToUse", "context", "extension", "priority", "argument", "fileFormat", "beep", "silence", "offsetSamples", "dateFormat", "timezone", "image", "text", "callerNumber", "callerName", "callerid", "musicClass", "grammar", "engine", "path", "offset", "message", "level", "line", "split", "name", "parsed", "code", "ResponseArguments", "parts", "val", "resolve", "reject", "queuedCommand", "err", "timeoutId", "responseHandler", "cleanup", "pendingCount", "clearedCount", "oldest", "import_util", "AGIServer", "port", "ip", "socket", "channel", "Channel", "event", "listener", "error", "resolve", "reject"]
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/AGIServer.ts", "../../src/Channel.ts", "../../src/ResponseArguments.ts"],
4
- "sourcesContent": ["// Copyright (c) 2020, Brandon Lehmann\n//\n// Please see the included LICENSE file for more information.\n\nimport * as net from 'net';\nimport {EventEmitter} from 'events';\nimport {Channel} from './Channel';\nimport {format} from 'util';\n\n/**\n * Represents an AGI server instance\n */\nexport class AGIServer extends EventEmitter {\n private readonly m_port: number;\n private readonly m_ip: string;\n private readonly m_server: net.Server = net.createServer();\n\n /**\n * Constructs a new instance of the object\n * @param port\n * @param ip\n */\n constructor(port: number = 3000, ip: string = '0.0.0.0') {\n super();\n this.setMaxListeners(10);\n\n this.m_port = port;\n this.m_ip = ip;\n\n this.m_server.on('connection', (socket: net.Socket) => {\n const channel = new Channel(socket);\n\n channel.on('ready', () => this.emit('channel', channel));\n });\n }\n\n /**\n * Event that is emitted when a new AGI channel has been established and is ready for interation\n * @param event\n * @param listener\n */\n public on(event: 'channel', listener: (channel: Channel) => void): this;\n\n /**\n * Event that is emitted when the AGI server is started and in a listening state\n * @param event\n * @param listener\n */\n public on(event: 'listening', listener: (port: number, ip: string) => void): this;\n\n /**\n * Event that is emitted when the server encounters and error\n * @param event\n * @param listener\n */\n public on(event: 'error', listener: (error: any) => void): this;\n\n /**\n * Event that emitted when the server is closed and stopped\n * @param event\n * @param listener\n */\n public on(event: 'close', listener: () => void): this;\n\n public on(event: any, listener: (...args: any[]) => void): this {\n return super.on(event, listener);\n }\n\n /**\n * Starts the AGI server\n */\n public async start(): Promise<void> {\n this.m_server.on('error', (error) =>\n this.emit('error', new Error(\n format('Internal TCP server error: %s', error.toString()),\n )),\n );\n\n this.m_server.on('close', () => this.emit('close'));\n\n this.m_server.listen(this.m_port, this.m_ip, () => {\n this.emit('listening', this.m_port, this.m_ip);\n });\n }\n\n /**\n * Stops the AGI server\n */\n public async stop(): Promise<void> {\n return new Promise((resolve, reject) => {\n this.m_server.close((error) => {\n if (error) {\n return reject(error);\n }\n return resolve();\n });\n });\n }\n}\n", "// Copyright (c) 2020, Brandon Lehmann\n//\n// Please see the included LICENSE file for more information.\n\nimport { EventEmitter } from 'node:events';\nimport type { Socket } from 'node:net';\nimport { format } from 'node:util';\nimport { ResponseArguments } from './ResponseArguments';\n\n/** @ignore */\nenum ContextState {\n INIT = 0,\n WAITING = 2,\n}\n\n/**\n * Represents the current channel state\n */\nexport enum ChannelState {\n DOWN_AVAILABLE = 0,\n DOWN_RESERVED,\n OFF_HOOK,\n DIGITS_DIALED,\n RINGING,\n REMOTE_RINGING,\n UP,\n BUSY,\n}\n\n/**\n * Represents the result of a Dial() attempt\n */\nexport enum DialStatus {\n ANSWER,\n BUSY,\n NOANSWER,\n CANCEL,\n CONGESTION,\n CHANUNAVAIL,\n DONTCALL,\n TORTURE,\n INVALIDARGS,\n}\n\n/**\n * Represents the playback status\n */\nexport enum PlaybackStatus {\n SUCCESS,\n USER_STOPPED,\n REMOTE_STOPPED,\n ERROR,\n}\n\n/** @ignore */\ninterface IResponse {\n code: number;\n result: number;\n arguments: ResponseArguments;\n}\n\n/** @ignore */\ninterface IQueuedCommand {\n command: string;\n resolve: (value: IResponse) => void;\n reject: (reason: any) => void;\n timeout?: number;\n timestamp: number;\n}\n\n/**\n * Represents an AGI Channel\n */\nexport class Channel extends EventEmitter {\n private readonly m_connection: Socket;\n private m_state: ContextState;\n private m_message: string = '';\n private m_network: string = '';\n private m_network_script: string = '';\n private m_request: string = '';\n private m_channel: string = '';\n private m_language: string = '';\n private m_type: string = '';\n private m_uniqueid: string = '';\n private m_version: string = '';\n private m_callerid: string = '';\n private m_calleridname: string = '';\n private m_callingpres: string = '';\n private m_callingani2: string = '';\n private m_callington: string = '';\n private m_callingtns: string = '';\n private m_dnid: string = '';\n private m_rdnis: string = '';\n private m_context: string = '';\n private m_extension: string = '';\n private m_priority: string = '';\n private m_enhanced: string = '';\n private m_accountcode: string = '';\n private m_threadid: string = '';\n private commandQueue: IQueuedCommand[] = [];\n private isProcessingCommand = false;\n private channelAlive = true;\n private readonly maxQueueSize = 100;\n private readonly defaultCommandTimeout = 10000;\n private readonly maxCallDuration = 21600000; // 6 horas (360 minutos)\n\n /**\n * Creates a new instance of a channel object\n * @param connection the AGI socket connection\n */\n constructor(connection: Socket) {\n super();\n this.setMaxListeners(10);\n\n this.m_connection = connection;\n this.m_state = ContextState.INIT;\n\n this.m_connection.on('data', (data: Buffer) => this.read(data));\n this.m_connection.on('close', () => {\n this.handleChannelClose();\n this.emit('close');\n });\n this.m_connection.on('error', (error) => this.emit('error', error));\n this.m_connection.on('timeout', () => this.emit('timeout'));\n this.on('hangup', () => {\n this.handleHangup();\n this.close();\n });\n }\n\n /**\n * Event that is emitted when the underlying socket encounters an error\n * @param event\n * @param listener\n */\n public on(event: 'error', listener: (error: any) => void): this;\n\n /**\n * Event that is emitted when the underlying socket is closed\n * @param event\n * @param listener\n */\n public on(event: 'close', listener: () => void): this;\n\n /**\n * Event that emitted when the underlying socket times out\n * @param event\n * @param listener\n */\n public on(event: 'timeout', listener: () => void): this;\n\n /**\n * Event that is emitted when the channel is ready\n * @param event\n * @param listener\n */\n public on(event: 'ready', listener: () => void): this;\n\n /**\n * Event that is emitted when a response is received from the Asterisk server\n * @param event\n * @param listener\n */\n public on(event: 'recv', listener: (response: string) => void): this;\n\n /**\n * Event that emitted when the channel is hung up\n * @param event\n * @param listener\n */\n public on(event: 'hangup', listener: () => void): this;\n\n /**\n * Event that emitted when the response from the Asterisk server is processed into a structured response\n * @param event\n * @param listener\n */\n public on(event: 'response', listener: (response: IResponse) => void): this;\n\n /**\n * Event that is emitted when data is sent to the Asterisk server\n * @param event\n * @param listener\n */\n public on(event: 'send', listener: (data: string) => void): this;\n\n public on(event: any, listener: (...args: any[]) => void): this {\n return super.on(event, listener);\n }\n\n /**\n * Whether this AGI request is over the network\n */\n public get network(): boolean {\n return this.m_network.toLowerCase() === 'yes';\n }\n\n /**\n * The network path included in the AGI request\n * ie. agi://127.0.0.1:3000/test\n * This value would return 'test'\n */\n public get network_script(): string {\n return this.m_network_script;\n }\n\n /**\n * The version of Asterisk\n */\n public get version(): string {\n return this.m_version;\n }\n\n /**\n * The filename of your script\n * ie. agi\n */\n public get request(): string {\n return this.m_request;\n }\n\n /**\n * The originating channel (your phone)\n */\n public get channel(): string {\n return this.m_channel;\n }\n\n /**\n * The language code (e.g. \u201Cen\u201D)\n */\n public get language(): string {\n return this.m_language;\n }\n\n /**\n * The originating channel type (e.g. \u201CSIP\u201D or \u201CZAP\u201D)\n */\n public get type(): string {\n return this.m_type;\n }\n\n /**\n * A unique ID for the call\n */\n public get uniqueid(): string {\n return this.m_uniqueid;\n }\n\n /**\n * The caller ID number (or \u201Cunknown\u201D)\n */\n public get callerid(): string {\n return this.m_callerid;\n }\n\n /**\n * The caller ID name (or \u201Cunknown\u201D)\n */\n public get calleridname(): string {\n return this.m_calleridname;\n }\n\n /**\n * The presentation for the callerid in a ZAP channel\n */\n public get callingpres(): string {\n return this.m_callingpres;\n }\n\n /**\n * The number which is defined in ANI2 see Asterisk Detailed Variable List (only for PRI Channels)\n */\n public get callingani2(): string {\n return this.m_callingani2;\n }\n\n /**\n * The type of number used in PRI Channels see Asterisk Detailed Variable List\n */\n public get callington(): string {\n return this.m_callington;\n }\n\n /**\n * An optional 4 digit number (Transit Network Selector) used in PRI Channels see Asterisk Detailed Variable List\n */\n public get callingtns(): string {\n return this.m_callingtns;\n }\n\n /**\n * The dialed number id (or \u201Cunknown\u201D)\n */\n public get dnid(): string {\n return this.m_dnid;\n }\n\n /**\n * The referring DNIS number (or \u201Cunknown\u201D)\n */\n public get rdnis(): string {\n return this.m_rdnis;\n }\n\n /**\n * Origin context in extensions.conf\n */\n public get context(): string {\n return this.m_context;\n }\n\n /**\n * The called number\n */\n public get extension(): string {\n return this.m_extension;\n }\n\n /**\n * The priority it was executed as in the dial plan\n */\n public get priority(): string {\n return this.m_priority;\n }\n\n /**\n * The flag value is 1.0 if started as an EAGI script, 0.0 otherwise\n */\n public get enhanced(): string {\n return this.m_enhanced;\n }\n\n /**\n * Account code of the origin channel\n */\n public get accountcode(): string {\n return this.m_accountcode;\n }\n\n /**\n * Thread ID of the AGI script\n */\n public get threadid(): string {\n return this.m_threadid;\n }\n\n /**\n * Answers channel if not already in answer state.\n */\n public async answer(): Promise<void> {\n const response = await this.sendCommand('ANSWER');\n\n if (response.code !== 200 || response.result !== 0) {\n throw new Error('Could not answer call');\n }\n }\n\n /**\n * Interrupts expected flow of Async AGI commands and returns control to\n * previous source (typically, the PBX dialplan).\n */\n public async break(): Promise<void> {\n const response = await this.sendCommand('ASYNCAGI BREAK');\n\n if (response.code !== 200 || response.result !== 0) {\n throw new Error('Could not interrupt processing');\n }\n\n return this.close();\n }\n\n /**\n * Returns status of the connected channel.\n * @param channel\n */\n public async channelStatus(channel?: string): Promise<ChannelState> {\n const response = await this.sendCommand(\n format('CHANNEL STATUS %s', channel || '')\n );\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not get channel status');\n }\n\n return response.result;\n }\n\n /**\n * Sends audio file on channel and allows the listener to control the stream.\n * @param filename\n * @param escapeDigits\n * @param skipms\n * @param fastForwardCharacter\n * @param rewindCharacter\n * @param pauseCharacter\n */\n public async controlStreamFile(\n filename: string,\n escapeDigits: string = '',\n skipms?: number,\n fastForwardCharacter?: string,\n rewindCharacter?: string,\n pauseCharacter?: string\n ): Promise<{\n digit: string;\n playbackStatus: PlaybackStatus;\n playbackOffset: number;\n }> {\n const response = await this.sendCommand(\n format(\n 'CONTROL STREAM FILE %s \"%s\" %s %s %s %s',\n filename,\n escapeDigits,\n skipms || '',\n fastForwardCharacter || '',\n rewindCharacter || '',\n pauseCharacter || ''\n )\n );\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not control stream file');\n }\n\n const playbackStatus = await this.getVariable('CPLAYBACKSTATUS ');\n\n const playbackOffset = await this.getVariable('CPLAYBACKOFFSET ');\n\n let status: PlaybackStatus = PlaybackStatus.ERROR;\n\n switch (playbackStatus.toUpperCase()) {\n case 'SUCCESS':\n status = PlaybackStatus.SUCCESS;\n break;\n case 'USERSTOPPED':\n status = PlaybackStatus.USER_STOPPED;\n break;\n case 'REMOTESTOPPED':\n status = PlaybackStatus.REMOTE_STOPPED;\n break;\n }\n\n return {\n digit: response.arguments.char('result'),\n playbackStatus: status,\n playbackOffset: parseInt(playbackOffset, 10),\n };\n }\n\n /**\n * Attempts to establish a new outgoing connection on a channel, and then link it to the calling input channel.\n *\n * **Important:** This method is blocking. It only returns when the call ends completely:\n * - If answered: returns after either party hangs up\n * - If not answered: returns after timeout expires\n * - If busy/unavailable: returns immediately\n *\n * @param target - The dial target (e.g., \"PJSIP/1000\", \"PJSIP/alice&PJSIP/bob\")\n * @param timeout - Ring timeout in seconds (default: 30)\n * @param params - Optional Dial parameters (e.g., \"m\" for music on hold, \"t\" for transfer)\n * @returns The dial status indicating how the call ended\n * @throws Error if an unknown dial status is returned\n *\n * @example\n * ```typescript\n * const status = await channel.dial('PJSIP/1000', 30, 'm');\n * if (status === DialStatus.ANSWER) {\n * console.log('Call was answered and has now ended');\n * } else if (status === DialStatus.BUSY) {\n * console.log('Destination was busy');\n * }\n * ```\n *\n * @see https://docs.asterisk.org/Asterisk_22_Documentation/API_Documentation/Dialplan_Applications/Dial\n */\n public async dial(\n target: string,\n timeout: number = 30,\n params?: string\n ): Promise<DialStatus> {\n // Note: exec('Dial') blocks until the call ends (bridge is destroyed or dial fails)\n await this.exec('Dial', format('%s,%s,%s', target, timeout, params || ''));\n\n const dialstatus = await this.getVariable('DIALSTATUS');\n\n switch (dialstatus.toUpperCase()) {\n case 'ANSWER':\n return DialStatus.ANSWER;\n case 'BUSY':\n return DialStatus.BUSY;\n case 'NOANSWER':\n return DialStatus.NOANSWER;\n case 'CANCEL':\n return DialStatus.CANCEL;\n case 'CONGESTION':\n return DialStatus.CONGESTION;\n case 'CHANUNAVAIL':\n return DialStatus.CHANUNAVAIL;\n case 'DONTCALL':\n return DialStatus.DONTCALL;\n case 'TORTURE':\n return DialStatus.TORTURE;\n case 'INVALIDARGS':\n return DialStatus.INVALIDARGS;\n default:\n throw new Error('Unknown dial status');\n }\n }\n\n /**\n * Deletes an entry in the Asterisk database for a given family and key.\n * @param family\n * @param key\n */\n public async databaseDel(family: string, key: string): Promise<void> {\n const response = await this.sendCommand(\n format('DATABASE DEL %s %s', family, key)\n );\n\n if (response.code !== 200 || response.result === 0) {\n throw new Error('Could not delete from the database');\n }\n }\n\n /**\n * Deletes a family or specific keytree within a family in the Asterisk database.\n * @param family\n * @param keyTree\n */\n public async databaseDelTree(\n family: string,\n keyTree?: string\n ): Promise<boolean> {\n const response = await this.sendCommand(\n format('DATABASE DELTREE %s %s', family, keyTree || '')\n );\n\n if (response.code !== 200) {\n throw new Error('Could not delete tree from database');\n }\n\n return response.result === 0;\n }\n\n /**\n * Retrieves an entry in the Asterisk database for a given family and key.\n * @param family\n * @param key\n */\n public async databaseGet(family: string, key: string): Promise<string> {\n const response = await this.sendCommand(\n format('DATABASE GET %s %s', family, key)\n );\n\n if (response.code !== 200 || response.result === 0) {\n throw new Error('Database key not set');\n }\n\n return response.arguments.nokey();\n }\n\n /**\n * Adds or updates an entry in the Asterisk database for a given family, key, and value.\n * @param family\n * @param key\n * @param value\n */\n public async databasePut(\n family: string,\n key: string,\n value: string\n ): Promise<string> {\n const response = await this.sendCommand(\n format('DATABASE PUT %s %s %s', family, key, value)\n );\n\n if (response.code !== 200 || response.result === 0) {\n throw new Error('Database key not set');\n }\n\n return response.arguments.string('value');\n }\n\n /**\n * Executes application with given options\n * @param application The application to execute (e.g., 'Dial', 'Playback')\n * @param args Application arguments\n * @param commandTimeout Optional timeout in milliseconds (default: 6 hours for EXEC, use Infinity for no timeout)\n */\n public async exec(\n application: string,\n args: string,\n commandTimeout?: number\n ): Promise<number> {\n const response = await this.sendCommand(\n format('EXEC %s %s', application, args),\n commandTimeout\n );\n\n if (response.code !== 200 || response.result === -2) {\n throw new Error('Could not execute application');\n }\n\n return response.result;\n }\n\n /**\n * Stream the given file, and receive DTMF data with inter-digit timeout support.\n * @param soundFile The audio file to play\n * @param timeout Total timeout in milliseconds for digit collection AFTER audio finishes (default: 5000ms)\n * @param maxDigits Maximum number of digits to collect\n * @param interDigitTimeout Timeout between digits in milliseconds. If provided, enables digit-by-digit collection with inter-digit timeout.\n */\n public async getData(\n soundFile: string,\n timeout: number = 5000,\n maxDigits?: number,\n interDigitTimeout?: number\n ): Promise<{ digits: string; timeout: boolean }> {\n // If maxDigits is specified and interDigitTimeout is provided, use digit-by-digit collection\n if (maxDigits && maxDigits > 1 && interDigitTimeout) {\n return this.getDataWithInterDigitTimeout(soundFile, timeout, maxDigits, interDigitTimeout);\n }\n\n // Use standard GET DATA for simple cases\n const command = maxDigits !== undefined\n ? format('GET DATA %s %s %s', soundFile, timeout, maxDigits)\n : format('GET DATA %s %s', soundFile, timeout);\n\n const response = await this.sendCommand(command);\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not get data from channel');\n }\n\n return {\n digits: response.arguments.string('result'),\n timeout: response.arguments.string('value') === '(timeout)',\n };\n }\n\n /**\n * Internal method to collect digits with inter-digit timeout support\n * @param soundFile The audio file to play\n * @param totalTimeout Total timeout in milliseconds\n * @param maxDigits Maximum number of digits to collect\n * @param interDigitTimeout Timeout between digits in milliseconds\n */\n private async getDataWithInterDigitTimeout(\n soundFile: string,\n totalTimeout: number,\n maxDigits: number,\n interDigitTimeout: number\n ): Promise<{ digits: string; timeout: boolean }> {\n let collectedDigits = '';\n\n // Play the sound file first, allowing any digit to interrupt\n try {\n // Use STREAM FILE directly instead of streamFile() to avoid PLAYBACKSTATUS check\n const response = await this.sendCommand(\n format('STREAM FILE %s \"%s\"', soundFile, '0123456789*#')\n );\n\n if (response.code === 200 && response.result !== -1) {\n const digit = response.arguments.char('result');\n\n // If user pressed a digit during playback, collect it\n if (digit) {\n collectedDigits += digit;\n\n // If we already have max digits, return immediately\n if (collectedDigits.length === maxDigits) {\n return { digits: collectedDigits, timeout: false };\n }\n }\n }\n } catch (error) {\n // Continue even if file fails to play\n }\n\n // Start timing AFTER audio finishes - totalTimeout only applies to digit collection\n const startTime = Date.now();\n\n // Collect remaining digits one by one with inter-digit timeout\n while (collectedDigits.length < maxDigits) {\n const elapsedTime = Date.now() - startTime;\n const remainingTotalTimeout = totalTimeout - elapsedTime;\n\n if (remainingTotalTimeout <= 0) {\n return { digits: collectedDigits, timeout: collectedDigits.length === 0 };\n }\n\n // For the first digit, use totalTimeout. For subsequent digits, use interDigitTimeout\n const timeoutToUse = collectedDigits.length === 0\n ? remainingTotalTimeout\n : Math.min(interDigitTimeout, remainingTotalTimeout);\n\n try {\n // Convert milliseconds to seconds for waitForDigit\n const digit = await this.waitForDigit(timeoutToUse / 1000);\n\n if (!digit) {\n // Timeout waiting for digit\n return { digits: collectedDigits, timeout: collectedDigits.length === 0 };\n }\n\n collectedDigits += digit;\n\n if (collectedDigits.length === maxDigits) {\n return { digits: collectedDigits, timeout: false };\n }\n } catch (error) {\n return { digits: collectedDigits, timeout: true };\n }\n }\n\n return { digits: collectedDigits, timeout: false };\n }\n\n /**\n * Evaluates a channel expression\n * Understands complex variable names and builtin variables, unlike GET VARIABLE.\n * @param key\n * @param channel\n */\n public async getFullVariable(key: string, channel?: string): Promise<string> {\n const response = await this.sendCommand(\n format('GET FULL VARIABLE %s %s', key.toUpperCase(), channel || '')\n );\n\n if (response.code !== 200 || response.result === 0) {\n throw new Error('Variable not set');\n }\n\n return response.arguments.nokey();\n }\n\n /**\n * Stream file, prompt for DTMF, with timeout.\n * Behaves similar to STREAM FILE but used with a timeout option.\n * @param soundFile\n * @param escapeDigits\n * @param timeout\n */\n public async getOption(\n soundFile: string,\n escapeDigits: string = '#',\n timeout: number = 5\n ): Promise<{ digit: string; endpos: number }> {\n const response = await this.sendCommand(\n format('GET OPTION %s \"%s\" %s', soundFile, escapeDigits, timeout * 1000)\n );\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not get option');\n }\n\n if (response.arguments.number('endpos') === 0) {\n throw new Error('Could Not play file');\n }\n\n return {\n digit: response.arguments.char('result'),\n endpos: response.arguments.number('endpos'),\n };\n }\n\n /**\n * Gets a channel variable.\n * @param key\n */\n public async getVariable(key: string): Promise<string> {\n const response = await this.sendCommand(\n format('GET VARIABLE %s', key.toUpperCase())\n );\n\n if (response.code !== 200 || response.result === 0) {\n throw new Error('Variable not set');\n }\n\n return response.arguments.nokey();\n }\n\n /**\n * Cause the channel to execute the specified dialplan subroutine.\n * @param context\n * @param extension\n * @param priority\n * @param argument\n */\n public async goSub(\n context: string,\n extension: string,\n priority: number,\n argument?: string\n ): Promise<void> {\n const response = await this.sendCommand(\n format('GOSUB %s %s %s %s', context, extension, priority, argument || '')\n );\n\n if (response.code !== 200 || response.result !== 0) {\n throw new Error('Could not execute gosub');\n }\n }\n\n /**\n * Hangs up the specified channel. If no channel name is given, hangs up the current channel\n * @param channel\n */\n public async hangup(channel?: string): Promise<void> {\n const response = await this.sendCommand(format('HANGUP %s', channel || ''));\n\n if (response.code !== 200 || response.result !== 1) {\n throw new Error('Could not hang up call');\n }\n }\n\n /**\n * Does nothing\n */\n public async noop(): Promise<void> {\n const response = await this.sendCommand('NOOP');\n\n if (response.code !== 200 || response.result !== 0) {\n throw new Error('Could not NOOP');\n }\n }\n\n /**\n * Receives one character from channels supporting it.\n * @param timeout\n */\n public async receiveChar(\n timeout: number = 5\n ): Promise<{ char: string; timeout: boolean }> {\n const response = await this.sendCommand(\n format('RECEIVE CHAR %s', timeout * 1000)\n );\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not get data from channel');\n }\n\n return {\n char: response.arguments.char('result'),\n timeout: response.arguments.boolean('timeout'),\n };\n }\n\n /**\n * Receives text from channels supporting it.\n * @param timeout\n */\n public async receiveText(timeout: number = 5): Promise<string> {\n const response = await this.sendCommand(\n format('RECEIVE TEXT %s', timeout * 1000)\n );\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not get data from channel');\n }\n\n return response.arguments.string('result');\n }\n\n /**\n * Records to a given file.\n * @param filename\n * @param fileFormat\n * @param escapeDigits\n * @param timeout\n * @param beep\n * @param silence\n * @param offsetSamples\n */\n public async recordFile(\n filename: string,\n fileFormat: string = 'gsm',\n escapeDigits: string = '#',\n timeout: number = 10,\n beep?: boolean,\n silence?: number,\n offsetSamples?: number\n ): Promise<{ digit: string; endpos: number; timeout: boolean }> {\n const response = await this.sendCommand(\n format(\n 'RECORD FILE %s %s \"%s\" %s %s %s %s',\n filename,\n fileFormat,\n escapeDigits,\n timeout * 1000,\n offsetSamples || '',\n beep ? 'BEEP' : '',\n silence ? format('s=%s', silence) : ''\n )\n );\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not record file');\n }\n\n return {\n digit: response.arguments.char('result'),\n endpos: response.arguments.number('endpos'),\n timeout: response.arguments.boolean('timeout'),\n };\n }\n\n /**\n * Says a given character string.\n * @param value\n * @param escapeDigits\n */\n public async sayAlpha(\n value: string,\n escapeDigits: string = '#'\n ): Promise<string> {\n const response = await this.sendCommand(\n format('SAY ALPHA %s \"%s\"', value, escapeDigits)\n );\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not say alpha');\n }\n\n return response.arguments.char('result');\n }\n\n /**\n * Says a given date.\n * @param value\n * @param escapeDigits\n */\n public async sayDate(\n value: Date | number,\n escapeDigits: string = '#'\n ): Promise<string> {\n const response = await this.sendCommand(\n format(\n 'SAY DATE %s \"%s\"',\n typeof value === 'number' ? value : Math.floor(value.getTime() / 1000),\n escapeDigits\n )\n );\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not say date');\n }\n\n return response.arguments.char('result');\n }\n\n /**\n * Says a given time as specified by the format given.\n * @param value\n * @param escapeDigits\n * @param dateFormat\n * @param timezone\n */\n public async sayDateTime(\n value: Date | number,\n escapeDigits: string = '#',\n dateFormat?: string,\n timezone?: string\n ): Promise<string> {\n const response = await this.sendCommand(\n format(\n 'SAY DATETIME %s \"%s\" %s %s',\n typeof value === 'number' ? value : Math.floor(value.getTime() / 1000),\n escapeDigits,\n dateFormat || '',\n timezone || ''\n )\n );\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not say date time');\n }\n\n return response.arguments.char('result');\n }\n\n /**\n * Says a given digit string.\n * @param value\n * @param escapeDigits\n */\n public async sayDigits(\n value: string,\n escapeDigits: string = '#'\n ): Promise<string> {\n const response = await this.sendCommand(\n format('SAY DIGITS %s \"%s\"', value, escapeDigits)\n );\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not say digits');\n }\n\n return response.arguments.char('result');\n }\n\n /**\n * Says a given number.\n * @param value\n * @param escapeDigits\n */\n public async sayNumber(\n value: number,\n escapeDigits: string = '#'\n ): Promise<string> {\n const response = await this.sendCommand(\n format('SAY NUMBER %s \"%s\"', value, escapeDigits)\n );\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not say number');\n }\n\n return response.arguments.char('result');\n }\n\n /**\n * Says a given character string with phonetics.\n * @param value\n * @param escapeDigits\n */\n public async sayPhonetic(\n value: string,\n escapeDigits: string = '#'\n ): Promise<string> {\n const response = await this.sendCommand(\n format('SAY PHONETIC %s \"%s\"', value, escapeDigits)\n );\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not say phonetic');\n }\n\n return response.arguments.char('result');\n }\n\n /**\n * Says a given time.\n * @param value\n * @param escapeDigits\n */\n public async sayTime(\n value: Date | number,\n escapeDigits: string = '#'\n ): Promise<string> {\n const response = await this.sendCommand(\n format(\n 'SAY TIME %s \"%s\"',\n typeof value === 'number' ? value : Math.floor(value.getTime() / 1000),\n escapeDigits\n )\n );\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not say time');\n }\n\n return response.arguments.char('result');\n }\n\n /**\n * Sends images to channels supporting it.\n * @param image\n */\n public async sendImage(image: string): Promise<void> {\n const response = await this.sendCommand(format('SEND IMAGE %s', image));\n\n if (response.code !== 200 || response.result !== 0) {\n throw new Error('Could not send image');\n }\n }\n\n /**\n * Sends text to channels supporting it.\n * @param text\n */\n public async sendText(text: string): Promise<void> {\n const response = await this.sendCommand(format('SEND TEXT \"%s\"', text));\n\n if (response.code !== 200 || response.result !== 0) {\n throw new Error('Could not send text');\n }\n }\n\n /**\n * Autohangup channel in some time.\n * @param timeout\n */\n public async setAutoHangup(timeout: number = 60): Promise<void> {\n const response = await this.sendCommand(\n format('SET AUTOHANGUP %s', timeout)\n );\n\n if (response.code !== 200 || response.result !== 0) {\n throw new Error('Could not set auto hangup');\n }\n }\n\n /**\n * Sets callerid for the current channel.\n * @param callerNumber\n * @param callerName\n */\n public async setCallerID(\n callerNumber: number,\n callerName?: string\n ): Promise<void> {\n const callerid = callerName\n ? format('\"%s\"<%s>', callerName, callerNumber)\n : callerNumber;\n\n const response = await this.sendCommand(\n format('SET CALLERID %s', callerid)\n );\n\n if (response.code !== 200 || response.result !== 1) {\n throw new Error('Could not set caller id');\n }\n }\n\n /**\n * Sets channel context.\n * @param context\n */\n public async setContext(context: string): Promise<void> {\n const response = await this.sendCommand(format('SET CONTEXT %s', context));\n\n if (response.code !== 200 || response.result !== 0) {\n throw new Error('Could not set context');\n }\n }\n\n /**\n * Changes channel extension.\n * @param extension\n */\n public async setExtension(extension: string): Promise<void> {\n const response = await this.sendCommand(\n format('SET EXTENSION %s', extension)\n );\n\n if (response.code !== 200 || response.result !== 0) {\n throw new Error('Could not set extension');\n }\n }\n\n /**\n * Enable/Disable Music on hold generator\n * @param status\n * @param musicClass\n */\n public async setMusic(\n status: boolean = true,\n musicClass?: string\n ): Promise<void> {\n const response = await this.sendCommand(\n format('SET MUSIC %s %s', status ? 'ON' : 'OFF', musicClass || '')\n );\n\n if (response.code !== 200 || response.result !== 0) {\n throw new Error('Could not set priority');\n }\n }\n\n /**\n * Set channel dialplan priority.\n * @param priority\n */\n public async setPriority(priority: number): Promise<void> {\n const response = await this.sendCommand(\n format('SET PRIORITY %s', priority)\n );\n\n if (response.code !== 200 || response.result !== 0) {\n throw new Error('Could not set priority');\n }\n }\n\n /**\n * Sets a channel variable.\n * @param key - The variable name\n * @param value - The variable value\n * @throws Error if the variable could not be set\n */\n public async setVariable(key: string, value: string): Promise<void> {\n const response = await this.sendCommand(\n format('SET VARIABLE %s \"%s\"', key.toUpperCase(), value)\n );\n\n if (response.code !== 200 || response.result !== 1) {\n throw new Error('Could not set variable');\n }\n }\n\n public async speechActivateGrammar(grammar: string): Promise<IResponse> {\n // TODO: Handle the response\n return this.sendCommand(format('SPEECH ACTIVATE GRAMMAR %s', grammar));\n }\n\n public async speechCreate(engine: string): Promise<IResponse> {\n // TODO: Handle the response\n return this.sendCommand(format('SPEECH CREATE ENGINE %s', engine));\n }\n\n public async speechDeactivateGrammar(grammar: string): Promise<IResponse> {\n // TODO: Handle the response\n return this.sendCommand(format('SPEECH DEACTIVATE GRAMMAR %s', grammar));\n }\n\n public async speechDestroy(): Promise<IResponse> {\n // TODO: Handle the response\n return this.sendCommand('SPEECH DESTROY');\n }\n\n public async speechLoadGrammar(\n grammar: string,\n path: string\n ): Promise<IResponse> {\n // TODO: Handle the response\n return this.sendCommand(format('SPEECH LOAD GRAMMAR %s %s', grammar, path));\n }\n\n public async speechRecognize(\n soundFile: string,\n timeout: number = 5,\n offset: number\n ): Promise<IResponse> {\n // TODO: Handle the response\n return this.sendCommand(\n format('SPEECH RECOGNIZE %s %s %s', soundFile, timeout * 1000, offset)\n );\n }\n\n public async speechSet(key: string, value: string): Promise<IResponse> {\n // TODO: Handle the response\n return this.sendCommand(format('SPEECH SET %s %s', key, value));\n }\n\n public async speedUnloadGrammar(grammar: string): Promise<IResponse> {\n // TODO: Handle the response\n return this.sendCommand(format('SPEECH UNLOAD GRAMMAR %s', grammar));\n }\n\n /**\n * Streams an audio file to the channel, allowing playback to be interrupted by DTMF digits.\n *\n * The file extension should not be included in the filename - Asterisk will automatically\n * select the best available format based on the channel's codec.\n *\n * @param filename - The audio file to play (without extension, e.g., \"welcome\" not \"welcome.wav\")\n * @param escapeDigits - DTMF digits that will interrupt playback (default: \"#\"). Use \"\" for none.\n * @param offset - Sample offset to start playback from (optional)\n * @returns Object containing:\n * - `digit`: The DTMF digit pressed to interrupt, or empty string if played to completion\n * - `endpos`: The sample position where playback stopped\n * @throws Error if the file could not be played or PLAYBACKSTATUS is not SUCCESS\n *\n * @example\n * ```typescript\n * // Play a file, allowing any digit to interrupt\n * const result = await channel.streamFile('welcome', '0123456789*#');\n * if (result.digit) {\n * console.log(`User pressed: ${result.digit}`);\n * }\n *\n * // Play a file without allowing interruption\n * await channel.streamFile('announcement', '');\n * ```\n *\n * @see https://docs.asterisk.org/Asterisk_22_Documentation/API_Documentation/AGI_Commands/stream_file\n */\n public async streamFile(\n filename: string,\n escapeDigits: string = '#',\n offset?: number\n ): Promise<{ digit: string; endpos: number }> {\n const response = await this.sendCommand(\n format('STREAM FILE %s \"%s\" %s', filename, escapeDigits, offset || '')\n );\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not stream file');\n }\n\n const status = await this.getVariable('PLAYBACKSTATUS');\n\n if (status !== 'SUCCESS') {\n throw new Error('Could not stream file');\n }\n\n return {\n digit: response.arguments.char('result'),\n endpos: response.arguments.number('endpos'),\n };\n }\n\n /**\n * Toggles TDD mode (for the deaf).\n * @param status\n */\n public async tddMode(status: boolean): Promise<void> {\n const response = await this.sendCommand(\n format('TDD MODE %s', status ? 'ON' : 'OFF')\n );\n\n if (response.code !== 200 || response.result !== 1) {\n throw new Error('Could not set TDD mode');\n }\n }\n\n /**\n * Logs a message to the asterisk verbose log.\n * @param message\n * @param level\n */\n public async verbose(message: string, level?: number): Promise<void> {\n const response = await this.sendCommand(\n format('VERBOSE \"%s\" %s', message, level || '')\n );\n\n if (response.code !== 200 || response.result !== 1) {\n throw new Error('Could not send logging message');\n }\n }\n\n /**\n * Waits for a digit to be pressed.\n * @param timeout Timeout in seconds\n */\n public async waitForDigit(timeout: number = 5): Promise<string> {\n // Convert timeout from seconds to milliseconds and add 2s safety margin for network/processing latency\n const commandTimeout = (timeout * 1000) + 2000;\n\n const response = await this.sendCommand(\n format('WAIT FOR DIGIT %s', timeout * 1000),\n commandTimeout\n );\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not wait for digit');\n }\n\n return response.arguments.char('result');\n }\n\n /* Internal Methods */\n\n private close() {\n this.m_connection.destroy();\n }\n\n private read(data: Buffer): void {\n if (data.length === 0) {\n return;\n }\n\n this.m_message += data.toString();\n\n if (this.m_state === ContextState.INIT) {\n if (this.m_message.indexOf('\\n\\n') === -1) {\n return;\n }\n\n this.readVariables(this.m_message);\n } else if (this.m_state === ContextState.WAITING) {\n if (this.m_message.indexOf('\\n') === -1) {\n return;\n }\n\n this.readResponse(this.m_message);\n }\n\n this.m_message = '';\n }\n\n private readVariables(message: string) {\n const lines = message.split('\\n');\n\n lines.map((line) => {\n const split = line.split(':');\n const name: string = (split[0] || '').trim();\n const value: string = (split[1] || '').trim();\n\n const id = name.substring(4);\n\n switch (id) {\n case 'network':\n return (this.m_network = value);\n case 'network_script':\n return (this.m_network_script = value);\n case 'request':\n return (this.m_request = value);\n case 'channel':\n return (this.m_channel = value);\n case 'language':\n return (this.m_language = value);\n case 'type':\n return (this.m_type = value);\n case 'uniqueid':\n return (this.m_uniqueid = value);\n case 'version':\n return (this.m_version = value);\n case 'callerid':\n return (this.m_callerid = value);\n case 'calleridname':\n return (this.m_calleridname = value);\n case 'callingpres':\n return (this.m_callingpres = value);\n case 'callingani2':\n return (this.m_callingani2 = value);\n case 'callington':\n return (this.m_callington = value);\n case 'callingtns':\n return (this.m_callingtns = value);\n case 'dnid':\n return (this.m_dnid = value);\n case 'rdnis':\n return (this.m_rdnis = value);\n case 'context':\n return (this.m_context = value);\n case 'extension':\n return (this.m_extension = value);\n case 'priority':\n return (this.m_priority = value);\n case 'enhanced':\n return (this.m_enhanced = value);\n case 'accountcode':\n return (this.m_accountcode = value);\n case 'threadid':\n return (this.m_threadid = value);\n }\n });\n\n this.m_state = ContextState.WAITING;\n\n this.emit('ready');\n }\n\n private readResponse(message: string) {\n const lines = message.split('\\n');\n\n lines.map((line) => this.readResponseLine(line));\n }\n\n private readResponseLine(line: string) {\n if (!line) {\n return;\n }\n\n this.emit('recv', line);\n\n const parsed = line.split(' ');\n\n if (!parsed || parsed[0] === 'HANGUP') {\n return this.emit('hangup');\n }\n\n const code = parseInt(parsed[0], 10);\n parsed.shift();\n\n const args: ResponseArguments = new ResponseArguments();\n\n for (const value of parsed) {\n if (value.indexOf('=') !== -1) {\n const parts = value.split('=', 2);\n const key = parts[0].trim();\n const val = parts[1].trim();\n args.addArgument(key, val);\n } else if (value.indexOf('(') !== -1) {\n const name = value.substring(1, value.length - 1);\n args.addArgument(name, true);\n } else {\n args.addArgument('value', value);\n }\n }\n\n const response: IResponse = {\n code: code,\n result: args.number('result'),\n arguments: args,\n };\n\n this.emit('response', response);\n }\n\n private async send(message: string): Promise<void> {\n return new Promise((resolve, reject) => {\n if (!this.m_connection || this.m_connection.destroyed) {\n return reject(new Error('Stream has been destroyed'));\n }\n this.emit('send', message);\n this.m_connection.write(message, (error) => {\n if (error) {\n return reject(error);\n }\n resolve();\n });\n });\n }\n\n /**\n * Sends an AGI command and waits for response using a FIFO queue\n * @param command AGI command to send\n * @param timeout Optional timeout in milliseconds (default: 10000ms)\n */\n private async sendCommand(\n command: string,\n timeout?: number\n ): Promise<IResponse> {\n return new Promise((resolve, reject) => {\n // Check if channel is still alive\n if (!this.channelAlive) {\n return reject(new Error('Channel is no longer alive'));\n }\n\n // Check queue size limit (backpressure)\n if (this.commandQueue.length >= this.maxQueueSize) {\n return reject(\n new Error(\n `Command queue full (${this.maxQueueSize}). Command rejected: ${command}`\n )\n );\n }\n\n // Add command to queue\n const queuedCommand: IQueuedCommand = {\n command,\n resolve,\n reject,\n timeout: timeout ?? this.getCommandTimeout(command),\n timestamp: Date.now(),\n };\n\n this.commandQueue.push(queuedCommand);\n\n // Emit event for monitoring\n this.emit('commandQueued', {\n command,\n queueSize: this.commandQueue.length,\n });\n\n // Start processing if not active\n if (!this.isProcessingCommand) {\n this.processCommandQueue();\n }\n });\n }\n\n /**\n * Gets the appropriate timeout for a given command\n * @param command The AGI command string\n * @returns Timeout in milliseconds (or Infinity for no timeout)\n */\n private getCommandTimeout(command: string): number {\n // Comandos r\u00E1pidos (devem responder em segundos)\n if (\n command.startsWith('ANSWER') ||\n command.startsWith('HANGUP') ||\n command.startsWith('CHANNEL STATUS') ||\n command.startsWith('GET VARIABLE') ||\n command.startsWith('SET VARIABLE') ||\n command.startsWith('DATABASE')\n ) {\n return 10000; // 10 segundos\n }\n\n // Comandos m\u00E9dios (audio playback, prompts)\n if (\n command.startsWith('STREAM FILE') ||\n command.startsWith('SAY ') ||\n command.startsWith('GET DATA') ||\n command.startsWith('GET OPTION')\n ) {\n return 60000; // 1 minuto\n }\n\n // Comandos de grava\u00E7\u00E3o\n if (command.startsWith('RECORD FILE')) {\n return 600000; // 10 minutos\n }\n\n // EXEC: pode incluir Dial, Queue, VoiceMail (podem durar horas)\n if (command.startsWith('EXEC')) {\n return this.maxCallDuration; // 6 horas padr\u00E3o\n }\n\n // Outros comandos\n return this.defaultCommandTimeout; // 10 segundos\n }\n\n /**\n * Processes the command queue sequentially (FIFO)\n */\n private async processCommandQueue(): Promise<void> {\n if (this.commandQueue.length === 0) {\n this.isProcessingCommand = false;\n this.emit('queueEmpty');\n return;\n }\n\n this.isProcessingCommand = true;\n const queuedCommand = this.commandQueue.shift()!;\n\n try {\n const response = await this.sendCommandInternal(\n queuedCommand.command,\n queuedCommand.timeout!\n );\n\n // Emit success event\n this.emit('commandProcessed', {\n command: queuedCommand.command,\n duration: Date.now() - queuedCommand.timestamp,\n });\n\n queuedCommand.resolve(response);\n } catch (err) {\n // Emit error event\n this.emit('commandFailed', {\n command: queuedCommand.command,\n error: err,\n });\n\n queuedCommand.reject(err);\n } finally {\n // Process next command (continues even with error)\n setImmediate(() => this.processCommandQueue());\n }\n }\n\n /**\n * Internal implementation of command sending\n * @param command The AGI command to send\n * @param timeout Timeout in milliseconds, or Infinity for no timeout\n */\n private sendCommandInternal(\n command: string,\n timeout: number\n ): Promise<IResponse> {\n return new Promise((resolve, reject) => {\n // Check connection state and channel status\n if (\n !this.channelAlive ||\n !this.m_connection ||\n this.m_connection.destroyed\n ) {\n return reject(new Error('Channel is no longer alive'));\n }\n\n let timeoutId: NodeJS.Timeout | null = null;\n\n const responseHandler = (response: IResponse) => {\n cleanup();\n resolve(response);\n };\n\n const cleanup = () => {\n this.removeListener('response', responseHandler);\n if (timeoutId) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n };\n\n // Register listener\n this.once('response', responseHandler);\n\n // Configurable timeout (supports Infinity for no timeout)\n if (timeout > 0 && timeout !== Infinity) {\n timeoutId = setTimeout(() => {\n cleanup();\n reject(new Error(`Command timeout after ${timeout}ms: ${command}`));\n }, timeout);\n }\n // If timeout is Infinity or <= 0, no timeout is set (relies on channelAlive)\n\n // Send command\n this.send(format('%s\\n', command.trim())).catch((err) => {\n cleanup();\n reject(err);\n });\n });\n }\n\n /**\n * Handles channel closure with pending commands\n */\n private handleChannelClose(): void {\n this.channelAlive = false;\n const pendingCount = this.commandQueue.length;\n\n if (pendingCount > 0) {\n this.emit('queueCleared', {\n reason: 'channel_closed',\n commandsCleared: pendingCount,\n });\n\n // Reject all pending commands\n while (this.commandQueue.length > 0) {\n const cmd = this.commandQueue.shift()!;\n cmd.reject(new Error('Channel closed before command could be sent'));\n }\n }\n\n this.isProcessingCommand = false;\n }\n\n /**\n * Handles HANGUP from Asterisk\n */\n private handleHangup(): void {\n this.channelAlive = false;\n const pendingCount = this.commandQueue.length;\n\n if (pendingCount > 0) {\n this.emit('queueCleared', {\n reason: 'hangup',\n commandsCleared: pendingCount,\n });\n\n // Reject pending commands\n while (this.commandQueue.length > 0) {\n const cmd = this.commandQueue.shift()!;\n cmd.reject(new Error('Call hung up before command could be executed'));\n }\n }\n\n this.isProcessingCommand = false;\n }\n\n /**\n * Manually clears the command queue (for emergency cases)\n */\n public clearCommandQueue(): number {\n const clearedCount = this.commandQueue.length;\n\n while (this.commandQueue.length > 0) {\n const cmd = this.commandQueue.shift()!;\n cmd.reject(new Error('Command queue manually cleared'));\n }\n\n this.isProcessingCommand = false;\n\n this.emit('queueCleared', {\n reason: 'manual',\n commandsCleared: clearedCount,\n });\n\n return clearedCount;\n }\n\n /**\n * Returns queue statistics\n */\n public getQueueStats(): {\n size: number;\n isProcessing: boolean;\n oldestCommandAge: number | null;\n } {\n const oldest = this.commandQueue[0];\n\n return {\n size: this.commandQueue.length,\n isProcessing: this.isProcessingCommand,\n oldestCommandAge: oldest ? Date.now() - oldest.timestamp : null,\n };\n }\n}\n", "// Copyright (c) 2020, Brandon Lehmann\n//\n// Please see the included LICENSE file for more information.\n\n/** @ignore */\nexport interface IResponseArguments {\n key: string;\n value: string | number | boolean;\n}\n\n/**\n * Represents a set of AGI response arguments\n * @ignore\n */\nexport class ResponseArguments {\n private m_args: IResponseArguments[] = [];\n\n /**\n * Adds a new argument to the set\n * @param key\n * @param value\n */\n public addArgument(key: string, value: string | number | boolean) {\n this.m_args.push({key, value});\n }\n\n /**\n * Retrieves the requested key as a string\n * @param key\n */\n public string(key: string): string {\n for (const arg of this.m_args) {\n if (arg.key === key) {\n return (arg.value as string);\n }\n }\n\n return '';\n }\n\n /**\n * Retrieves the requested key as a number\n * @param key\n */\n public number(key: string): number {\n for (const arg of this.m_args) {\n if (arg.key === key) {\n return parseInt((arg.value as string), 10);\n }\n }\n\n return 0;\n }\n\n /**\n * Retrieves the request key as a boolean\n * @param key\n */\n public boolean(key: string): boolean {\n for (const arg of this.m_args) {\n if (arg.key === key) {\n return (arg.value as boolean);\n }\n }\n\n return false;\n }\n\n /**\n * Retrieves the requested key from a character code\n * @param key\n */\n public char(key: string): string {\n const num = this.number(key);\n\n return (num !== 0) ? String.fromCharCode(num) : '';\n }\n\n /**\n * Retrieves the value from the arguments that has no key, if it exists\n */\n public nokey(): string {\n for (const arg of this.m_args) {\n if (arg.key !== 'result' && arg.value) {\n return arg.key;\n }\n }\n\n return '';\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["// Copyright (c) 2020, Brandon Lehmann\n//\n// Please see the included LICENSE file for more information.\n\nimport * as net from 'net';\nimport {EventEmitter} from 'events';\nimport {Channel} from './Channel';\nimport {format} from 'util';\n\n/**\n * Represents an AGI server instance\n */\nexport class AGIServer extends EventEmitter {\n private readonly m_port: number;\n private readonly m_ip: string;\n private readonly m_server: net.Server = net.createServer();\n\n /**\n * Constructs a new instance of the object\n * @param port\n * @param ip\n */\n constructor(port: number = 3000, ip: string = '0.0.0.0') {\n super();\n this.setMaxListeners(10);\n\n this.m_port = port;\n this.m_ip = ip;\n\n this.m_server.on('connection', (socket: net.Socket) => {\n const channel = new Channel(socket);\n\n channel.on('ready', () => this.emit('channel', channel));\n });\n }\n\n /**\n * Event that is emitted when a new AGI channel has been established and is ready for interation\n * @param event\n * @param listener\n */\n public on(event: 'channel', listener: (channel: Channel) => void): this;\n\n /**\n * Event that is emitted when the AGI server is started and in a listening state\n * @param event\n * @param listener\n */\n public on(event: 'listening', listener: (port: number, ip: string) => void): this;\n\n /**\n * Event that is emitted when the server encounters and error\n * @param event\n * @param listener\n */\n public on(event: 'error', listener: (error: any) => void): this;\n\n /**\n * Event that emitted when the server is closed and stopped\n * @param event\n * @param listener\n */\n public on(event: 'close', listener: () => void): this;\n\n public on(event: any, listener: (...args: any[]) => void): this {\n return super.on(event, listener);\n }\n\n /**\n * Starts the AGI server\n */\n public async start(): Promise<void> {\n this.m_server.on('error', (error) =>\n this.emit('error', new Error(\n format('Internal TCP server error: %s', error.toString()),\n )),\n );\n\n this.m_server.on('close', () => this.emit('close'));\n\n this.m_server.listen(this.m_port, this.m_ip, () => {\n this.emit('listening', this.m_port, this.m_ip);\n });\n }\n\n /**\n * Stops the AGI server\n */\n public async stop(): Promise<void> {\n return new Promise((resolve, reject) => {\n this.m_server.close((error) => {\n if (error) {\n return reject(error);\n }\n return resolve();\n });\n });\n }\n}\n", "// Copyright (c) 2020, Brandon Lehmann\n//\n// Please see the included LICENSE file for more information.\n\nimport { EventEmitter } from 'node:events';\nimport type { Socket } from 'node:net';\nimport { format } from 'node:util';\nimport { ResponseArguments } from './ResponseArguments';\n\n/** @ignore */\nenum ContextState {\n INIT = 0,\n WAITING = 2,\n}\n\n/**\n * Represents the current channel state\n */\nexport enum ChannelState {\n DOWN_AVAILABLE = 0,\n DOWN_RESERVED,\n OFF_HOOK,\n DIGITS_DIALED,\n RINGING,\n REMOTE_RINGING,\n UP,\n BUSY,\n}\n\n/**\n * Represents the result of a Dial() attempt\n */\nexport enum DialStatus {\n ANSWER,\n BUSY,\n NOANSWER,\n CANCEL,\n CONGESTION,\n CHANUNAVAIL,\n DONTCALL,\n TORTURE,\n INVALIDARGS,\n}\n\n/**\n * Represents the playback status\n */\nexport enum PlaybackStatus {\n SUCCESS,\n USER_STOPPED,\n REMOTE_STOPPED,\n ERROR,\n}\n\n/** @ignore */\ninterface IResponse {\n code: number;\n result: number;\n arguments: ResponseArguments;\n}\n\n/** @ignore */\ninterface IQueuedCommand {\n command: string;\n resolve: (value: IResponse) => void;\n reject: (reason: any) => void;\n timeout?: number;\n timestamp: number;\n}\n\n/**\n * Represents an AGI Channel\n */\nexport class Channel extends EventEmitter {\n private readonly m_connection: Socket;\n private m_state: ContextState;\n private m_message: string = '';\n private m_network: string = '';\n private m_network_script: string = '';\n private m_request: string = '';\n private m_channel: string = '';\n private m_language: string = '';\n private m_type: string = '';\n private m_uniqueid: string = '';\n private m_version: string = '';\n private m_callerid: string = '';\n private m_calleridname: string = '';\n private m_callingpres: string = '';\n private m_callingani2: string = '';\n private m_callington: string = '';\n private m_callingtns: string = '';\n private m_dnid: string = '';\n private m_rdnis: string = '';\n private m_context: string = '';\n private m_extension: string = '';\n private m_priority: string = '';\n private m_enhanced: string = '';\n private m_accountcode: string = '';\n private m_threadid: string = '';\n private commandQueue: IQueuedCommand[] = [];\n private isProcessingCommand = false;\n private channelAlive = true;\n private readonly maxQueueSize = 100;\n private readonly defaultCommandTimeout = 10000;\n private readonly maxCallDuration = 21600000; // 6 horas (360 minutos)\n\n /**\n * Creates a new instance of a channel object\n * @param connection the AGI socket connection\n */\n constructor(connection: Socket) {\n super();\n this.setMaxListeners(10);\n\n this.m_connection = connection;\n this.m_state = ContextState.INIT;\n\n this.m_connection.on('data', (data: Buffer) => this.read(data));\n this.m_connection.on('close', () => {\n this.handleChannelClose();\n this.emit('close');\n });\n this.m_connection.on('error', (error) => this.emit('error', error));\n this.m_connection.on('timeout', () => this.emit('timeout'));\n this.on('hangup', () => {\n this.handleHangup();\n this.close();\n });\n }\n\n /**\n * Event that is emitted when the underlying socket encounters an error\n * @param event\n * @param listener\n */\n public on(event: 'error', listener: (error: any) => void): this;\n\n /**\n * Event that is emitted when the underlying socket is closed\n * @param event\n * @param listener\n */\n public on(event: 'close', listener: () => void): this;\n\n /**\n * Event that emitted when the underlying socket times out\n * @param event\n * @param listener\n */\n public on(event: 'timeout', listener: () => void): this;\n\n /**\n * Event that is emitted when the channel is ready\n * @param event\n * @param listener\n */\n public on(event: 'ready', listener: () => void): this;\n\n /**\n * Event that is emitted when a response is received from the Asterisk server\n * @param event\n * @param listener\n */\n public on(event: 'recv', listener: (response: string) => void): this;\n\n /**\n * Event that emitted when the channel is hung up\n * @param event\n * @param listener\n */\n public on(event: 'hangup', listener: () => void): this;\n\n /**\n * Event that emitted when the response from the Asterisk server is processed into a structured response\n * @param event\n * @param listener\n */\n public on(event: 'response', listener: (response: IResponse) => void): this;\n\n /**\n * Event that is emitted when data is sent to the Asterisk server\n * @param event\n * @param listener\n */\n public on(event: 'send', listener: (data: string) => void): this;\n\n public on(event: any, listener: (...args: any[]) => void): this {\n return super.on(event, listener);\n }\n\n /**\n * Whether this AGI request is over the network\n */\n public get network(): boolean {\n return this.m_network.toLowerCase() === 'yes';\n }\n\n /**\n * The network path included in the AGI request\n * ie. agi://127.0.0.1:3000/test\n * This value would return 'test'\n */\n public get network_script(): string {\n return this.m_network_script;\n }\n\n /**\n * The version of Asterisk\n */\n public get version(): string {\n return this.m_version;\n }\n\n /**\n * The filename of your script\n * ie. agi\n */\n public get request(): string {\n return this.m_request;\n }\n\n /**\n * The originating channel (your phone)\n */\n public get channel(): string {\n return this.m_channel;\n }\n\n /**\n * The language code (e.g. \u201Cen\u201D)\n */\n public get language(): string {\n return this.m_language;\n }\n\n /**\n * The originating channel type (e.g. \u201CSIP\u201D or \u201CZAP\u201D)\n */\n public get type(): string {\n return this.m_type;\n }\n\n /**\n * A unique ID for the call\n */\n public get uniqueid(): string {\n return this.m_uniqueid;\n }\n\n /**\n * The caller ID number (or \u201Cunknown\u201D)\n */\n public get callerid(): string {\n return this.m_callerid;\n }\n\n /**\n * The caller ID name (or \u201Cunknown\u201D)\n */\n public get calleridname(): string {\n return this.m_calleridname;\n }\n\n /**\n * The presentation for the callerid in a ZAP channel\n */\n public get callingpres(): string {\n return this.m_callingpres;\n }\n\n /**\n * The number which is defined in ANI2 see Asterisk Detailed Variable List (only for PRI Channels)\n */\n public get callingani2(): string {\n return this.m_callingani2;\n }\n\n /**\n * The type of number used in PRI Channels see Asterisk Detailed Variable List\n */\n public get callington(): string {\n return this.m_callington;\n }\n\n /**\n * An optional 4 digit number (Transit Network Selector) used in PRI Channels see Asterisk Detailed Variable List\n */\n public get callingtns(): string {\n return this.m_callingtns;\n }\n\n /**\n * The dialed number id (or \u201Cunknown\u201D)\n */\n public get dnid(): string {\n return this.m_dnid;\n }\n\n /**\n * The referring DNIS number (or \u201Cunknown\u201D)\n */\n public get rdnis(): string {\n return this.m_rdnis;\n }\n\n /**\n * Origin context in extensions.conf\n */\n public get context(): string {\n return this.m_context;\n }\n\n /**\n * The called number\n */\n public get extension(): string {\n return this.m_extension;\n }\n\n /**\n * The priority it was executed as in the dial plan\n */\n public get priority(): string {\n return this.m_priority;\n }\n\n /**\n * The flag value is 1.0 if started as an EAGI script, 0.0 otherwise\n */\n public get enhanced(): string {\n return this.m_enhanced;\n }\n\n /**\n * Account code of the origin channel\n */\n public get accountcode(): string {\n return this.m_accountcode;\n }\n\n /**\n * Thread ID of the AGI script\n */\n public get threadid(): string {\n return this.m_threadid;\n }\n\n /**\n * Answers channel if not already in answer state.\n */\n public async answer(): Promise<void> {\n const response = await this.sendCommand('ANSWER');\n\n if (response.code !== 200 || response.result !== 0) {\n throw new Error('Could not answer call');\n }\n }\n\n /**\n * Interrupts expected flow of Async AGI commands and returns control to\n * previous source (typically, the PBX dialplan).\n */\n public async break(): Promise<void> {\n const response = await this.sendCommand('ASYNCAGI BREAK');\n\n if (response.code !== 200 || response.result !== 0) {\n throw new Error('Could not interrupt processing');\n }\n\n return this.close();\n }\n\n /**\n * Returns status of the connected channel.\n * @param channel\n */\n public async channelStatus(channel?: string): Promise<ChannelState> {\n const response = await this.sendCommand(\n format('CHANNEL STATUS %s', channel || '')\n );\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not get channel status');\n }\n\n return response.result;\n }\n\n /**\n * Sends audio file on channel and allows the listener to control the stream.\n * @param filename\n * @param escapeDigits\n * @param skipms\n * @param fastForwardCharacter\n * @param rewindCharacter\n * @param pauseCharacter\n */\n public async controlStreamFile(\n filename: string,\n escapeDigits: string = '',\n skipms?: number,\n fastForwardCharacter?: string,\n rewindCharacter?: string,\n pauseCharacter?: string\n ): Promise<{\n digit: string;\n playbackStatus: PlaybackStatus;\n playbackOffset: number;\n }> {\n const response = await this.sendCommand(\n format(\n 'CONTROL STREAM FILE %s \"%s\" %s %s %s %s',\n filename,\n escapeDigits,\n skipms || '',\n fastForwardCharacter || '',\n rewindCharacter || '',\n pauseCharacter || ''\n )\n );\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not control stream file');\n }\n\n const playbackStatus = await this.getVariable('CPLAYBACKSTATUS ');\n\n const playbackOffset = await this.getVariable('CPLAYBACKOFFSET ');\n\n let status: PlaybackStatus = PlaybackStatus.ERROR;\n\n switch (playbackStatus.toUpperCase()) {\n case 'SUCCESS':\n status = PlaybackStatus.SUCCESS;\n break;\n case 'USERSTOPPED':\n status = PlaybackStatus.USER_STOPPED;\n break;\n case 'REMOTESTOPPED':\n status = PlaybackStatus.REMOTE_STOPPED;\n break;\n }\n\n return {\n digit: response.arguments.char('result'),\n playbackStatus: status,\n playbackOffset: parseInt(playbackOffset, 10),\n };\n }\n\n /**\n * Attempts to establish a new outgoing connection on a channel, and then link it to the calling input channel.\n *\n * **Important:** This method is blocking. It only returns when the call ends completely:\n * - If answered: returns after either party hangs up\n * - If not answered: returns after timeout expires\n * - If busy/unavailable: returns immediately\n *\n * @param target - The dial target (e.g., \"PJSIP/1000\", \"PJSIP/alice&PJSIP/bob\")\n * @param timeout - Ring timeout in seconds (default: 30)\n * @param params - Optional Dial parameters (e.g., \"m\" for music on hold, \"t\" for transfer)\n * @returns The dial status indicating how the call ended\n * @throws Error if an unknown dial status is returned\n *\n * @example\n * ```typescript\n * const status = await channel.dial('PJSIP/1000', 30, 'm');\n * if (status === DialStatus.ANSWER) {\n * console.log('Call was answered and has now ended');\n * } else if (status === DialStatus.BUSY) {\n * console.log('Destination was busy');\n * }\n * ```\n *\n * @see https://docs.asterisk.org/Asterisk_22_Documentation/API_Documentation/Dialplan_Applications/Dial\n */\n public async dial(\n target: string,\n timeout: number = 30,\n params?: string\n ): Promise<DialStatus> {\n // Note: exec('Dial') blocks until the call ends (bridge is destroyed or dial fails)\n await this.exec('Dial', format('%s,%s,%s', target, timeout, params || ''));\n\n const dialstatus = await this.getVariable('DIALSTATUS');\n\n switch (dialstatus.toUpperCase()) {\n case 'ANSWER':\n return DialStatus.ANSWER;\n case 'BUSY':\n return DialStatus.BUSY;\n case 'NOANSWER':\n return DialStatus.NOANSWER;\n case 'CANCEL':\n return DialStatus.CANCEL;\n case 'CONGESTION':\n return DialStatus.CONGESTION;\n case 'CHANUNAVAIL':\n return DialStatus.CHANUNAVAIL;\n case 'DONTCALL':\n return DialStatus.DONTCALL;\n case 'TORTURE':\n return DialStatus.TORTURE;\n case 'INVALIDARGS':\n return DialStatus.INVALIDARGS;\n default:\n throw new Error('Unknown dial status');\n }\n }\n\n /**\n * Deletes an entry in the Asterisk database for a given family and key.\n * @param family\n * @param key\n */\n public async databaseDel(family: string, key: string): Promise<void> {\n const response = await this.sendCommand(\n format('DATABASE DEL %s %s', family, key)\n );\n\n if (response.code !== 200 || response.result === 0) {\n throw new Error('Could not delete from the database');\n }\n }\n\n /**\n * Deletes a family or specific keytree within a family in the Asterisk database.\n * @param family\n * @param keyTree\n */\n public async databaseDelTree(\n family: string,\n keyTree?: string\n ): Promise<boolean> {\n const response = await this.sendCommand(\n format('DATABASE DELTREE %s %s', family, keyTree || '')\n );\n\n if (response.code !== 200) {\n throw new Error('Could not delete tree from database');\n }\n\n return response.result === 0;\n }\n\n /**\n * Retrieves an entry in the Asterisk database for a given family and key.\n * @param family\n * @param key\n */\n public async databaseGet(family: string, key: string): Promise<string> {\n const response = await this.sendCommand(\n format('DATABASE GET %s %s', family, key)\n );\n\n if (response.code !== 200 || response.result === 0) {\n throw new Error('Database key not set');\n }\n\n return response.arguments.nokey();\n }\n\n /**\n * Adds or updates an entry in the Asterisk database for a given family, key, and value.\n * @param family\n * @param key\n * @param value\n */\n public async databasePut(\n family: string,\n key: string,\n value: string\n ): Promise<string> {\n const response = await this.sendCommand(\n format('DATABASE PUT %s %s %s', family, key, value)\n );\n\n if (response.code !== 200 || response.result === 0) {\n throw new Error('Database key not set');\n }\n\n return response.arguments.string('value');\n }\n\n /**\n * Executes application with given options\n * @param application The application to execute (e.g., 'Dial', 'Playback')\n * @param args Application arguments\n * @param commandTimeout Optional timeout in milliseconds (default: 6 hours for EXEC, use Infinity for no timeout)\n */\n public async exec(\n application: string,\n args: string,\n commandTimeout?: number\n ): Promise<number> {\n const response = await this.sendCommand(\n format('EXEC %s %s', application, args),\n commandTimeout\n );\n\n if (response.code !== 200 || response.result === -2) {\n throw new Error('Could not execute application');\n }\n\n return response.result;\n }\n\n /**\n * Streams an audio file and collects DTMF digits from the channel.\n *\n * This method plays the specified audio file and waits for the user to enter DTMF digits.\n * The audio can be interrupted by pressing any digit. Collection ends when:\n * - The user presses `#` (terminator)\n * - `maxDigits` is reached\n * - Timeout expires\n *\n * **Standard mode** (without `interDigitTimeout`):\n * Uses the native AGI GET DATA command. The `timeout` parameter controls both the\n * first digit timeout and inter-digit timeout (Asterisk defaults: 6000ms/2000ms).\n *\n * **Inter-digit timeout mode** (with `interDigitTimeout`):\n * Uses a custom implementation that provides separate control over:\n * - `timeout`: Maximum time to wait for the first digit after audio ends\n * - `interDigitTimeout`: Maximum time to wait between subsequent digits\n *\n * @param soundFile - The audio file to play (without extension)\n * @param timeout - Timeout in milliseconds (default: 5000ms). In standard mode, this is\n * used for both first digit and inter-digit timeout.\n * @param maxDigits - Maximum number of digits to collect (default: 1024)\n * @param interDigitTimeout - Optional. If provided, enables custom inter-digit timeout mode\n * with separate timeout between digits in milliseconds.\n * @returns Object containing:\n * - `digits`: The collected DTMF digits (without the # terminator)\n * - `timeout`: True if collection ended due to timeout, false otherwise\n * @throws Error if the channel encounters an error during collection\n *\n * @example\n * ```typescript\n * // Standard mode: collect up to 4 digits with 10 second timeout\n * const result = await channel.getData('enter-pin', 10000, 4);\n * console.log(`User entered: ${result.digits}`);\n *\n * // Inter-digit timeout mode: 10s for first digit, 3s between digits\n * const result = await channel.getData('enter-account', 10000, 10, 3000);\n * if (result.timeout) {\n * console.log('User timed out');\n * }\n * ```\n *\n * @see https://docs.asterisk.org/Asterisk_22_Documentation/API_Documentation/AGI_Commands/get_data\n */\n public async getData(\n soundFile: string,\n timeout: number = 5000,\n maxDigits?: number,\n interDigitTimeout?: number\n ): Promise<{ digits: string; timeout: boolean }> {\n // If maxDigits is specified and interDigitTimeout is provided, use digit-by-digit collection\n if (maxDigits && maxDigits > 1 && interDigitTimeout) {\n return this.getDataWithInterDigitTimeout(soundFile, timeout, maxDigits, interDigitTimeout);\n }\n\n // Use standard GET DATA for simple cases\n const command = maxDigits !== undefined\n ? format('GET DATA %s %s %s', soundFile, timeout, maxDigits)\n : format('GET DATA %s %s', soundFile, timeout);\n\n const response = await this.sendCommand(command);\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not get data from channel');\n }\n\n return {\n digits: response.arguments.string('result'),\n timeout: response.arguments.string('value') === '(timeout)',\n };\n }\n\n /**\n * Internal method to collect digits with separate inter-digit timeout control.\n *\n * This method provides more granular control over digit collection than the standard\n * AGI GET DATA command by implementing custom timeout logic:\n *\n * 1. Plays the audio file (interruptible by any digit)\n * 2. Waits up to `totalTimeout` for the first digit\n * 3. For each subsequent digit, waits up to `interDigitTimeout`\n * 4. Returns when `maxDigits` is reached, `#` is pressed, or timeout occurs\n *\n * @param soundFile - The audio file to play (without extension)\n * @param totalTimeout - Maximum time in milliseconds to wait for the first digit after audio\n * @param maxDigits - Maximum number of digits to collect\n * @param interDigitTimeout - Maximum time in milliseconds to wait between subsequent digits\n * @returns Object with collected digits and timeout flag\n * @internal\n */\n private async getDataWithInterDigitTimeout(\n soundFile: string,\n totalTimeout: number,\n maxDigits: number,\n interDigitTimeout: number\n ): Promise<{ digits: string; timeout: boolean }> {\n let collectedDigits = '';\n\n // Play the sound file first, allowing any digit to interrupt\n try {\n // Use STREAM FILE directly instead of streamFile() to avoid PLAYBACKSTATUS check\n const response = await this.sendCommand(\n format('STREAM FILE %s \"%s\"', soundFile, '0123456789*#')\n );\n\n if (response.code === 200 && response.result !== -1) {\n const digit = response.arguments.char('result');\n\n // If user pressed a digit during playback, collect it\n if (digit) {\n collectedDigits += digit;\n\n // If we already have max digits, return immediately\n if (collectedDigits.length === maxDigits) {\n return { digits: collectedDigits, timeout: false };\n }\n }\n }\n } catch (error) {\n // Continue even if file fails to play\n }\n\n // Start timing AFTER audio finishes - totalTimeout only applies to digit collection\n const startTime = Date.now();\n\n // Collect remaining digits one by one with inter-digit timeout\n while (collectedDigits.length < maxDigits) {\n const elapsedTime = Date.now() - startTime;\n const remainingTotalTimeout = totalTimeout - elapsedTime;\n\n if (remainingTotalTimeout <= 0) {\n return { digits: collectedDigits, timeout: collectedDigits.length === 0 };\n }\n\n // For the first digit, use totalTimeout. For subsequent digits, use interDigitTimeout\n const timeoutToUse = collectedDigits.length === 0\n ? remainingTotalTimeout\n : Math.min(interDigitTimeout, remainingTotalTimeout);\n\n try {\n // Convert milliseconds to seconds for waitForDigit\n const digit = await this.waitForDigit(timeoutToUse / 1000);\n\n if (!digit) {\n // Timeout waiting for digit\n return { digits: collectedDigits, timeout: collectedDigits.length === 0 };\n }\n\n collectedDigits += digit;\n\n if (collectedDigits.length === maxDigits) {\n return { digits: collectedDigits, timeout: false };\n }\n } catch (error) {\n return { digits: collectedDigits, timeout: true };\n }\n }\n\n return { digits: collectedDigits, timeout: false };\n }\n\n /**\n * Evaluates a channel expression\n * Understands complex variable names and builtin variables, unlike GET VARIABLE.\n * @param key\n * @param channel\n */\n public async getFullVariable(key: string, channel?: string): Promise<string> {\n const response = await this.sendCommand(\n format('GET FULL VARIABLE %s %s', key.toUpperCase(), channel || '')\n );\n\n if (response.code !== 200 || response.result === 0) {\n throw new Error('Variable not set');\n }\n\n return response.arguments.nokey();\n }\n\n /**\n * Stream file, prompt for DTMF, with timeout.\n * Behaves similar to STREAM FILE but used with a timeout option.\n * @param soundFile\n * @param escapeDigits\n * @param timeout\n */\n public async getOption(\n soundFile: string,\n escapeDigits: string = '#',\n timeout: number = 5\n ): Promise<{ digit: string; endpos: number }> {\n const response = await this.sendCommand(\n format('GET OPTION %s \"%s\" %s', soundFile, escapeDigits, timeout * 1000)\n );\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not get option');\n }\n\n if (response.arguments.number('endpos') === 0) {\n throw new Error('Could Not play file');\n }\n\n return {\n digit: response.arguments.char('result'),\n endpos: response.arguments.number('endpos'),\n };\n }\n\n /**\n * Gets a channel variable.\n * @param key\n */\n public async getVariable(key: string): Promise<string> {\n const response = await this.sendCommand(\n format('GET VARIABLE %s', key.toUpperCase())\n );\n\n if (response.code !== 200 || response.result === 0) {\n throw new Error('Variable not set');\n }\n\n return response.arguments.nokey();\n }\n\n /**\n * Cause the channel to execute the specified dialplan subroutine.\n * @param context\n * @param extension\n * @param priority\n * @param argument\n */\n public async goSub(\n context: string,\n extension: string,\n priority: number,\n argument?: string\n ): Promise<void> {\n const response = await this.sendCommand(\n format('GOSUB %s %s %s %s', context, extension, priority, argument || '')\n );\n\n if (response.code !== 200 || response.result !== 0) {\n throw new Error('Could not execute gosub');\n }\n }\n\n /**\n * Hangs up the specified channel. If no channel name is given, hangs up the current channel\n * @param channel\n */\n public async hangup(channel?: string): Promise<void> {\n const response = await this.sendCommand(format('HANGUP %s', channel || ''));\n\n if (response.code !== 200 || response.result !== 1) {\n throw new Error('Could not hang up call');\n }\n }\n\n /**\n * Does nothing\n */\n public async noop(): Promise<void> {\n const response = await this.sendCommand('NOOP');\n\n if (response.code !== 200 || response.result !== 0) {\n throw new Error('Could not NOOP');\n }\n }\n\n /**\n * Receives one character from channels supporting it.\n * @param timeout\n */\n public async receiveChar(\n timeout: number = 5\n ): Promise<{ char: string; timeout: boolean }> {\n const response = await this.sendCommand(\n format('RECEIVE CHAR %s', timeout * 1000)\n );\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not get data from channel');\n }\n\n return {\n char: response.arguments.char('result'),\n timeout: response.arguments.boolean('timeout'),\n };\n }\n\n /**\n * Receives text from channels supporting it.\n * @param timeout\n */\n public async receiveText(timeout: number = 5): Promise<string> {\n const response = await this.sendCommand(\n format('RECEIVE TEXT %s', timeout * 1000)\n );\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not get data from channel');\n }\n\n return response.arguments.string('result');\n }\n\n /**\n * Records to a given file.\n * @param filename\n * @param fileFormat\n * @param escapeDigits\n * @param timeout\n * @param beep\n * @param silence\n * @param offsetSamples\n */\n public async recordFile(\n filename: string,\n fileFormat: string = 'gsm',\n escapeDigits: string = '#',\n timeout: number = 10,\n beep?: boolean,\n silence?: number,\n offsetSamples?: number\n ): Promise<{ digit: string; endpos: number; timeout: boolean }> {\n const response = await this.sendCommand(\n format(\n 'RECORD FILE %s %s \"%s\" %s %s %s %s',\n filename,\n fileFormat,\n escapeDigits,\n timeout * 1000,\n offsetSamples || '',\n beep ? 'BEEP' : '',\n silence ? format('s=%s', silence) : ''\n )\n );\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not record file');\n }\n\n return {\n digit: response.arguments.char('result'),\n endpos: response.arguments.number('endpos'),\n timeout: response.arguments.boolean('timeout'),\n };\n }\n\n /**\n * Says a given character string.\n * @param value\n * @param escapeDigits\n */\n public async sayAlpha(\n value: string,\n escapeDigits: string = '#'\n ): Promise<string> {\n const response = await this.sendCommand(\n format('SAY ALPHA %s \"%s\"', value, escapeDigits)\n );\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not say alpha');\n }\n\n return response.arguments.char('result');\n }\n\n /**\n * Says a given date.\n * @param value\n * @param escapeDigits\n */\n public async sayDate(\n value: Date | number,\n escapeDigits: string = '#'\n ): Promise<string> {\n const response = await this.sendCommand(\n format(\n 'SAY DATE %s \"%s\"',\n typeof value === 'number' ? value : Math.floor(value.getTime() / 1000),\n escapeDigits\n )\n );\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not say date');\n }\n\n return response.arguments.char('result');\n }\n\n /**\n * Says a given time as specified by the format given.\n * @param value\n * @param escapeDigits\n * @param dateFormat\n * @param timezone\n */\n public async sayDateTime(\n value: Date | number,\n escapeDigits: string = '#',\n dateFormat?: string,\n timezone?: string\n ): Promise<string> {\n const response = await this.sendCommand(\n format(\n 'SAY DATETIME %s \"%s\" %s %s',\n typeof value === 'number' ? value : Math.floor(value.getTime() / 1000),\n escapeDigits,\n dateFormat || '',\n timezone || ''\n )\n );\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not say date time');\n }\n\n return response.arguments.char('result');\n }\n\n /**\n * Says a given digit string.\n * @param value\n * @param escapeDigits\n */\n public async sayDigits(\n value: string,\n escapeDigits: string = '#'\n ): Promise<string> {\n const response = await this.sendCommand(\n format('SAY DIGITS %s \"%s\"', value, escapeDigits)\n );\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not say digits');\n }\n\n return response.arguments.char('result');\n }\n\n /**\n * Says a given number.\n * @param value\n * @param escapeDigits\n */\n public async sayNumber(\n value: number,\n escapeDigits: string = '#'\n ): Promise<string> {\n const response = await this.sendCommand(\n format('SAY NUMBER %s \"%s\"', value, escapeDigits)\n );\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not say number');\n }\n\n return response.arguments.char('result');\n }\n\n /**\n * Says a given character string with phonetics.\n * @param value\n * @param escapeDigits\n */\n public async sayPhonetic(\n value: string,\n escapeDigits: string = '#'\n ): Promise<string> {\n const response = await this.sendCommand(\n format('SAY PHONETIC %s \"%s\"', value, escapeDigits)\n );\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not say phonetic');\n }\n\n return response.arguments.char('result');\n }\n\n /**\n * Says a given time.\n * @param value\n * @param escapeDigits\n */\n public async sayTime(\n value: Date | number,\n escapeDigits: string = '#'\n ): Promise<string> {\n const response = await this.sendCommand(\n format(\n 'SAY TIME %s \"%s\"',\n typeof value === 'number' ? value : Math.floor(value.getTime() / 1000),\n escapeDigits\n )\n );\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not say time');\n }\n\n return response.arguments.char('result');\n }\n\n /**\n * Sends images to channels supporting it.\n * @param image\n */\n public async sendImage(image: string): Promise<void> {\n const response = await this.sendCommand(format('SEND IMAGE %s', image));\n\n if (response.code !== 200 || response.result !== 0) {\n throw new Error('Could not send image');\n }\n }\n\n /**\n * Sends text to channels supporting it.\n * @param text\n */\n public async sendText(text: string): Promise<void> {\n const response = await this.sendCommand(format('SEND TEXT \"%s\"', text));\n\n if (response.code !== 200 || response.result !== 0) {\n throw new Error('Could not send text');\n }\n }\n\n /**\n * Autohangup channel in some time.\n * @param timeout\n */\n public async setAutoHangup(timeout: number = 60): Promise<void> {\n const response = await this.sendCommand(\n format('SET AUTOHANGUP %s', timeout)\n );\n\n if (response.code !== 200 || response.result !== 0) {\n throw new Error('Could not set auto hangup');\n }\n }\n\n /**\n * Sets callerid for the current channel.\n * @param callerNumber\n * @param callerName\n */\n public async setCallerID(\n callerNumber: number,\n callerName?: string\n ): Promise<void> {\n const callerid = callerName\n ? format('\"%s\"<%s>', callerName, callerNumber)\n : callerNumber;\n\n const response = await this.sendCommand(\n format('SET CALLERID %s', callerid)\n );\n\n if (response.code !== 200 || response.result !== 1) {\n throw new Error('Could not set caller id');\n }\n }\n\n /**\n * Sets channel context.\n * @param context\n */\n public async setContext(context: string): Promise<void> {\n const response = await this.sendCommand(format('SET CONTEXT %s', context));\n\n if (response.code !== 200 || response.result !== 0) {\n throw new Error('Could not set context');\n }\n }\n\n /**\n * Changes channel extension.\n * @param extension\n */\n public async setExtension(extension: string): Promise<void> {\n const response = await this.sendCommand(\n format('SET EXTENSION %s', extension)\n );\n\n if (response.code !== 200 || response.result !== 0) {\n throw new Error('Could not set extension');\n }\n }\n\n /**\n * Enable/Disable Music on hold generator\n * @param status\n * @param musicClass\n */\n public async setMusic(\n status: boolean = true,\n musicClass?: string\n ): Promise<void> {\n const response = await this.sendCommand(\n format('SET MUSIC %s %s', status ? 'ON' : 'OFF', musicClass || '')\n );\n\n if (response.code !== 200 || response.result !== 0) {\n throw new Error('Could not set priority');\n }\n }\n\n /**\n * Set channel dialplan priority.\n * @param priority\n */\n public async setPriority(priority: number): Promise<void> {\n const response = await this.sendCommand(\n format('SET PRIORITY %s', priority)\n );\n\n if (response.code !== 200 || response.result !== 0) {\n throw new Error('Could not set priority');\n }\n }\n\n /**\n * Sets a channel variable.\n * @param key - The variable name\n * @param value - The variable value\n * @throws Error if the variable could not be set\n */\n public async setVariable(key: string, value: string): Promise<void> {\n const response = await this.sendCommand(\n format('SET VARIABLE %s \"%s\"', key.toUpperCase(), value)\n );\n\n if (response.code !== 200 || response.result !== 1) {\n throw new Error('Could not set variable');\n }\n }\n\n public async speechActivateGrammar(grammar: string): Promise<IResponse> {\n // TODO: Handle the response\n return this.sendCommand(format('SPEECH ACTIVATE GRAMMAR %s', grammar));\n }\n\n public async speechCreate(engine: string): Promise<IResponse> {\n // TODO: Handle the response\n return this.sendCommand(format('SPEECH CREATE ENGINE %s', engine));\n }\n\n public async speechDeactivateGrammar(grammar: string): Promise<IResponse> {\n // TODO: Handle the response\n return this.sendCommand(format('SPEECH DEACTIVATE GRAMMAR %s', grammar));\n }\n\n public async speechDestroy(): Promise<IResponse> {\n // TODO: Handle the response\n return this.sendCommand('SPEECH DESTROY');\n }\n\n public async speechLoadGrammar(\n grammar: string,\n path: string\n ): Promise<IResponse> {\n // TODO: Handle the response\n return this.sendCommand(format('SPEECH LOAD GRAMMAR %s %s', grammar, path));\n }\n\n public async speechRecognize(\n soundFile: string,\n timeout: number = 5,\n offset: number\n ): Promise<IResponse> {\n // TODO: Handle the response\n return this.sendCommand(\n format('SPEECH RECOGNIZE %s %s %s', soundFile, timeout * 1000, offset)\n );\n }\n\n public async speechSet(key: string, value: string): Promise<IResponse> {\n // TODO: Handle the response\n return this.sendCommand(format('SPEECH SET %s %s', key, value));\n }\n\n public async speedUnloadGrammar(grammar: string): Promise<IResponse> {\n // TODO: Handle the response\n return this.sendCommand(format('SPEECH UNLOAD GRAMMAR %s', grammar));\n }\n\n /**\n * Streams an audio file to the channel, allowing playback to be interrupted by DTMF digits.\n *\n * The file extension should not be included in the filename - Asterisk will automatically\n * select the best available format based on the channel's codec.\n *\n * @param filename - The audio file to play (without extension, e.g., \"welcome\" not \"welcome.wav\")\n * @param escapeDigits - DTMF digits that will interrupt playback (default: \"#\"). Use \"\" for none.\n * @param offset - Sample offset to start playback from (optional)\n * @returns Object containing:\n * - `digit`: The DTMF digit pressed to interrupt, or empty string if played to completion\n * - `endpos`: The sample position where playback stopped\n * @throws Error if the file could not be played or PLAYBACKSTATUS is not SUCCESS\n *\n * @example\n * ```typescript\n * // Play a file, allowing any digit to interrupt\n * const result = await channel.streamFile('welcome', '0123456789*#');\n * if (result.digit) {\n * console.log(`User pressed: ${result.digit}`);\n * }\n *\n * // Play a file without allowing interruption\n * await channel.streamFile('announcement', '');\n * ```\n *\n * @see https://docs.asterisk.org/Asterisk_22_Documentation/API_Documentation/AGI_Commands/stream_file\n */\n public async streamFile(\n filename: string,\n escapeDigits: string = '#',\n offset?: number\n ): Promise<{ digit: string; endpos: number }> {\n const response = await this.sendCommand(\n format('STREAM FILE %s \"%s\" %s', filename, escapeDigits, offset || '')\n );\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not stream file');\n }\n\n const status = await this.getVariable('PLAYBACKSTATUS');\n\n if (status !== 'SUCCESS') {\n throw new Error('Could not stream file');\n }\n\n return {\n digit: response.arguments.char('result'),\n endpos: response.arguments.number('endpos'),\n };\n }\n\n /**\n * Toggles TDD mode (for the deaf).\n * @param status\n */\n public async tddMode(status: boolean): Promise<void> {\n const response = await this.sendCommand(\n format('TDD MODE %s', status ? 'ON' : 'OFF')\n );\n\n if (response.code !== 200 || response.result !== 1) {\n throw new Error('Could not set TDD mode');\n }\n }\n\n /**\n * Logs a message to the asterisk verbose log.\n * @param message\n * @param level\n */\n public async verbose(message: string, level?: number): Promise<void> {\n const response = await this.sendCommand(\n format('VERBOSE \"%s\" %s', message, level || '')\n );\n\n if (response.code !== 200 || response.result !== 1) {\n throw new Error('Could not send logging message');\n }\n }\n\n /**\n * Waits for a digit to be pressed.\n * @param timeout Timeout in seconds\n */\n public async waitForDigit(timeout: number = 5): Promise<string> {\n // Convert timeout from seconds to milliseconds and add 2s safety margin for network/processing latency\n const commandTimeout = (timeout * 1000) + 2000;\n\n const response = await this.sendCommand(\n format('WAIT FOR DIGIT %s', timeout * 1000),\n commandTimeout\n );\n\n if (response.code !== 200 || response.result === -1) {\n throw new Error('Could not wait for digit');\n }\n\n return response.arguments.char('result');\n }\n\n /* Internal Methods */\n\n private close() {\n this.m_connection.destroy();\n }\n\n private read(data: Buffer): void {\n if (data.length === 0) {\n return;\n }\n\n this.m_message += data.toString();\n\n if (this.m_state === ContextState.INIT) {\n if (this.m_message.indexOf('\\n\\n') === -1) {\n return;\n }\n\n this.readVariables(this.m_message);\n } else if (this.m_state === ContextState.WAITING) {\n if (this.m_message.indexOf('\\n') === -1) {\n return;\n }\n\n this.readResponse(this.m_message);\n }\n\n this.m_message = '';\n }\n\n private readVariables(message: string) {\n const lines = message.split('\\n');\n\n lines.map((line) => {\n const split = line.split(':');\n const name: string = (split[0] || '').trim();\n const value: string = (split[1] || '').trim();\n\n const id = name.substring(4);\n\n switch (id) {\n case 'network':\n return (this.m_network = value);\n case 'network_script':\n return (this.m_network_script = value);\n case 'request':\n return (this.m_request = value);\n case 'channel':\n return (this.m_channel = value);\n case 'language':\n return (this.m_language = value);\n case 'type':\n return (this.m_type = value);\n case 'uniqueid':\n return (this.m_uniqueid = value);\n case 'version':\n return (this.m_version = value);\n case 'callerid':\n return (this.m_callerid = value);\n case 'calleridname':\n return (this.m_calleridname = value);\n case 'callingpres':\n return (this.m_callingpres = value);\n case 'callingani2':\n return (this.m_callingani2 = value);\n case 'callington':\n return (this.m_callington = value);\n case 'callingtns':\n return (this.m_callingtns = value);\n case 'dnid':\n return (this.m_dnid = value);\n case 'rdnis':\n return (this.m_rdnis = value);\n case 'context':\n return (this.m_context = value);\n case 'extension':\n return (this.m_extension = value);\n case 'priority':\n return (this.m_priority = value);\n case 'enhanced':\n return (this.m_enhanced = value);\n case 'accountcode':\n return (this.m_accountcode = value);\n case 'threadid':\n return (this.m_threadid = value);\n }\n });\n\n this.m_state = ContextState.WAITING;\n\n this.emit('ready');\n }\n\n private readResponse(message: string) {\n const lines = message.split('\\n');\n\n lines.map((line) => this.readResponseLine(line));\n }\n\n private readResponseLine(line: string) {\n if (!line) {\n return;\n }\n\n this.emit('recv', line);\n\n const parsed = line.split(' ');\n\n if (!parsed || parsed[0] === 'HANGUP') {\n return this.emit('hangup');\n }\n\n const code = parseInt(parsed[0], 10);\n parsed.shift();\n\n const args: ResponseArguments = new ResponseArguments();\n\n for (const value of parsed) {\n if (value.indexOf('=') !== -1) {\n const parts = value.split('=', 2);\n const key = parts[0].trim();\n const val = parts[1].trim();\n args.addArgument(key, val);\n } else if (value.indexOf('(') !== -1) {\n const name = value.substring(1, value.length - 1);\n args.addArgument(name, true);\n } else {\n args.addArgument('value', value);\n }\n }\n\n const response: IResponse = {\n code: code,\n result: args.number('result'),\n arguments: args,\n };\n\n this.emit('response', response);\n }\n\n private async send(message: string): Promise<void> {\n return new Promise((resolve, reject) => {\n if (!this.m_connection || this.m_connection.destroyed) {\n return reject(new Error('Stream has been destroyed'));\n }\n this.emit('send', message);\n this.m_connection.write(message, (error) => {\n if (error) {\n return reject(error);\n }\n resolve();\n });\n });\n }\n\n /**\n * Sends an AGI command and waits for response using a FIFO queue\n * @param command AGI command to send\n * @param timeout Optional timeout in milliseconds (default: 10000ms)\n */\n private async sendCommand(\n command: string,\n timeout?: number\n ): Promise<IResponse> {\n return new Promise((resolve, reject) => {\n // Check if channel is still alive\n if (!this.channelAlive) {\n return reject(new Error('Channel is no longer alive'));\n }\n\n // Check queue size limit (backpressure)\n if (this.commandQueue.length >= this.maxQueueSize) {\n return reject(\n new Error(\n `Command queue full (${this.maxQueueSize}). Command rejected: ${command}`\n )\n );\n }\n\n // Add command to queue\n const queuedCommand: IQueuedCommand = {\n command,\n resolve,\n reject,\n timeout: timeout ?? this.getCommandTimeout(command),\n timestamp: Date.now(),\n };\n\n this.commandQueue.push(queuedCommand);\n\n // Emit event for monitoring\n this.emit('commandQueued', {\n command,\n queueSize: this.commandQueue.length,\n });\n\n // Start processing if not active\n if (!this.isProcessingCommand) {\n this.processCommandQueue();\n }\n });\n }\n\n /**\n * Gets the appropriate timeout for a given command\n * @param command The AGI command string\n * @returns Timeout in milliseconds (or Infinity for no timeout)\n */\n private getCommandTimeout(command: string): number {\n // Comandos r\u00E1pidos (devem responder em segundos)\n if (\n command.startsWith('ANSWER') ||\n command.startsWith('HANGUP') ||\n command.startsWith('CHANNEL STATUS') ||\n command.startsWith('GET VARIABLE') ||\n command.startsWith('SET VARIABLE') ||\n command.startsWith('DATABASE')\n ) {\n return 10000; // 10 segundos\n }\n\n // Comandos m\u00E9dios (audio playback, prompts)\n if (\n command.startsWith('STREAM FILE') ||\n command.startsWith('SAY ') ||\n command.startsWith('GET DATA') ||\n command.startsWith('GET OPTION')\n ) {\n return 60000; // 1 minuto\n }\n\n // Comandos de grava\u00E7\u00E3o\n if (command.startsWith('RECORD FILE')) {\n return 600000; // 10 minutos\n }\n\n // EXEC: pode incluir Dial, Queue, VoiceMail (podem durar horas)\n if (command.startsWith('EXEC')) {\n return this.maxCallDuration; // 6 horas padr\u00E3o\n }\n\n // Outros comandos\n return this.defaultCommandTimeout; // 10 segundos\n }\n\n /**\n * Processes the command queue sequentially (FIFO)\n */\n private async processCommandQueue(): Promise<void> {\n if (this.commandQueue.length === 0) {\n this.isProcessingCommand = false;\n this.emit('queueEmpty');\n return;\n }\n\n this.isProcessingCommand = true;\n const queuedCommand = this.commandQueue.shift()!;\n\n try {\n const response = await this.sendCommandInternal(\n queuedCommand.command,\n queuedCommand.timeout!\n );\n\n // Emit success event\n this.emit('commandProcessed', {\n command: queuedCommand.command,\n duration: Date.now() - queuedCommand.timestamp,\n });\n\n queuedCommand.resolve(response);\n } catch (err) {\n // Emit error event\n this.emit('commandFailed', {\n command: queuedCommand.command,\n error: err,\n });\n\n queuedCommand.reject(err);\n } finally {\n // Process next command (continues even with error)\n setImmediate(() => this.processCommandQueue());\n }\n }\n\n /**\n * Internal implementation of command sending\n * @param command The AGI command to send\n * @param timeout Timeout in milliseconds, or Infinity for no timeout\n */\n private sendCommandInternal(\n command: string,\n timeout: number\n ): Promise<IResponse> {\n return new Promise((resolve, reject) => {\n // Check connection state and channel status\n if (\n !this.channelAlive ||\n !this.m_connection ||\n this.m_connection.destroyed\n ) {\n return reject(new Error('Channel is no longer alive'));\n }\n\n let timeoutId: NodeJS.Timeout | null = null;\n\n const responseHandler = (response: IResponse) => {\n cleanup();\n resolve(response);\n };\n\n const cleanup = () => {\n this.removeListener('response', responseHandler);\n if (timeoutId) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n };\n\n // Register listener\n this.once('response', responseHandler);\n\n // Configurable timeout (supports Infinity for no timeout)\n if (timeout > 0 && timeout !== Infinity) {\n timeoutId = setTimeout(() => {\n cleanup();\n reject(new Error(`Command timeout after ${timeout}ms: ${command}`));\n }, timeout);\n }\n // If timeout is Infinity or <= 0, no timeout is set (relies on channelAlive)\n\n // Send command\n this.send(format('%s\\n', command.trim())).catch((err) => {\n cleanup();\n reject(err);\n });\n });\n }\n\n /**\n * Handles channel closure with pending commands\n */\n private handleChannelClose(): void {\n this.channelAlive = false;\n const pendingCount = this.commandQueue.length;\n\n if (pendingCount > 0) {\n this.emit('queueCleared', {\n reason: 'channel_closed',\n commandsCleared: pendingCount,\n });\n\n // Reject all pending commands\n while (this.commandQueue.length > 0) {\n const cmd = this.commandQueue.shift()!;\n cmd.reject(new Error('Channel closed before command could be sent'));\n }\n }\n\n this.isProcessingCommand = false;\n }\n\n /**\n * Handles HANGUP from Asterisk\n */\n private handleHangup(): void {\n this.channelAlive = false;\n const pendingCount = this.commandQueue.length;\n\n if (pendingCount > 0) {\n this.emit('queueCleared', {\n reason: 'hangup',\n commandsCleared: pendingCount,\n });\n\n // Reject pending commands\n while (this.commandQueue.length > 0) {\n const cmd = this.commandQueue.shift()!;\n cmd.reject(new Error('Call hung up before command could be executed'));\n }\n }\n\n this.isProcessingCommand = false;\n }\n\n /**\n * Manually clears the command queue (for emergency cases)\n */\n public clearCommandQueue(): number {\n const clearedCount = this.commandQueue.length;\n\n while (this.commandQueue.length > 0) {\n const cmd = this.commandQueue.shift()!;\n cmd.reject(new Error('Command queue manually cleared'));\n }\n\n this.isProcessingCommand = false;\n\n this.emit('queueCleared', {\n reason: 'manual',\n commandsCleared: clearedCount,\n });\n\n return clearedCount;\n }\n\n /**\n * Returns queue statistics\n */\n public getQueueStats(): {\n size: number;\n isProcessing: boolean;\n oldestCommandAge: number | null;\n } {\n const oldest = this.commandQueue[0];\n\n return {\n size: this.commandQueue.length,\n isProcessing: this.isProcessingCommand,\n oldestCommandAge: oldest ? Date.now() - oldest.timestamp : null,\n };\n }\n}\n", "// Copyright (c) 2020, Brandon Lehmann\n//\n// Please see the included LICENSE file for more information.\n\n/** @ignore */\nexport interface IResponseArguments {\n key: string;\n value: string | number | boolean;\n}\n\n/**\n * Represents a set of AGI response arguments\n * @ignore\n */\nexport class ResponseArguments {\n private m_args: IResponseArguments[] = [];\n\n /**\n * Adds a new argument to the set\n * @param key\n * @param value\n */\n public addArgument(key: string, value: string | number | boolean) {\n this.m_args.push({key, value});\n }\n\n /**\n * Retrieves the requested key as a string\n * @param key\n */\n public string(key: string): string {\n for (const arg of this.m_args) {\n if (arg.key === key) {\n return (arg.value as string);\n }\n }\n\n return '';\n }\n\n /**\n * Retrieves the requested key as a number\n * @param key\n */\n public number(key: string): number {\n for (const arg of this.m_args) {\n if (arg.key === key) {\n return parseInt((arg.value as string), 10);\n }\n }\n\n return 0;\n }\n\n /**\n * Retrieves the request key as a boolean\n * @param key\n */\n public boolean(key: string): boolean {\n for (const arg of this.m_args) {\n if (arg.key === key) {\n return (arg.value as boolean);\n }\n }\n\n return false;\n }\n\n /**\n * Retrieves the requested key from a character code\n * @param key\n */\n public char(key: string): string {\n const num = this.number(key);\n\n return (num !== 0) ? String.fromCharCode(num) : '';\n }\n\n /**\n * Retrieves the value from the arguments that has no key, if it exists\n */\n public nokey(): string {\n for (const arg of this.m_args) {\n if (arg.key !== 'result' && arg.value) {\n return arg.key;\n }\n }\n\n return '';\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["net", "EventEmitter", "EventEmitter", "format", "ResponseArguments", "key", "value", "arg", "num", "ChannelState", "DialStatus", "PlaybackStatus", "Channel", "EventEmitter", "connection", "data", "error", "event", "listener", "response", "channel", "format", "filename", "escapeDigits", "skipms", "fastForwardCharacter", "rewindCharacter", "pauseCharacter", "playbackStatus", "playbackOffset", "status", "target", "timeout", "params", "family", "key", "keyTree", "value", "application", "args", "commandTimeout", "soundFile", "maxDigits", "interDigitTimeout", "command", "totalTimeout", "collectedDigits", "digit", "startTime", "elapsedTime", "remainingTotalTimeout", "timeoutToUse", "context", "extension", "priority", "argument", "fileFormat", "beep", "silence", "offsetSamples", "dateFormat", "timezone", "image", "text", "callerNumber", "callerName", "callerid", "musicClass", "grammar", "engine", "path", "offset", "message", "level", "line", "split", "name", "parsed", "code", "ResponseArguments", "parts", "val", "resolve", "reject", "queuedCommand", "err", "timeoutId", "responseHandler", "cleanup", "pendingCount", "clearedCount", "oldest", "format", "AGIServer", "EventEmitter", "port", "ip", "socket", "channel", "Channel", "event", "listener", "error", "resolve", "reject"]
7
7
  }
@@ -310,22 +310,70 @@ export declare class Channel extends EventEmitter {
310
310
  */
311
311
  exec(application: string, args: string, commandTimeout?: number): Promise<number>;
312
312
  /**
313
- * Stream the given file, and receive DTMF data with inter-digit timeout support.
314
- * @param soundFile The audio file to play
315
- * @param timeout Total timeout in milliseconds for digit collection AFTER audio finishes (default: 5000ms)
316
- * @param maxDigits Maximum number of digits to collect
317
- * @param interDigitTimeout Timeout between digits in milliseconds. If provided, enables digit-by-digit collection with inter-digit timeout.
313
+ * Streams an audio file and collects DTMF digits from the channel.
314
+ *
315
+ * This method plays the specified audio file and waits for the user to enter DTMF digits.
316
+ * The audio can be interrupted by pressing any digit. Collection ends when:
317
+ * - The user presses `#` (terminator)
318
+ * - `maxDigits` is reached
319
+ * - Timeout expires
320
+ *
321
+ * **Standard mode** (without `interDigitTimeout`):
322
+ * Uses the native AGI GET DATA command. The `timeout` parameter controls both the
323
+ * first digit timeout and inter-digit timeout (Asterisk defaults: 6000ms/2000ms).
324
+ *
325
+ * **Inter-digit timeout mode** (with `interDigitTimeout`):
326
+ * Uses a custom implementation that provides separate control over:
327
+ * - `timeout`: Maximum time to wait for the first digit after audio ends
328
+ * - `interDigitTimeout`: Maximum time to wait between subsequent digits
329
+ *
330
+ * @param soundFile - The audio file to play (without extension)
331
+ * @param timeout - Timeout in milliseconds (default: 5000ms). In standard mode, this is
332
+ * used for both first digit and inter-digit timeout.
333
+ * @param maxDigits - Maximum number of digits to collect (default: 1024)
334
+ * @param interDigitTimeout - Optional. If provided, enables custom inter-digit timeout mode
335
+ * with separate timeout between digits in milliseconds.
336
+ * @returns Object containing:
337
+ * - `digits`: The collected DTMF digits (without the # terminator)
338
+ * - `timeout`: True if collection ended due to timeout, false otherwise
339
+ * @throws Error if the channel encounters an error during collection
340
+ *
341
+ * @example
342
+ * ```typescript
343
+ * // Standard mode: collect up to 4 digits with 10 second timeout
344
+ * const result = await channel.getData('enter-pin', 10000, 4);
345
+ * console.log(`User entered: ${result.digits}`);
346
+ *
347
+ * // Inter-digit timeout mode: 10s for first digit, 3s between digits
348
+ * const result = await channel.getData('enter-account', 10000, 10, 3000);
349
+ * if (result.timeout) {
350
+ * console.log('User timed out');
351
+ * }
352
+ * ```
353
+ *
354
+ * @see https://docs.asterisk.org/Asterisk_22_Documentation/API_Documentation/AGI_Commands/get_data
318
355
  */
319
356
  getData(soundFile: string, timeout?: number, maxDigits?: number, interDigitTimeout?: number): Promise<{
320
357
  digits: string;
321
358
  timeout: boolean;
322
359
  }>;
323
360
  /**
324
- * Internal method to collect digits with inter-digit timeout support
325
- * @param soundFile The audio file to play
326
- * @param totalTimeout Total timeout in milliseconds
327
- * @param maxDigits Maximum number of digits to collect
328
- * @param interDigitTimeout Timeout between digits in milliseconds
361
+ * Internal method to collect digits with separate inter-digit timeout control.
362
+ *
363
+ * This method provides more granular control over digit collection than the standard
364
+ * AGI GET DATA command by implementing custom timeout logic:
365
+ *
366
+ * 1. Plays the audio file (interruptible by any digit)
367
+ * 2. Waits up to `totalTimeout` for the first digit
368
+ * 3. For each subsequent digit, waits up to `interDigitTimeout`
369
+ * 4. Returns when `maxDigits` is reached, `#` is pressed, or timeout occurs
370
+ *
371
+ * @param soundFile - The audio file to play (without extension)
372
+ * @param totalTimeout - Maximum time in milliseconds to wait for the first digit after audio
373
+ * @param maxDigits - Maximum number of digits to collect
374
+ * @param interDigitTimeout - Maximum time in milliseconds to wait between subsequent digits
375
+ * @returns Object with collected digits and timeout flag
376
+ * @internal
329
377
  */
330
378
  private getDataWithInterDigitTimeout;
331
379
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"Channel.d.ts","sourceRoot":"","sources":["../../src/Channel.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Channel.d.ts","sourceRoot":"","sources":["../../src/Channel.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "typescript-agi-ipcom",
3
- "version": "0.0.10-beta.1",
3
+ "version": "0.0.10",
4
4
  "type": "module",
5
5
  "description": "NodeJS TypeScript Library for Asterisk AGI Interfaces",
6
6
  "types": "dist/types/index.d.ts",