-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathassemblyai.go
195 lines (155 loc) · 4.05 KB
/
assemblyai.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
package assemblyai
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"mime"
"net/http"
"net/url"
"os"
)
const (
version = "1.10.0"
defaultBaseURLScheme = "https"
defaultBaseURLHost = "api.assemblyai.com"
)
// Client manages the communication with the AssemblyAI API.
type Client struct {
baseURL *url.URL
userAgent string
apiKey string
httpClient *http.Client
Transcripts *TranscriptService
LeMUR *LeMURService
RealTime *RealTimeService
}
// NewClientWithOptions returns a new configurable AssemblyAI client. If you provide client
// options, they override the default values. Most users will want to use
// [NewClientWithAPIKey].
func NewClientWithOptions(opts ...ClientOption) *Client {
defaultAPIKey := os.Getenv("ASSEMBLYAI_API_KEY")
c := &Client{
baseURL: &url.URL{
Scheme: defaultBaseURLScheme,
Host: defaultBaseURLHost,
},
userAgent: fmt.Sprintf("AssemblyAI/1.0 (sdk=Go/%s)", version),
httpClient: &http.Client{},
apiKey: defaultAPIKey,
}
for _, f := range opts {
f(c)
}
c.Transcripts = &TranscriptService{client: c}
c.LeMUR = &LeMURService{client: c}
c.RealTime = &RealTimeService{client: c}
return c
}
// NewClient returns a new authenticated AssemblyAI client.
func NewClient(apiKey string) *Client {
return NewClientWithOptions(WithAPIKey(apiKey))
}
// ClientOption lets you configure the AssemblyAI client.
type ClientOption func(*Client)
// WithHTTPClient sets the http.Client used for making requests to the API.
func WithHTTPClient(httpClient *http.Client) ClientOption {
return func(c *Client) {
c.httpClient = httpClient
}
}
// WithBaseURL sets the API endpoint used by the client. Mainly used for testing.
func WithBaseURL(rawurl string) ClientOption {
return func(c *Client) {
if u, err := url.Parse(rawurl); err == nil {
c.baseURL = u
}
}
}
// WithUserAgent sets the user agent used by the client.
func WithUserAgent(userAgent string) ClientOption {
return func(c *Client) {
c.userAgent = userAgent
}
}
// WithAPIKey sets the API key used for authentication.
func WithAPIKey(key string) ClientOption {
return func(c *Client) {
c.apiKey = key
}
}
func (c *Client) newJSONRequest(ctx context.Context, method, path string, body interface{}) (*http.Request, error) {
var buf io.ReadWriter
if body != nil {
buf = new(bytes.Buffer)
if err := json.NewEncoder(buf).Encode(body); err != nil {
return nil, err
}
}
req, err := c.newRequest(ctx, method, path, buf)
if err != nil {
return nil, err
}
if body != nil {
req.Header.Set("Content-Type", "application/json")
}
return req, nil
}
func (c *Client) newRequest(ctx context.Context, method, path string, body io.Reader) (*http.Request, error) {
rel, err := url.Parse(path)
if err != nil {
return nil, err
}
rawurl := c.baseURL.ResolveReference(rel).String()
req, err := http.NewRequestWithContext(ctx, method, rawurl, body)
if err != nil {
return nil, err
}
req.Header.Set("User-Agent", c.userAgent)
req.Header.Set("Authorization", c.apiKey)
return req, err
}
func (c *Client) do(req *http.Request, v interface{}) error {
resp, err := c.httpClient.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
contentType := resp.Header.Get("Content-Type")
mimeType, _, err := mime.ParseMediaType(contentType)
if err != nil {
return err
}
isJSONResponse := mimeType == "application/json"
isAPIError := resp.StatusCode < 200 || resp.StatusCode >= 400
if isAPIError {
var buf bytes.Buffer
_, err := io.Copy(&buf, resp.Body)
if err != nil {
return err
}
var apierr APIError
if isJSONResponse {
if err := json.Unmarshal(buf.Bytes(), &apierr); err != nil {
return err
}
}
// Reset response body so that clients can read it again.
resp.Body = io.NopCloser(bytes.NewBuffer(buf.Bytes()))
apierr.Status = resp.StatusCode
apierr.Response = resp
return apierr
}
if v != nil {
switch val := v.(type) {
case *[]byte:
*val, err = io.ReadAll(resp.Body)
default:
if isJSONResponse {
err = json.NewDecoder(resp.Body).Decode(v)
}
}
}
return err
}