Skip to content

Commit

Permalink
VT-3665 MPC Enhancements for Go SDK (#124)
Browse files Browse the repository at this point in the history
* VT-3665 MPC Enhancements for Go SDK

* VT-3665 Renamed json response filed

* VT-3665 Modified the uuid in UT

* VT-3665 Added UTs for XML changes

* VT-3665 Renamed all the MPC Json files which starts with 'mPC'.

* VT-3665 Added UTs for XML changes

* VT-3665 Renamed all the json files starting with MPC to mPC.

* VT-3665 code review changes

* Added SDK Versioning

* Removed code changes of Recording start and Recording Stop announcements on MPC

* Reverting back the reverted changes

* Update CHANGELOG.md

Co-authored-by: Mohammed Huzaif <[email protected]>
  • Loading branch information
Abinaya-Shunmugavel and huzaif-plivo authored Nov 23, 2021
1 parent 617b886 commit a747cdf
Show file tree
Hide file tree
Showing 8 changed files with 208 additions and 76 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Change Log

## [7.3.0](https://github.com/plivo/plivo-go/tree/v7.3.0) (2021-11-23)
**Features - Voice: Multiparty calls**
- The [Add Multiparty Call API](https://www.plivo.com/docs/voice/api/multiparty-call/participants#add-a-participant) allows for greater functionality by accepting options like `start recording audio`, `stop recording audio`, and their HTTP methods.
- [Multiparty Calls](https://www.plivo.com/docs/voice/api/multiparty-call/) now has new APIs to `stop` and `play` audio.


## [7.2.2](https://github.com/plivo/plivo-go/tree/v7.2.2) (2021-07-29)
- Removed validation for `ringtimeout` and `delaydial` params in [Start a multi party call](https://www.plivo.com/docs/voice/api/multiparty-call#start-a-new-multiparty-call).

Expand Down
2 changes: 1 addition & 1 deletion baseclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
"github.com/google/go-querystring/query"
)

const sdkVersion = "7.2.2"
const sdkVersion = "7.3.0"

const lookupBaseUrl = "lookup.plivo.com"

Expand Down
6 changes: 6 additions & 0 deletions fixtures/mPCStartParticipantRecordResponse.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"api_id": "e05b5263-45dc-11eb-9014-0242ac110003",
"message": "MPC: test_mpc_1 record started",
"recording_id": "e06ac332-45dc-11eb-94fe-06dd7f581a50",
"recording_url": "https://media.plivo.com/v1/Account/MAOTE1OWE0MDK0MTLHYW/Recording/e06ac332-45dc-11eb-94fe-06dd7f581a50.mp3"
}
8 changes: 8 additions & 0 deletions fixtures/mPCStartPlayAudioResponse.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"api_id": "da5ac1fc-3bb3-11ec-b7b2-0242ac11000a",
"message": "play queued into MPC",
"mpcMemberId": [
"1825"
],
"mpcName": "MyMPC"
}
118 changes: 76 additions & 42 deletions multipartycall.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,48 +21,52 @@ type MPCUpdateResponse struct {
}

type MultiPartyCallAddParticipantParams struct {
Role string `json:"role,omitempty" url:"role,omitempty"`
From string `json:"from,omitempty" url:"from,omitempty"`
To string `json:"to,omitempty" url:"to,omitempty"`
CallUuid string `json:"call_uuid,omitempty" url:"call_uuid,omitempty"`
CallerName string `json:"caller_name,omitempty" url:"caller_name,omitempty"`
CallStatusCallbackUrl string `json:"call_status_callback_url,omitempty" url:"call_status_callback_url,omitempty"`
CallStatusCallbackMethod string `json:"call_status_callback_method,omitempty" url:"call_status_callback_method,omitempty"`
SipHeaders string `json:"sip_headers,omitempty" url:"sip_headers,omitempty"`
ConfirmKey string `json:"confirm_key,omitempty" url:"confirm_key,omitempty"`
ConfirmKeySoundUrl string `json:"confirm_key_sound_url,omitempty" url:"confirm_key_sound_url,omitempty"`
ConfirmKeySoundMethod string `json:"confirm_key_sound_method,omitempty" url:"confirm_key_sound_method,omitempty"`
DialMusic string `json:"dial_music,omitempty" url:"dial_music,omitempty"`
RingTimeout interface{} `json:"ring_timeout,omitempty" url:"ring_timeout,omitempty"`
DelayDial interface{} `json:"delay_dial,omitempty" uril:"caller_name,omitempty"`
MaxDuration int64 `json:"max_duration,omitempty" url:"max_duration,omitempty"`
MaxParticipants int64 `json:"max_participants,omitempty" url:"max_participants,omitempty"`
WaitMusicUrl string `json:"wait_music_url,omitempty" url:"wait_music_url,omitempty"`
WaitMusicMethod string `json:"wait_music_method,omitempty" url:"wait_music_method,omitempty"`
AgentHoldMusicUrl string `json:"agent_hold_music_url,omitempty" url:"agent_hold_music_url,omitempty"`
AgentHoldMusicMethod string `json:"agent_hold_music_method,omitempty" url:"agent_hold_music_method,omitempty"`
CustomerHoldMusicUrl string `json:"customer_hold_music_url,omitempty" url:"customer_hold_music_url,omitempty"`
CustomerHoldMusicMethod string `json:"customer_hold_music_method,omitempty" url:"customer_hold_music_method,omitempty"`
RecordingCallbackUrl string `json:"recording_callback_url,omitempty" url:"recording_callback_url,omitempty"`
RecordingCallbackMethod string `json:"recording_callback_method,omitempty" url:"recording_callback_method,omitempty"`
StatusCallbackUrl string `json:"status_callback_url,omitempty" url:"status_callback_url,omitempty"`
StatusCallbackMethod string `json:"status_callback_method,omitempty" url:"status_callback_method,omitempty"`
OnExitActionUrl string `json:"on_exit_action_url,omitempty" url:"on_exit_action_url,omitempty"`
OnExitActionMethod string `json:"on_exit_action_method,omitempty" url:"on_exit_action_method,omitempty"`
Record bool `json:"record,omitempty" url:"record,omitempty"`
RecordFileFormat string `json:"record_file_format,omitempty" url:"record_file_format,omitempty"`
StatusCallbackEvents string `json:"status_callback_events,omitempty" url:"status_callback_events,omitempty"`
StayAlone bool `json:"stay_alone,omitempty" url:"stay_alone,omitempty"`
CoachMode bool `json:"coach_mode,omitempty" url:"coach_mode,omitempty"`
Mute bool `json:"mute,omitempty" url:"mute,omitempty"`
Hold bool `json:"hold,omitempty" url:"hold,omitempty"`
StartMpcOnEnter *bool `json:"start_mpc_on_enter,omitempty" url:"start_mpc_on_enter,omitempty"`
EndMpcOnExit bool `json:"end_mpc_on_exit,omitempty" url:"end_mpc_on_exit,omitempty"`
RelayDtmfInputs bool `json:"relay_dtmf_inputs,omitempty" url:"relay_dtmf_inputs,omitempty"`
EnterSound string `json:"enter_sound,omitempty" url:"enter_sound,omitempty"`
EnterSoundMethod string `json:"enter_sound_method,omitempty" url:"enter_sound_method,omitempty"`
ExitSound string `json:"exit_sound,omitempty" url:"exit_sound,omitempty"`
ExitSoundMethod string `json:"exit_sound_method,omitempty" url:"exit_sound_method,omitempty"`
Role string `json:"role,omitempty" url:"role,omitempty"`
From string `json:"from,omitempty" url:"from,omitempty"`
To string `json:"to,omitempty" url:"to,omitempty"`
CallUuid string `json:"call_uuid,omitempty" url:"call_uuid,omitempty"`
CallerName string `json:"caller_name,omitempty" url:"caller_name,omitempty"`
CallStatusCallbackUrl string `json:"call_status_callback_url,omitempty" url:"call_status_callback_url,omitempty"`
CallStatusCallbackMethod string `json:"call_status_callback_method,omitempty" url:"call_status_callback_method,omitempty"`
SipHeaders string `json:"sip_headers,omitempty" url:"sip_headers,omitempty"`
ConfirmKey string `json:"confirm_key,omitempty" url:"confirm_key,omitempty"`
ConfirmKeySoundUrl string `json:"confirm_key_sound_url,omitempty" url:"confirm_key_sound_url,omitempty"`
ConfirmKeySoundMethod string `json:"confirm_key_sound_method,omitempty" url:"confirm_key_sound_method,omitempty"`
DialMusic string `json:"dial_music,omitempty" url:"dial_music,omitempty"`
RingTimeout interface{} `json:"ring_timeout,omitempty" url:"ring_timeout,omitempty"`
DelayDial interface{} `json:"delay_dial,omitempty" uril:"caller_name,omitempty"`
MaxDuration int64 `json:"max_duration,omitempty" url:"max_duration,omitempty"`
MaxParticipants int64 `json:"max_participants,omitempty" url:"max_participants,omitempty"`
WaitMusicUrl string `json:"wait_music_url,omitempty" url:"wait_music_url,omitempty"`
WaitMusicMethod string `json:"wait_music_method,omitempty" url:"wait_music_method,omitempty"`
AgentHoldMusicUrl string `json:"agent_hold_music_url,omitempty" url:"agent_hold_music_url,omitempty"`
AgentHoldMusicMethod string `json:"agent_hold_music_method,omitempty" url:"agent_hold_music_method,omitempty"`
CustomerHoldMusicUrl string `json:"customer_hold_music_url,omitempty" url:"customer_hold_music_url,omitempty"`
CustomerHoldMusicMethod string `json:"customer_hold_music_method,omitempty" url:"customer_hold_music_method,omitempty"`
RecordingCallbackUrl string `json:"recording_callback_url,omitempty" url:"recording_callback_url,omitempty"`
RecordingCallbackMethod string `json:"recording_callback_method,omitempty" url:"recording_callback_method,omitempty"`
StatusCallbackUrl string `json:"status_callback_url,omitempty" url:"status_callback_url,omitempty"`
StatusCallbackMethod string `json:"status_callback_method,omitempty" url:"status_callback_method,omitempty"`
OnExitActionUrl string `json:"on_exit_action_url,omitempty" url:"on_exit_action_url,omitempty"`
OnExitActionMethod string `json:"on_exit_action_method,omitempty" url:"on_exit_action_method,omitempty"`
Record bool `json:"record,omitempty" url:"record,omitempty"`
RecordFileFormat string `json:"record_file_format,omitempty" url:"record_file_format,omitempty"`
StatusCallbackEvents string `json:"status_callback_events,omitempty" url:"status_callback_events,omitempty"`
StayAlone bool `json:"stay_alone,omitempty" url:"stay_alone,omitempty"`
CoachMode bool `json:"coach_mode,omitempty" url:"coach_mode,omitempty"`
Mute bool `json:"mute,omitempty" url:"mute,omitempty"`
Hold bool `json:"hold,omitempty" url:"hold,omitempty"`
StartMpcOnEnter *bool `json:"start_mpc_on_enter,omitempty" url:"start_mpc_on_enter,omitempty"`
EndMpcOnExit bool `json:"end_mpc_on_exit,omitempty" url:"end_mpc_on_exit,omitempty"`
RelayDtmfInputs bool `json:"relay_dtmf_inputs,omitempty" url:"relay_dtmf_inputs,omitempty"`
EnterSound string `json:"enter_sound,omitempty" url:"enter_sound,omitempty"`
EnterSoundMethod string `json:"enter_sound_method,omitempty" url:"enter_sound_method,omitempty"`
ExitSound string `json:"exit_sound,omitempty" url:"exit_sound,omitempty"`
ExitSoundMethod string `json:"exit_sound_method,omitempty" url:"exit_sound_method,omitempty"`
StartRecordingAudio string `json:"start_recording_audio,omitempty" url:"start_recording_audio,omitempty"`
StartRecordingAudioMethod string `json:"start_recording_audio_method,omitempty" url:"start_recording_audio_method,omitempty"`
StopRecordingAudio string `json:"stop_recording_audio,omitempty" url:"stop_recording_audio,omitempty"`
StopRecordingAudioMethod string `json:"stop_recording_audio_method,omitempty" url:"stop_recording_audio_method,omitempty"`
}

type MultiPartyCallListParams struct {
Expand Down Expand Up @@ -184,6 +188,17 @@ type MultiPartyCallUpdateParticipantResponse struct {
MPCUpdateResponse
}

type MultiPartyCallAudioParams struct {
Url string `json:"url" url:"url"`
}

type MultiPartyCallAudioResponse struct {
APIID string `json:"api_id" url:"api_id"`
Message string `json:"message" url:"message"`
MemberId []string `json:"mpcMemberId,omitempty" url:"mpcMemberId,omitempty"`
FriendlyName string `json:"mpcName,omitempty" url:"mpcName,omitempty"`
}

func (service *MultiPartyCallService) List(params MultiPartyCallListParams) (response *MultiPartyCallListResponse, err error) {
req, err := service.client.NewRequest("GET", params, "MultiPartyCall")
if err != nil {
Expand Down Expand Up @@ -385,7 +400,26 @@ func (service *MultiPartyCallService) GetParticipant(basicParams MultiPartyCallP
err = service.client.ExecuteRequest(req, response, isVoiceRequest())
return
}
func (service *MultiPartyCallService) StartPlayAudio(basicParams MultiPartyCallParticipantParams, url MultiPartyCallAudioParams) (response *MultiPartyCallAudioResponse, err error) {
mpcId := MakeMPCId(basicParams.MpcUuid, basicParams.FriendlyName)
req, err := service.client.NewRequest("POST", url, "MultiPartyCall/%s/Member/%s/Play", mpcId, basicParams.ParticipantId)
if err != nil {
return
}
response = &MultiPartyCallAudioResponse{}
err = service.client.ExecuteRequest(req, response, isVoiceRequest())
return
}

func (service *MultiPartyCallService) StopPlayAudio(basicParams MultiPartyCallParticipantParams) (err error) {
mpcId := MakeMPCId(basicParams.MpcUuid, basicParams.FriendlyName)
req, err := service.client.NewRequest("DELETE", nil, "MultiPartyCall/%s/Member/%s/Play", mpcId, basicParams.ParticipantId)
if err != nil {
return
}
err = service.client.ExecuteRequest(req, nil, isVoiceRequest())
return
}
func MakeMPCId(MpcUuid string, FriendlyName string) string {
mpcId := ""
if MpcUuid != "" {
Expand Down
58 changes: 58 additions & 0 deletions multipartycall_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,3 +135,61 @@ func TestMPCService_GetParticipant(t *testing.T) {

assertRequest(t, "GET", "MultiPartyCall/%s/Participant/%s", "uuid_ebacced2-21ab-466d-9df4-67339991761b", "209")
}

func TestMPCService_StartParticipantRecord(t *testing.T) {
expectResponse("MPCStartParticipantRecordResponse.json", 200)

if _, err := client.MultiPartyCall.StartParticipantRecording(MultiPartyCallParticipantParams{MpcUuid: "ebacced2-21ab-466d-9df4-67339991761b", ParticipantId: "209"}, MultiPartyCallStartRecordingParams{FileFormat: "wav", StatusCallbackUrl: "https://www.google.com", StatusCallbackMethod: "GET"}); err != nil {
panic(err)
}

assertRequest(t, "POST", "MultiPartyCall/%s/Participant/%s/Record", "uuid_ebacced2-21ab-466d-9df4-67339991761b", "209")
}

func TestMPCService_StopParticipantRecord(t *testing.T) {
expectResponse("", 204)
if err := client.MultiPartyCall.StopParticipantRecording(MultiPartyCallParticipantParams{MpcUuid: "ebacced2-21ab-466d-9df4-67339991761b", ParticipantId: "209"}); err != nil {
panic(err)
}

assertRequest(t, "DELETE", "MultiPartyCall/%s/Participant/%s/Record", "uuid_ebacced2-21ab-466d-9df4-67339991761b", "209")
}

func TestMPCService_ResumeParticipantRecord(t *testing.T) {
expectResponse("", 204)
if err := client.MultiPartyCall.ResumeParticipantRecording(MultiPartyCallParticipantParams{MpcUuid: "ebacced2-21ab-466d-9df4-67339991761b", ParticipantId: "209"}); err != nil {
panic(err)
}

assertRequest(t, "POST", "MultiPartyCall/%s/Participant/%s/Record/Resume", "uuid_ebacced2-21ab-466d-9df4-67339991761b", "209")
}

func TestMPCService_PauseParticipantRecord(t *testing.T) {
expectResponse("", 204)

if err := client.MultiPartyCall.PauseParticipantRecording(MultiPartyCallParticipantParams{MpcUuid: "ebacced2-21ab-466d-9df4-67339991761b", ParticipantId: "209"}); err != nil {
panic(err)
}

assertRequest(t, "POST", "MultiPartyCall/%s/Participant/%s/Record/Pause", "uuid_ebacced2-21ab-466d-9df4-67339991761b", "209")
}
func TestMPCService_StartPlayAudio(t *testing.T) {
expectResponse("MPCStartPlayAudioResponse.json", 202)

if response, err := client.MultiPartyCall.StartPlayAudio(MultiPartyCallParticipantParams{MpcUuid: "ebacced2-21ab-466d-9df4-67339991761b", ParticipantId: "209"}, MultiPartyCallAudioParams{Url: "https://s3.amazonaws.com/plivocloud/music.mp3"}); err != nil {
panic(err)
} else {
log.Println(response)
}

assertRequest(t, "POST", "MultiPartyCall/%s/Member/%s/Play", "uuid_ebacced2-21ab-466d-9df4-67339991761b", "209")
}

func TestMPCService_StopPlayAudio(t *testing.T) {
expectResponse("", 204)

if err := client.MultiPartyCall.StopPlayAudio(MultiPartyCallParticipantParams{MpcUuid: "ebacced2-21ab-466d-9df4-67339991761b", ParticipantId: "209"}); err != nil {
panic(err)
}
assertRequest(t, "DELETE", "MultiPartyCall/%s/Member/%s/Play", "uuid_ebacced2-21ab-466d-9df4-67339991761b", "209")
}
Loading

0 comments on commit a747cdf

Please sign in to comment.