Skip to content

Commit e7d2fce

Browse files
committed
Add recordings and transcriptions
1 parent 8a1e15b commit e7d2fce

File tree

3 files changed

+222
-0
lines changed

3 files changed

+222
-0
lines changed

voice/leg.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@ package voice
33
import (
44
"encoding/json"
55
"fmt"
6+
"reflect"
67
"time"
8+
9+
messagebird "github.com/messagebird/go-rest-api"
710
)
811

912
// LegStatus enumerates all valid values for a leg status.
@@ -144,3 +147,8 @@ func (leg *Leg) UnmarshalJSON(data []byte) error {
144147
}
145148
return nil
146149
}
150+
151+
// Recordings retrieves the Recording objects associated with a leg.
152+
func (leg *Leg) Recordings(client *messagebird.Client) *Paginator {
153+
return newPaginator(client, fmt.Sprintf("calls/%s/legs/%s/recordings", leg.CallID, leg.ID), reflect.TypeOf(Recording{}))
154+
}

voice/recording.go

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
package voice
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"io"
7+
"net/http"
8+
"reflect"
9+
"runtime"
10+
"time"
11+
12+
messagebird "github.com/messagebird/go-rest-api"
13+
)
14+
15+
// RecordingStatus enumerates all valid values for the status of a recording.
16+
type RecordingStatus string
17+
18+
const (
19+
// RecordingStatusInitialised indicates that the recording has been created
20+
// but has not begun just yet.
21+
RecordingStatusInitialised RecordingStatus = "initialised"
22+
// RecordingStatusRecording indicates that recording is currently in progress.
23+
RecordingStatusRecording RecordingStatus = "recording"
24+
// RecordingStatusDone indicates that a recording is completed and may be downloaded.
25+
RecordingStatusDone RecordingStatus = "done"
26+
// RecordingStatusFailed indicates that something went wrong while
27+
// recording a leg.
28+
RecordingStatusFailed RecordingStatus = "failed"
29+
)
30+
31+
// A Recording describes a voice recording of a leg.
32+
//
33+
// You can initiate a recording of a leg by having a step in your callflow with
34+
// the record action set.
35+
type Recording struct {
36+
// The unique ID of the recording.
37+
ID string
38+
// The format of the recording. Supported formats are: wav.
39+
Format string
40+
// The ID of the leg that the recording belongs to.
41+
LegID string
42+
// The status of the recording. Available statuses are: initialised, recording, done and failed
43+
Status RecordingStatus
44+
// The duration of the recording.
45+
//
46+
// Truncated to seconds.
47+
Duration time.Duration
48+
// The date-time the call was created.
49+
CreatedAt time.Time
50+
// The date-time the call was last updated.
51+
UpdatedAt time.Time
52+
53+
// A hash with HATEOAS links related to the object. This includes the file
54+
// link that has the URI for downloading the wave file of the recording.
55+
links map[string]string
56+
}
57+
58+
type jsonRecording struct {
59+
ID string `json:"id"`
60+
Format string `json:"format"`
61+
LegID string `json:"legID"`
62+
Status string `json:"status"`
63+
Duration int `json:"duration"`
64+
CreatedAt string `json:"createdAt"`
65+
UpdatedAt string `json:"updatedAt"`
66+
Links map[string]string `json:"_links"`
67+
}
68+
69+
// UnmarshalJSON implements the json.Unmarshaler interface.
70+
func (rec *Recording) UnmarshalJSON(data []byte) error {
71+
var raw jsonRecording
72+
if err := json.Unmarshal(data, &raw); err != nil {
73+
return err
74+
}
75+
createdAt, err := time.Parse(time.RFC3339, raw.CreatedAt)
76+
if err != nil {
77+
return fmt.Errorf("unable to parse Recording CreatedAt: %v", err)
78+
}
79+
updatedAt, err := time.Parse(time.RFC3339, raw.UpdatedAt)
80+
if err != nil {
81+
return fmt.Errorf("unable to parse Recording UpdatedAt: %v", err)
82+
}
83+
*rec = Recording{
84+
ID: raw.ID,
85+
Format: raw.Format,
86+
LegID: raw.LegID,
87+
Status: RecordingStatus(raw.Status),
88+
Duration: time.Second * time.Duration(raw.Duration),
89+
CreatedAt: createdAt,
90+
UpdatedAt: updatedAt,
91+
links: raw.Links,
92+
}
93+
return nil
94+
}
95+
96+
// Transcriptions returns a paginator for retrieving all Transcription objects.
97+
func (rec *Recording) Transcriptions(client *messagebird.Client) *Paginator {
98+
path := rec.links["self"] + "/transcriptions"
99+
return newPaginator(client, path, reflect.TypeOf(Transcription{}))
100+
}
101+
102+
// DownloadFile streams the recorded WAV file.
103+
func (rec *Recording) DownloadFile(client *messagebird.Client) (io.ReadCloser, error) {
104+
req, err := http.NewRequest("GET", messagebird.Endpoint+rec.links["file"], nil)
105+
if err != nil {
106+
return nil, err
107+
}
108+
req.Header.Set("Accept", "audio/*")
109+
req.Header.Set("Authorization", "AccessKey "+client.AccessKey)
110+
req.Header.Set("User-Agent", "MessageBird/ApiClient/"+messagebird.ClientVersion+" Go/"+runtime.Version())
111+
112+
resp, err := client.HTTPClient.Do(req)
113+
if err != nil {
114+
return nil, err
115+
}
116+
if resp.StatusCode != http.StatusOK {
117+
return nil, fmt.Errorf("bad HTTP status: %d", resp.StatusCode)
118+
}
119+
return resp.Body, nil
120+
}

