Skip to content

Commit

Permalink
Merge pull request #30 from plivo/beta
Browse files Browse the repository at this point in the history
PHLO support
  • Loading branch information
nixonsam authored Mar 13, 2019
2 parents bf9d343 + 868f68d commit 8dcdb2a
Show file tree
Hide file tree
Showing 23 changed files with 781 additions and 111 deletions.
Binary file added .DS_Store
Binary file not shown.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# Change Log

## [4.1.0](https://github.com/plivo/plivo-go/tree/v4.1.0) (2019-03-12)
- Add PHLO support
- Add Multi-party call triggers

## [4.0.6-beta1](https://github.com/plivo/plivo-go/tree/v4.0.6-beta1) (2019-02-05)
- Add PHLO support in beta
- Add Multi-party call triggers

## [4.0.5](https://github.com/plivo/plivo-go/tree/v4.0.5) (2018-11-19)
- Add hangup party details to CDR. CDR filtering allowed by hangup_source and hangup_cause_code.
- Add sub-account cascade delete support.
Expand Down
13 changes: 13 additions & 0 deletions base_resources.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package plivo

// BaseResource and BaseResourceInterface only supports PhloClient type as of now.
// Todo: Change client type to *BaseClient and try to pass *PhloClient to client?

type BaseResource struct {
client *PhloClient
}

type BaseResourceInterface struct {
client *PhloClient
resourceType BaseResource // Todo: Need this?
}
114 changes: 114 additions & 0 deletions baseclient.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package plivo

import (
"bytes"
"encoding/json"
"errors"
"fmt"
"github.com/google/go-querystring/query"
"io/ioutil"
"net/http"
"net/url"
"reflect"
)

const sdkVersion = "4.1.0"

type ClientOptions struct {
HttpClient *http.Client
}

type BaseClient struct {
httpClient *http.Client

AuthId string
AuthToken string

BaseUrl *url.URL
userAgent string

RequestInterceptor func(request *http.Request)
ResponseInterceptor func(response *http.Response)
}

func (client *BaseClient) NewRequest(method string, params interface{}, baseRequestString string, formatString string,
formatParams ...interface{}) (request *http.Request, err error) {

if client == nil || client.httpClient == nil {
err = errors.New("client and httpClient cannot be nil")
return
}

for i, param := range formatParams {
if param == nil || param == "" {
err = errors.New(fmt.Sprintf("Request path parameter #%d is nil/empty but should not be so.", i))
return
}
}

requestUrl := *client.BaseUrl

requestUrl.Path = fmt.Sprintf(baseRequestString, fmt.Sprintf(formatString, formatParams...))
var buffer = new(bytes.Buffer)
if method == "GET" {
var values url.Values
if values, err = query.Values(params); err != nil {
return
}

requestUrl.RawQuery = values.Encode()
} else {
if(reflect.ValueOf(params).Kind().String() != "map"){
if err = json.NewEncoder(buffer).Encode(params); err != nil {
return
}
}else if (reflect.ValueOf(params).Kind().String() == "map" && !reflect.ValueOf(params).IsNil()) {
if err = json.NewEncoder(buffer).Encode(params); err != nil {
return
}
}

}

request, err = http.NewRequest(method, requestUrl.String(), buffer)

request.Header.Add("User-Agent", client.userAgent)
request.Header.Add("Content-Type", "application/json")

request.SetBasicAuth(client.AuthId, client.AuthToken)

return
}

func (client *BaseClient) ExecuteRequest(request *http.Request, body interface{}) (err error) {
if client == nil {
return errors.New("client cannot be nil")
}

if client.httpClient == nil {
return errors.New("httpClient cannot be nil")
}


response, err := client.httpClient.Do(request)
if err != nil {
return
}

data, err := ioutil.ReadAll(response.Body)
if err == nil && data != nil && len(data) > 0 {
if response.StatusCode >= 200 && response.StatusCode < 300 {
if body != nil {
err = json.Unmarshal(data, body)
}
} else {
if (string(data) == "{}" && response.StatusCode == 404){
err = errors.New(string("Resource not found exception \n" + response.Status))
}else{
err = errors.New(string(data))
}
}
}

return
}
Empty file.
4 changes: 4 additions & 0 deletions fixtures/multiPartyCallCallResponse.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"ApiID":"7ebd8daa-d216-495a-ab94-7c71a776be28",
"Error":""
}
4 changes: 4 additions & 0 deletions fixtures/multiPartyCallColdTransferResponse.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"ApiID":"7ebd8daa-d216-495a-ab94-7c71a776be28",
"Error":""
}
4 changes: 4 additions & 0 deletions fixtures/multiPartyCallMemberActionResponse.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"ApiID":"43edda77-87eb-4fc2-9c73-cf346b6328a8",
"Error":""
}
7 changes: 7 additions & 0 deletions fixtures/multiPartyCallResponse.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"node_id":"b18848dd-e308-4758-bc5c-fb9c274d5fb7",
"phlo_id":"2e802f94-cc03-4e35-b4c8-5a0328544135",
"name":"Multi-Party Call_1",
"node_type":"multi_party_call",
"created_on":"2018-11-20 04:46:20.349505+00:00"
}
4 changes: 4 additions & 0 deletions fixtures/multiPartyCallWarmTransferResponse.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"ApiID":"7ebd8daa-d216-495a-ab94-7c71a776be28",
"Error":""
}
8 changes: 8 additions & 0 deletions fixtures/nodeGetResponse.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"api_id":"8ad6e47f-de2c-4b40-8e35-3b416d1b10e6",
"node_id":"b18848dd-e308-4758-bc5c-fb9c274d5fb7",
"phlo_id":"2e802f94-cc03-4e35-b4c8-5a0328544135",
"name":"Multi-Party Call_1",
"node_type":"multi_party_call",
"created_on":"2018-11-20 04:46:20.349505+00:00"
}
7 changes: 7 additions & 0 deletions fixtures/phloGetResoponse.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"api_id":"52d7d3d4-9a47-44c9-8c08-436aac427220",
"phlo_id":"2e802f94-cc03-4e35-b4c8-5a0328544135",
"name":"multiparty+ucase1_test+flow",
"created_on":"2018-11-20 04:46:20.307414+00:00",
"BaseResource":"test"
}
6 changes: 6 additions & 0 deletions fixtures/phloRunResponse.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"api_id":"52d7d3d4-9a47-44c9-8c08-436aac427220",
"phlo_run_id":"2e802f94-cc03-4e35-b4c8-5a0328544135",
"phlo_id":"2e802f94-cc03-4e35-b4c8-5a0328544135",
"message":"stopped. next node uuid not found for b'Start' - b'Start' with output state: http - phlo_run_id 52d7d3d4-9a47-44c9-8c08-436aac427220"
}
40 changes: 40 additions & 0 deletions multiparty_call.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package plivo

