UNPKG

@twilio/flex-plugins-library-utils

Version:

Flex Plugins Library Utils

469 lines (398 loc) 16 kB
import { Twilio } from 'twilio'; import { retryHandler } from '../../common/retryHandler'; import { PluginsUtilsMetaData } from '../../types'; import { Parameters, ApiReturnType } from '../../types'; import { isNumber, isObject, isString } from 'lodash'; import { CallInstance } from 'twilio/lib/rest/api/v2010/account/call'; import { QueueInstance } from 'twilio/lib/rest/api/v2010/account/queue'; import { RecordingInstance as CallRecordingInstance, RecordingListInstanceCreateOptions, } from 'twilio/lib/rest/api/v2010/account/call/recording'; import { RecordingInstance, } from 'twilio/lib/rest/api/v2010/account/recording'; import { OutgoingCallerIdInstance } from 'twilio/lib/rest/api/v2010/account/outgoingCallerId'; import { RecordingInstance as ConferenceRecordingInstance } from 'twilio/lib/rest/api/v2010/account/conference/recording'; import { fetchRecording, fetchVoiceQueue, updateCall, updateCallRecordingParams, updateConferenceRecording } from './types'; import { PluginUtils } from '../../common/BaseClasses/PluginUtils'; import { HttpErrorCode } from '../../constants/statusCodes'; import { PluginUtilsErrorManager } from '../../common/PluginUtilsErrorManager'; import TwilioRecordingAPI from './Api'; import { RETRY_STRATEGY } from 'src/constants/api'; export default class ProgrammableVoiceUtils extends PluginUtils { private config: PluginsUtilsMetaData; private api: TwilioRecordingAPI; /** * Utility class for Twilio's Programmable Voice resources * @param {Twilio} client Twilio client * @param {TaskRouterMetaData} config.maxBackoff Twilio service backoff max timeout * @param {TaskRouterMetaData} config.minBackoff Twilio service backoff min timeout * @param {TaskRouterMetaData} config.retryLimit Service retry limit * @param {TaskRouterMetaData} config.accountSid Twilio account sid * @param {TaskRouterMetaData} config.authToken Twilio auth token * */ constructor(client: Twilio, config: PluginsUtilsMetaData) { super(client); this.config = { ...config, maxBackoff: config.maxBackoff || RETRY_STRATEGY.MAX_BACKOFF, minBackoff: config.minBackoff || RETRY_STRATEGY.MIN_BACKOFF, retryLimit: config.retryLimit || RETRY_STRATEGY.RETRY_LIMIT, }; const { accountSid, authToken, region } = config; this.api = new TwilioRecordingAPI(accountSid, authToken, region); } /** * @param {string} parameters.callSid the unique call SID to fetch * @returns {Map} The given call's properties * @description fetches the given call SID's properties */ public async fetchProperties( parameters: Parameters & { callSid: string }, ): Promise<ApiReturnType & { callProperties?: CallInstance }> { const { callSid, attempts } = parameters; const parameterChecks = { callSid: 'string', }; try { const inputError = PluginUtilsErrorManager.checkInvalidParameters<Parameters & { callSid: string }>( parameters, parameterChecks, ); if (inputError) { throw new PluginUtilsErrorManager(inputError, HttpErrorCode.BadRequest); } const callProperties = await this.client.calls(callSid).fetch(); return { success: true, callProperties, status: HttpErrorCode.OK }; } catch (error) { if (error.code === HttpErrorCode.BadRequest) { return { success: false, status: HttpErrorCode.BadRequest, message: error.message, }; } return retryHandler<Parameters & { callSid: string }>(this.config, error,{ ...parameters , attempts: !attempts ? 0 : attempts},this.fetchProperties); } } /** * @param {string} parameters.callSid the unique call SID to fetch * @param {string} parameters.twiml the response of twiml based on to and from arguments of event * @returns {object} generic response object * @description cold transfers the given call SID to the given phone number */ public async coldTransfer(parameters: Parameters & { callSid: string; twiml: string; }): Promise<ApiReturnType> { const { callSid, twiml, attempts } = parameters; const parameterChecks = { callSid: 'string', twiml: 'string', }; try { const inputError = PluginUtilsErrorManager.checkInvalidParameters<Parameters & { callSid: string; twiml: string; }>( parameters, parameterChecks, ); if (inputError) { throw new PluginUtilsErrorManager(inputError, HttpErrorCode.BadRequest); } await this.client.calls(callSid).update({ twiml }); return { success: true, status: HttpErrorCode.OK }; } catch (error) { if (error.code === HttpErrorCode.BadRequest) { return { success: false, status: HttpErrorCode.BadRequest, message: error.message, }; } return retryHandler<Parameters & { callSid: string; twiml: string }>( this.config, error, { ...parameters, attempts: !attempts ? 0 : attempts }, this.coldTransfer, ); } } /** * @param {string} parameters.callSid the unique call SID to fetch * @param {object} parameters.params recording creation parameters * @returns {Map} The new recording's properties * @description creates recording for the given call SID */ public async createRecording( parameters: Parameters & { callSid: string; params: RecordingListInstanceCreateOptions }, ): Promise<ApiReturnType & { recording?: CallRecordingInstance }> { const { callSid, params, attempts } = parameters; const parameterChecks = { callSid: 'string', params: 'object', }; try { const inputError = PluginUtilsErrorManager.checkInvalidParameters< Parameters & { callSid: string; params: RecordingListInstanceCreateOptions } >(parameters, parameterChecks); if (inputError) { throw new PluginUtilsErrorManager(inputError, HttpErrorCode.BadRequest); } const recording = await this.client.calls(callSid).recordings.create(params); return { success: true, recording, status: HttpErrorCode.OK }; } catch (error) { if (error.code === HttpErrorCode.BadRequest) { return { success: false, status: HttpErrorCode.BadRequest, message: error.message, }; } return retryHandler<Parameters & { callSid: string; params: RecordingListInstanceCreateOptions }>( this.config, error, { ...parameters , attempts: !attempts ? 0 : attempts}, this.createRecording, ); } } /** * @param {string} parameters.callSid the unique call SID to update recording * @param {string} parameters.recordingSid the unique recording SID to update * @param {object} parameters.params recording update parameters * @returns {Map} The recording's properties * @description updates the given recording for the given call */ public async updateCallRecording( parameters: updateCallRecordingParams, ): Promise<ApiReturnType & { recording?: CallRecordingInstance }> { const { callSid, recordingSid, params, attempts } = parameters; const parameterChecks = { callSid: 'string', recordingSid: 'string', params: 'object', }; try { const inputError = PluginUtilsErrorManager.checkInvalidParameters<updateCallRecordingParams>( parameters, parameterChecks, ); if (inputError) { throw new PluginUtilsErrorManager(inputError, HttpErrorCode.BadRequest); } const recording = await this.client.calls(callSid).recordings(recordingSid).update(params); return { success: true, recording, status: HttpErrorCode.OK }; } catch (error) { if (error.code === HttpErrorCode.BadRequest) { return { success: false, status: HttpErrorCode.BadRequest, message: error.message, }; } return retryHandler<updateCallRecordingParams>(this.config, error,{ ...parameters , attempts: !attempts ? 0 : attempts},this.updateCallRecording); } } /** * @param {string} parameters.conferenceSid the unique conference SID to update recording * @param {string} parameters.recordingSid the unique recording SID to update * @param {object} parameters.params recording update parameters * @returns {Map} The recording's properties * @description updates the given recording for the given call */ public async updateConferenceRecording( parameters: updateConferenceRecording, ): Promise<ApiReturnType & { recording?: ConferenceRecordingInstance }> { const { conferenceSid, recordingSid, params, attempts } = parameters; const parameterChecks = { conferenceSid: 'string', recordingSid: 'string', params: 'object', }; try { const inputError = PluginUtilsErrorManager.checkInvalidParameters<updateConferenceRecording>( parameters, parameterChecks, ); if (inputError) { throw new PluginUtilsErrorManager(inputError, HttpErrorCode.BadRequest); } const recording = await this.client.conferences(conferenceSid).recordings(recordingSid).update(params); return { success: true, recording, status: HttpErrorCode.OK }; } catch (error) { if (error.code === HttpErrorCode.BadRequest) { return { success: false, status: HttpErrorCode.BadRequest, message: error.message, }; } return retryHandler<updateConferenceRecording>(this.config, error,{ ...parameters , attempts: !attempts ? 0 : attempts},this.updateConferenceRecording); } } /** * @param {string} parameters.callSid the unique call SID to update * @param {object} parameters.params recording update parameters * @returns {Map} The call's properties * @description updates the given call */ public async updateCall( parameters: updateCall, ): Promise<ApiReturnType & { call?: CallInstance }> { const { callSid, params, attempts } = parameters; const parameterChecks = { callSid: 'string', params: 'object', }; try { const inputError = PluginUtilsErrorManager.checkInvalidParameters<updateCall>( parameters, parameterChecks, ); if (inputError) { throw new PluginUtilsErrorManager(inputError, HttpErrorCode.BadRequest); } const call = await this.client.calls(callSid).update(params); return { success: true, call, status: HttpErrorCode.OK }; } catch (error) { if (error.code === HttpErrorCode.BadRequest) { return { success: false, status: HttpErrorCode.BadRequest, message: error.message, }; } return retryHandler<updateCall>(this.config, error,{ ...parameters , attempts: !attempts ? 0 : attempts},this.updateCall); } } /** * @param {string} parameters.queueSid the unique queue SID to fetch * @param {object} parameters.params recording update parameters * @returns {Map} The given queue's properties * @description fetches the given queue SID's properties */ public async fetchVoiceQueue( parameters: fetchVoiceQueue, ): Promise<ApiReturnType & { queueProperties?: QueueInstance }> { const { queueSid, attempts } = parameters; const parameterChecks = { queueSid: 'string', }; try { const inputError = PluginUtilsErrorManager.checkInvalidParameters<fetchVoiceQueue>( parameters, parameterChecks, ); if (inputError) { throw new PluginUtilsErrorManager(inputError, HttpErrorCode.BadRequest); } const queueProperties = await this.client.queues(queueSid).fetch(); return { success: true, queueProperties, status: HttpErrorCode.OK }; } catch (error) { if (error.code === HttpErrorCode.BadRequest) { return { success: false, status: HttpErrorCode.BadRequest, message: error.message, }; } return retryHandler<fetchVoiceQueue>(this.config, error,{ ...parameters , attempts: !attempts ? 0 : attempts},this.fetchVoiceQueue); } } /** * @param {string} parameters.recordingSid the unique recording SID to fetch * @param {object} parameters.params recording update parameters * @returns {Map} The given recording's properties * @description fetches the given recording SID's properties */ public async fetchRecording( parameters: fetchRecording, ): Promise<ApiReturnType & { recordingProperties?: RecordingInstance }> { const { recordingSid,attempts } = parameters; const parameterChecks = { recordingSid: 'string', }; try { const inputError = PluginUtilsErrorManager.checkInvalidParameters<fetchRecording>( parameters, parameterChecks, ); if (inputError) { throw new PluginUtilsErrorManager(inputError, HttpErrorCode.BadRequest); } const recordingProperties = await this.client.recordings(recordingSid).fetch(); return { success: true, recordingProperties, status: HttpErrorCode.OK }; } catch (error) { if (error.code === HttpErrorCode.BadRequest) { return { success: false, status: HttpErrorCode.BadRequest, message: error.message, }; } return retryHandler<fetchRecording>(this.config, error,{ ...parameters , attempts: !attempts ? 0 : attempts},this.fetchRecording); } } /** * @param {string} parameters.recordingSid the unique recording SID to fetch * @param {object} parameters.params recording update parameters * @returns {Map} The given recording's properties * @description fetches the given recording SID's properties */ public async fetchRecordingMedia( parameters: fetchRecording, ): Promise<ApiReturnType & { recording?: any , type?: string}> { const { recordingSid, attempts } = parameters; const parameterChecks = { recordingSid: 'string', }; try { const inputError = PluginUtilsErrorManager.checkInvalidParameters<fetchRecording>( parameters, parameterChecks, ); if (inputError) { throw new PluginUtilsErrorManager(inputError, HttpErrorCode.BadRequest); } const { data, headers: responseHeaders } = await this.api.getRecordingMedia(recordingSid); const recording = data; const type = responseHeaders['content-type']; return { success: true, recording, type, status: HttpErrorCode.OK }; } catch (error) { if (error.code === HttpErrorCode.BadRequest) { return { success: false, status: HttpErrorCode.BadRequest, message: error.message, }; } return retryHandler<fetchRecording>(this.config, error,{ ...parameters , attempts: !attempts ? 0 : attempts},this.fetchRecordingMedia); } } /** * @returns {Array<PhoneNumber>} An array of outbound caller ids for the account * @description the following method is used to robustly retrieve * the outbound caller ids for the account */ public async listOutgoingCallerIds( parameters: Parameters, ): Promise<ApiReturnType & { callerIds?: Array<OutgoingCallerIdInstance> }> { try { const callerIds = await this.client.outgoingCallerIds.list(); return { success: true, callerIds, status: HttpErrorCode.OK }; } catch (error) { if (error.code === HttpErrorCode.BadRequest) { return { success: false, status: HttpErrorCode.BadRequest, message: error.message, }; } return retryHandler( this.config, error, { ...parameters, attempts: !parameters.attempts ? 0 : parameters.attempts }, this.fetchRecording, ); } } }