Merge pull request #162 from plivo/VT-2219_MPC_Changes

Vt 2219 mpc changes
This commit is contained in:
Mohammed Huzaif 2021-04-19 20:25:41 +05:30 committed by GitHub
commit f296a70f15
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 1492 additions and 6 deletions

View file

@ -1,5 +1,8 @@
# Change Log
## [4.16.0](https://github.com/plivo/plivo-node/releases/tag/v4.16.0)(2021-04-19)
- Added SDK support for Voice MultiPartyCall APIs and XML
## [4.15.0](https://github.com/plivo/plivo-node/releases/tag/v4.15.0)(2021-04-19)
- Add support for Regulatory Compliance APIs.
- Add "npanxx" and "local_calling_area" support for Search Phone Number.

View file

@ -4,6 +4,9 @@ let actionKey = Symbol('api action');
let klassKey = Symbol('constructor');
let idKey = Symbol('id filed');
let clientKey = Symbol('make api call');
let secondaryActionKey = Symbol('api action');
let secondaryKlassKey = Symbol('constructor');
let secondaryIdKey = Symbol('id filed');
export class PlivoGenericResponse {
constructor(params, idString) {
@ -123,6 +126,36 @@ export class PlivoResource {
}
}
export class PlivoSecondaryResource {
constructor(action, klass, idField, secondaryAction, secondaryKlass, secondaryIdField, request) {
this[actionKey] = action;
this[klassKey] = klass;
this[idKey] = idField;
this[clientKey] = request;
this[secondaryActionKey] = secondaryAction;
this[secondaryKlassKey] = secondaryKlass;
this[secondaryIdKey] = secondaryIdField;
}
executeAction(task = '', secondaryTask = '', method = 'GET', params = {}, action, secondaryAction) {
let client = this[clientKey];
action = action == null ? this[actionKey] : action;
let idField = this[idKey];
secondaryAction = secondaryAction == null ? this[secondaryActionKey] : secondaryAction;
let secondaryIdField = this[secondaryIdKey]
return new Promise((resolve, reject) => {
client(method, action + task + '/' + secondaryAction + secondaryTask + '/', params)
.then(response => {
resolve(new PlivoGenericResponse(response.body, secondaryIdField));
})
.catch(error => {
reject(error);
});
});
}
}
export class PlivoResourceInterface {
constructor(action, klass, idField, request) {
this[actionKey] = action;

View file

@ -327,4 +327,4 @@ export class ApplicationInterface extends PlivoResourceInterface {
id: id
}).delete(params, id);
}
}
}

View file

