Skip to content

Commit 5838d37

Browse files
authored
Merge pull request #8 from mutablelogic/v1
Major updates
2 parents 3c52b9b + 8370ee1 commit 5838d37

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

65 files changed

+1595
-2381
lines changed

Makefile

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
GO := $(shell which go)
33

44
# Build flags
5-
BUILD_MODULE := $(shell go list -m)
5+
BUILD_MODULE := $(shell cat go.mod | head -1 | cut -d ' ' -f 2)
66
BUILD_LD_FLAGS += -X $(BUILD_MODULE)/pkg/version.GitSource=${BUILD_MODULE}
7-
BUILD_LD_FLAGS += -X $(BUILD_MODULE)/pkg/version.GitTag=$(shell git describe --tags)
7+
BUILD_LD_FLAGS += -X $(BUILD_MODULE)/pkg/version.GitTag=$(shell git describe --tags --always)
88
BUILD_LD_FLAGS += -X $(BUILD_MODULE)/pkg/version.GitBranch=$(shell git name-rev HEAD --name-only --always)
99
BUILD_LD_FLAGS += -X $(BUILD_MODULE)/pkg/version.GitHash=$(shell git rev-parse HEAD)
1010
BUILD_LD_FLAGS += -X $(BUILD_MODULE)/pkg/version.GoBuildTime=$(shell date -u '+%Y-%m-%dT%H:%M:%SZ')

cmd/cli/elevenlabs.go

+32-50
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,20 @@ import (
66
"regexp"
77
"strings"
88

9-
// Packages
9+
// Package imports
1010
"github.com/mutablelogic/go-client/pkg/client"
1111
"github.com/mutablelogic/go-client/pkg/elevenlabs"
12-
13-
// Namespace imports
14-
. "github.com/djthorpe/go-errors"
1512
)
1613

14+
/////////////////////////////////////////////////////////////////////
15+
// TYPES
16+
17+
type result struct {
18+
Path string `json:"path"`
19+
Bytes int64 `json:"bytes_written"`
20+
Mime string `json:"mime_type,omitempty"`
21+
}
22+
1723
/////////////////////////////////////////////////////////////////////
1824
// GLOBALS
1925