voice/transcription.go

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
package voice
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"io/ioutil"
7+
"net/http"
8+
"runtime"
9+
"time"
10+
11+
messagebird "github.com/messagebird/go-rest-api"
12+
)
13+
14+
// A Transcription is a textual representation of a recording as text.
15+
//
16+
// You can request an automated transcription for a recording by doing a POST
17+
// request to the API.
18+
type Transcription struct {
19+
// The unique ID of the transcription.
20+
ID string
21+
// The ID of the recording that the transcription belongs to.
22+
RecordingID string
23+
// In case that an error was occurred while executing the transcription
24+
// request, it appears here.
25+
Error string
26+
// The date-time the transcription was created/requested.
27+
CreatedAt time.Time
28+
// The date-time the transcription was last updated.
29+
UpdatedAt time.Time
30+
31+
// A hash with HATEOAS links related to the object. This includes the file
32+
// link that has the URI for downloading the text transcription of a
33+
// recording.
34+
links map[string]string
35+
}
36+
37+
type jsonTranscription struct {
38+
ID string `json:"id"`
39+
RecordingID string `json:"recordingID"`
40+
Error string `json:"error"`
41+
CreatedAt string `json:"createdAt"`
42+
UpdatedAt string `json:"updatedAt"`
43+
Links map[string]string `json:"_links"`
44+
}
45+
46+
// UnmarshalJSON implements the json.Unmarshaler interface.
47+
func (trans *Transcription) UnmarshalJSON(data []byte) error {
48+
var raw jsonTranscription
49+
if err := json.Unmarshal(data, &raw); err != nil {
50+
return err
51+
}
52+
createdAt, err := time.Parse(time.RFC3339, raw.CreatedAt)
53+
if err != nil {
54+
return fmt.Errorf("unable to parse Recording CreatedAt: %v", err)
55+
}
56+
updatedAt, err := time.Parse(time.RFC3339, raw.UpdatedAt)
57+
if err != nil {
58+
return fmt.Errorf("unable to parse Recording UpdatedAt: %v", err)
59+
}
60+
*trans = Transcription{
61+
ID: raw.ID,
62+
RecordingID: raw.RecordingID,
63+
Error: raw.Error,
64+
CreatedAt: createdAt,
65+
UpdatedAt: updatedAt,
66+
links: raw.Links,
67+
}
68+
return nil
69+
}
70+
71+
// Contents gets the transcription file.
72+
//
73+
// This is a plain text file.
74+
func (trans *Transcription) Contents(client *messagebird.Client) (string, error) {
75+
req, err := http.NewRequest("GET", messagebird.Endpoint+trans.links["file"], nil)
76+
if err != nil {
77+
return "", err
78+
}
79+
req.Header.Set("Accept", "text/plain")
80+
req.Header.Set("Authorization", "AccessKey "+client.AccessKey)
81+
req.Header.Set("User-Agent", "MessageBird/ApiClient/"+messagebird.ClientVersion+" Go/"+runtime.Version())
82+
83+
resp, err := client.HTTPClient.Do(req)
84+
if err != nil {
85+
return "", err
86+
}
87+
if resp.StatusCode != http.StatusOK {
88+
return "", fmt.Errorf("bad HTTP status: %d", resp.StatusCode)
89+
}
90+
91+
defer resp.Body.Close()
92+
b, err := ioutil.ReadAll(resp.Body)
93+
return string(b), err
94+
}

0 commit comments

Comments
 (0)