UNPKG

@vonage/voice

Version:

The Voice API lets you create outbound calls, control in-progress calls and get information about historical calls.

1,635 lines (1,613 loc) 55.6 kB
"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // lib/index.ts var index_exports = {}; __export(index_exports, { AdvancedMachineDetectionMode: () => AdvancedMachineDetectionMode, CallDirection: () => CallDirection, CallStatus: () => CallStatus, Connect: () => Connect, ConnectEventType: () => ConnectEventType, Conversation: () => Conversation, HttpMethod: () => HttpMethod, Input: () => Input, MachineDetection: () => MachineDetection, MachineDetectionBehavior: () => MachineDetectionBehavior, NCCOActions: () => NCCOActions, NCCOBuilder: () => NCCOBuilder, Notify: () => Notify, OutboundCallWithAnswerURL: () => OutboundCallWithAnswerURL, OutboundCallWithNCCO: () => OutboundCallWithNCCO, Record: () => Record, RecordingFormat: () => RecordingFormat, Stream: () => Stream, TTSLanguages: () => TTSLanguages, TTSVoices: () => TTSVoices, Talk: () => Talk, Voice: () => Voice, WebsocketBitrate: () => WebsocketBitrate }); module.exports = __toCommonJS(index_exports); // lib/enums/AdvancedMachineDetectionMode.ts var AdvancedMachineDetectionMode = /* @__PURE__ */ ((AdvancedMachineDetectionMode2) => { AdvancedMachineDetectionMode2["DEFAULT"] = "default"; AdvancedMachineDetectionMode2["DETECT"] = "detect"; AdvancedMachineDetectionMode2["DETECTBEEP"] = "detect_beep"; return AdvancedMachineDetectionMode2; })(AdvancedMachineDetectionMode || {}); // lib/enums/CallDirection.ts var CallDirection = /* @__PURE__ */ ((CallDirection2) => { CallDirection2["OUTBOUND"] = "outbound"; CallDirection2["INBOUND"] = "inbound"; return CallDirection2; })(CallDirection || {}); // lib/enums/CallStatus.ts var CallStatus = /* @__PURE__ */ ((CallStatus2) => { CallStatus2["STARTED"] = "started"; CallStatus2["RINGING"] = "ringing"; CallStatus2["ANSWERED"] = "answered"; CallStatus2["MACHINE"] = "machine"; CallStatus2["COMPLETED"] = "completed"; CallStatus2["BUSY"] = "busy"; CallStatus2["CANCELLED"] = "cancelled"; CallStatus2["FAILED"] = "failed"; CallStatus2["REJECTED"] = "rejected"; CallStatus2["TIMEOUT"] = "timeout"; CallStatus2["UNANSWERED"] = "unanswered"; return CallStatus2; })(CallStatus || {}); // lib/enums/HttpMethod.ts var HttpMethod = /* @__PURE__ */ ((HttpMethod2) => { HttpMethod2["GET"] = "GET"; HttpMethod2["POST"] = "POST"; return HttpMethod2; })(HttpMethod || {}); // lib/enums/MachineDetctionBehavior.ts var MachineDetectionBehavior = /* @__PURE__ */ ((MachineDetectionBehavior2) => { MachineDetectionBehavior2["CONTINUE"] = "continue"; MachineDetectionBehavior2["HANGUP"] = "hangup"; return MachineDetectionBehavior2; })(MachineDetectionBehavior || {}); // lib/enums/NCCOActions.ts var NCCOActions = /* @__PURE__ */ ((NCCOActions2) => { NCCOActions2["CONNECT"] = "connect"; NCCOActions2["CONVERSATION"] = "conversation"; NCCOActions2["INPUT"] = "input"; NCCOActions2["NOTIFY"] = "notify"; NCCOActions2["RECORD"] = "record"; NCCOActions2["STREAM"] = "stream"; NCCOActions2["TALK"] = "talk"; return NCCOActions2; })(NCCOActions || {}); // lib/enums/TTSLanguages.ts var TTSLanguages = /* @__PURE__ */ ((TTSLanguages3) => { TTSLanguages3["AF_ZA"] = "af-ZA"; TTSLanguages3["AR"] = "ar"; TTSLanguages3["BG_BG"] = "bg-BG"; TTSLanguages3["BN_IN"] = "bn-IN"; TTSLanguages3["CA_ES"] = "ca-ES"; TTSLanguages3["CMN_CN"] = "cmn-CN"; TTSLanguages3["CMN_TW"] = "cmn-TW"; TTSLanguages3["CS_CZ"] = "cs-CZ"; TTSLanguages3["CY_GB"] = "cy-GB"; TTSLanguages3["DA_DK"] = "da-DK"; TTSLanguages3["DE_AT"] = "de-AT"; TTSLanguages3["DE_DE"] = "de-DE"; TTSLanguages3["DE_ET"] = "de-ET"; TTSLanguages3["EL_GR"] = "el-GR"; TTSLanguages3["EN_AU"] = "en-AU"; TTSLanguages3["EN_GB"] = "en-GB"; TTSLanguages3["EN_GB_SCT"] = "en-GB-SCT"; TTSLanguages3["EN_GB_WLS"] = "en-GB-WLS"; TTSLanguages3["EN_IE"] = "en-IE"; TTSLanguages3["EN_IN"] = "en-IN"; TTSLanguages3["EN_NZ"] = "en-NZ"; TTSLanguages3["EN_US"] = "en-US"; TTSLanguages3["EN_ZA"] = "en-ZA"; TTSLanguages3["ES_CO"] = "es-CO"; TTSLanguages3["ES_ES"] = "es-ES"; TTSLanguages3["ES_MX"] = "es-MX"; TTSLanguages3["ES_US"] = "es-US"; TTSLanguages3["EU_ES"] = "eu-ES"; TTSLanguages3["FI_FI"] = "fi-FI"; TTSLanguages3["FIL_PH"] = "fil-PH"; TTSLanguages3["FR_CA"] = "fr-CA"; TTSLanguages3["FR_FR"] = "fr-FR"; TTSLanguages3["GL_ES"] = "gl-ES"; TTSLanguages3["GU_IN"] = "gu-IN"; TTSLanguages3["HE_IL"] = "he-IL"; TTSLanguages3["HI_IN"] = "hi-IN"; TTSLanguages3["HU_HU"] = "hu-HU"; TTSLanguages3["ID_ID"] = "id-ID"; TTSLanguages3["IS_IS"] = "is-IS"; TTSLanguages3["IT_IT"] = "it-IT"; TTSLanguages3["JA_JP"] = "ja-JP"; TTSLanguages3["KN_IN"] = "kn-IN"; TTSLanguages3["KO_KR"] = "ko-KR"; TTSLanguages3["LV_LV"] = "lv-LV"; TTSLanguages3["ML_IN"] = "ml-IN"; TTSLanguages3["MS_MY"] = "ms-MY"; TTSLanguages3["NB_NO"] = "nb-NO"; TTSLanguages3["NL_BE"] = "nl-BE"; TTSLanguages3["NL_NL"] = "nl-NL"; TTSLanguages3["NO_NO"] = "no-NO"; TTSLanguages3["PA_IN"] = "pa-IN"; TTSLanguages3["PL_PL"] = "pl-PL"; TTSLanguages3["PT_BR"] = "pt-BR"; TTSLanguages3["PT_PT"] = "pt-PT"; TTSLanguages3["RO_RO"] = "ro-RO"; TTSLanguages3["RU_RU"] = "ru-RU"; TTSLanguages3["SK_SK"] = "sk-SK"; TTSLanguages3["SR_RS"] = "sr-RS"; TTSLanguages3["SV_SE"] = "sv-SE"; TTSLanguages3["TA_IN"] = "ta-IN"; TTSLanguages3["TE_IN"] = "te-IN"; TTSLanguages3["TH_TH"] = "th-TH"; TTSLanguages3["TR_TR"] = "tr-TR"; TTSLanguages3["UK_UA"] = "uk-UA"; TTSLanguages3["VI_VN"] = "vi-VN"; TTSLanguages3["YUE_CN"] = "yue-CN"; return TTSLanguages3; })(TTSLanguages || {}); // lib/enums/TTSVoices.ts var TTSVoices = /* @__PURE__ */ ((TTSVoices2) => { TTSVoices2["ADITI"] = "Aditi"; TTSVoices2["AGNIESZKA"] = "Agnieszka"; TTSVoices2["ALVA"] = "Alva"; TTSVoices2["AMY"] = "Amy"; TTSVoices2["ASTRID"] = "Astrid"; TTSVoices2["BIANCA"] = "Bianca"; TTSVoices2["BRIAN"] = "Brian"; TTSVoices2["CARLA"] = "Carla"; TTSVoices2["CARMEN"] = "Carmen"; TTSVoices2["CARMIT"] = "Carmit"; TTSVoices2["CATARINA"] = "Catarina"; TTSVoices2["CELINE"] = "Celine"; TTSVoices2["CEM"] = "Cem"; TTSVoices2["CHANTAL"] = "Chantal"; TTSVoices2["CHIPMUNK"] = "Chipmunk"; TTSVoices2["CONCHITA"] = "Conchita"; TTSVoices2["CRISTIANO"] = "Cristiano"; TTSVoices2["DAMAYANTI"] = "Damayanti"; TTSVoices2["DORA"] = "Dora"; TTSVoices2["EMMA"] = "Emma"; TTSVoices2["EMPAR"] = "Empar"; TTSVoices2["ENRIQUE"] = "Enrique"; TTSVoices2["ERIC"] = "Eric"; TTSVoices2["EWA"] = "Ewa"; TTSVoices2["FELIPE"] = "Felipe"; TTSVoices2["FILIZ"] = "Filiz"; TTSVoices2["GERAINT"] = "Geraint"; TTSVoices2["GIORGIO"] = "Giorgio"; TTSVoices2["GWYNETH"] = "Gwyneth"; TTSVoices2["HANS"] = "Hans"; TTSVoices2["HENRIK"] = "Henrik"; TTSVoices2["INES"] = "Ines"; TTSVoices2["IOANA"] = "Ioana"; TTSVoices2["IVETA"] = "Iveta"; TTSVoices2["IVY"] = "Ivy"; TTSVoices2["JACEK"] = "Jacek"; TTSVoices2["JAN"] = "Jan"; TTSVoices2["JENNIFER"] = "Jennifer"; TTSVoices2["JOANA"] = "Joana"; TTSVoices2["JOANNA"] = "Joanna"; TTSVoices2["JOEY"] = "Joey"; TTSVoices2["JORDI"] = "Jordi"; TTSVoices2["JUSTIN"] = "Justin"; TTSVoices2["KANYA"] = "Kanya"; TTSVoices2["KARL"] = "Karl"; TTSVoices2["KENDRA"] = "Kendra"; TTSVoices2["KIMBERLY"] = "Kimberly"; TTSVoices2["LAILA"] = "Laila"; TTSVoices2["LAURA"] = "Laura"; TTSVoices2["LEA"] = "Lea"; TTSVoices2["LEKHA"] = "Lekha"; TTSVoices2["LIV"] = "Liv"; TTSVoices2["LOTTE"] = "Lotte"; TTSVoices2["LUCIA"] = "Lucia"; TTSVoices2["LUCIANA"] = "Luciana"; TTSVoices2["MADS"] = "Mads"; TTSVoices2["MAGED"] = "Maged"; TTSVoices2["MAJA"] = "Maja"; TTSVoices2["MARISKA"] = "Mariska"; TTSVoices2["MARLENE"] = "Marlene"; TTSVoices2["MATHIEU"] = "Mathieu"; TTSVoices2["MATTHEW"] = "Matthew"; TTSVoices2["MAXIM"] = "Maxim"; TTSVoices2["MEI_JIA"] = "Mei-Jia"; TTSVoices2["MELINA"] = "Melina"; TTSVoices2["MIA"] = "Mia"; TTSVoices2["MIGUEL"] = "Miguel"; TTSVoices2["MIREN"] = "Miren"; TTSVoices2["MIZUKI"] = "Mizuki"; TTSVoices2["MONTSERRAT"] = "Montserrat"; TTSVoices2["NAJA"] = "Naja"; TTSVoices2["NICOLE"] = "Nicole"; TTSVoices2["NIKOS"] = "Nikos"; TTSVoices2["NORA"] = "Nora"; TTSVoices2["OSKAR"] = "Oskar"; TTSVoices2["PENELOPE"] = "Penelope"; TTSVoices2["RAVEENA"] = "Raveena"; TTSVoices2["RICARDO"] = "Ricardo"; TTSVoices2["RUBEN"] = "Ruben"; TTSVoices2["RUSSELL"] = "Russell"; TTSVoices2["SALLI"] = "Salli"; TTSVoices2["SATU"] = "Satu"; TTSVoices2["SEOYEON"] = "Seoyeon"; TTSVoices2["SIN_JI"] = "Sin-Ji"; TTSVoices2["SORA"] = "Sora"; TTSVoices2["TAKUMI"] = "Takumi"; TTSVoices2["TARIK"] = "Tarik"; TTSVoices2["TATYANA"] = "Tatyana"; TTSVoices2["TESSA"] = "Tessa"; TTSVoices2["TIAN_TIAN"] = "Tian-Tian"; TTSVoices2["VICKI"] = "Vicki"; TTSVoices2["VITORIA"] = "Vitoria"; TTSVoices2["YELDA"] = "Yelda"; TTSVoices2["ZEINA"] = "Zeina"; TTSVoices2["ZHIYU"] = "Zhiyu"; TTSVoices2["ZUZANA"] = "Zuzana"; return TTSVoices2; })(TTSVoices || {}); // lib/enums/Endpoint/WebsocketBitrate.ts var WebsocketBitrate = /* @__PURE__ */ ((WebsocketBitrate2) => { WebsocketBitrate2["RATE_8000"] = "audio/l16;rate=8000"; WebsocketBitrate2["RATE_16000"] = "audio/l16;rate=16000"; return WebsocketBitrate2; })(WebsocketBitrate || {}); // lib/enums/NCCO/ConnectEventType.ts var ConnectEventType = /* @__PURE__ */ ((ConnectEventType3) => { ConnectEventType3["SYNCHRONOUS"] = "synchronous"; return ConnectEventType3; })(ConnectEventType || {}); // lib/enums/NCCO/MachineDetection.ts var MachineDetection = /* @__PURE__ */ ((MachineDetection3) => { MachineDetection3["CONTINUE"] = "continue"; MachineDetection3["HANGUP"] = "hangup"; return MachineDetection3; })(MachineDetection || {}); // lib/enums/NCCO/RecordingFormat.ts var RecordingFormat = /* @__PURE__ */ ((RecordingFormat3) => { RecordingFormat3["MP3"] = "mp3"; RecordingFormat3["WAV"] = "wav"; RecordingFormat3["OGG"] = "ogg"; return RecordingFormat3; })(RecordingFormat || {}); // lib/voice.ts var import_server_client = require("@vonage/server-client"); var import_vetch = require("@vonage/vetch"); var apiCallsToCalls = (call) => { delete call._links; const transformedCall = import_server_client.Client.transformers.camelCaseObjectKeys( call, true, true ); delete transformedCall.conversationUuid; return { ...transformedCall, conversationUUID: call.conversation_uuid }; }; var NCCOToApiCalls = (ncco) => ncco.map((action) => { switch (action.action) { case "connect" /* CONNECT */: return { ...action, endpoint: action.endpoint?.map((endpoint) => { switch (endpoint.type) { case "sip": return { type: "sip", uri: endpoint.uri, headers: endpoint.headers, standardHeaders: { "User-to-User": Object.hasOwn(endpoint.standardHeaders || {}, "User-to-User") ? { ...endpoint.standardHeaders }["User-to-User"] : endpoint.standardHeaders?.userToUser } }; default: return endpoint; } }) }; default: return action; } }); var Voice = class extends import_server_client.Client { authType = import_server_client.AuthenticationType.JWT; /** * Retrieves details of all calls using pagination. * * @param {GetCallDetailsParameters} params - Optional parameters for filtering and pagination. * @return {AsyncGenerator<CallDetail, void, undefined>} An async generator that yields call details or void when there are no more results. * * @example * ```ts * for await (const call of voiceClient.getAllCalls()) { * console.log(call.startTime); * } * ``` */ async *getAllCalls(params = {}) { let next = null; params.recordIndex = params?.recordIndex || 0; do { const resp = await this.getCallsPage(params); yield* resp?._embedded?.calls.map(apiCallsToCalls); next = resp?._links?.next ? new URL(resp._links.next.href) : null; if (next) { params.recordIndex = parseInt( next.searchParams.get("record_index") ); } } while (next); } /** * Retrieves a page of call details based on the specified parameters. * * @param {GetCallDetailsParameters} params - Optional parameters for filtering and pagination. * @return {Promise<CallPageResponse>} A promise that resolves to a page of call details. * * @example * ```ts * const page = await voiceClient.getCallsPage(); * for (const call of page._embedded.calls) { * console.log(call.startTime); * } * ``` * * @example * Get the next page of call details * ```ts * const page = await voiceClient.getCallsPage({ * pageSize: 4, * recordIndex: 10, * }); * for (const call of page._embedded.calls) { * console.log(call.startTime); * } * ``` * * @example * Get all started calls * ```ts * import { CallStatus } from '@vonage/voice'; * * const page = await voiceClient.getCallsPage({ * pageSize: 4, * recordIndex: 10, * status: CallStatus.STARTED, * }); * for (const call of page._embedded.calls) { * console.log(call.startTime); * } * ``` */ async getCallsPage(params) { const resp = await this.sendGetRequest( `${this.config.apiHost}/v1/calls`, import_server_client.Client.transformers.snakeCaseObjectKeys(params) ); return { ...resp.data }; } /** * Searches for call details based on the provided filter. * * @param {GetCallDetailsParameters} [filter] - Optional filter criteria to narrow down the search. * @return {Promise<CallPageResponse>} A promise that resolves to a page of call details matching the filter. * * @example * ```ts * const page = await voiceClient.search({ * pageSize: 4, * }); * * for (const call of page._embedded.calls) { * console.log(call.startTime); * console.log(call.status); * console.log(call.direction); * console.log(call.duration); * }; * ``` */ async search(filter) { return this.getCallsPage(filter); } /** * Retrieves detailed information about a specific call using its UUID. * * @param {string} uuid - The UUID of the call to retrieve details for. * @return {Promise<CallDetail>} A promise that resolves to detailed information about the call. * * @example * ```ts * const call = await voiceClient.getCall('CALL_UUID'); * console.log(call.startTime); * ``` */ async getCall(uuid) { const resp = await this.sendGetRequest( `${this.config.apiHost}/v1/calls/${uuid}` ); return apiCallsToCalls(resp.data); } /** * Initiates an outbound call with the specified configuration. * * @param {OutboundCall} call - The configuration for the outbound call. * @return {Promise<CallResult>} A promise that resolves to the result of the outbound call initiation. * * @example * Create a call with answer NCCO * ```ts * const call = await voiceClient.createOutboundCall({ * to: [{ * type: 'phone', * number: TO_NUMBER * }], * asnwer_url: ['https://example.com/answer'], * }); * * console.log(call.uuid); * * ``` * @example * Create a call with answer URL * ```ts * const call = await voiceClient.createOutboundCall({ * to: [{ * type: 'phone', * number: TO_NUMBER * }], * ncco: [{ * action: 'talk', * text: 'This is a text to speech call from Vonage' * }] * }); * * console.log(call.uuid); * ``` */ async createOutboundCall(call) { const callRequest = import_server_client.Client.transformers.snakeCaseObjectKeys(call, true); if (call.ncco) { callRequest.ncco = call.ncco; } const to = call.to.map((endpoint) => { switch (endpoint.type) { case "sip": return { type: "sip", uri: endpoint.uri, headers: endpoint.headers, standard_headers: { "User-to-User": endpoint.standardHeaders?.userToUser } }; } return endpoint; }); callRequest.to = to; const resp = await this.sendPostRequest( `${this.config.apiHost}/v1/calls`, callRequest ); const result = import_server_client.Client.transformers.camelCaseObjectKeys( resp.data, true, true ); delete result.conversationUuid; result.conversationUUID = resp.data.conversation_uuid; return result; } /** * Plays DTMF (Dual-Tone Multi-Frequency) tones on an active call. * * @param {string} uuid - The UUID of the call on which to play DTMF tones. * @param {string} digits - The DTMF tones to play. * @return {Promise<CallUpdateResult>} A promise that resolves to the result of playing DTMF tones on the call. * * @example * ```ts * const result = await voiceClient.playDTMF('CALL_UUID', '1234'); * console.log(result.status); * ``` */ async playDTMF(uuid, digits) { const resp = await this.sendPutRequest( `${this.config.apiHost}/v1/calls/${uuid}/dtmf`, { digits } ); return import_server_client.Client.transformers.snakeCaseObjectKeys( resp.data, true, true ); } /** * Register a listener to receive asynchronous DTMF inputs from a call * * This is only applicable to Input NCCO events with the mode set to * asynchronous. The payload delivered to this URL will be an Input webhook * event with a single DTMF digit every time the callee enters DTMF into the * call. * * @param {string} uuid - The UUID of the call leg * @param {string} eventUrl - The The URL to send DTMF events to, as a POST request. * @return {Promise<void>} A promise that resolves to the result * * @example * ```ts * const result = await voiceClient.subscribeDTMF('CALL_UUID', 'https://example.com/dtmf'); * console.log(result.status); * ``` */ async subscribeDTMF(uuid, eventUrl) { await this.sendPutRequest( `${this.config.apiHost}/v1/calls/${uuid}/input/dtmf`, { event_url: [eventUrl] } ); } /** * Removes the registered DTMF listener * @param {string} uuid - The UUID of the call leg * @return {Promise<void>} A promise that resolves to the result * * @example * ```ts * const result = await voiceClient.subscribeDTMF('CALL_UUID', 'https://example.com/dtmf'); * console.log(result.status); * ``` */ async unsubscribeDTMF(uuid) { await this.sendDeleteRequest( `${this.config.apiHost}/v1/calls/${uuid}/input/dtmf` ); } /** * Plays text-to-speech (TTS) audio on an active call. * * @param {string} uuid - The UUID of the call on which to play TTS audio. * @param {TalkAction} action - The TTS action configuration. * @return {Promise<CallUpdateResult>} A promise that resolves to the result of playing TTS audio on the call. * * @example * ```ts * const result = await voiceClient.playTTS( * CALL_UUID, * { * text: 'This is a text to speech call from Vonage', * }, * ); * * console.log(result.status); * ``` */ async playTTS(uuid, action) { const resp = await this.sendPutRequest( `${this.config.apiHost}/v1/calls/${uuid}/talk`, { text: action.text, loop: action.loop, level: action.level, language: action.language, style: action.style, premium: action.premium } ); return import_server_client.Client.transformers.snakeCaseObjectKeys( resp.data, true, true ); } /** * Stops any ongoing text-to-speech (TTS) audio playback on an active call. * * @param {string} uuid - The UUID of the call on which to stop TTS audio playback. * @return {Promise<CallUpdateResult>} A promise that resolves to the result of stopping TTS audio playback on the call. * * @example * * ```ts * const result = await voiceClient.stopTTS(CALL_UUID); * console.log(result.status); * ``` */ async stopTTS(uuid) { const resp = await this.sendDeleteRequest( `${this.config.apiHost}/v1/calls/${uuid}/talk` ); return import_server_client.Client.transformers.snakeCaseObjectKeys( resp.data, true, true ); } /** * Stream audio to an active call, allowing you to play audio files or live audio streams. * * @param {string} uuid - The UUID of the call to which to stream audio. * @param {string} url - The URL of the audio stream to play. * @param {number} [loop=1] - The number of times to loop the audio stream (default is 1). * @param {number} [volumeLevel=0.0] - The volume level of the audio stream (0.0 to 1.0, default is 0.0). * @return {Promise<UpdateCallResponse>} A promise that resolves to the result of streaming audio to the call. * * * @example * ```ts * const result = await voiceClient.streamAudio(CALL_UUID, 'https://example.com/audio.mp3'); * console.log(result.message); * ``` */ async streamAudio(uuid, url, loop = 1, volumeLevel = 0) { const resp = await this.sendPutRequest( `${this.config.apiHost}/v1/calls/${uuid}/stream`, { stream_url: [url], loop, level: String(volumeLevel) } ); return import_server_client.Client.transformers.snakeCaseObjectKeys( resp.data, true, true ); } /** * Stop streaming audio to an active call. * * @param {string} uuid - The UUID of the call from which to stop streaming audio. * @return {Promise<CallUpdateResult>} A promise that resolves to the result of stopping audio streaming to the call. * * @example * ```ts * const result = await voiceClient.stopStreamAudio(CALL_UUID); * console.log(result.message); * ``` */ async stopStreamAudio(uuid) { const resp = await this.sendDeleteRequest( `${this.config.apiHost}/v1/calls/${uuid}/stream` ); return import_server_client.Client.transformers.snakeCaseObjectKeys( resp.data, true, true ); } /** * Transfer an active call to a new destination using a Nexmo Call Control Object (NCCO). * * @param {string} uuid - The UUID of the call to transfer. * @param {Action[]} ncco - The NCCO actions defining the transfer destination. * @return {Promise<void>} A promise that resolves when the call has been successfully transferred. * * @example * ```ts * await voiceClient.transferCallWithNCCO( * CALL_UUID, * [{ * action: 'talk', * text: 'You will now be transferred to a new destination'' * }], * ) * ``` */ async transferCallWithNCCO(uuid, ncco) { return this.callAction( uuid, "transfer", { type: "ncco", ncco: NCCOToApiCalls(ncco) } ); } /** * Transfer an active call to a new destination using a URL. * * @param {string} uuid - The UUID of the call to transfer. * @param {string} url - The URL of the transfer destination. * @return {Promise<void>} A promise that resolves when the call has been successfully transferred. * * @example * ```ts * await voiceClient.transferCallWithURL( * CALL_UUID, * 'https://example.com/transfer', * ); * ``` */ async transferCallWithURL(uuid, url) { return this.callAction(uuid, "transfer", { type: "ncco", url: [url] }); } /** * Hang up an active call. * * @param {string} uuid - The UUID of the call to hang up. * @return {Promise<void>} A promise that resolves when the call has been successfully hung up. * @example * ```ts * await voiceClient.hangupCall(CALL_UUID); * ``` */ async hangupCall(uuid) { return this.callAction(uuid, "hangup"); } /** * Mute an active call. * * @param {string} uuid - The UUID of the call to mute. * @return {Promise<void>} A promise that resolves when the call has been successfully muted. * * @example * ```ts * await voiceClient.muteCall(CALL_UUID); * ``` */ async muteCall(uuid) { return this.callAction(uuid, "mute"); } /** * Unmute a muted call, allowing audio to be transmitted again. * * @param {string} uuid - The UUID of the call to unmute. * @return {Promise<void>} A promise that resolves when the call has been successfully unmuted. * * @example * ```ts * await voiceClient.unmuteCall(CALL_UUID); * ``` */ async unmuteCall(uuid) { return this.callAction(uuid, "unmute"); } /** * Places a call on earmuff, muting the audio for all participants except the user. * * @param {string} uuid - The UUID of the call to earmuff. * @return {Promise<void>} A promise that resolves when the call has been successfully earmuffed. * * @example * ```ts * await voiceClient.earmuffCall(CALL_UUID); * ``` */ async earmuffCall(uuid) { return this.callAction(uuid, "earmuff"); } /** * Remove an earmuff from a call, allowing all participants to hear each other again. * * @param {string} uuid - The UUID of the call to unearmuff. * @return {Promise<void>} A promise that resolves when the call has been successfully unearmuffed. * * @example * ```ts * await voiceClient.unearmuffCall(CALL_UUID); * ``` */ async unearmuffCall(uuid) { return this.callAction(uuid, "unearmuff"); } /** * Download the recording of a call to the specified file path. * * @param {string} file - The name or recording id of the recording file to download. * @param {string} path - The local file path where the recording will be saved. * @return {Promise<void>} A promise that resolves when the recording has been successfully downloaded. * * @example * ```ts * await voiceClient.downloadRecording(RECORDING_UUID, './recording.mp3'); * ``` */ async downloadRecording(file, path) { const config = this.config; config.responseType = import_vetch.ResponseTypes.stream; const client = new import_server_client.FileClient(this.auth, config); return await client.downloadFile(file, path); } /** * Download the transcription of a call to the specified file path. * * @param {string} file - The name or transcription id of the recording file to download. * @param {string} path - The local file path where the transcription will be saved. * @return {Promise<void>} A promise that resolves when the transcription has been successfully downloaded. * * @example * ```ts * await voiceClient.downloadTranscription(TRANSCRIPTION_UUID, './transcription.txt'); * ``` */ async downloadTranscription(file, path) { const config = this.config; config.responseType = import_vetch.ResponseTypes.text; const client = new import_server_client.FileClient(this.auth, config); return await client.downloadFile(file, path); } /** * Send a call action to a specific call identified by its UUID. * * @param {string} uuid - The UUID of the call to which the action should be applied. * @param {string} action - The action to perform on the call (e.g., 'hangup', 'mute', 'unmute'). * @param {NCCODestination} [destination] - The destination details for transfer actions. * @return {Promise<void>} A promise that resolves when the call action has been successfully executed. * * @example * ```ts * await voiceClient.callAction(CALL_UUID, 'mute'); * ``` */ async callAction(uuid, action, destination) { await this.sendPutRequest(`${this.config.apiHost}/v1/calls/${uuid}`, { action, ...destination ? { destination } : {} }); } }; // lib/classes/NCCO/Connect.ts var Connect = class { /** * The action type, which is always 'connect'. */ action = "connect" /* CONNECT */; /** * An array of CallEndpoint objects representing the endpoints to connect to in the call. * * @param {CallEndpoint} endpoint - An array of CallEndpoint objects * representing the endpoints to connect to in the call. */ endpoint; /** * The caller's phone number to display as the caller ID. * * @param {string} from - The caller's phone number to display as the caller ID. */ from; /** * Set to true to use a random phone number as the caller ID from the list of * numbers assigned to the current application. * * @param {boolean} randomFromNumber - Set to true to use a random phone number as the caller ID. */ randomFromNumber; /** * The event type for call progress events sent to the specified event URL. * * @param {ConnectEventType} eventType - The event type for call progress events. */ eventType; /** * The time in seconds that Vonage waits for the call to be answered before timing out. * * @param {number} timeout - The timeout value in seconds. */ timeout; /** * The maximum number of concurrent calls that can be handled by your application. * * @param {number} limit - The maximum number of concurrent calls. */ limit; /** * Configure the behavior when Vonage detects that the call is answered by voicemail. * * @param {MachineDetection} machineDetection - The behavior when voicemail is detected. */ machineDetection; /** * An array of event URLs where call progress events are sent to. Multiple URLs can be specified. * * @param {string} eventUrl - An array of event URLs. */ eventUrl; /** * The HTTP method used to send event information to the event URL(s). * * @param {string} eventMethod - The HTTP method used for event callbacks. */ eventMethod; /** * The URL of a ringback tone to play to the caller while waiting for the call to be answered. * * @param {string} ringbackTone - The URL of the ringback tone audio file. */ ringbackTone; /** * Create a new Connect instance. * * @param {CallEndpoint} endpoint - An array of CallEndpoint objects representing the endpoints to connect to in the call. * @param {string} from - The caller's phone number to display as the caller ID. * @param {boolean} randomFromNumber - Set to true to use a random phone number as the caller ID. * @param {ConnectEventType} eventType - The event type for call progress events. * @param {number} timeout - The timeout value in seconds. * @param {number} limit - The maximum number of concurrent calls. * @param {MachineDetection} machineDetection - The behavior when voicemail is detected. * @param {string} eventUrl - An array of event URLs. * @param {string} eventMethod - The HTTP method used for event callbacks. * @param {string} ringbackTone - The URL of the ringback tone audio file. */ constructor(endpoint, from, randomFromNumber, eventType, timeout, limit, machineDetection, eventUrl, eventMethod, ringbackTone) { this.endpoint = [endpoint]; if (from) { this.from = from; } if (randomFromNumber) { this.randomFromNumber = randomFromNumber; } if (eventType) { this.eventType = eventType; } if (timeout) { this.timeout = timeout; } if (limit) { this.limit = limit; } if (machineDetection) { this.machineDetection = machineDetection; } if (eventUrl) { this.eventUrl = [eventUrl]; } if (eventMethod) { this.eventMethod = eventMethod; } if (ringbackTone) { this.ringbackTone = ringbackTone; } } /** * Serialize the Connect action to a Nexmo Call Control Object (NCCO) format. * * @return {ConnectAction} - The serialized Connect action. */ serializeToNCCO() { const data = { action: "connect" /* CONNECT */, endpoint: this.endpoint }; if (this.from) { data.from = this.from; } if (this.randomFromNumber) { data.randomFromNumber = this.randomFromNumber; } if (this.eventType) { data.eventType = this.eventType; } if (this.timeout) { data.timeout = this.timeout; } if (this.limit) { data.limit = this.limit; } if (this.machineDetection) { data.machineDetection = this.machineDetection; } if (this.eventUrl) { data.eventUrl = this.eventUrl; } if (this.eventMethod) { data.eventMethod = this.eventMethod; } if (this.ringbackTone) { data.ringbackTone = this.ringbackTone; } return data; } }; // lib/classes/NCCO/Conversation.ts var Conversation = class { /** * The action type, which is always 'conversation'. */ action = "conversation" /* CONVERSATION */; /** * The name of the conversation. * * @param {string} name - The name of the conversation. */ name; /** * An array of URLs for music to be played while participants are on hold. * * @param {string[]} musicOnHoldUrl - An array of music on hold URLs. */ musicOnHoldUrl; /** * Set to true to start the conversation when a participant enters. * * @param {boolean} startOnEnter - Set to true to start the conversation on participant enter. */ startOnEnter; /** * Set to true to end the conversation when the last participant exits. * * @param {boolean} endOnExit - Set to true to end the conversation on last participant exit. */ endOnExit; /** * Set to true to record the conversation. * * @param {boolean} record - Set to true to record the conversation. */ record; /** * An array of participant IDs (e.g., phone numbers) who can speak in the conversation. * * @param {string[]} canSpeak - An array of participant IDs who can speak in the conversation. */ canSpeak; /** * An array of participant IDs (e.g., phone numbers) who can hear in the conversation. * * @param {string[]} canHear - An array of participant IDs who can hear in the conversation. */ canHear; /** * Set to true to mute all participants in the conversation. * * @param {boolean} mute - Set to true to mute all participants in the conversation. */ mute; /** * Create a new Conversation instance. * * @param {string} name - The name of the conversation. * @param {string} musicOnHoldUrl - An array of music on hold URLs. * @param {boolean} startOnEnter - Set to true to start the conversation on participant enter. * @param {boolean} endOnExit - Set to true to end the conversation on last participant exit. * @param {boolean} record - Set to true to record the conversation. * @param {string[]} canSpeak - An array of participant IDs who can speak in the conversation. * @param {string[]} canHear - An array of participant IDs who can hear in the conversation. * @param {boolean} mute - Set to true to mute all participants in the conversation. */ constructor(name, musicOnHoldUrl, startOnEnter, endOnExit, record, canSpeak, canHear, mute) { this.name = name; if (musicOnHoldUrl) { this.musicOnHoldUrl = [musicOnHoldUrl]; } if (startOnEnter) { this.startOnEnter = startOnEnter; } if (endOnExit) { this.endOnExit = endOnExit; } if (record) { this.record = record; } if (canSpeak) { this.canSpeak = canSpeak; } if (canHear) { this.canHear = canHear; } if (mute) { this.mute = mute; } } /** * Serialize the Conversation action to a Nexmo Call Control Object (NCCO) format. * * @return {ConversationAction} - The serialized Conversation action. */ serializeToNCCO() { const data = { action: "conversation" /* CONVERSATION */, name: this.name }; if (this.musicOnHoldUrl) { data.musicOnHoldUrl = this.musicOnHoldUrl; } if (this.startOnEnter) { data.startOnEnter = this.startOnEnter; } if (this.endOnExit) { data.endOnExit = this.endOnExit; } if (this.record) { data.record = this.record; } if (this.canSpeak) { data.canSpeak = this.canSpeak; } if (this.canHear) { data.canHear = this.canHear; } if (this.mute) { data.mute = this.mute; } return data; } }; // lib/classes/NCCO/Input.ts var Input = class { /** * The action type, which is always 'input'. */ action = "input" /* INPUT */; /** * An array of input types ('dtmf' and/or 'speech'). */ type = []; /** * DTMF input settings. */ dtmf; /** * Speech input settings. */ speech; /** * An array of URLs to send events to asynchronously. */ eventUrl = []; /** * The HTTP method used to send events (e.g., 'POST' or 'GET'). */ eventMethod; /** * Input processing mode, currently only applicable to DTMF. Valid values are * synchronous (the default) and asynchronous. If set to asynchronous, all * DTMF settings must be left blank. In asynchronous mode, digits are sent one * at a time to the event webhook in real time. In the default synchronous * mode, this is controlled by the DTMF settings instead and the inputs are * sent in batch. */ mode; /** * Create a new Input instance. * * @param {DTMFSettings} dtmf - DTMF input settings. * @param {SpeechSettings} speech - Speech input settings. * @param {string} eventUrl - URL to send events to asynchronously. * @param {string} eventMethod - The HTTP method used to send events. */ constructor(dtmf, speech, eventUrl, eventMethod, mode) { if (dtmf) { this.type.push("dtmf"); this.dtmf = dtmf; } if (speech) { this.type.push("speech"); this.speech = speech; } if (eventUrl) { this.eventUrl = [eventUrl]; } if (eventMethod) { this.eventMethod = eventMethod; } if (mode) { this.mode = mode; } if (this.type.length === 0) { throw new TypeError( "Input action must have at least either DTMF or Speech settings" ); } } /** * Serialize the Input action to a Nexmo Call Control Object (NCCO) format. * * @return {InputAction} - The serialized Input action. */ serializeToNCCO() { const data = { action: "input" /* INPUT */, type: this.type }; if (this.dtmf) { data.dtmf = this.dtmf; } if (this.speech) { data.speech = this.speech; } if (this.eventUrl) { data.eventUrl = this.eventUrl; } if (this.eventMethod) { data.eventMethod = this.eventMethod; } return data; } }; // lib/classes/NCCO/NCCOBuilder.ts var NCCOBuilder = class { actions = []; /** * Add an action to the NCCO builder. * * @param {Action} action - The action to add to the NCCO. * @return {NCCOBuilder} - The NCCO builder instance (for method chaining). */ addAction(action) { this.actions.push( "serializeToNCCO" in action ? action.serializeToNCCO() : action ); return this; } /** * Build the NCCO by serializing the added actions. * * @return {Array<Action | Serializable>} - The built NCCO, which is an array of actions. */ build() { return this.actions; } }; // lib/classes/NCCO/Notify.ts var Notify = class { action = "notify" /* NOTIFY */; payload; eventUrl; eventMethod; /** * Creates a new Notify action. * * @param {Object} payload - The payload data to send with the notification. * @param {string} eventUrl - The URL where the notification events will be sent. * @param {string} [eventMethod] - The HTTP method for sending notification events (e.g., "POST"). */ constructor(payload, eventUrl, eventMethod) { this.payload = payload; this.eventUrl = [eventUrl]; if (eventMethod) { this.eventMethod = eventMethod; } } /** * Serialize the Notify action to an NCCO-compatible format. * * @return {NotifyAction} - The serialized Notify action. */ serializeToNCCO() { const data = { action: "notify" /* NOTIFY */, payload: this.payload, eventUrl: this.eventUrl }; if (this.eventMethod) { data.eventMethod = this.eventMethod; } return data; } }; // lib/classes/NCCO/Record.ts var Record = class { /** * The action type for the Record action. */ action = "record" /* RECORD */; /** * The recording format (e.g., "mp3", "wav"). */ format; /** * The split type for recording (always "conversation"). */ wrappedSplit; /** * The number of audio channels (1 to 32). */ wrappedChannels; /** * The duration of silence (in seconds) to end the recording (3 to 10 seconds). */ wrappedEndOnSilence; /** * The DTMF key that ends the recording (e.g., "0", "*", "#"). */ wrappedEndOnKey; /** * The maximum recording duration in seconds (3 to 7200 seconds). */ wrappedTimeOut; /** * Whether to play a beep before recording starts. */ beepStart; /** * The URL where recording events will be sent. */ eventUrl; /** * The HTTP method for sending recording events (e.g., "POST"). */ eventMethod; /** * Creates a new Record action. * * @param {RecordingFormat} format - The recording format (e.g., "mp3", "wav"). * @param {string} split - The split type for recording (should be "conversation"). * @param {number} channels - The number of audio channels (1 to 32). * @param {number} endOnSilence - The duration of silence (in seconds) to end the recording (3 to 10 seconds). * @param {string} endOnKey - The DTMF key that ends the recording (e.g., "0", "*", "#"). * @param {number} timeout - The maximum recording duration in seconds (3 to 7200 seconds). * @param {boolean} beepStart - Whether to play a beep before recording starts. * @param {string} eventUrl - The URL where recording events will be sent. * @param {string} eventMethod - The HTTP method for sending recording events (e.g., "POST"). */ constructor(format, split, channels, endOnSilence, endOnKey, timeout, beepStart, eventUrl, eventMethod) { if (format) { this.format = format; } if (split) { this.split = split; } if (channels) { this.channels = channels; } if (endOnSilence) { this.endOnSilence = endOnSilence; } if (endOnKey) { this.endOnKey = endOnKey; } if (timeout) { this.timeout = timeout; } if (beepStart) { this.beepStart = beepStart; } if (eventUrl) { this.eventUrl = [eventUrl]; } if (eventMethod) { this.eventMethod = eventMethod; } } /** * Getter for the number of audio channels. * * @return {number | undefined} - The current number of audio channels. */ get channels() { return this.wrappedChannels; } /** * Setter for the number of audio channels. * * @param {number} channels - The number of audio channels (1 to 32). * @throws {Error} - If the channel value is invalid or split is not set to "conversation." */ set channels(channels) { if (channels < 1 || channels > 32) { throw new Error("Channels must be between 1 and 32, inclusive"); } if (this.wrappedSplit !== "conversation") { throw new Error( "Channels must have split set to 'conversation' before changing channel numbers" ); } this.wrappedChannels = channels; } /** * Getter for the character that signals the end of recording. * * @return {string | undefined} - The character that signals the end of recording. */ get endOnKey() { return this.wrappedEndOnKey; } /** * Setter for the DTMF key that ends the recording. * * @param {string} character - The DTMF key that ends the recording (e.g., "0", "*", "#"). * @throws {Error} - If the character is not a valid DTMF key. */ set endOnKey(character) { const re = /^[0-9*#]$/; if (!re.test(character)) { throw new Error("Valid characters are 0-9, *, and # only"); } this.wrappedEndOnKey = character; } /** * Getter for the duration of silence (in seconds) that signals the end of recording. * * @return {number | undefined} - The duration of silence (in seconds) that signals the end of recording. */ get endOnSilence() { return this.wrappedEndOnSilence; } /** * Setter for the duration of silence to end the recording. * * @param {number} numSeconds - The duration of silence in seconds (3 to 10 seconds). * @throws {Error} - If the duration value is out of the valid range. */ set endOnSilence(numSeconds) { if (numSeconds < 3 || numSeconds > 10) { throw new Error( "End on Silence must be between 3 and 10 seconds, inclusive" ); } this.wrappedEndOnSilence = numSeconds; } /** * Getter for the recording split type. * * @return {string} - The recording split type, which is always 'conversation'. */ get split() { return "conversation"; } /** * Setter for the recording split type. * * @param {string} splitType - The recording split type. Must be set to 'conversation'. * @throws {Error} - Throws an error if the splitType is not 'conversation'. */ set split(splitType) { if (splitType !== "conversation") { throw new Error("Recording can only be split to 'conversation'"); } this.wrappedSplit = splitType; } /** * Getter for the recording timeout duration in seconds. * * @return {number | undefined } - The recording timeout duration in seconds. */ get timeout() { return this.wrappedTimeOut; } /** * Setter for the recording timeout. * * @param {number} seconds - The maximum recording duration in seconds (3 to 7200 seconds). * @throws {Error} - If the timeout value is out of the valid range. */ set timeout(seconds) { if (seconds < 3 || seconds > 7200) { throw new Error( "Recording timeout must be between 3 and 7200 seconds, inclusive" ); } this.wrappedTimeOut = seconds; } /** * Serializes the Record action to NCCO format. * * @return {RecordAction} - The serialized Record action. */ serializeToNCCO() { const data = { action: "record" /* RECORD */ }; if (this.format) { data.format = this.format; } if (this.wrappedSplit) { data.split = this.split; } if (this.wrappedChannels) { data.channels = this.wrappedChannels; } if (this.wrappedEndOnKey) { data.endOnKey = this.endOnKey; } if (this.wrappedEndOnSilence) { data.endOnSilence = this.endOnSilence; } if (this.wrappedTimeOut) { data.timeOut = this.wrappedTimeOut; } if (this.beepStart) { data.beepStart = this.beepStart; } if (this.eventUrl) { data.eventUrl = this.eventUrl; } if (this.eventMethod) { data.eventMethod = this.eventMethod; } return data; } }; // lib/classes/NCCO/Stream.ts var Stream = class { /** * The action type for this NCCO action. */ action = "stream" /* STREAM */; /** * An array of stream URLs to play audio from. */ streamUrl; /** * The audio level at which to play the stream (optional). */ level; /** * Indicates whether the stream should allow barge-in (optional). */ bargeIn; /** * The number of times to loop the audio (optional). */ loop; /** * Creates a new Stream action. * * @param {string} streamUrl - The URL of the audio stream. * @param {number} [level] - The audio level at which to play the stream (optional). * @param {boolean} [bargeIn] - Indicates whether the stream should allow barge-in (optional). * @param {number} [loop] - The number of times to loop the audio (optional). */ constructor(streamUrl, level, bargeIn, loop) { this.streamUrl = [streamUrl]; if (level) { this.level = level; } if (bargeIn) { this.bargeIn = bargeIn; } if (loop) { this.loop = loop; } } /** * Serializes the Stream action to a Nexmo Call Control Object (NCCO). * * @return {StreamAction} - The serialized Stream action. */ serializeToNCCO() { const data = { action: "stream" /* STREAM */, streamUrl: this.streamUrl }; if (this.level) { data.level = this.level; } if (this.bargeIn) { data.bargeIn = this.bargeIn; } if (this.loop) { data.loop = this.loop; } return data; } }; // lib/classes/NCCO/Talk.ts var Talk = class { /** * The action type for this