package utils import ( "encoding/json" "errors" ) // Response represents an API response 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 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 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 var ( ErrUnauthorized = errors.New("unauthorized") ErrBadRequest = errors.New("bad request") ErrNotFound = errors.New("not found") ErrNetwork = errors.New("network error") ErrTimeout = errors.New("timeout") ErrSchemaMismatch = errors.New("schema mismatch") ) // YandexMusicError is the base error type type YandexMusicError struct { Message string Err error } func (e *YandexMusicError) Error() string { if e.Err != nil { return e.Message + ": " + e.Err.Error() } return e.Message } func (e *YandexMusicError) Unwrap() error { return e.Err } // NewYandexMusicError creates a new YandexMusicError func NewYandexMusicError(message string, err error) *YandexMusicError { return &YandexMusicError{Message: message, Err: err} } // IsUnauthorizedError checks if error is unauthorized 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 error is bad request 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 error is not found 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 error is 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 error is timeout func IsTimeoutError(err error) bool { var yme *YandexMusicError if errors.As(err, &yme) { return errors.Is(yme.Err, ErrTimeout) } return errors.Is(err, ErrTimeout) }