@@ -26,18 +32,10 @@ var (
2632

2733
func ElevenlabsFlags(flags *Flags) {
2834
flags.String("elevenlabs-api-key", "${ELEVENLABS_API_KEY}", "ElevenLabs API key")
29-
flags.String("elevenlabs-voice", "", "Voice")
3035
}
3136

3237
func ElevenlabsRegister(cmd []Client, opts []client.ClientOpt, flags *Flags) ([]Client, error) {
33-
// Get API key
34-
key, err := flags.GetString("elevenlabs-api-key")
35-
if err != nil {
36-
return nil, err
37-
}
38-
39-
// Create client
40-
elevenlabs, err := elevenlabs.New(key, opts...)
38+
elevenlabs, err := elevenlabs.New(flags.GetString("elevenlabs-api-key"), opts...)
4139
if err != nil {
4240
return nil, err
4341
}
@@ -46,10 +44,9 @@ func ElevenlabsRegister(cmd []Client, opts []client.ClientOpt, flags *Flags) ([]
4644
cmd = append(cmd, Client{
4745
ns: "elevenlabs",
4846
cmd: []Command{
49-
{Name: "voices", Description: "Return registered voices", MinArgs: 2, MaxArgs: 2, Fn: elevenlabsVoices(elevenlabs, flags)},
50-
{Name: "voice", Description: "Return a voice", Syntax: "<voice>", MinArgs: 3, MaxArgs: 3, Fn: elevenlabsVoice(elevenlabs, flags)},
51-
{Name: "preview", Description: "Preview a voice", Syntax: "<voice>", MinArgs: 3, MaxArgs: 3, Fn: elevenlabsVoicePreview(elevenlabs, flags)},
52-
{Name: "say", Description: "Text-to-speech", Syntax: "<voice> <text>", MinArgs: 3, MaxArgs: 3, Fn: elevenlabsTextToSpeech(elevenlabs, flags)},
47+
{Name: "voices", Description: "Return registered voices", MinArgs: 2, MaxArgs: 2, Fn: elVoices(elevenlabs, flags)},
48+
{Name: "voice", Description: "Return voice information", Syntax: "<voice-id>", MinArgs: 3, MaxArgs: 3, Fn: elVoice(elevenlabs, flags)},
49+
{Name: "speak", Description: "Create speech from a prompt", Syntax: "<voice> <prompt>", MinArgs: 4, MaxArgs: 4, Fn: elSpeak(elevenlabs, flags)},
5350
},
5451
})
5552

@@ -60,7 +57,7 @@ func ElevenlabsRegister(cmd []Client, opts []client.ClientOpt, flags *Flags) ([]
6057
/////////////////////////////////////////////////////////////////////
6158
// API CALL FUNCTIONS
6259

63-
func elevenlabsVoices(client *elevenlabs.Client, flags *Flags) CommandFn {
60+
func elVoices(client *elevenlabs.Client, flags *Flags) CommandFn {
6461
return func() error {
6562
if voices, err := client.Voices(); err != nil {
6663
return err
@@ -70,55 +67,40 @@ func elevenlabsVoices(client *elevenlabs.Client, flags *Flags) CommandFn {
7067
}
7168
}
7269

73-
func elevenlabsVoice(client *elevenlabs.Client, flags *Flags) CommandFn {
70+
func elVoice(client *elevenlabs.Client, flags *Flags) CommandFn {
7471
return func() error {
75-
voice, err := elevenlabsGetVoiceId(client, flags.Arg(2))
76-
if err != nil {
77-
return err
78-
} else if voice, err := client.Voice(voice); err != nil {
72+
if voice, err := client.Voice(flags.Arg(2)); err != nil {
7973
return err
8074
} else {
8175
return flags.Write(voice)
8276
}
8377
}
8478
}
8579

86-
func elevenlabsVoicePreview(client *elevenlabs.Client, flags *Flags) CommandFn {
80+
func elSpeak(client *elevenlabs.Client, flags *Flags) CommandFn {
8781
return func() error {
88-
voice, err := elevenlabsGetVoiceId(client, flags.Arg(2))
82+
voice, err := elGetVoiceId(client, flags.Arg(2))
8983
if err != nil {
9084
return err
91-
} else if voice, err := client.Voice(voice); err != nil {
92-
return err
93-
} else if voice.PreviewUrl == "" {
94-
return ErrNotFound.Withf("%q", flags.Arg(2))
95-
} else {
96-
fmt.Println(voice.PreviewUrl)
97-
return nil
9885
}
99-
}
100-
}
10186

102-
func elevenlabsTextToSpeech(client *elevenlabs.Client, flags *Flags) CommandFn {
103-
return func() error {
104-
// Determine the voice to use
105-
voice, err := flags.GetString("elevenlabs-voice")
106-
if err != nil {
107-
return err
108-
} else if voice == "" {
109-
return fmt.Errorf("missing argument: -elevenlabs-voice")
110-
}
111-
voice, err = elevenlabsGetVoiceId(client, voice)
87+
// Set options
88+
opts := []elevenlabs.Opt{}
89+
90+
// Create the audio
91+
out := flags.GetOutFilename("speech.mp3", 0)
92+
file, err := os.Create(out)
11293
if err != nil {
11394
return err
11495
}
115-
116-
data, err := client.TextToSpeech(flags.Arg(2), voice)
117-
if err != nil {
96+
defer file.Close()
97+
if n, err := client.TextToSpeech(file, voice, flags.Arg(3), opts...); err != nil {
11898
return err
119-
} else if _, err := os.Stdout.Write(data); err != nil {
99+
} else if err := flags.Write(result{Path: out, Bytes: n}); err != nil {
120100
return err
121101
}
102+
103+
// Return success
122104
return nil
123105
}
124106
}
@@ -127,7 +109,7 @@ func elevenlabsTextToSpeech(client *elevenlabs.Client, flags *Flags) CommandFn {
127109
// PRIVATE METHODS
128110

129111
// return a voice-id given a parameter, which can be a voice-id or name
130-
func elevenlabsGetVoiceId(client *elevenlabs.Client, voice string) (string, error) {
112+
func elGetVoiceId(client *elevenlabs.Client, voice string) (string, error) {
131113
if reVoiceId.MatchString(voice) {
132114
return voice, nil
133115
} else if voices, err := client.Voices(); err != nil {
@@ -139,5 +121,5 @@ func elevenlabsGetVoiceId(client *elevenlabs.Client, voice string) (string, erro
139121
}
140122
}
141123
}
142-
return "", ErrNotFound.Withf("%q", voice)
124+
return "", fmt.Errorf("voice not found: %q", voice)
143125
}

cmd/cli/flags.go

+72-23
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,22 @@ import (
66
"os"
77
"path/filepath"
88
"strconv"
9+
"strings"
910
"time"
1011

1112
// Packages
12-
"github.com/djthorpe/go-errors"
13-
"github.com/mutablelogic/go-client/pkg/writer"
13+
tablewriter "github.com/djthorpe/go-tablewriter"
14+
15+
// Namespace imports
16+
. "github.com/djthorpe/go-errors"
1417
)
1518

1619
///////////////////////////////////////////////////////////////////////////////
1720
// TYPES
1821

1922
type Flags struct {
2023
*flag.FlagSet
21-
writer *writer.TableWriter
24+
writer *tablewriter.TableWriter
2225
}
2326

2427
type FlagsRegister func(*Flags)
@@ -33,7 +36,7 @@ func NewFlags(name string, args []string, register ...FlagsRegister) (*Flags, er
3336
// Register flags
3437
flags.Bool("debug", false, "Enable debug logging")
3538
flags.Duration("timeout", 0, "Timeout")
36-
flags.String("out", "txt", "Output format <txt|csv|tsv|json> or file name <filename>.<txt|csv|tsv|json>")
39+
flags.String("out", "", "Output format or file name")
3740
flags.String("cols", "", "Comma-separated list of columns to output")
3841
for _, fn := range register {
3942
fn(flags)
@@ -45,7 +48,7 @@ func NewFlags(name string, args []string, register ...FlagsRegister) (*Flags, er
4548
}
4649

4750
// Create a writer
48-
flags.writer = writer.New(os.Stdout)
51+
flags.writer = tablewriter.New(os.Stdout)
4952

5053
// Return success
5154
return flags, nil
@@ -63,13 +66,24 @@ func (flags *Flags) Timeout() time.Duration {
6366
}
6467

6568
func (flags *Flags) GetOut() string {
66-
v, _ := flags.GetString("out")
67-
return v
69+
return flags.GetString("out")
70+
}
71+
72+
func (flags *Flags) GetOutExt() string {
73+
out := flags.GetOut()
74+
if out == "" {
75+
return ""
76+
}
77+
if ext := filepath.Ext(out); ext == "" {
78+
return out
79+
} else {
80+
return strings.TrimPrefix(ext, ".")
81+
}
6882
}
6983

7084
// Return a filename for output, returns an empty string if the output
7185
// argument is not a filename (it requires an extension)
72-
func (flags *Flags) GetOutFilename(def string, n uint) string {
86+
func (flags *Flags) GetOutFilename(def string, n int) string {
7387
filename := flags.GetOut()
7488
if filename == "" {
7589
filename = filepath.Base(def)
@@ -89,38 +103,73 @@ func (flags *Flags) GetOutFilename(def string, n uint) string {
89103
return filepath.Clean(filename)
90104
}
91105

92-
func (flags *Flags) GetString(key string) (string, error) {
106+
func (flags *Flags) GetString(key string) string {
93107
if flag := flags.Lookup(key); flag == nil {
94-
return "", errors.ErrNotFound.With(key)
108+
return ""
95109
} else {
96-
return os.ExpandEnv(flag.Value.String()), nil
110+
return os.ExpandEnv(flag.Value.String())
97111
}
98112
}
99113

100114
func (flags *Flags) GetUint(key string) (uint, error) {
101115
if flag := flags.Lookup(key); flag == nil {
102-
return 0, errors.ErrNotFound.With(key)
116+
return 0, ErrNotFound.With(key)
103117
} else if v, err := strconv.ParseUint(os.ExpandEnv(flag.Value.String()), 10, 64); err != nil {
104-
return 0, errors.ErrBadParameter.With(key)
118+
return 0, ErrBadParameter.With(key)
105119
} else {
106120
return uint(v), nil
107121
}
108122
}
109123

124+
func (flags *Flags) GetInt(key string) (int, error) {
125+
if flag := flags.Lookup(key); flag == nil {
126+
return 0, ErrNotFound.With(key)
127+
} else if v, err := strconv.ParseInt(os.ExpandEnv(flag.Value.String()), 10, 64); err != nil {
128+
return 0, ErrBadParameter.With(key)
129+
} else {
130+
return int(v), nil
131+
}
132+
}
133+
134+
func (flags *Flags) GetBool(key string) bool {
135+
if flag := flags.Lookup(key); flag == nil {
136+
return false
137+
} else if v, err := strconv.ParseBool(os.ExpandEnv(flag.Value.String())); err != nil {
138+
return false
139+
} else {
140+
return v
141+
}
142+
}
143+
144+
func (flags *Flags) GetFloat64(key string) *float64 {
145+
if flag := flags.Lookup(key); flag == nil {
146+
return nil
147+
} else if v, err := strconv.ParseFloat(os.ExpandEnv(flag.Value.String()), 64); err != nil {
148+
return nil
149+
} else {
150+
return &v
151+
}
152+
}
153+
110154
func (flags *Flags) Write(v any) error {
111-
opts := []writer.TableOpt{}
155+
opts := []tablewriter.TableOpt{}
156+
157+
// Set header
158+
opts = append(opts, tablewriter.OptHeader())
112159

113160
// Set terminal options
114-
opts = append(opts, TerminalOpts(flags.Output())...)
161+
//opts = append(opts, TerminalOpts(flags.Output())...)
115162

116163
// Set output options
117-
switch flags.GetOut() {
118-
case "text", "txt", "ascii":
119-
opts = append(opts, writer.OptText('|', true, 0))
120-
case "csv":
121-
opts = append(opts, writer.OptCSV(',', true))
122-
case "tsv":
123-
opts = append(opts, writer.OptCSV('\t', true))
124-
}
164+
/*
165+
switch flags.GetOut() {
166+
case "text", "txt", "ascii":
167+
opts = append(opts, writer.OptText('|', true, 0))
168+
case "csv":
169+
opts = append(opts, writer.OptCSV(',', true))
170+
case "tsv":
171+
opts = append(opts, writer.OptCSV('\t', true))
172+
}
173+
*/
125174
return flags.writer.Write(v, opts...)
126175
}

0 commit comments

Comments
 (0)