package cmd
import (
"encoding/json"
"fmt"
"os"
"strings"
"text/tabwriter"
"github.com/neosapience/cast/internal/client"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
var voicesCmd = &cobra.Command{
Use: "voices",
Short: "Manage voices",
}
var voicesListCmd = &cobra.Command{
Use: "list",
Short: "List available voices",
RunE: func(cmd *cobra.Command, args []string) error {
flags := cmd.Flags()
model, _ := flags.GetString("model")
gender, _ := flags.GetString("gender")
age, _ := flags.GetString("age")
useCase, _ := flags.GetString("use-case")
name, _ := flags.GetString("name")
emotion, _ := flags.GetString("emotion")
asJSON, _ := flags.GetBool("json")
baseURL := viper.GetString("base_url")
var c *client.Client
if baseURL != "" {
c = client.NewWithBaseURL(viper.GetString("api_key"), baseURL)
} else {
c = client.New(viper.GetString("api_key"))
}
voices, err := c.ListVoices(client.ListVoicesParams{
Model: model,
Gender: gender,
Age: age,
UseCase: useCase,
})
if err != nil {
return err
}
// Client-side filters (not supported by API).
if name != "" {
voices = filterVoicesByName(voices, name)
}
if emotion != "" {
voices = filterVoicesByEmotion(voices, emotion)
}
if asJSON {
enc := json.NewEncoder(os.Stdout)
enc.SetIndent("", " ")
return enc.Encode(voices)
}
w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
fmt.Fprintln(w, "ID\tNAME\tGENDER\tAGE\tMODELS")
for _, v := range voices {
modelNames := make([]string, len(v.Models))
for i, m := range v.Models {
modelNames[i] = m.Version
}
fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\n",
v.VoiceID, v.VoiceName, v.Gender, v.Age,
strings.Join(modelNames, ", "))
}
return w.Flush()
},
}
func filterVoicesByName(voices []client.Voice, name string) []client.Voice {
lower := strings.ToLower(name)
out := voices[:0]
for _, v := range voices {
if strings.Contains(strings.ToLower(v.VoiceName), lower) {
out = append(out, v)
}
}
return out
}
func filterVoicesByEmotion(voices []client.Voice, emotion string) []client.Voice {
out := voices[:0]
for _, v := range voices {
for _, m := range v.Models {
if containsString(m.Emotions, emotion) {
out = append(out, v)
break
}
}
}
return out
}
func containsString(slice []string, s string) bool {
for _, v := range slice {
if v == s {
return true
}
}
return false
}
var voicesGetCmd = &cobra.Command{
Use: "get