Skip to content

Commit a95f6ae

Browse files
committed
Added some elevenlabs methods
1 parent 8f8887d commit a95f6ae

File tree

11 files changed

+315
-12
lines changed

11 files changed

+315
-12
lines changed

go.mod

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ go 1.20
44

55
require (
66
github.com/djthorpe/go-errors v1.0.3
7-
github.com/mutablelogic/go-server v1.1.16
87
github.com/stretchr/testify v1.8.4
98
)
109

go.sum

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
22
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
33
github.com/djthorpe/go-errors v1.0.3 h1:GZeMPkC1mx2vteXLI/gvxZS0Ee9zxzwD1mcYyKU5jD0=
44
github.com/djthorpe/go-errors v1.0.3/go.mod h1:HtfrZnMd6HsX75Mtbv9Qcnn0BqOrrFArvCaj3RMnZhY=
5-
github.com/mutablelogic/go-server v1.1.16 h1:in897acxmw/WIdxoafDQFcJ5mpRaLriCK5bXUy3JYt0=
6-
github.com/mutablelogic/go-server v1.1.16/go.mod h1:R9jcFJzVKtduwmWazGaBX5EBRqlQ0BCpmAxUrlWRZLs=
75
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
86
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
97
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=

pkg/client/client.go

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,13 @@ type Client struct {
3333
sync.Mutex
3434
*http.Client
3535

36-
endpoint *url.URL
37-
ua string
38-
rate float32 // number of requests allowed per second
39-
strict bool
40-
token Token // token for authentication on requests
41-
ts time.Time
42-
skipverify bool
36+
endpoint *url.URL
37+
ua string
38+
rate float32 // number of requests allowed per second
39+
strict bool
40+
token Token // token for authentication on requests
41+
headers map[string]string // Headers for every request
42+
ts time.Time
4343
}
4444

4545
type ClientOpt func(*Client) error
@@ -50,7 +50,7 @@ type RequestOpt func(*http.Request) error
5050

5151
const (
5252
DefaultTimeout = time.Second * 10
53-
DefaultUserAgent = "github.com/mutablelogic/go-server"
53+
DefaultUserAgent = "github.com/mutablelogic/go-client"
5454
PathSeparator = string(os.PathSeparator)
5555
ContentTypeJson = "application/json"
5656
ContentTypeTextXml = "text/xml"
@@ -195,6 +195,17 @@ func (client *Client) request(method, accept, mimetype string, body io.Reader) (
195195
r.Header.Set("User-Agent", client.ua)
196196
}
197197

198+
// If there are headers, add them
199+
if len(client.headers) > 0 {
200+
for k, v := range client.headers {
201+
if v == "" {
202+
r.Header.Del(k)
203+
} else {
204+
r.Header.Set(k, v)
205+
}
206+
}
207+
}
208+
198209
// Return success
199210
return r, nil
200211
}

pkg/client/client_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package client_test
33
import (
44
"testing"
55

6-
"github.com/mutablelogic/go-server/pkg/client"
6+
"github.com/mutablelogic/go-client/pkg/client"
77
"github.com/stretchr/testify/assert"
88
)
99

pkg/client/clientopts.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,3 +99,17 @@ func OptSkipVerify() ClientOpt {
9999
return nil
100100
}
101101
}
102+
103+
// OptHeader appends a custom header to each request
104+
func OptHeader(key, value string) ClientOpt {
105+
return func(client *Client) error {
106+
if client.headers == nil {
107+
client.headers = make(map[string]string, 1)
108+
}
109+
if key == "" {
110+
return ErrBadParameter.With("OptHeader")
111+
}
112+
client.headers[key] = value
113+
return nil
114+
}
115+
}

