@vonage/voice
Version:
The Voice API lets you create outbound calls, control in-progress calls and get information about historical calls.
562 lines • 19.9 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.Voice = void 0;
const server_client_1 = require("@vonage/server-client");
const vetch_1 = require("@vonage/vetch");
const enums_1 = require("./enums");
const apiCallsToCalls = (call) => {
delete call._links;
const transformedCall = server_client_1.Client.transformers.camelCaseObjectKeys(call, true, true);
delete transformedCall.conversationUuid;
return {
...transformedCall,
conversationUUID: call.conversation_uuid,
};
};
const NCCOToApiCalls = (ncco) => ncco.map((action) => {
switch (action.action) {
case enums_1.NCCOActions.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;
}
});
/**
* A Clint to make calls to the Vonage Voice API.
*
* @remarks
* Vonage API's will return information using `snake_case`. This represents the
* pure response before the client will transform the keys into `camelCase`.
*
* @example
* Create a standalone Voice client
*
* ```ts
* import { Voice } from '@vonage/voice';
*
* const voiceClient = new Voice({
* apiKey: VONAGE_API_KEY,
* apiSecret: VONAGE_API_SECRET
* });
* ```
*
* @example
* Create an Voice client from the Vonage client
*
* ```ts
* import { Vonage } from '@vonage/server-client';
*
* const vonage = new Vonage({
* apiKey: VONAGE_API_KEY,
* apiSecret: VONAGE_API_SECRET
* });
*
* const voiceClient = vonage.voice;
* ```
*/
class Voice extends server_client_1.Client {
authType = server_client_1.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`, server_client_1.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 = server_client_1.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 = server_client_1.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: digits });
return server_client_1.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 server_client_1.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 server_client_1.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.0) {
const resp = await this.sendPutRequest(`${this.config.apiHost}/v1/calls/${uuid}/stream`, {
stream_url: [url],
loop,
level: String(volumeLevel),
});
return server_client_1.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 server_client_1.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 = vetch_1.ResponseTypes.stream;
const client = new server_client_1.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 = vetch_1.ResponseTypes.text;
const client = new server_client_1.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: action,
...(destination ? { destination: destination } : {}),
});
}
}
exports.Voice = Voice;
//# sourceMappingURL=voice.js.map