@ -0,0 +1,592 @@
import {extend, validate} from '../utils/common.js';
import {PlivoResource, PlivoResourceInterface, PlivoSecondaryResource} from '../base';
import {
validSubAccount,
validUrl,
validParam,
validDateFormat,
validRange,
validMultipleDestinationNos,
isOneAmongStringUrl, multiValidParam
} from '../rest/utils.js'
const clientKey = Symbol();
const action = 'MultiPartyCall/';
const idField = 'mpcUuid';
const secondaryAction = 'Participant/';
const secondaryIdField = 'participantUuid';
export class MPCError extends Error { }
export class MultiPartyCall extends PlivoResource{
constructor(client, data = {}) {
super(action, MultiPartyCall, idField, client);
if (idField in data) {
this.id = data[idField];
}
extend(this, data);
this[clientKey] = client;
}
get(params = {}){
params.isVoiceRequest = 'true';
return super.executeAction(this.id, 'GET', params);
}
addParticipant(params){
if((params.from && params.to) && (params.callUuid)){
throw new MPCError('cannot specify callUuid when (from, to) is provided')
}
if((!params.from && !params.to) && !params.callUuid){
throw new MPCError('specify either callUuid or (from, to)')
}
if((!params.callUuid) && (!params.from || !params.to)){
throw new MPCError('specify (from, to) when not adding an existing callUuid to multi party participant')
}
validParam('role', params.role.toLowerCase(), [String], true, ['agent', 'supervisor', 'customer'])
if(params.from){
validParam('from', params.from, [String], false)
}
if(params.to){
validParam('to', params.to, [String], false)
validMultipleDestinationNos('to', params.to, {role: params.role, delimiter: '<', agentLimit: 20})
}
if(params.callUuid){
validParam('callUuid', params.callUuid, [String], false)
}
if(params.callStatusCallbackUrl){
validUrl('callStatusCallbackUrl', params.callStatusCallbackUrl, false)
}
if(params.callStatusCallbackMethod){
validParam('callStatusCallbackMethod', params.callStatusCallbackMethod.toUpperCase(), [String], false, ['GET', 'POST'])
}
else{
params.callStatusCallbackMethod = 'POST'
}
if(params.sipHeaders){
validParam('sipHeaders', params.sipHeaders, [String], false)
}
if(params.confirmKey){
validParam('confirmKey', params.confirmKey, [String], false, ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '#', '*'])
}
if(params.confirmKeySoundUrl){
validUrl('confirmKeySoundUrl', params.confirmKeySoundUrl, false)
}
if(params.confirmKeySoundMethod){
validParam('confirmKeySoundMethod)', params.confirmKeySoundMethod.toUpperCase(), [String], false, ['GET', 'POST'])
}
else{
params.confirmKeySoundMethod = 'GET'
}
if(params.dialMusic){
isOneAmongStringUrl('dialMusic', params.dialMusic, false, ['real', 'none'])
}
else {
params.dialMusic = 'Real'
}
if(params.ringTimeout || params.ringTimeout === 0){
validRange('ringTimeout', params.ringTimeout, false, 15, 120)
}
else {
params.ringTimeout = 45
}
if(params.maxDuration || params.maxDuration === 0){
validRange('maxDuration', params.maxDuration, false, 300, 28800)
}
else {
params.maxDuration = 14400
}
if(params.maxParticipants || params.maxParticipants === 0){
validRange('maxParticipants', params.maxParticipants, false, 2, 10)
}
else {
params.maxParticipants = 10
}
if(params.waitMusicUrl){
validUrl('waitMusicUrl', params.waitMusicUrl, false)
}
if(params.waitMusicMethod){
validParam('waitMusicMethod', params.waitMusicMethod.toUpperCase(), [String], false, ['GET', 'POST'])
}
else {
params.waitMusicMethod = 'GET'
}
if(params.agentHoldMusicUrl){
validUrl('agentHoldMusicUrl', params.agentHoldMusicUrl, false)
}
if(params.agentHoldMusicMethod){
validParam('agentHoldMusicMethod', params.agentHoldMusicMethod.toUpperCase(), [String], false, ['GET', 'POST'])
}
else {
params.agentHoldMusicMethod = 'GET'
}
if(params.customerHoldMusicUrl){
validUrl('customerHoldMusicUrl', params.customerHoldMusicUrl, false)
}
if(params.customerHoldMusicMethod){
validParam('customerHoldMusicMethod', params.customerHoldMusicMethod.toUpperCase(), [String], false, ['GET', 'POST'])
}
else {
params.customerHoldMusicMethod = 'GET'
}
if(params.recordingCallbackUrl){
validUrl('recordingCallbackUrl', params.recordingCallbackUrl, false)
}
if(params.recordingCallbackMethod){
validParam('recordingCallbackMethod', params.recordingCallbackMethod.toUpperCase(), [String], false, ['GET', 'POST'])
}
else {
params.recordingCallbackMethod = 'GET'
}
if(params.statusCallbackUrl){
validUrl('statusCallbackUrl', params.statusCallbackUrl, false)
}
if(params.statusCallbackMethod){
validParam('statusCallbackMethod', params.statusCallbackMethod.toUpperCase(), [String], false, ['GET', 'POST'])
}
else {
params.statusCallbackMethod = 'GET'
}
if(params.onExitActionUrl){
validUrl('onExitActionUrl', params.onExitActionUrl, false)
}
if(params.onExitActionMethod){
validParam('statusCallbackMethod', params.statusCallbackMethod.toUpperCase(), [String], false, ['GET', 'POST'])
}
else {
params.onExitActionMethod = 'POST'
}
if(params.record){
validParam('record', params.record, [Boolean, String], false)
}
else {
params.record = 'false'
}
if(params.recordFileFormat){
validParam('recordFileFormat', params.recordFileFormat.toLowerCase(), [String], false, ['mp3', 'wav'])
}
else {
params.recordFileFormat = 'mp3'
}
if(params.statusCallbackEvents){
multiValidParam('statusCallbackEvents', params.statusCallbackEvents.toLowerCase(), [String], false, ['mpc-state-changes', 'participant-state-changes', 'participant-speak-events', 'participant-digit-input-events', 'add-participant-api-events'], true,',')
}
else {
params.statusCallbackEvents = 'mpc-state-changes,participant-state-changes'
}
if(params.stayAlone){
validParam('stayAlone', params.stayAlone, [Boolean, String], false)
}
else {
params.stayAlone = 'false'
}
if(params.coachMode){
validParam('coachMode', params.coachMode, [Boolean, String], false)
}
else {
params.coachMode = 'true'
}
if(params.mute){
validParam('mute', params.mute, [Boolean, String], false)
}
else {
params.mute = 'false'
}
if(params.hold){
validParam('hold', params.hold, [Boolean, String], false)
}
else {
params.hold = 'false'
}
if(params.startMpcOnEnter){
validParam('startMpcOnEnter', params.startMpcOnEnter, [Boolean, String], false)
}
else {
params.startMpcOnEnter = 'true'
}
if(params.endMpcOnExit){
validParam('endMpcOnExit', params.endMpcOnExit, [Boolean, String], false)
}
else {
params.endMpcOnExit = 'false'
}
if(params.relayDTMFInputs){
validParam('relayDTMFInputs', params.relayDTMFInputs, [Boolean, String], false)
}
else {
params.relayDTMFInputs = 'false'
}
if(params.enterSound){
isOneAmongStringUrl('enterSound', params.enterSound, false, ['beep:1', 'beep:2', 'none'])
}
else {
params.enterSound = 'beep:1'
}
if(params.enterSoundMethod){
validParam('enterSoundMethod', params.enterSoundMethod.toUpperCase(), [String], false, ['GET', 'POST'])
}
else {
params.enterSoundMethod = 'GET'
}
if(params.exitSound){
isOneAmongStringUrl('exitSound', params.exitSound, false, ['beep:1', 'beep:2', 'none'])
}
else {
params.exitSound = 'beep:2'
}
if(params.exitSoundMethod){
validParam('exitSoundMethod', params.exitSoundMethod.toUpperCase(), [String], false, ['GET', 'POST'])
}
else {
params.exitSoundMethod = 'GET'
}
params.isVoiceRequest = 'true';
return super.executeAction(this.id + '/Participant/', 'POST', params)
}
start(){
return super.executeAction(this.id + '/', 'POST', {'status' : 'active', 'isVoiceRequest' : 'true'})
}
stop(){
return super.delete({'isVoiceRequest' : 'true'})
}
startRecording(params = {}){
if(params.fileFormat){
validParam('fileFormat', params.fileFormat, [String], false, ['mp3', 'wav'])
}
else {
params.fileFormat = 'mp3'
}
if(params.statusCallbackUrl){
validUrl('statusCallbackUrl', params.statusCallbackUrl, false)
}
if(params.statusCallbackMethod){
validParam('statusCallbackMethod', params.statusCallbackMethod.toUpperCase(), [String], false, ['GET', 'POST'])
}
else {
params.statusCallbackMethod = 'POST'
}
params.isVoiceRequest = 'true';
return super.executeAction(this.id + '/Record/', 'POST', params)
}
stopRecording(){
return super.executeAction(this.id + '/Record/', 'DELETE',{'isVoiceRequest' : 'true'})
}
pauseRecording(){
return super.executeAction(this.id + '/Record/Pause/', 'POST',{'isVoiceRequest' : 'true'})
}
resumeRecording(){
return super.executeAction(this.id + '/Record/Resume/', 'POST',{'isVoiceRequest' : 'true'})
}
listParticipants(params = {}){
if(params.callUuid){
validParam('callUuid', params.callUuid, [String], false)
}
params.isVoiceRequest = 'true';
return super.executeAction(this.id + '/Participant/', 'GET', params)
}
}
export class MultiPartyCallParticipant extends PlivoSecondaryResource{
constructor(client, data = {}) {
super(action, MultiPartyCall, idField, secondaryAction, MultiPartyCallParticipant, secondaryIdField, client);
if (idField in data) {
this.id = data[idField];
}
if(secondaryIdField in data){
this.secondaryId = data[secondaryIdField];
}
extend(this, data);
this[clientKey] = client;
}
updateParticipant(params = {}){
if(params.coachMode){
validParam('coachMode', params.coachMode, [Boolean, String], false)
}
if(params.mute){
validParam('mute', params.mute, [Boolean, String], false)
}
if(params.hold){
validParam('hold', params.hold, [Boolean, String], false)
}
params.isVoiceRequest = 'true';
return super.executeAction(this.id, this.secondaryId, 'POST', params)
}
kickParticipant(){
return super.executeAction(this.id, this.secondaryId, 'DELETE',{'isVoiceRequest' : 'true'})
}
getParticipant(){
return super.executeAction(this.id, this.secondaryId, 'GET',{'isVoiceRequest' : 'true'})
}
}
export class MultiPartyCallInterface extends PlivoResourceInterface{
constructor(client, data = {}) {
super(action, MultiPartyCall, idField, client);
extend(this, data);
this[clientKey] = client;
}
makeMpcId(uuid = null, friendlyName = null){
if(!uuid && !friendlyName){
throw new MPCError('Specify either multi party call friendly name or uuid')
}
if(uuid && friendlyName){
throw new MPCError('Cannot specify both multi party call friendly name or uuid')
}
let identifier = ''
if(uuid){
identifier = ['uuid_', uuid]
}
else{
identifier = ['name_', friendlyName]
}
return identifier;
}
list(params={}) {
if(params.subAccount){
validSubAccount(params.subAccount);
}
if(params.friendlyName){
validParam('friendlyName', params.friendlyName, [String], false)
}
if(params.status){
validParam('status', params.status.toLowerCase(), [String], false, ['initialized', 'active', 'ended'])
}
if(params.terminationCauseCode){
validParam('terminationCauseCode', params.terminationCauseCode, [Number, String], false)
}
if(params.end_time__gt){
validDateFormat('end_time__gt', params.end_time__gt, false)
}
if(params.end_time__gte){
validDateFormat('end_time__gte', params.end_time__gte, false)
}
if(params.end_time__lt){
validDateFormat('end_time__lt', params.end_time__lt, false)
}
if(params.end_time__lte){
validDateFormat('end_time__lte', params.end_time__lte, false)
}
if(params.creation_time__gt){
validDateFormat('creation_time__gt', params.creation_time__gt, false)
}
if(params.creation_time__gte){
validDateFormat('creation_time__gte', params.creation_time__gte, false)
}
if(params.creation_time__lt){
validDateFormat('creation_time__lt', params.creation_time__lt, false)
}
if(params.creation_time__lte){
validDateFormat('creation_time__lte', params.creation_time__lte, false)
}
if(params.limit){
validRange('limit', params.limit, false, 1, 20)
}
if(params.offset){
validRange('offset', params.offset, false, 0)
}
params.isVoiceRequest = 'true';
return super.list(params);
}
get(uuid = null, friendlyName = null){
if(uuid){
validParam('uuid', uuid, [String], false)
}
if(friendlyName){
validParam('friendlyName', friendlyName, [String], false)
}
let mpcId = this.makeMpcId(uuid, friendlyName)
return new MultiPartyCall(this[clientKey], {id: mpcId[0] + mpcId[1]}).get();
}
addParticipant(role, params = {}){
if(params.uuid){
validParam('uuid', params.uuid, [String], false)
}
if(params.friendlyName){
validParam('friendlyName', params.friendlyName, [String], false)
}
let mpcId = this.makeMpcId(params.uuid, params.friendlyName)
delete params.uuid
delete params.friendlyName
params.role = role
return new MultiPartyCall(this[clientKey], {id: mpcId[0] + mpcId[1]}).addParticipant(params)
}
start(uuid = null, friendlyName = null){
if(uuid){
validParam('uuid', uuid, [String], false)
}
if(friendlyName){
validParam('friendlyName', friendlyName, [String], false)
}
let mpcId = this.makeMpcId(uuid, friendlyName)
return new MultiPartyCall(this[clientKey], {id: mpcId[0] + mpcId[1]}).start()
}
stop(uuid = null, friendlyName = null){
if(uuid){
validParam('uuid', uuid, [String], false)
}
if(friendlyName){
validParam('friendlyName', friendlyName, [String], false)
}
let mpcId = this.makeMpcId(uuid, friendlyName)
return new MultiPartyCall(this[clientKey], {id: mpcId[0] + mpcId[1]}).stop()
}
startRecording(uuid = null, friendlyName = null, params){
if(uuid){
validParam('uuid', uuid, [String], false)
}
if(friendlyName){
validParam('friendlyName', friendlyName, [String], false)
}
let mpcId = this.makeMpcId(uuid, friendlyName)
return new MultiPartyCall(this[clientKey], {id: mpcId[0] + mpcId[1]}).startRecording(params)
}
stopRecording(uuid = null, friendlyName = null){
if(uuid){
validParam('uuid', uuid, [String], false)
}
if(friendlyName){
validParam('friendlyName', friendlyName, [String], false)
}
let mpcId = this.makeMpcId(uuid, friendlyName)
return new MultiPartyCall(this[clientKey], {id: mpcId[0] + mpcId[1]}).stopRecording()
}
pauseRecording(uuid = null, friendlyName = null){
if(uuid){
validParam('uuid', uuid, [String], false)
}
if(friendlyName){
validParam('friendlyName', friendlyName, [String], false)
}
let mpcId = this.makeMpcId(uuid, friendlyName)
return new MultiPartyCall(this[clientKey], {id: mpcId[0] + mpcId[1]}).pauseRecording()
}
resumeRecording(uuid = null, friendlyName = null){
if(uuid){
validParam('uuid', uuid, [String], false)
}
if(friendlyName){
validParam('friendlyName', friendlyName, [String], false)
}
let mpcId = this.makeMpcId(uuid, friendlyName)
return new MultiPartyCall(this[clientKey], {id: mpcId[0] + mpcId[1]}).resumeRecording()
}
listParticipants(uuid = null, friendlyName = null, params){
if(uuid){
validParam('uuid', uuid, [String], false)
}
if(friendlyName){
validParam('friendlyName', friendlyName, [String], false)
}
let mpcId = this.makeMpcId(uuid, friendlyName)
return new MultiPartyCall(this[clientKey], {id: mpcId[0] + mpcId[1]}).listParticipants(params)
}
updateParticipant(participantId, uuid= null, friendlyName = null, params){
validParam('participantId', participantId, [String, Number], true)
if(uuid){
validParam('uuid', uuid, [String], false)
}
if(friendlyName){
validParam('friendlyName', friendlyName, [String], false)
}
let mpcId = this.makeMpcId(uuid, friendlyName)
return new MultiPartyCallParticipant(this[clientKey], {id: mpcId[0] + mpcId[1], secondaryId: participantId}).updateParticipant(params)
}
kickParticipant(participantId, uuid = null, friendlyName = null){
validParam('participantId', participantId, [String, Number], true)
if(uuid){
validParam('uuid', uuid, [String], false)
}
if(friendlyName){
validParam('friendlyName', friendlyName, [String], false)
}
let mpcId = this.makeMpcId(uuid, friendlyName)
return new MultiPartyCallParticipant(this[clientKey], {id: mpcId[0] + mpcId[1], secondaryId: participantId}).kickParticipant()
}
getParticipant(participantId, uuid = null, friendlyName = null){
validParam('participantId', participantId, [String, Number], true)
if(uuid){
validParam('uuid', uuid, [String], false)
}
if(friendlyName){
validParam('friendlyName', friendlyName, [String], false)
}
let mpcId = this.makeMpcId(uuid, friendlyName)
return new MultiPartyCallParticipant(this[clientKey], {id: mpcId[0] + mpcId[1], secondaryId: participantId}).getParticipant()
}
}

