// Package utils provides utility functions for the Yandex Music API client. package utils import ( "encoding/json" "errors" ) // Response represents an API response from the Yandex Music API. type Response struct { Result json.RawMessage `json:"result"` Error string `json:"error,omitempty"` ErrorDescription string `json:"errorDescription,omitempty"` } // GetResult returns the result as raw JSON. func (r *Response) GetResult() json.RawMessage { return r.Result } // GetError returns the error message from the response. // It returns Error if set, otherwise ErrorDescription, or "Unknown error" if neither is set. func (r *Response) GetError() string { if r.Error != "" { return r.Error } if r.ErrorDescription != "" { return r.ErrorDescription } return "Unknown error" } // HasError returns true if the response contains an error. func (r *Response) HasError() bool { return r.Error != "" || r.ErrorDescription != "" } // UnmarshalJSON implements custom unmarshaling for Response. // If result is missing, the whole response is wrapped in result. func (r *Response) UnmarshalJSON(data []byte) error { // First try to unmarshal as a standard response type Alias Response aux := &struct { *Alias }{ Alias: (*Alias)(r), } if err := json.Unmarshal(data, aux); err != nil { return err } // If result is missing, wrap the whole response in result if r.Result == nil { r.Result = data } return nil } // DeJSON creates a Response from JSON data. func DeJSON(data []byte) (*Response, error) { var resp Response if err := json.Unmarshal(data, &resp); err != nil { return nil, err } return &resp, nil } // Error types for the Yandex Music API client. var ( // ErrUnauthorized is returned when authentication fails (HTTP 401/403). ErrUnauthorized = errors.New("unauthorized") // ErrBadRequest is returned when the request is malformed (HTTP 400). ErrBadRequest = errors.New("bad request") // ErrNotFound is returned when the requested resource is not found (HTTP 404). ErrNotFound = errors.New("not found") // ErrNetwork is returned for network-related errors. ErrNetwork = errors.New("network error") // ErrTimeout is returned when a request times out. ErrTimeout = errors.New("timeout") // ErrSchemaMismatch is returned when the API response schema doesn't match expectations. ErrSchemaMismatch = errors.New("schema mismatch") ) // YandexMusicError is the base error type for Yandex Music API errors. // It wraps an underlying error with a descriptive message. type YandexMusicError struct { Message string Err error } // Error returns the error message, including the wrapped error if present. func (e *YandexMusicError) Error() string { if e.Err != nil { return e.Message + ": " + e.Err.Error() } return e.Message } // Unwrap returns the underlying error for compatibility with errors.Is and errors.As. func (e *YandexMusicError) Unwrap() error { return e.Err } // NewYandexMusicError creates a new YandexMusicError with the given message and underlying error. func NewYandexMusicError(message string, err error) *YandexMusicError { return &YandexMusicError{Message: message, Err: err} } // IsUnauthorizedError checks if an error is an unauthorized error. func IsUnauthorizedError(err error) bool { var yme *YandexMusicError if errors.As(err, &yme) { return errors.Is(yme.Err, ErrUnauthorized) } return errors.Is(err, ErrUnauthorized) } // IsBadRequestError checks if an error is a bad request error. func IsBadRequestError(err error) bool { var yme *YandexMusicError if errors.As(err, &yme) { return errors.Is(yme.Err, ErrBadRequest) } return errors.Is(err, ErrBadRequest) } // IsNotFoundError checks if an error is a not found error. func IsNotFoundError(err error) bool { var yme *YandexMusicError if errors.As(err, &yme) { return errors.Is(yme.Err, ErrNotFound) } return errors.Is(err, ErrNotFound) } // IsNetworkError checks if an error is a network error. func IsNetworkError(err error) bool { var yme *YandexMusicError if errors.As(err, &yme) { return errors.Is(yme.Err, ErrNetwork) } return errors.Is(err, ErrNetwork) } // IsTimeoutError checks if an error is a timeout error. func IsTimeoutError(err error) bool { var yme *YandexMusicError if errors.As(err, &yme) { return errors.Is(yme.Err, ErrTimeout) } return errors.Is(err, ErrTimeout) }