Skip to content

Commit 69cb51f

Browse files
committed
Add the voice call model
1 parent b76ded2 commit 69cb51f

File tree

1 file changed

+145
-0
lines changed

1 file changed

+145
-0
lines changed

voice/call.go

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
package voice
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"reflect"
7+
"time"
8+
9+
messagebird "github.com/messagebird/go-rest-api"
10+
)
11+
12+
// CallStatus enumerates all valid values for a call status.
13+
type CallStatus string
14+
15+
const (
16+
// CallStatusStarting is the status of a call that is currently being set up.
17+
CallStatusStarting CallStatus = "starting"
18+
// CallStatusOngoing indicates that a call is active.
19+
CallStatusOngoing CallStatus = "ongoing"
20+
// CallStatusEnded indicates that a call has been terminated.
21+
CallStatusEnded CallStatus = "ended"
22+
)
23+
24+
// A Call describes a voice call which is made to a number.
25+
//
26+
// A call has legs which are incoming or outgoing voice connections. An
27+
// incoming leg is created when somebody calls a number. Outgoing legs are
28+
// created when a call is transferred.
29+
type Call struct {
30+
ID string
31+
Status CallStatus
32+
Source string
33+
Destination string
34+
NumberID string
35+
CreatedAt time.Time
36+
UpdatedAt time.Time
37+
EndedAt *time.Time
38+
}
39+
40+
type jsonCall struct {
41+
ID string `json:"id"`
42+
Status string `json:"status"`
43+
Source string `json:"source"`
44+
Destination string `json:"destination"`
45+
NumberID string `json:"numberId"`
46+
CreatedAt string `json:"createdAt"`
47+
UpdatedAt string `json:"updatedAt"`
48+
EndedAt string `json:"endedAt,omitempty"`
49+
}
50+
51+
// MarshalJSON implements the json.Marshaler interface.
52+
func (call Call) MarshalJSON() ([]byte, error) {
53+
endedAt := ""
54+
if call.EndedAt != nil {
55+
endedAt = call.EndedAt.Format(time.RFC3339)
56+
}
57+
data := jsonCall{
58+
ID: call.ID,
59+
Status: string(call.Status),
60+
Source: call.Source,
61+
Destination: call.Destination,
62+
NumberID: call.NumberID,
63+
CreatedAt: call.CreatedAt.Format(time.RFC3339),
64+
UpdatedAt: call.UpdatedAt.Format(time.RFC3339),
65+
EndedAt: endedAt,
66+
}
67+
return json.Marshal(data)
68+
}
69+
70+
// UnmarshalJSON implements the json.Unmarshaler interface.
71+
func (call *Call) UnmarshalJSON(data []byte) error {
72+
var raw jsonCall
73+
if err := json.Unmarshal(data, &raw); err != nil {
74+
return err
75+
}
76+
createdAt, err := time.Parse(time.RFC3339, raw.CreatedAt)
77+
if err != nil {
78+
return fmt.Errorf("unable to parse CallFlow CreatedAt: %v", err)
79+
}
80+
updatedAt, err := time.Parse(time.RFC3339, raw.UpdatedAt)
81+
if err != nil {
82+
return fmt.Errorf("unable to parse CallFlow UpdatedAt: %v", err)
83+
}
84+
var endedAt *time.Time
85+
if raw.EndedAt != "" {
86+
eat, err := time.Parse(time.RFC3339, raw.EndedAt)
87+
if err != nil {
88+
return fmt.Errorf("unable to parse CallFlow EndedAt: %v", err)
89+
}
90+
endedAt = &eat
91+
}
92+
*call = Call{
93+
ID: raw.ID,
94+
Status: CallStatus(raw.Status),
95+
Source: raw.Source,
96+
Destination: raw.Destination,
97+
NumberID: raw.NumberID,
98+
CreatedAt: createdAt,
99+
UpdatedAt: updatedAt,
100+
EndedAt: endedAt,
101+
}
102+
return nil
103+
}
104+
105+
// CallByID fetches a call by it's ID.
106+
//
107+
// An error is returned if no such call flow exists or is accessible.
108+
func CallByID(client *messagebird.Client, id string) (*Call, error) {
109+
call := &Call{}
110+
err := client.Request(call, "GET", "calls/"+id, nil)
111+
return call, err
112+
}
113+
114+
// Calls returns a Paginator which iterates over all Calls.
115+
func Calls(client *messagebird.Client) *Paginator {
116+
return newPaginator(client, "calls/", reflect.TypeOf(Call{}))
117+
}
118+
119+
// InitiateCall initiates an outbound call.
120+
//
121+
// When placing a call, you pass the source (the caller ID), the destination
122+
// (the number/address that will be called), and the callFlow (the call flow to
123+
// execute when the call is answered).
124+
func InitiateCall(client *messagebird.Client, source, destination string, callflow CallFlow) (*Call, error) {
125+
body := struct {
126+
Source string `json:"source"`
127+
Destination string `json:"destination"`
128+
Callflow CallFlow `json:"callflow"`
129+
// TODO: Optional webhook
130+
}{
131+
Source: source,
132+
Destination: destination,
133+
Callflow: callflow,
134+
}
135+
call := &Call{}
136+
err := client.Request(call, "POST", "calls/", body)
137+
return call, err
138+
}
139+
140+
// Delete deletes the Call.
141+
//
142+
// If the call is in progress, it hangs up all legs.
143+
func (call *Call) Delete(client *messagebird.Client) error {
144+
return client.Request(nil, "DELETE", "calls/"+call.ID, nil)
145+
}

0 commit comments

Comments
 (0)