View file

@ -48,6 +48,7 @@ import {
import {
MediaInterface
} from '../resources/media.js';
import {MultiPartyCallInterface} from "../resources/multiPartyCall";
export class Client {
constructor(authId, authToken, proxy) {
@ -95,6 +96,7 @@ export class Client {
this.complianceDocuments = new ComplianceDocumentInterface(client);
this.complianceRequirements = new ComplianceRequirementInterface(client);
this.complianceApplications = new ComplianceApplicationInterface(client);
this.multiPartyCalls = new MultiPartyCallInterface(client);
}
}

View file

@ -25,6 +25,7 @@ import { ComplianceDocumentTypeInterface } from "../resources/complianceDocument
import { ComplianceDocumentInterface} from "../resources/complianceDocuments";
import { ComplianceRequirementInterface } from "../resources/complianceRequirements";
import { ComplianceApplicationInterface } from "../resources/complianceApplications";
import {MultiPartyCallInterface} from "../resources/multiPartyCall";
exports.Response = function() {
return new Response();
@ -92,6 +93,7 @@ export class Client {
this.complianceDocuments = new ComplianceDocumentInterface(client);
this.complianceRequirements = new ComplianceRequirementInterface(client);
this.complianceApplications = new ComplianceApplicationInterface(client);
this.multiPartyCalls = new MultiPartyCallInterface(client);
}
toJSON() {

View file

@ -583,6 +583,306 @@ export function Request(config) {
});
}
// ============= MultiPartyCalls ===============
else if (method === 'GET' && action === 'MultiPartyCall/'){
resolve({
response: {},
body: {
"api_id": "d53ab14c-eddb-11ea-b02e-0242ac110003",
"meta": {
"count": 6,
"limit": 20,
"next": null,
"offset": 0,
"previous": null
},
"objects": [
{
"billed_amount": "0.00500",
"billed_duration": 60,
"creation_time": "2020-08-31 15:12:03+00:00",
"duration": 3,
"end_time": "2020-08-31 15:12:06+00:00",
"friendly_name": "TestMPC",
"mpc_uuid": "ca8e8a44-48e1-445d-afd5-1fcccdbccd9d",
"participants": "/v1/Account/MAMDJMMTEZOWY0ZMQWM2/MultiPartyCall/uuid_ca8e8a44-48e1-445d-afd5-1fcccdbccd9d/Participant/",
"recording": null,
"resource_uri": "/v1/Account/MAMDJMMTEZOWY0ZMQWM2/MultiPartyCall/uuid_ca8e8a44-48e1-445d-afd5-1fcccdbccd9d/",
"start_time": null,
"status": "Ended",
"stay_alone": false,
"sub_account": null,
"termination_cause": "No Active Participants",
"termination_cause_code": 1000
},
{
"billed_amount": "0.00500",
"billed_duration": 60,
"creation_time": "2020-08-31 14:32:40+00:00",
"duration": 5,
"end_time": "2020-08-31 14:32:45+00:00",
"friendly_name": "TestMPC",
"mpc_uuid": "9b531a1f-1692-4802-a7d6-3ef25bcfe3fc",
"participants": "/v1/Account/MAMDJMMTEZOWY0ZMQWM2/MultiPartyCall/uuid_9b531a1f-1692-4802-a7d6-3ef25bcfe3fc/Participant/",
"recording": null,
"resource_uri": "/v1/Account/MAMDJMMTEZOWY0ZMQWM2/MultiPartyCall/uuid_9b531a1f-1692-4802-a7d6-3ef25bcfe3fc/",
"start_time": null,
"status": "Ended",
"stay_alone": false,
"sub_account": null,
"termination_cause": "No Active Participants",
"termination_cause_code": 1000
},
{
"billed_amount": "0.01000",
"billed_duration": 120,
"creation_time": "2020-08-31 14:32:11+00:00",
"duration": 11,
"end_time": "2020-08-31 14:32:22+00:00",
"friendly_name": "TestMPC",
"mpc_uuid": "6f84d47c-ee82-4172-a155-c6e22f87d874",
"participants": "/v1/Account/MAMDJMMTEZOWY0ZMQWM2/MultiPartyCall/uuid_6f84d47c-ee82-4172-a155-c6e22f87d874/Participant/",
"recording": null,
"resource_uri": "/v1/Account/MAMDJMMTEZOWY0ZMQWM2/MultiPartyCall/uuid_6f84d47c-ee82-4172-a155-c6e22f87d874/",
"start_time": null,
"status": "Ended",
"stay_alone": false,
"sub_account": null,
"termination_cause": "Stay Alone Not Permitted",
"termination_cause_code": 1010
},
{
"billed_amount": "0.00500",
"billed_duration": 60,
"creation_time": "2020-08-31 14:31:20+00:00",
"duration": 3,
"end_time": "2020-08-31 14:31:23+00:00",
"friendly_name": "TestMPC",
"mpc_uuid": "0746f6c6-7447-4e0a-9013-186e4220aaf4",
"participants": "/v1/Account/MAMDJMMTEZOWY0ZMQWM2/MultiPartyCall/uuid_0746f6c6-7447-4e0a-9013-186e4220aaf4/Participant/",
"recording": null,
"resource_uri": "/v1/Account/MAMDJMMTEZOWY0ZMQWM2/MultiPartyCall/uuid_0746f6c6-7447-4e0a-9013-186e4220aaf4/",
"start_time": "2020-08-31 14:31:20+00:00",
"status": "Ended",
"stay_alone": false,
"sub_account": null,
"termination_cause": "No Active Participants",
"termination_cause_code": 1000
},
{
"billed_amount": "0.00500",
"billed_duration": 60,
"creation_time": "2020-08-31 06:42:50+00:00",
"duration": 36,
"end_time": "2020-08-31 06:43:26+00:00",
"friendly_name": "TestMPC",
"mpc_uuid": "b89150fd-0387-4bf8-bde7-a4fed39601ce",
"participants": "/v1/Account/MAMDJMMTEZOWY0ZMQWM2/MultiPartyCall/uuid_b89150fd-0387-4bf8-bde7-a4fed39601ce/Participant/",
"recording": null,
"resource_uri": "/v1/Account/MAMDJMMTEZOWY0ZMQWM2/MultiPartyCall/uuid_b89150fd-0387-4bf8-bde7-a4fed39601ce/",
"start_time": "2020-08-31 06:42:50+00:00",
"status": "Ended",
"stay_alone": false,
"sub_account": null,
"termination_cause": "No Active Participants",
"termination_cause_code": 1000
},
{
"billed_amount": "0.00500",
"billed_duration": 60,
"creation_time": "2020-08-28 17:30:10+00:00",
"duration": 2,
"end_time": "2020-08-28 17:30:12+00:00",
"friendly_name": "tank",
"mpc_uuid": "2999c70d-b635-420f-b6f2-2fd4421f0381",
"participants": "/v1/Account/MAMDJMMTEZOWY0ZMQWM2/MultiPartyCall/uuid_2999c70d-b635-420f-b6f2-2fd4421f0381/Participant/",
"recording": null,
"resource_uri": "/v1/Account/MAMDJMMTEZOWY0ZMQWM2/MultiPartyCall/uuid_2999c70d-b635-420f-b6f2-2fd4421f0381/",
"start_time": "2020-08-28 17:30:10+00:00",
"status": "Ended",
"stay_alone": true,
"sub_account": null,
"termination_cause": "No Active Participants",
"termination_cause_code": 1000
}
]
}
});
}
else if (method === 'GET' && action === 'MultiPartyCall/uuid_ca8e8a44-48e1-445d-afd5-1fcccdbccd9d'){
resolve({
response: {},
body: {
"api_id": "8970c2b3-edfb-11ea-b02e-0242ac110003",
"billed_amount": "0.00500",
"billed_duration": 60,
"creation_time": "2020-08-31 15:12:03+00:00",
"duration": 3,
"end_time": "2020-08-31 15:12:06+00:00",
"friendly_name": "TestMPC",
"mpc_uuid": "ca8e8a44-48e1-445d-afd5-1fcccdbccd9d",
"participants": "/v1/Account/MAMDJMMTEZOWY0ZMQWM2/MultiPartyCall/uuid_ca8e8a44-48e1-445d-afd5-1fcccdbccd9d/Participant/",
"recording": null,
"resource_uri": "/v1/Account/MAMDJMMTEZOWY0ZMQWM2/MultiPartyCall/uuid_ca8e8a44-48e1-445d-afd5-1fcccdbccd9d/",
"start_time": null,
"status": "Ended",
"stay_alone": false,
"sub_account": null,
"termination_cause": "No Active Participants",
"termination_cause_code": 1000
}
});
}
else if (method === 'POST' && action === 'MultiPartyCall/name_Voice/Participant/' && params.role === 'Agent' && params.from === '+919090909090' && params.to === '+918309866821'){
resolve({
response: {},
body: {
"api_id": "1cebd713-ee00-11ea-b02e-0242ac110003",
"calls": [
{
"to": "sip:koushikqa119062465586783372208@phone-qa.voice.plivodev.com",
"from": "918888888888",
"call_uuid": "c0267574-5c12-4861-8990-da9404c8cdf6"
}
],
"message": "add participant action initiated",
"request_uuid": "c0267574-5c12-4861-8990-da9404c8cdf6"
}
});
}
else if (method === 'POST' && action === 'MultiPartyCall/name_Voice/' && params.status === 'active'){
resolve({
response: {},
body: {}
});
}
else if (method === 'DELETE' && action === 'MultiPartyCall/name_Voice/'){
resolve({
response: {},
body: {}
});
}
else if (method === 'POST' && action === 'MultiPartyCall/name_TestMPC/Record/'){
resolve({
response: {},
body: {
"api_id" : "e9b9b0cf-ee0a-11ea-b02e-0242ac110003",
"message" : "MPC: TestMPC record started",
"recording_id" : "e9bd7634-ee0a-11ea-9ddf-06feebbe3347",
"recording_url" : "https://media-qa.voice.plivodev.com/v1/Account/MAMDJMMTEZOWY0ZMQWM2/Recording/e9bd7634-ee0a-11ea-9ddf-06feebbe3347.mp3"
}
});
}
else if (method === 'DELETE' && action === 'MultiPartyCall/name_TestMPC/Record/'){
resolve({
response: {},
body: {
}
});
}
else if (method === 'POST' && action === 'MultiPartyCall/name_TestMPC/Record/Pause/'){
resolve({
response: {},
body: {
}
});
}
else if (method === 'POST' && action === 'MultiPartyCall/name_TestMPC/Record/Resume/'){
resolve({
response: {},
body: {
}
});
}
else if (method === 'GET' && action === 'MultiPartyCall/uuid_12345678-90123456/Participant/'){
resolve({
response: {},
body: {
"api_id": "d53e6c49-ee0e-11ea-b02e-0242ac110003",
"meta": {
"count": 1,
"limit": 20,
"next": null,
"offset": 0,
"previous": null
},
"objects": [
{
"billed_amount": null,
"billed_duration": null,
"call_uuid": "426c1fb3-8f47-46e5-a916-51faa85ca90e",
"coach_mode": false,
"duration": null,
"end_mpc_on_exit": false,
"exit_cause": null,
"exit_time": null,
"hold": false,
"join_time": "2020-09-03 17:24:12+00:00",
"member_id": "2132",
"mpc_uuid": "7503f05f-2d6e-4ab3-b9e6-3b0d81ae9087",
"mute": false,
"resource_uri": "/v1/Account/MAMDJMMTEZOWY0ZMQWM2/MultiPartyCall/uuid_7503f05f-2d6e-4ab3-b9e6-3b0d81ae9087/Participant/2132/",
"role": "agent",
"start_mpc_on_enter": true
}
]
}
});
}
else if (method === 'POST' && action === 'MultiPartyCall/uuid_12345678-90123456/Participant/10/'){
resolve({
response: {},
body: {
"api_id" : "be5a333a-ee0f-11ea-b02e-0242ac110003",
"hold" : "MPC: TestMPC hold/unhold member(s) succeded",
"mute" : "MPC: TestMPC mute/unmute member(s) succeded"
}
});
}
else if (method === 'DELETE' && action === 'MultiPartyCall/uuid_12345678-90123456/Participant/10/'){
resolve({
response: {},
body: {
}
});
}
else if (method === 'GET' && action === 'MultiPartyCall/uuid_7503f05f-2d6e-4ab3-b9e6-3b0d81ae9087/Participant/2132/'){
resolve({
response: {},
body: {
"api_id": "7ca274bb-ee11-11ea-b02e-0242ac110003",
"billed_amount": null,
"billed_duration": null,
"call_uuid": "426c1fb3-8f47-46e5-a916-51faa85ca90e",
"coach_mode": false,
"duration": null,
"end_mpc_on_exit": false,
"exit_cause": null,
"exit_time": null,
"hold": false,
"join_time": "2020-09-03 17:24:12+00:00",
"member_id": "2132",
"mpc_uuid": "7503f05f-2d6e-4ab3-b9e6-3b0d81ae9087",
"mute": false,
"resource_uri": "/v1/Account/MAMDJMMTEZOWY0ZMQWM2/MultiPartyCall/uuid_7503f05f-2d6e-4ab3-b9e6-3b0d81ae9087/Participant/2132/",
"role": "agent",
"start_mpc_on_enter": true
}
});
}
// ============= Numbers ===================
else if (method == 'GET' && action == 'Number/+919999999990/') {
resolve({

View file

@ -5,6 +5,8 @@ import _mapValues from 'lodash/mapValues';
import _map from 'lodash/map';
import { parseString } from 'xml2js';
export class InvalidRequestError extends Error {}
function recursivelyRenameObject(object, renameFunc) {
if (!(object instanceof Object)) {
return object;
@ -79,3 +81,203 @@ export function validateSpeakAttributes(content, voice) {
}
}
export function validSubAccount(accountId){
if(accountId.constructor !== String){
throw new InvalidRequestError('Subaccount Id must be a string');
}
if(accountId.length !== 20){
throw new InvalidRequestError('Subaccount Id should be of length 20');
}
if(accountId.substring(0,2) !== 'SA'){
throw new InvalidRequestError("Subaccount Id should start with 'SA'");
}
return true;
}
export function validMultipleDestinationNos(paramName, paramValue, options = {}){
if(paramValue.split(options.delimiter).length > 1 && options.role.toLowerCase()!=='agent'){
throw new InvalidRequestError('Multiple ' + paramName + ' values given for role ' + options.role)
}
else if (paramValue.split(options.delimiter).length >= options.agentLimit){
throw new InvalidRequestError('No of ' + paramName + ' values provided should be lesser than ' + options.agentLimit)
}
else {
return true
}
}
export function validParam(paramName, paramValue, expectedTypes = null, mandatory = false, expectedValues = null){
if(mandatory && !paramValue){
throw new InvalidRequestError(paramName + " is a required parameter");
}
if (!paramValue){
return true;
}
if(!expectedValues){
return expectedType(paramName, expectedTypes, paramValue);
}
if(expectedValue(paramName, expectedValues, paramValue)){
return true;
}
}
export function expectedType(paramName, expectedTypes, paramValue){
if(!expectedTypes){
return true;
}
if(expectedTypes.indexOf(paramValue.constructor)===-1){
throw new InvalidRequestError(paramName + ": Expected one of " + expectedTypes + " but received " + paramValue.constructor + " instead")
}
return true;
}
export function expectedValue(paramName, expectedValues, paramValue){
if(!expectedValues){
return true;
}
if(expectedValues.constructor === Array){
if(expectedValues.indexOf(paramValue) === -1){
throw new InvalidRequestError(paramName + ': Expected one of ' + expectedValues + ' but received ' + paramValue + ' instead');
}
return true;
}
else{
if(expectedValues !== paramValue){
throw new InvalidRequestError(paramName + ': Expected ' + expectedValues + ' but received ' + paramValue + ' instead')
}
return true;
}
}
export function multiValidParam(paramName, paramValue, expectedTypes = null, mandatory = false, expectedValues = null, makeLowerCase = false, seperator = ','){
if(mandatory && !paramValue){
throw new InvalidRequestError(paramName + 'is a required parameter');
}
if(!paramValue){
return true;
}
if(makeLowerCase){
paramValue = paramValue.toLowerCase();
}
else{
paramValue = paramValue.toUpperCase();
}
let values = paramValue.split(seperator)
if(expectedValues) {
for (let i = 0; i < values.length; i++) {
expectedValue(paramName, expectedValues, values[i].trim());
}
}
return true;
}
export function validUrl(paramName, paramValue, mandatory = false){
if(mandatory && !paramValue){
throw new InvalidRequestError(paramName + 'is a required parameter');
}
if(!paramValue){
return true;
}
let response = paramValue.match(/(http(s)?:\/\/.)?(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/g);
if(response == null){
throw new InvalidRequestError("Invalid URL : Doesn't satisfy the URL format")
}
else {
return true;
}
}
export function isOneAmongStringUrl(paramName, paramValue, mandatory = false, expectedValues = null){
if(mandatory && !paramValue){
throw new InvalidRequestError(paramName + 'is a required parameter');
}
if(!paramValue){
return true;
}
if(!(expectedValues.indexOf(paramValue.toLowerCase()) === -1) || !(expectedValues.indexOf(paramValue.toUpperCase()) === -1)){
return true;
}
else if (validUrl(paramName, paramValue)){
return true;
}
else {
throw new InvalidRequestError(paramName + ' neither a valid URL nor in the expected values')
}
}
export function validDateFormat(paramName, paramValue, mandatory = false){
if(mandatory && !paramValue){
throw new InvalidRequestError(paramName + " is a required parameter")
}
if(!paramValue){
return true;
}
let response = paramValue.match(/^\d{4}\-\d{2}\-\d{2} \d{2}:\d{2}(:\d{2}(\.\d{1,6})?)?$/);
if(response == null){
throw new InvalidRequestError("Invalid Date : Doesn't satisfy the date format")
}
else {
return true;
}
}
export function validRange(paramName, paramValue, mandatory = false, lowerBound = null, upperBound = null){
if(mandatory && !paramValue){
throw new InvalidRequestError(paramName + " is a required parameter")
}
if(!paramValue && paramValue !== 0){
return true;
}
if(!expectedType(paramName, [Number], paramValue)){
throw new InvalidRequestError(paramName + ": Expected an Integer but received " + paramValue.constructor + " instead")
}
if(lowerBound && upperBound){
if(paramValue < lowerBound || paramValue > upperBound) {
throw new InvalidRequestError(paramName + " ranges between " + lowerBound + " and " + upperBound)
}
if(paramValue >= lowerBound && paramValue <= upperBound){
return true;
}
}
else if(lowerBound){
if(paramValue < lowerBound){
throw new InvalidRequestError(paramName + " should be greater than " + lowerBound)
}
if(paramValue >= lowerBound){
return true;
}
}
else if(upperBound){
if(paramValue > upperBound){
throw new InvalidRequestError(paramName + " should be lesser than " + upperBound)
}
if(paramValue <= upperBound){
return true;
}
}
else{
throw new InvalidRequestError("Any one or both of lower and upper bound should be provided")
}
}

View file

@ -2,7 +2,6 @@ var qs = require('querystring');
var xmlBuilder = require('xmlbuilder');
var util = require('util');
var plivoUtils = require('./../rest/utils');
import * as Exceptions from './exceptions';
var jsonStringifier = require('./jsonStrinfigier');
@ -15,7 +14,7 @@ export class PlivoXMLError extends Error { }
export function Response() {
this.element = 'Response';
this.nestables = ['Speak', 'Play', 'GetDigits', 'GetInput', 'Record', 'Dial', 'Message',
'Redirect', 'Wait', 'Hangup', 'PreAnswer', 'Conference', 'DTMF'];
'Redirect', 'Wait', 'Hangup', 'PreAnswer', 'Conference', 'DTMF', 'MultiPartyCall'];
this.valid_attributes = [];
this.elem = xmlBuilder.begin().ele(this.element);
}
@ -440,6 +439,234 @@ Response.prototype = {
return this.add(new DTMF(Response), body, attributes);
},
/**
* Add a MultiPartyCall element
* @method
* @param {string} body
* @param {object} attributes
* @param {string} [attributes.role]
* @param {number} [attributes.maxDuration]
* @param {number} [attributes.maxParticipants]
* @param {string} [attributes.waitMusicMethod]
* @param {string} [attributes.agentHoldMusicMethod]
* @param {string} [attributes.customerHoldMusicMethod]
* @param {boolean} [attributes.record]
* @param {string} [attributes.recordFileFormat]
* @param {string} [attributes.recordingCallbackMethod]
* @param {string} [attributes.statusCallbackEvents]
* @param {string} [attributes.statusCallbackMethod]
* @param {boolean} [attributes.stayAlone]
* @param {boolean} [attributes.coachMode]
* @param {boolean} [attributes.mute]
* @param {boolean} [attributes.hold]
* @param {boolean} [attributes.startMpcOnEnter]
* @param {boolean} [attributes.endMpcOnExit]
* @param {string} [attributes.enterSound]
* @param {string} [attributes.enterSoundMethod]
* @param {string} [attributes.exitSound]
* @param {string} [attributes.exitSoundMethod]
* @param {string} [attributes.onExitActionMethod]
* @param {boolean} [attributes.relayDTMFInputs]
* @param {string} [attributes.waitMusicUrl]
* @param {string} [attributes.agentHoldMusicUrl]
* @param {string} [attributes.customerHoldMusicUrl]
* @param {string} [attributes.recordingCallbackUrl]
* @param {string} [attributes.statusCallbackUrl]
* @param {string} [attributes.customerHoldMusicUrl]
*/
addMultiPartyCall: function (body, attributes){
const VALID_ROLE_VALUES = ['agent', 'supervisor', 'customer']
const VALID_METHOD_VALUES = ['GET', 'POST']
const VALID_BOOL_VALUES = [true, false]
const VALID_RECORD_FILE_FORMAT_VALUES = ['mp3', 'wav']
if(attributes.role && VALID_ROLE_VALUES.indexOf(attributes.role.toLowerCase())===-1){
throw new PlivoXMLError('Invalid attribute value ' + attributes.role + ' for role')
}
else if (!attributes.role){
throw new PlivoXMLError('role not mentioned : possible values - Agent / Supervisor / Customer')
}
if(attributes.maxDuration && (attributes.maxDuration<300 || attributes.maxDuration>28800)){
throw new PlivoXMLError('Invalid attribute value ' + attributes.maxDuration + ' for maxDuration')
}
else if(!attributes.maxDuration){
attributes.maxDuration = 14400
}
if(attributes.maxParticipants && (attributes.maxParticipants<2 || attributes.maxParticipants>10)){
throw new PlivoXMLError('Invalid attribute value ' + attributes.maxParticipants + ' for maxParticipants')
}
else if(!attributes.maxParticipants){
attributes.maxParticipants = 10
}
if(attributes.waitMusicMethod && VALID_METHOD_VALUES.indexOf(attributes.waitMusicMethod.toUpperCase())===-1){
throw new PlivoXMLError('Invalid attribute value ' + attributes.waitMusicMethod + ' for waitMusicMethod')
}
else if (!attributes.waitMusicMethod){
attributes.waitMusicMethod = 'GET'
}
if(attributes.agentHoldMusicMethod && VALID_METHOD_VALUES.indexOf(attributes.agentHoldMusicMethod.toUpperCase())===-1){
throw new PlivoXMLError('Invalid attribute value ' + attributes.agentHoldMusicMethod + ' for agentHoldMusicMethod')
}
else if (!attributes.agentHoldMusicMethod){
attributes.agentHoldMusicMethod = 'GET'
}
if(attributes.customerHoldMusicMethod && VALID_METHOD_VALUES.indexOf(attributes.customerHoldMusicMethod.toUpperCase())===-1){
throw new PlivoXMLError('Invalid attribute value ' + attributes.customerHoldMusicMethod + ' for customerHoldMusicMethod')
}
else if (!attributes.customerHoldMusicMethod){
attributes.customerHoldMusicMethod = 'GET'
}
if(attributes.record && VALID_BOOL_VALUES.indexOf(attributes.record)===-1){
throw new PlivoXMLError('Invalid attribute value ' + attributes.record + ' for record')
}
else if (!attributes.record){
attributes.record = false
}
if(attributes.recordFileFormat && VALID_RECORD_FILE_FORMAT_VALUES.indexOf(attributes.recordFileFormat.toLowerCase())===-1){
throw new PlivoXMLError('Invalid attribute value ' + attributes.recordFileFormat + ' for recordFileFormat')
}
else if (!attributes.recordFileFormat){
attributes.recordFileFormat = 'mp3'
}
if(attributes.recordingCallbackMethod && VALID_METHOD_VALUES.indexOf(attributes.recordingCallbackMethod.toUpperCase())===-1){
throw new PlivoXMLError('Invalid attribute value ' + attributes.recordingCallbackMethod + ' for recordingCallbackMethod')
}
else if (!attributes.recordingCallbackMethod){
attributes.recordingCallbackMethod = 'GET'
}
if(attributes.statusCallbackEvents && !plivoUtils.multiValidParam('statusCallbackEvents', attributes.statusCallbackEvents, String, false, ['mpc-state-changes', 'participant-state-changes', 'participant-speak-events', 'participant-digit-input-events', 'add-participant-api-events'], true, ',')){
throw new PlivoXMLError('Invalid attribute value ' + attributes.statusCallbackEvents + ' for statusCallbackEvents')
}
else if(!attributes.statusCallbackEvents){
attributes.statusCallbackEvents = 'mpc-state-changes,participant-state-changes'
}
if(attributes.statusCallbackMethod && VALID_METHOD_VALUES.indexOf(attributes.statusCallbackMethod.toUpperCase())===-1){
throw new PlivoXMLError('Invalid attribute value ' + attributes.statusCallbackMethod + ' for statusCallbackMethod')
}
else if (!attributes.statusCallbackMethod){
attributes.statusCallbackMethod = 'POST'
}
if(attributes.stayAlone && VALID_BOOL_VALUES.indexOf(attributes.stayAlone)===-1){
throw new PlivoXMLError('Invalid attribute value ' + attributes.stayAlone + ' for stayAlone')
}
else if (!attributes.stayAlone){
attributes.stayAlone = false
}
if(attributes.coachMode && VALID_BOOL_VALUES.indexOf(attributes.coachMode)===-1){
throw new PlivoXMLError('Invalid attribute value ' + attributes.coachMode + ' for coachMode')
}
else if (!attributes.coachMode){
attributes.coachMode = true
}
if(attributes.mute && VALID_BOOL_VALUES.indexOf(attributes.mute)===-1){
throw new PlivoXMLError('Invalid attribute value ' + attributes.mute + ' for mute')
}
else if (!attributes.mute){
attributes.mute = false
}
if(attributes.hold && VALID_BOOL_VALUES.indexOf(attributes.hold)===-1){
throw new PlivoXMLError('Invalid attribute value ' + attributes.hold + ' for hold')
}
else if (!attributes.hold){
attributes.hold = false
}
if(attributes.startMpcOnEnter && VALID_BOOL_VALUES.indexOf(attributes.startMpcOnEnter)===-1){
throw new PlivoXMLError('Invalid attribute value ' + attributes.startMpcOnEnter + ' for startMpcOnEnter')
}
else if (!attributes.startMpcOnEnter){
attributes.startMpcOnEnter = true
}
if(attributes.endMpcOnExit && VALID_BOOL_VALUES.indexOf(attributes.endMpcOnExit)===-1){
throw new PlivoXMLError('Invalid attribute value ' + attributes.endMpcOnExit + ' for endMpcOnExit')
}
else if (!attributes.endMpcOnExit){
attributes.endMpcOnExit = false
}
if(attributes.enterSound && !plivoUtils.isOneAmongStringUrl('enterSound', attributes.enterSound, false, ['beep:1', 'beep:2', 'none'])){
throw new PlivoXMLError('Invalid attribute value ' + attributes.enterSound + ' for enterSound')
}
else if(!attributes.enterSound){
attributes.enterSound = 'beep:1'
}
if(attributes.enterSoundMethod && VALID_METHOD_VALUES.indexOf(attributes.enterSoundMethod.toUpperCase())===-1){
throw new PlivoXMLError('Invalid attribute value ' + attributes.enterSoundMethod + ' for enterSoundMethod')
}
else if (!attributes.enterSoundMethod){
attributes.enterSoundMethod = 'GET'
}
if(attributes.exitSound && !plivoUtils.isOneAmongStringUrl('exitSound', attributes.exitSound, false, ['beep:1', 'beep:2', 'none'])){
throw new PlivoXMLError('Invalid attribute value ' + attributes.exitSound + ' for exitSound')
}
else if(!attributes.exitSound){
attributes.exitSound = 'beep:2'
}
if(attributes.exitSoundMethod && VALID_METHOD_VALUES.indexOf(attributes.exitSoundMethod.toUpperCase())===-1){
throw new PlivoXMLError('Invalid attribute value ' + attributes.exitSoundMethod + ' for exitSoundMethod')
}
else if (!attributes.exitSoundMethod){
attributes.exitSoundMethod = 'GET'
}
if(attributes.onExitActionMethod && VALID_METHOD_VALUES.indexOf(attributes.onExitActionMethod.toUpperCase())===-1){
throw new PlivoXMLError('Invalid attribute value ' + attributes.onExitActionMethod + ' for onExitActionMethod')
}
else if (!attributes.onExitActionMethod){
attributes.onExitActionMethod = 'POST'
}
if(attributes.relayDTMFInputs && VALID_BOOL_VALUES.indexOf(attributes.relayDTMFInputs)===-1){
throw new PlivoXMLError('Invalid attribute value ' + attributes.relayDTMFInputs + ' for relayDTMFInputs')
}
else if (!attributes.relayDTMFInputs){
attributes.relayDTMFInputs = false
}
if(attributes.waitMusicUrl && !plivoUtils.validUrl('waitMusicUrl', attributes.waitMusicUrl, false)){
throw new PlivoXMLError('Invalid attribute value ' + attributes.waitMusicUrl + ' for waitMusicUrl')
}
if(attributes.agentHoldMusicUrl && !plivoUtils.validUrl('agentHoldMusicUrl', attributes.agentHoldMusicUrl, false)){
throw new PlivoXMLError('Invalid attribute value ' + attributes.agentHoldMusicUrl + ' for agentHoldMusicUrl')
}
if(attributes.customerHoldMusicUrl && !plivoUtils.validUrl('customerHoldMusicUrl', attributes.customerHoldMusicUrl, false)){
throw new PlivoXMLError('Invalid attribute value ' + attributes.customerHoldMusicUrl + ' for customerHoldMusicUrl')
}
if(attributes.recordingCallbackUrl && !plivoUtils.validUrl('recordingCallbackUrl', attributes.recordingCallbackUrl, false)){
throw new PlivoXMLError('Invalid attribute value ' + attributes.recordingCallbackUrl + ' for recordingCallbackUrl')
}
if(attributes.statusCallbackUrl && !plivoUtils.validUrl('statusCallbackUrl', attributes.statusCallbackUrl, false)){
throw new PlivoXMLError('Invalid attribute value ' + attributes.statusCallbackUrl + ' for statusCallbackUrl')
}
if(attributes.customerHoldMusicUrl && !plivoUtils.validUrl('customerHoldMusicUrl', attributes.customerHoldMusicUrl, false)){
throw new PlivoXMLError('Invalid attribute value ' + attributes.customerHoldMusicUrl + ' for customerHoldMusicUrl')
}
return this.add(new MultiPartyCall(Response), body, attributes);
},
toXML: function () {
return this.elem.toString();
},
@ -521,7 +748,7 @@ function GetInput(Response) {
this.element = 'GetInput';
this.valid_attributes = ['action', 'method', 'inputType', 'executionTimeout',
'digitEndTimeout', 'speechEndTimeout', 'finishOnKey', 'numDigits',
'speechModel', 'hints','language', 'interimSpeechResultsCallback',
'speechModel', 'hints','language', 'interimSpeechResultsCallback',
'interimSpeechResultsCallbackMethod', 'log', 'redirect', 'profanityFilter'];
this.nestables = ['Speak', 'Play', 'Wait'];
}
@ -741,4 +968,22 @@ function DTMF(Response) {
this.valid_attributes = ['digits', 'async'];
}
util.inherits(DTMF, Response);
util.inherits(DTMF, Response);
/**
* MultiPartyCall element
* @constructor
*/
function MultiPartyCall(Response){
this.element = 'MultiPartyCall';
this.nestables = [];
this.valid_attributes = ['role', 'maxDuration', 'maxParticipants', 'waitMusicUrl',
'waitMusicMethod', 'agentHoldMusicUrl', 'agentHoldMusicMethod',
'customerHoldMusicUrl', 'customerHoldMusicMethod', 'record',
'recordFileFormat', 'recordingCallbackUrl', 'recordingCallbackMethod',
'statusCallbackEvents', 'statusCallbackUrl', 'statusCallbackMethod',
'stayAlone', 'coachMode', 'mute', 'hold', 'startMpcOnEnter', 'endMpcOnExit',
'enterSound', 'enterSoundMethod', 'exitSound', 'exitSoundMethod',
'onExitActionUrl', 'onExitActionMethod', 'relayDTMFInputs'];
}
util.inherits(MultiPartyCall, Response);

View file

@ -1,6 +1,6 @@
{
"name": "plivo",
"version": "4.15.0",
"version": "4.16.0",
"description": "A Node.js SDK to make voice calls and send SMS using Plivo and to generate Plivo XML",
"homepage": "https://github.com/plivo/plivo-node",
"files": [

View file

@ -68,6 +68,7 @@ describe('calls', function () {
client.calls.get(1)
.then(function(call){
return call.transfer()
done()
})
.then(function(call) {
assert.equal(call.id, 5)

95
test/multiPartyCalls.js Normal file
View file

@ -0,0 +1,95 @@
import assert from 'assert';
import sinon from 'sinon';
import {Client} from '../lib/rest/client-test';
import {PlivoGenericResponse} from '../lib/base.js';
import {MultiPartyCall} from "../lib/resources/multiPartyCall";
let client = new Client('sampleid', 'sammpletoken', 'sampleproxy');
describe('multiPartyCalls', function (){
it('should list all MultiPartyCalls', function (){
return client.multiPartyCalls.list().then(function (response){
for(let i=0; i< response.length;i++) {
assert(response[i] instanceof MultiPartyCall)
}
})
});
it('should get details of a MultiPartyCall', function (){
return client.multiPartyCalls.get('ca8e8a44-48e1-445d-afd5-1fcccdbccd9d').then(function (response){
assert(response instanceof PlivoGenericResponse)
assert.equal(response.id, 'ca8e8a44-48e1-445d-afd5-1fcccdbccd9d')
assert.equal(response.resourceUri, '/v1/Account/MAMDJMMTEZOWY0ZMQWM2/MultiPartyCall/uuid_ca8e8a44-48e1-445d-afd5-1fcccdbccd9d/')
})
});
it('should add a Participant', function (){
return client.multiPartyCalls.addParticipant('Agent', {'friendlyName' : 'Voice', 'from' : '+919090909090', 'to' : '+918309866821'}).then(function (response){
assert(response instanceof PlivoGenericResponse)
assert.equal(response.message, 'add participant action initiated')
})
});
it('should start an MPC', function (){
return client.multiPartyCalls.start(null, 'Voice').then(function (response){
assert(response instanceof PlivoGenericResponse)
})
});
it('should end an MPC', function (){
return client.multiPartyCalls.stop(null, 'Voice').then(function (response){
assert(response, true)
})
});
it('should start MPC Recording', function (){
return client.multiPartyCalls.startRecording(null, 'TestMPC').then(function (response){
assert(response.message, "MPC: TestMPC record started")
})
});
it('should stop MPC Recording', function (){
return client.multiPartyCalls.stopRecording(null, 'TestMPC').then(function (response){
assert(response instanceof PlivoGenericResponse)
})
});
it('should pause MPC Recording', function (){
return client.multiPartyCalls.pauseRecording(null, 'TestMPC').then(function (response){
assert(response instanceof PlivoGenericResponse)
})
});
it('should resume MPC Recording', function (){
return client.multiPartyCalls.resumeRecording(null, 'TestMPC').then(function (response){
assert(response instanceof PlivoGenericResponse)
})
});
it('should list MPC Participants', function (){
return client.multiPartyCalls.listParticipants('12345678-90123456', null).then(function (response){
assert(response instanceof PlivoGenericResponse)
})
});
it('should update MPC Participant', function (){
return client.multiPartyCalls.updateParticipant(10, '12345678-90123456', null).then(function (response){
assert(response instanceof PlivoGenericResponse)
assert.equal(response.hold, 'MPC: TestMPC hold/unhold member(s) succeded')
assert.equal(response.mute, 'MPC: TestMPC mute/unmute member(s) succeded')
})
});
it('should kick MPC Participant', function (){
return client.multiPartyCalls.kickParticipant(10, '12345678-90123456', null).then(function (response){
assert(response instanceof PlivoGenericResponse)
})
});
it('should get MPC Participant', function (){
return client.multiPartyCalls.getParticipant(2132, '7503f05f-2d6e-4ab3-b9e6-3b0d81ae9087', null).then(function (response){
assert(response instanceof PlivoGenericResponse)
assert.equal(response.resourceUri, '/v1/Account/MAMDJMMTEZOWY0ZMQWM2/MultiPartyCall/uuid_7503f05f-2d6e-4ab3-b9e6-3b0d81ae9087/Participant/2132/')
})
});
})

View file

@ -29,4 +29,15 @@ describe('PlivoXML', function () {
done("Failed to test Plivo Xml due to unknown error");
});
});
it('tests MultiPartyCall', function (done){
const mpcResponse = new Response();
mpcResponse.addMultiPartyCall('Nairobi',{
role: 'Agent',
maxDuration: 1000,
statusCallbackEvents: 'participant-speak-events, participant-digit-input-events, add-participant-api-events, participant-state-changes, mpc-state-changes'
});
assert.equal('<Response><MultiPartyCall role="Agent" maxDuration="1000" statusCallbackEvents="participant-speak-events, participant-digit-input-events, add-participant-api-events, participant-state-changes, mpc-state-changes" maxParticipants="10" waitMusicMethod="GET" agentHoldMusicMethod="GET" customerHoldMusicMethod="GET" record="false" recordFileFormat="mp3" recordingCallbackMethod="GET" statusCallbackMethod="POST" stayAlone="false" coachMode="true" mute="false" hold="false" startMpcOnEnter="true" endMpcOnExit="false" enterSound="beep:1" enterSoundMethod="GET" exitSound="beep:2" exitSoundMethod="GET" onExitActionMethod="POST" relayDTMFInputs="false">Nairobi</MultiPartyCall></Response>',mpcResponse.toXML());
done();
})
});