type MultiPartyCall struct {
Node
BaseResource
}

type MultiPartyCallActionPayload struct {
Action string `json:"action" url:"action"`
To string `json:"to" url:"to"`
Role string `json:"role" url:"role"`
TriggerSource string `json:"trigger_source" url:"trigger_source"`
}


func (self *MultiPartyCall) update(params MultiPartyCallActionPayload) (response *NodeActionResponse, err error) {
req, err := self.client.NewRequest("POST", params, "phlo/%s/%s/%s", self.PhloID, self.NodeType,
self.NodeID)
if (err != nil) {
return
}
response = &NodeActionResponse{}
err = self.client.ExecuteRequest(req, response)

return
}

func (self *MultiPartyCall) Call(params MultiPartyCallActionPayload) (*NodeActionResponse, error) {
return self.update(params)
}

func (self *MultiPartyCall) WarmTransfer(params MultiPartyCallActionPayload) (response *NodeActionResponse,
err error) {
return self.update(params)
}

func (self *MultiPartyCall) ColdTransfer(params MultiPartyCallActionPayload) (response *NodeActionResponse,
err error) {
return self.update(params)
}
58 changes: 58 additions & 0 deletions multiparty_call_member.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package plivo

const HOLD = "hold"
const UNHOLD = "unhold"
const HANGUP = "hangup"
const RESUME_CALL = "resume_call"
const ABORT_TRANSFER = "abort_transfer"
const VOICEMAIL_DROP = "voicemail_drop"


type MultiPartyCallMemberActionPayload struct {
Action string `json:"action" url:"action"`
}

type MultiPartyCallMember struct {
NodeID string `json:"node_id" url:"node_id"`
PhloID string `json:"phlo_id" url:"phlo_id"`
NodeType string `json:"node_type" url:"node_type"`
MemberAddress string `json:"member_address" url:"member_address"`
BaseResource
}

func (self *MultiPartyCall) Member(memberID string) (response *MultiPartyCallMember) {
response = &MultiPartyCallMember{self.NodeID, self.PhloID, self.NodeType, memberID, BaseResource{self.client}}
return
}

func (self *MultiPartyCallMember) AbortTransfer() (*NodeActionResponse,error) {
return self.update(MultiPartyCallMemberActionPayload{ABORT_TRANSFER})
}

func (service *MultiPartyCallMember) ResumeCall() (*NodeActionResponse, error) {
return service.update(MultiPartyCallMemberActionPayload{RESUME_CALL})
}
func (service *MultiPartyCallMember) VoiceMailDrop() (*NodeActionResponse, error) {
return service.update(MultiPartyCallMemberActionPayload{VOICEMAIL_DROP})
}
func (service *MultiPartyCallMember) HangUp() (*NodeActionResponse, error) {
return service.update(MultiPartyCallMemberActionPayload{HANGUP})
}
func (service *MultiPartyCallMember) Hold() (*NodeActionResponse, error) {
return service.update(MultiPartyCallMemberActionPayload{HOLD})
}
func (service *MultiPartyCallMember) UnHold() (*NodeActionResponse, error) {
return service.update(MultiPartyCallMemberActionPayload{UNHOLD})
}

func (service *MultiPartyCallMember) update(params MultiPartyCallMemberActionPayload) (response *NodeActionResponse, err error) {
req, err := service.client.NewRequest("POST", params, "phlo/%s/%s/%s/members/%s", service.PhloID, service.NodeType,
service.NodeID, service.MemberAddress)
if err != nil {
return
}
response = &NodeActionResponse{}
err = service.client.ExecuteRequest(req, response)

return
}
Loading

0 comments on commit 8dcdb2a

Please sign in to comment.