pkg/client/token.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,10 @@ const (
2020

2121
// Stringify the token value
2222
func (token Token) String() string {
23+
// Set default
24+
if token.Scheme == "" {
25+
token.Scheme = Bearer
26+
}
27+
// Return token as a string
2328
return token.Scheme + " " + token.Value
2429
}

pkg/client/token_test.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package client_test
2+
3+
import (
4+
"testing"
5+
6+
// Packages
7+
"github.com/mutablelogic/go-client/pkg/client"
8+
"github.com/stretchr/testify/assert"
9+
)
10+
11+
func Test_token_001(t *testing.T) {
12+
assert := assert.New(t)
13+
token := client.Token{Value: "test"}
14+
assert.Equal("Bearer test", token.String())
15+
}
16+
17+
func Test_token_002(t *testing.T) {
18+
assert := assert.New(t)
19+
token := client.Token{Scheme: "Other", Value: "test"}
20+
assert.Equal("Other test", token.String())
21+
}

pkg/elevenlabs/client.go

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
/*
2+
elevenlabs implements an API client for elevenlabs (https://elevenlabs.io/docs/api-reference/text-to-speech)
3+
*/
4+
package elevenlabs
5+
6+
import (
7+
"net/http"
8+
9+
// Packages
10+
"github.com/mutablelogic/go-client/pkg/client"
11+
)
12+
13+
///////////////////////////////////////////////////////////////////////////////
14+
// TYPES
15+
16+
type Client struct {
17+
*client.Client
18+
}
19+
20+
///////////////////////////////////////////////////////////////////////////////
21+
// GLOBALS
22+
23+
const (
24+
endPoint = "https://api.elevenlabs.io/v1"
25+
Sample64 = "mp3_44100_64" // mp3 with 44.1kHz sample rate at 64kbps
26+
Sample96 = "mp3_44100_96" // mp3 with 44.1kHz sample rate at 96kbps
27+
Sample128 = "mp3_44100_128" // default output format, mp3 with 44.1kHz sample rate at 128kbps
28+
Sample192 = "mp3_44100_192" // mp3 with 44.1kHz sample rate at 192kbps
29+
SamplePCM16 = "pcm_16000" // PCM format (S16LE) with 16kHz sample rate
30+
SamplePCM22 = "pcm_22050" // PCM format (S16LE) with 22.05kHz sample rate
31+
SamplePCM24 = "pcm_24000" // PCM format (S16LE) with 24kHz sample rate
32+
SamplePCM44 = "pcm_44100" // PCM format (S16LE) with 44.1kHz sample rate
33+
SampleU8 = "ulaw_8000" // μ-law format (sometimes written mu-law, often approximated as u-law) with 8kHz sample rate
34+
)
35+
36+
///////////////////////////////////////////////////////////////////////////////
37+
// SCHEMA
38+
39+
type Request struct {
40+
client.Payload `json:"-"`
41+
Model string `json:"model_id"`
42+
Text string `json:"text"`
43+
VoiceSettings struct {
44+
SimilarityBoost float64 `json:"similarity_boost"`
45+
Stability float64 `json:"stability"`
46+
Style string `json:"style,omitempty"`
47+
UseSpeakerBoost bool `json:"use_speaker_boost"`
48+
} `json:"voice_settings"`
49+
}
50+
51+
func (r Request) Method() string {
52+
return http.MethodGet
53+
}
54+
55+
func (r Request) Type() string {
56+
return ""
57+
}
58+
59+
func (r Request) Accept() string {
60+
return client.ContentTypeJson
61+
}
62+
63+
type VoicesResponse struct {
64+
Voices []Voice `json:"voices"`
65+
}
66+
67+
type Voice struct {
68+
Id string `json:"voice_id"`
69+
Name string `json:"name"`
70+
Description string `json:"description,omitempty"`
71+
PreviewUrl string `json:"preview_url,omitempty"`
72+
Category string `json:"category,omitempty"`
73+
}
74+
75+
///////////////////////////////////////////////////////////////////////////////
76+
// LIFECYCLE
77+
78+
func New(ApiKey string, opts ...client.ClientOpt) (*Client, error) {
79+
// Create client
80+
client, err := client.New(append(opts, client.OptEndpoint(endPoint), client.OptHeader("Xi-Api-Key", ApiKey))...)
81+
if err != nil {
82+
return nil, err
83+
}
84+
85+
// Return the client
86+
return &Client{client}, nil
87+
}
88+
89+
///////////////////////////////////////////////////////////////////////////////
90+
// PUBLIC METHODS
91+
92+
// Return current set of voices
93+
func (c *Client) Voices() ([]Voice, error) {
94+
var request Request
95+
var response VoicesResponse
96+
if err := c.Do(request, &response, client.OptPath("voices")); err != nil {
97+
return nil, err
98+
}
99+
return response.Voices, nil
100+
}
101+
102+
// Get returns the current IP address from the API
103+
func (c *Client) TextToSpeech(Text string) ([]byte, error) {
104+
var request Request
105+
if err := c.Do(request, nil, client.OptPath("text-to-speech", "test")); err != nil {
106+
return nil, err
107+
}
108+
return nil, nil
109+
}

pkg/elevenlabs/client_test.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package elevenlabs_test
2+
3+
import (
4+
"encoding/json"
5+
"os"
6+
"testing"
7+
8+
// Packages
9+
opts "github.com/mutablelogic/go-client/pkg/client"
10+
elevenlabs "github.com/mutablelogic/go-client/pkg/elevenlabs"
11+
assert "github.com/stretchr/testify/assert"
12+
)
13+
14+
func Test_elevenlabs_001(t *testing.T) {
15+
assert := assert.New(t)
16+
client, err := elevenlabs.New(GetApiKey(t), opts.OptTrace(os.Stderr, true))
17+
assert.NoError(err)
18+
assert.NotNil(client)
19+
response, err := client.Voices()
20+
assert.NoError(err)
21+
assert.NotEmpty(response)
22+
data, err := json.MarshalIndent(response, "", " ")
23+
assert.NoError(err)
24+
t.Log(string(data))
25+
}
26+
27+
func XX_Test_elevenlabs_002(t *testing.T) {
28+
assert := assert.New(t)
29+
client, err := elevenlabs.New(GetApiKey(t), opts.OptTrace(os.Stderr, true))
30+
assert.NoError(err)
31+
assert.NotNil(client)
32+
response, err := client.TextToSpeech("test")
33+
assert.NoError(err)
34+
assert.NotEmpty(response)
35+
t.Log(response)
36+
}
37+
38+
///////////////////////////////////////////////////////////////////////////////
39+
// ENVIRONMENT
40+
41+
func GetApiKey(t *testing.T) string {
42+
key := os.Getenv("ELEVENLABS_API_KEY")
43+
if key == "" {
44+
t.Skip("ELEVENLABS_API_KEY not set")
45+
t.SkipNow()
46+
}
47+
return ""
48+
}

pkg/ipify/client.go

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/*
2+
ipify implements a generic API client which parses a JSON response. Mostly used
3+
to test the client package.
4+
*/
5+
package ipify
6+
7+
import (
8+
"net/http"
9+
"net/url"
10+
11+
// Packages
12+
"github.com/mutablelogic/go-client/pkg/client"
13+
)
14+
15+
///////////////////////////////////////////////////////////////////////////////
16+
// TYPES
17+
18+
type Client struct {
19+
*client.Client
20+
}
21+
22+
///////////////////////////////////////////////////////////////////////////////
23+
// GLOBALS
24+
25+
const (
26+
endPoint = "https://api.ipify.org/"
27+
)
28+
29+
///////////////////////////////////////////////////////////////////////////////
30+
// SCHEMA
31+
32+
type Request struct {
33+
client.Payload `json:"-"`
34+
}
35+
36+
type Response struct {
37+
IP string `json:"ip"`
38+
}
39+
40+
func (r Request) Method() string {
41+
return http.MethodGet
42+
}
43+
44+
func (r Request) Type() string {
45+
return ""
46+
}
47+
48+
func (r Request) Accept() string {
49+
return client.ContentTypeJson
50+
}
51+
52+
///////////////////////////////////////////////////////////////////////////////
53+
// LIFECYCLE
54+
55+
func New(opts ...client.ClientOpt) (*Client, error) {
56+
// Create client
57+
client, err := client.New(append(opts, client.OptEndpoint(endPoint))...)
58+
if err != nil {
59+
return nil, err
60+
}
61+
62+
// Return the client
63+
return &Client{client}, nil
64+
}
65+
66+
///////////////////////////////////////////////////////////////////////////////
67+
// PUBLIC METHODS
68+
69+
// Get returns the current IP address from the API
70+
func (c *Client) Get() (string, error) {
71+
var response Response
72+
if err := c.Do(nil, &response, client.OptQuery(url.Values{"format": []string{"json"}})); err != nil {
73+
return "", err
74+
}
75+
return response.IP, nil
76+
}

0 commit comments

Comments
 (0)