diff --git a/client/types/types.go b/client/types/types.go index 22a3763..9f66b5c 100644 --- a/client/types/types.go +++ b/client/types/types.go @@ -9,8 +9,6 @@ type AddVoiceResponse struct { VoiceID string `json:"voice_id"` } -type AnyOfValidationErrorLocItems struct{} - type HistoryPost struct { HistoryItemIds []string `json:"history_item_ids"` } @@ -25,11 +23,6 @@ type TTS struct { VoiceSettings SynthesisOptions `json:"voice_settings,omitempty"` // Voice settings are applied only on the given TTS request. } -var DefaultSynthesisOptions = SynthesisOptions{ - Stability: 75, - SimilarityBoost: 75, -} - type SynthesisOptions struct { Stability float64 `json:"stability"` SimilarityBoost float64 `json:"similarity_boost"` @@ -51,7 +44,7 @@ type ExtendedSubscriptionResponseModel struct { CanUseDelayedPaymentMethods bool `json:"can_use_delayed_payment_methods"` Currency string `json:"currency"` Status string `json:"status"` - NextInvoice InvoiceResponseModel `json:"next_invoice"` + NextInvoice Invoice `json:"next_invoice"` } type FeedbackResponseModel struct { ThumbsUp bool `json:"thumbs_up"` @@ -93,9 +86,6 @@ type HistoryItemList struct { Settings *interface{} `json:"settings"` Feedback *FeedbackResponseModel `json:"feedback"` } -type HttpValidationError struct { - Detail []ValidationError `json:"detail,omitempty"` -} type Invoice struct { AmountDueCents int32 `json:"amount_due_cents"` NextPaymentAttemptUnix int32 `json:"next_payment_attempt_unix"` @@ -147,9 +137,9 @@ type UserResponseModel struct { XiAPIKey string `json:"xi_api_key"` } type ValidationError struct { - Loc []AnyOfValidationErrorLocItems `json:"loc"` - Msg string `json:"msg"` - Type_ string `json:"type"` + Loc any `json:"loc"` + Msg string `json:"msg"` + Type_ string `json:"type"` } func (ve ValidationError) Error() string { diff --git a/client/voices.go b/client/voices.go index f362802..cf7e553 100644 --- a/client/voices.go +++ b/client/voices.go @@ -2,47 +2,244 @@ package client import ( "context" + "encoding/json" + "errors" + "fmt" "net/http" "os" "strings" + + "github.com/taigrr/elevenlabs/client/types" ) -func (c Client) CreateVoice(ctx context.Context, name string, files []*os.File, description string, labels string) (AddVoiceResponseModel, *http.Response, error) { +func (c Client) CreateVoice(ctx context.Context, name string, files []*os.File, description string, labels string) error { localVarHttpMethod = strings.ToUpper("Post") localVarPath := a.client.cfg.BasePath + "/v1/voices/add" } -func (c Client) DeleteVoice(ctx context.Context, voiceId string) (Object, *http.Response, error) { - localVarHttpMethod = strings.ToUpper("Delete") - localVarPath := a.client.cfg.BasePath + "/v1/voices/{voice_id}" +func (c Client) DeleteVoice(ctx context.Context, voiceID string) error { + url := fmt.Sprintf(c.endpoint+"/v1/voices/%s", voiceID) + client := &http.Client{} + req, err := http.NewRequestWithContext(ctx, http.MethodDelete, url, nil) + if err != nil { + return err + } + req.Header.Set("xi-api-key", c.apiKey) + req.Header.Set("User-Agent", "github.com/taigrr/elevenlabs") + req.Header.Set("accept", "application/json") + res, err := client.Do(req) + switch res.StatusCode { + case 422: + ve := types.ValidationError{} + defer res.Body.Close() + jerr := json.NewDecoder(res.Body).Decode(&ve) + if jerr != nil { + err = errors.Join(err, jerr) + } else { + err = errors.Join(err, ve) + } + return err + case 401: + return ErrUnauthorized + case 200: + if err != nil { + return err + } + return nil + default: + return errors.Join(err, ErrUnspecified) + } } -func (c Client) EditVoiceSettings(ctx context.Context, body Settings, voiceId string) (Object, *http.Response, error) { - localVarHttpMethod = strings.ToUpper("Post") - localVarPath := a.client.cfg.BasePath + "/v1/voices/{voice_id}/settings/edit" +func (c Client) EditVoiceSettings(ctx context.Context, voiceID string, types.SynthesisOptions) error { + url := fmt.Sprintf(c.endpoint+"/v1/voices/%s/settings/edit", voiceID) + client := &http.Client{} + req, err := http.NewRequestWithContext(ctx, http.MethodPost, url, nil) + if err != nil { + return err + } + req.Header.Set("xi-api-key", c.apiKey) + req.Header.Set("User-Agent", "github.com/taigrr/elevenlabs") + req.Header.Set("accept", "application/json") + res, err := client.Do(req) + switch res.StatusCode { + case 422: + ve := types.ValidationError{} + defer res.Body.Close() + jerr := json.NewDecoder(res.Body).Decode(&ve) + if jerr != nil { + err = errors.Join(err, jerr) + } else { + err = errors.Join(err, ve) + } + return err + case 401: + return ErrUnauthorized + case 200: + if err != nil { + return err + } + so := types.SynthesisOptions{} + defer res.Body.Close() + jerr := json.NewDecoder(res.Body).Decode(&so) + if jerr != nil { + return jerr + } + return nil + default: + return errors.Join(err, ErrUnspecified) + } } -func (c Client) EditVoice(ctx context.Context, name string, files []*os.File, description string, labels string, voiceId string) (Object, *http.Response, error) { +func (c Client) EditVoice(ctx context.Context, voiceID, name, description string, files []*os.File, labels []string ) error { localVarHttpMethod = strings.ToUpper("Post") localVarPath := a.client.cfg.BasePath + "/v1/voices/{voice_id}/edit" } -func (c Client) DefaultVoiceSettings(ctx context.Context) (VoiceSettingsResponseModel, *http.Response, error) { - localVarHttpMethod = strings.ToUpper("Get") - localVarPath := a.client.cfg.BasePath + "/v1/voices/settings/default" +func (c Client) defaultVoiceSettings(ctx context.Context) (types.SynthesisOptions, error) { + url := c.endpoint + "/v1/voices/settings/default" + client := &http.Client{} + req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) + if err != nil { + return types.SynthesisOptions{}, err + } + req.Header.Set("xi-api-key", c.apiKey) + req.Header.Set("User-Agent", "github.com/taigrr/elevenlabs") + req.Header.Set("accept", "application/json") + res, err := client.Do(req) + switch res.StatusCode { + case 422: + ve := types.ValidationError{} + defer res.Body.Close() + jerr := json.NewDecoder(res.Body).Decode(&ve) + if jerr != nil { + err = errors.Join(err, jerr) + } else { + err = errors.Join(err, ve) + } + return types.SynthesisOptions{}, err + case 401: + return types.SynthesisOptions{}, ErrUnauthorized + case 200: + if err != nil { + return types.SynthesisOptions{}, err + } + so := types.SynthesisOptions{} + defer res.Body.Close() + jerr := json.NewDecoder(res.Body).Decode(&so) + if jerr != nil { + return types.SynthesisOptions{}, jerr + } + return so, nil + default: + return types.SynthesisOptions{}, errors.Join(err, ErrUnspecified) + } } func (c Client) GetVoiceSettings(ctx context.Context, voiceId string) (VoiceSettingsResponseModel, *http.Response, error) { localVarHttpMethod = strings.ToUpper("Get") localVarPath := a.client.cfg.BasePath + "/v1/voices/{voice_id}/settings" + url := fmt.Sprintf(c.endpoint+"/v1/voices/%s", voiceID) + client := &http.Client{} + req, err := http.NewRequestWithContext(ctx, http.MethodDelete, url, nil) + if err != nil { + return err + } + req.Header.Set("xi-api-key", c.apiKey) + req.Header.Set("User-Agent", "github.com/taigrr/elevenlabs") + req.Header.Set("accept", "application/json") + res, err := client.Do(req) + switch res.StatusCode { + case 422: + ve := types.ValidationError{} + defer res.Body.Close() + jerr := json.NewDecoder(res.Body).Decode(&ve) + if jerr != nil { + err = errors.Join(err, jerr) + } else { + err = errors.Join(err, ve) + } + return err + case 401: + return ErrUnauthorized + case 200: + if err != nil { + return err + } + return nil + default: + return errors.Join(err, ErrUnspecified) + } } func (c Client) GetVoice(ctx context.Context, voiceId string) (VoiceResponseModel, *http.Response, error) { localVarHttpMethod = strings.ToUpper("Get") localVarPath := a.client.cfg.BasePath + "/v1/voices/{voice_id}" + url := fmt.Sprintf(c.endpoint+"/v1/voices/%s", voiceID) + client := &http.Client{} + req, err := http.NewRequestWithContext(ctx, http.MethodDelete, url, nil) + if err != nil { + return err + } + req.Header.Set("xi-api-key", c.apiKey) + req.Header.Set("User-Agent", "github.com/taigrr/elevenlabs") + req.Header.Set("accept", "application/json") + res, err := client.Do(req) + switch res.StatusCode { + case 422: + ve := types.ValidationError{} + defer res.Body.Close() + jerr := json.NewDecoder(res.Body).Decode(&ve) + if jerr != nil { + err = errors.Join(err, jerr) + } else { + err = errors.Join(err, ve) + } + return err + case 401: + return ErrUnauthorized + case 200: + if err != nil { + return err + } + return nil + default: + return errors.Join(err, ErrUnspecified) + } } func (c Client) GetVoices(ctx context.Context) (GetVoicesResponseModel, *http.Response, error) { localVarHttpMethod = strings.ToUpper("Get") localVarPath := a.client.cfg.BasePath + "/v1/voices" + url := fmt.Sprintf(c.endpoint+"/v1/voices/%s", voiceID) + client := &http.Client{} + req, err := http.NewRequestWithContext(ctx, http.MethodDelete, url, nil) + if err != nil { + return err + } + req.Header.Set("xi-api-key", c.apiKey) + req.Header.Set("User-Agent", "github.com/taigrr/elevenlabs") + req.Header.Set("accept", "application/json") + res, err := client.Do(req) + switch res.StatusCode { + case 422: + ve := types.ValidationError{} + defer res.Body.Close() + jerr := json.NewDecoder(res.Body).Decode(&ve) + if jerr != nil { + err = errors.Join(err, jerr) + } else { + err = errors.Join(err, ve) + } + return err + case 401: + return ErrUnauthorized + case 200: + if err != nil { + return err + } + return nil + default: + return errors.Join(err, ErrUnspecified) + } }