Add comprehensive godoc documentation to all exported symbols

- Document all exported types, functions, methods, and constants across 52 files
- Add package-level doc comments to client, models, utils, and ynison packages
- Document HTTP method and endpoint path for each API client method
- Document model struct fields and DeJSON/DeList/ToJSON/ToMap methods
- Fix duplicate package doc comment in internal/models/base.go

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
MrixsandClaude Code committed 2026-10-18 08:57:43 +03:00
1 parent 7a68ad86cb
commit 0456ca0665
54 files changed
+1085 -640

No files matched your search

+2
View File
@@ -0,0 +1,2 @@
/cache
/project.local.yml
+163
View File
@@ -0,0 +1,163 @@
# the name by which the project can be referenced within Serena/when chatting with the LLM.
project_name: "yandex-music-api-go"
# list of languages for which language servers are started (LSP backend only); choose from:
# ada al angular ansible bash
# bsl clojure cpp cpp_ccls crystal
# csharp csharp_omnisharp cue dart elixir
# elm erlang fortran fsharp gdscript
# go groovy haskell haxe hlsl
# html java json julia kotlin
# latex lean4 lua luau markdown
# matlab msl nix ocaml pascal
# perl php php_phpactor php_phpantom powershell
# python python_jedi python_pyrefly python_ty r
# rego ruby ruby_solargraph rust scala
# scss solidity svelte swift systemverilog
# terraform toml typescript typescript_vts vue
# yaml zig
# (This list may be outdated; generated with scripts/print_language_list.py;
# For the current list, see values of Language enum here:
# https://github.com/oraios/serena/blob/main/src/solidlsp/ls_config.py)
# For some languages, there are alternative language servers, e.g. csharp_omnisharp, ruby_solargraph.)
# Note:
# - For C, use cpp
# - For JavaScript, use typescript
# - For Angular projects, use angular (subsumes typescript+html; requires `npm install` in the project root)
# - For Svelte projects, use svelte (subsumes typescript/javascript for .svelte projects; requires npm)
# - For SCSS / Sass / plain CSS, use scss (some-sass-language-server handles all three)
# - For Free Pascal/Lazarus, use pascal
# Special requirements:
# Some languages require additional setup/installations.
# See here for details: https://oraios.github.io/serena/01-about/020_programming-languages.html#language-servers
# When using multiple languages, the first language server that supports a given file will be used for that file.
# The first language is the default language and the respective language server will be used as a fallback.
# Note that when using the JetBrains backend, language servers are not used and this list is correspondingly ignored.
languages:
- python
- go
- markdown
- json
# the encoding used by text files in the project
# For a list of possible encodings, see https://docs.python.org/3.11/library/codecs.html#standard-encodings
encoding: "utf-8"
# optional shell command to run before the language backend (LSP or JetBrains) is initialised.
# the command runs in the project root directory and is only executed if the project is trusted
# (see trusted_project_path_patterns in the global configuration).
# serena waits for the command to exit: a non-zero exit code is logged as an error but does not
# abort activation. a per-project timeout (activation_command_timeout, default 180s) is the safety
# backstop for non-terminating commands; on expiry the process is killed and activation continues.
# example: activation_command: "npx nx run-many -t build"
activation_command:
# maximum time in seconds to wait for activation_command to complete before killing it (default 180s).
# must be a positive number.
activation_command_timeout: 180.0
# line ending convention to use when writing source files.
# Possible values: unset (use global setting), "lf", "crlf", or "native" (platform default)
# This does not affect Serena's own files (e.g. memories and configuration files), which always use native line endings.
line_ending:
# The language backend to use for this project.
# If not set, the global setting from serena_config.yml is used.
# Valid values: LSP, JetBrains
# Note: the backend is fixed at startup. If a project with a different backend
# is activated post-init, an error will be returned.
language_backend:
# whether to use project's .gitignore files to ignore files
ignore_all_files_in_gitignore: true
# advanced configuration option allowing to configure language server-specific options.
# Maps the language key to the options.
# The settings are considered only if the project is trusted (see global configuration to define trusted projects).
# See https://oraios.github.io/serena/02-usage/050_configuration.html#language-server-specific-settings
ls_specific_settings: {}
# list of workspace folder paths (LSP backend only).
# These folders will be used to build up Serena's symbol index.
# Paths must be within the project root and should thus be relative to the project root.
# Furthermore, the paths should not be filtered by ignore settings.
# Default setting: The entire project root folder (".") is considered.
# In (large) monorepos, this can be used to index only subfolders of the project root, e.g.
# ls_workspace_folders:
# - "./subproject1"
# - "./subproject2"
ls_workspace_folders:
- "."
# list of additional workspace folder paths for cross-package reference support.
# Paths can be absolute or relative to the project root.
# Each folder is registered as an LSP workspace folder, enabling language servers to discover
# symbols and references across package boundaries, but these folders are not indexed by Serena,
# i.e. the respective symbols will not be found using Serena's symbol search tools.
# Example:
# additional_workspace_folders:
# - ../sibling-package
# - ../shared-lib
ls_additional_workspace_folders: []
# list of additional paths to ignore in this project.
# Same syntax as gitignore, so you can use * and **.
# Note: global ignored_paths from serena_config.yml are also applied additively.
ignored_paths: []
# whether the project is in read-only mode
# If set to true, all editing tools will be disabled and attempts to use them will result in an error
# Added on 2025-04-18
read_only: false
# list of tool names to exclude.
# This extends the existing exclusions (e.g. from the global configuration)
# Find the list of tools here: https://oraios.github.io/serena/01-about/035_tools.html
excluded_tools: []
# list of tools to include that would otherwise be disabled (particularly optional tools that are disabled by default).
# This extends the existing inclusions (e.g. from the global configuration).
# Find the list of tools here: https://oraios.github.io/serena/01-about/035_tools.html
included_optional_tools: []
# fixed set of tools to use as the base tool set (if non-empty), replacing Serena's default set of tools.
# This cannot be combined with non-empty excluded_tools or included_optional_tools.
# Find the list of tools here: https://oraios.github.io/serena/01-about/035_tools.html
fixed_tools: []
# list of mode names that are to be activated by default, overriding the setting in the global configuration.
# The full set of modes to be activated is base_modes (from global config) + default_modes + added_modes.
# If the setting is undefined/empty, the default_modes from the global configuration (serena_config.yml) apply.
# Otherwise, this overrides the setting from the global configuration (serena_config.yml).
# Therefore, you can set this to [] if you do not want the default modes defined in the global config to apply
# for this project.
# This setting can, in turn, be overridden by CLI parameters (--mode).
# See https://oraios.github.io/serena/02-usage/050_configuration.html#modes
default_modes:
# list of mode names to be activated additionally for this project, e.g. ["query-projects"]
# The full set of modes to be activated is base_modes (from global config) + default_modes + added_modes.
# See https://oraios.github.io/serena/02-usage/050_configuration.html#modes
added_modes:
# initial prompt for the project. It will always be given to the LLM upon activating the project
# (contrary to the memories, which are loaded on demand).
initial_prompt: ""
# time budget (seconds) per tool call for the retrieval of additional symbol information
# such as docstrings or parameter information.
# This overrides the corresponding setting in the global configuration; see the documentation there.
# If null or missing, use the setting from the global configuration.
symbol_info_budget:
# list of regex patterns which, when matched, mark a memory entry as read‑only.
# Extends the list from the global configuration, merging the two lists.
read_only_memory_patterns: []
# list of regex patterns for memories to completely ignore.
# Matching memories will not appear in list_memories or activate_project output
# and cannot be accessed via read_memory or write_memory.
# To access ignored memory files, use the read_file tool on the raw file path.
# Extends the list from the global configuration, merging the two lists.
# Example: ["_archive/.*", "_episodes/.*"]
ignored_memory_patterns: []
+182
View File
@@ -0,0 +1,182 @@
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Project Overview
This is a Go port of the [yandex-music-api](https://github.com/MarshalX/yandex-music-api) Python library. The original Python library is in `yandex-music-api-python/` and serves as the reference implementation.
The Python library provides:
- **Sync and async HTTP clients** for Yandex Music API
- **Ynison protocol support** for player synchronization across devices
- **Radio sessions** (My Wave, generative stations)
- **High-level wrapper objects** (Track, Album, Artist, Playlist, etc.)
- **Schema mismatch handling** for API evolution
- **Multiple JSON backend support** (orjson, pydantic-core, ujson, stdlib json)
## Python Library Architecture (Reference)
### Core Structure
```
yandex_music/
├── client.py # Sync Client (main entry point)
├── client_async.py # Async ClientAsync
├── _client_base.py # Shared base class with common attributes
├── base.py # YandexMusicObject base model with de_json/de_list
├── exceptions.py # Custom exceptions
├── utils/
│ ├── request.py # Sync HTTP request handling
│ ├── request_async.py # Async HTTP request handling
│ ├── json_backend.py # Pluggable JSON backends
│ └── schema_mismatch.py # Schema mismatch reporting
├── _client/ # Generated sync method mixins (20+ files)
├── _client_async/ # Generated async method mixins
├── track/, album/, artist/, playlist/, etc. # Model packages
├── ynison/ # Ynison protocol (WebSocket)
│ ├── client.py # Sync Ynison client
│ ├── client_async.py # Async Ynison client
│ └── models/ # Protobuf-generated models
└── supplement/ # Lyrics, video supplements
```
### Key Patterns
- **Mixin-based Client**: `Client` inherits from 20+ mixins (AccountMixin, AlbumsMixin, TracksMixin, etc.)
- **Model deserialization**: Each model has `de_json(data, client)` and `de_list(list_data, client)` classmethods
- **Request signing**: Requests to `api.music.yandex.net` are signed with a custom algorithm
- **Device auth**: OAuth Device Flow for token acquisition
- **Generated code**: Sync/async clients and models are partially code-generated from OpenAPI spec
## Go Project Structure (Target)
```
yandex-music-api-go/
├── go.mod
├── go.sum
├── cmd/
│ └── examples/ # Example applications
├── internal/
│ ├── client/ # Core HTTP client
│ │ ├── client.go # Main Client struct
│ │ ├── request.go # Request building/signing
│ │ └── auth.go # Device auth, token handling
│ ├── models/ # Data models (Track, Album, Artist, etc.)
│ │ ├── base.go # BaseModel interface
│ │ ├── track.go
│ │ ├── album.go
│ │ └── ...
│ ├── ynison/ # Ynison WebSocket client
│ │ ├── client.go
│ │ └── proto/ # Protobuf-generated Go code
│ └── utils/
│ ├── json.go # JSON handling
│ └── schema.go # Schema mismatch handling
├── yandexmusic/ # Public API package (re-exports)
│ ├── client.go # Public Client interface
│ └── models.go # Public model types
└── tests/ # Integration tests
```
## Development Commands
### Go Toolchain
```bash
# Initialize module (run once)
go mod init github.com/your-org/yandex-music-api-go
# Download dependencies
go mod tidy
# Build
go build ./...
# Run tests
go test ./...
# Run tests with coverage
go test -cover ./...
# Run single test
go test -v -run TestName ./path/to/package
# Lint (requires golangci-lint)
golangci-lint run
# Format
go fmt ./...
# Vet
go vet ./...
# Generate code (if using code generation)
go generate ./...
```
### Protobuf (for Ynison)
```bash
# Install protoc and plugins
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
go install github.com/bufbuild/buf/cmd/buf@latest # optional, for buf.yaml workflow
# Generate from .proto files
protoc --go_out=. --go_opt=paths=source_relative \
--go-grpc_out=. --go-grpc_opt=paths=source_relative \
internal/ynison/proto/*.proto
# Or with buf
buf generate
```
## Key Implementation Notes
### Request Signing
The Python library signs requests with a custom algorithm. Port this exactly from `yandex_music/utils/request.py`:
- Request parameters are sorted and concatenated
- Signed with a secret key
- Signature added as `sign` parameter
### JSON Handling
Go's standard `encoding/json` is fast enough. No need for multiple backends. Use `json.RawMessage` for flexible fields.
### Schema Mismatch Handling
Port the Python `SchemaMismatch` logic:
- Track unknown fields in API responses
- Configurable: ignore, warn, or strict (error)
- Callback support for custom handling (e.g., Sentry)
### Ynison Protocol
- Uses WebSocket with protobuf messages
- Python uses `betterproto` for protobuf; Go uses standard `protobuf` module
- Port the message types from `yandex_music/ynison/models/`
### Model Structure
Follow Python patterns:
```go
// Base interface for all models
type Model interface {
// DeJSON deserializes from JSON
DeJSON(data []byte, client *Client) (Model, error)
// DeList deserializes a list
DeList(data []byte, client *Client) ([]Model, error)
}
```
### Client Design
- Single `Client` struct with methods (not mixins - Go doesn't have them)
- Group methods by feature using separate files: `client_tracks.go`, `client_albums.go`, etc.
- Support both sync and async (context-based) patterns
## Testing Strategy
- Unit tests for models (de/serialization)
- Integration tests against mock server (use `httptest`)
- Test schema mismatch handling
- Test request signing
## License
LGPL-3.0-only (same as Python library)
## References
- Python library: `yandex-music-api-python/`
- OpenAPI spec: https://ym.marshal.dev/api/openapi.json
- Documentation: https://ym.marshal.dev/
- Telegram: https://t.me/yandex_music_api
+10 -8
View File
@@ -1,3 +1,4 @@
// Package client provides methods for interacting with Yandex Music API endpoints.
package client package client
import ( import (
@@ -6,7 +7,7 @@ import (
"gitea.mrixs.me/Mrixs/yandex-music-api-go/internal/models" "gitea.mrixs.me/Mrixs/yandex-music-api-go/internal/models"
) )
// GetAccountSettings gets account settings (current user's settings from /account/settings) // GetAccountSettings gets account settings (current user's settings from /account/settings).
func (c *Client) GetAccountSettings(ctx context.Context) (*models.UserSettings, error) { func (c *Client) GetAccountSettings(ctx context.Context) (*models.UserSettings, error) {
var result models.UserSettings var result models.UserSettings
if err := c.request.Get(ctx, "/account/settings", nil, &result); err != nil { if err := c.request.Get(ctx, "/account/settings", nil, &result); err != nil {
@@ -15,7 +16,7 @@ func (c *Client) GetAccountSettings(ctx context.Context) (*models.UserSettings,
return &result, nil return &result, nil
} }
// UpdateAccountSettings updates account settings // UpdateAccountSettings updates account settings (PUT /account/settings).
func (c *Client) UpdateAccountSettings(ctx context.Context, settings *models.AccountSettings) (*models.AccountSettings, error) { func (c *Client) UpdateAccountSettings(ctx context.Context, settings *models.AccountSettings) (*models.AccountSettings, error) {
var result models.AccountSettings var result models.AccountSettings
if err := c.request.Put(ctx, "/account/settings", settings, &result); err != nil { if err := c.request.Put(ctx, "/account/settings", settings, &result); err != nil {
@@ -24,7 +25,7 @@ func (c *Client) UpdateAccountSettings(ctx context.Context, settings *models.Acc
return &result, nil return &result, nil
} }
// GetSubscription gets user subscription info // GetSubscription gets user subscription info (GET /account/subscription).
func (c *Client) GetSubscription(ctx context.Context) (*models.Subscription, error) { func (c *Client) GetSubscription(ctx context.Context) (*models.Subscription, error) {
var result models.Subscription var result models.Subscription
if err := c.request.Get(ctx, "/account/subscription", nil, &result); err != nil { if err := c.request.Get(ctx, "/account/subscription", nil, &result); err != nil {
@@ -33,7 +34,7 @@ func (c *Client) GetSubscription(ctx context.Context) (*models.Subscription, err
return &result, nil return &result, nil
} }
// GetPlusInfo gets Plus subscription info // GetPlusInfo gets Plus subscription info (GET /account/plus).
func (c *Client) GetPlusInfo(ctx context.Context) (*models.PlusInfo, error) { func (c *Client) GetPlusInfo(ctx context.Context) (*models.PlusInfo, error) {
var result models.PlusInfo var result models.PlusInfo
if err := c.request.Get(ctx, "/account/plus", nil, &result); err != nil { if err := c.request.Get(ctx, "/account/plus", nil, &result); err != nil {
@@ -42,7 +43,7 @@ func (c *Client) GetPlusInfo(ctx context.Context) (*models.PlusInfo, error) {
return &result, nil return &result, nil
} }
// GetPromoCodeStatus gets promo code status // GetPromoCodeStatus gets promo code status (GET /promo-code-status).
func (c *Client) GetPromoCodeStatus(ctx context.Context, code string) (*models.PromoCodeStatus, error) { func (c *Client) GetPromoCodeStatus(ctx context.Context, code string) (*models.PromoCodeStatus, error) {
params := map[string]string{ params := map[string]string{
"code": code, "code": code,
@@ -54,7 +55,7 @@ func (c *Client) GetPromoCodeStatus(ctx context.Context, code string) (*models.P
return &result, nil return &result, nil
} }
// ActivatePromoCode activates a promo code // ActivatePromoCode activates a promo code (POST /promo-code/activate).
func (c *Client) ActivatePromoCode(ctx context.Context, code string) (*models.PromoCodeStatus, error) { func (c *Client) ActivatePromoCode(ctx context.Context, code string) (*models.PromoCodeStatus, error) {
params := map[string]string{ params := map[string]string{
"code": code, "code": code,
@@ -66,7 +67,7 @@ func (c *Client) ActivatePromoCode(ctx context.Context, code string) (*models.Pr
return &result, nil return &result, nil
} }
// GetUserSettings gets user settings // GetUserSettings gets user settings for a specific user (GET /user/settings).
func (c *Client) GetUserSettings(ctx context.Context, userID string) (*models.UserSettings, error) { func (c *Client) GetUserSettings(ctx context.Context, userID string) (*models.UserSettings, error) {
params := map[string]string{ params := map[string]string{
"user_id": userID, "user_id": userID,
@@ -78,7 +79,8 @@ func (c *Client) GetUserSettings(ctx context.Context, userID string) (*models.Us
return &result, nil return &result, nil
} }
// GetAccountStatus fetches account status // GetAccountStatus fetches account status (GET /account/status).
// It returns the account status including account info and Plus subscription status.
func (c *Client) GetAccountStatus(ctx context.Context) (*Status, error) { func (c *Client) GetAccountStatus(ctx context.Context) (*Status, error) {
var result Status var result Status
if err := c.request.Get(ctx, "/account/status", nil, &result); err != nil { if err := c.request.Get(ctx, "/account/status", nil, &result); err != nil {
+7 -3
View File
@@ -1,3 +1,4 @@
// Package client provides methods for interacting with Yandex Music API endpoints.
package client package client
import ( import (
@@ -7,7 +8,8 @@ import (
"gitea.mrixs.me/Mrixs/yandex-music-api-go/internal/utils" "gitea.mrixs.me/Mrixs/yandex-music-api-go/internal/utils"
) )
// GetAlbums gets albums by IDs // GetAlbums gets albums by their IDs (GET /tracks?album-ids=...).
// Returns a slice of Album pointers, or nil if no IDs are provided.
func (c *Client) GetAlbums(ctx context.Context, albumIDs []string) ([]*models.Album, error) { func (c *Client) GetAlbums(ctx context.Context, albumIDs []string) ([]*models.Album, error) {
if len(albumIDs) == 0 { if len(albumIDs) == 0 {
return nil, nil return nil, nil
@@ -30,7 +32,8 @@ func (c *Client) GetAlbums(ctx context.Context, albumIDs []string) ([]*models.Al
return albums, nil return albums, nil
} }
// GetAlbum gets a single album by ID // GetAlbum gets a single album by ID using GetAlbums.
// Returns an error if no album is found with the given ID.
func (c *Client) GetAlbum(ctx context.Context, albumID string) (*models.Album, error) { func (c *Client) GetAlbum(ctx context.Context, albumID string) (*models.Album, error) {
albums, err := c.GetAlbums(ctx, []string{albumID}) albums, err := c.GetAlbums(ctx, []string{albumID})
if err != nil { if err != nil {
@@ -42,7 +45,8 @@ func (c *Client) GetAlbum(ctx context.Context, albumID string) (*models.Album, e
return albums[0], nil return albums[0], nil
} }
// GetAlbumsWithTracks gets albums with tracks expanded // GetAlbumsWithTracks gets albums with tracks expanded (GET /tracks?with-tracks=true).
// Returns a slice of Album pointers with their tracks populated.
func (c *Client) GetAlbumsWithTracks(ctx context.Context, albumIDs []string) ([]*models.Album, error) { func (c *Client) GetAlbumsWithTracks(ctx context.Context, albumIDs []string) ([]*models.Album, error) {
if len(albumIDs) == 0 { if len(albumIDs) == 0 {
return nil, nil return nil, nil
+9 -6
View File
@@ -1,3 +1,4 @@
// Package client provides methods for interacting with Yandex Music API endpoints.
package client package client
import ( import (
@@ -8,7 +9,8 @@ import (
"gitea.mrixs.me/Mrixs/yandex-music-api-go/internal/utils" "gitea.mrixs.me/Mrixs/yandex-music-api-go/internal/utils"
) )
// GetArtists gets artists by IDs // GetArtists gets artists by their IDs (GET /tracks?artist-ids=...).
// Returns a slice of Artist pointers, or nil if no IDs are provided.
func (c *Client) GetArtists(ctx context.Context, artistIDs []string) ([]*models.Artist, error) { func (c *Client) GetArtists(ctx context.Context, artistIDs []string) ([]*models.Artist, error) {
if len(artistIDs) == 0 { if len(artistIDs) == 0 {
return nil, nil return nil, nil
@@ -31,7 +33,8 @@ func (c *Client) GetArtists(ctx context.Context, artistIDs []string) ([]*models.
return artists, nil return artists, nil
} }
// GetArtist gets a single artist by ID // GetArtist gets a single artist by ID using GetArtists.
// Returns an error if no artist is found with the given ID.
func (c *Client) GetArtist(ctx context.Context, artistID string) (*models.Artist, error) { func (c *Client) GetArtist(ctx context.Context, artistID string) (*models.Artist, error) {
artists, err := c.GetArtists(ctx, []string{artistID}) artists, err := c.GetArtists(ctx, []string{artistID})
if err != nil { if err != nil {
@@ -43,8 +46,8 @@ func (c *Client) GetArtist(ctx context.Context, artistID string) (*models.Artist
return artists[0], nil return artists[0], nil
} }
// GetArtistAlbums gets albums by an artist // GetArtistAlbums gets albums by an artist (GET /artists/{artist_id}/direct-albums).
// GET /artists/{artist_id}/direct-albums // The page and pageSize parameters control pagination.
func (c *Client) GetArtistAlbums(ctx context.Context, artistID string, page, pageSize int) (*models.ArtistAlbums, error) { func (c *Client) GetArtistAlbums(ctx context.Context, artistID string, page, pageSize int) (*models.ArtistAlbums, error) {
params := map[string]string{ params := map[string]string{
"page": fmt.Sprintf("%d", page), "page": fmt.Sprintf("%d", page),
@@ -59,8 +62,8 @@ func (c *Client) GetArtistAlbums(ctx context.Context, artistID string, page, pag
return &result, nil return &result, nil
} }
// GetArtistTracks gets tracks by an artist // GetArtistTracks gets tracks by an artist (GET /artists/{artist_id}/tracks).
// GET /artists/{artist_id}/tracks // The page and pageSize parameters control pagination.
func (c *Client) GetArtistTracks(ctx context.Context, artistID string, page, pageSize int) (*models.ArtistTracks, error) { func (c *Client) GetArtistTracks(ctx context.Context, artistID string, page, pageSize int) (*models.ArtistTracks, error) {
params := map[string]string{ params := map[string]string{
"page": fmt.Sprintf("%d", page), "page": fmt.Sprintf("%d", page),
+10 -6
View File
@@ -13,7 +13,7 @@ import (
"gitea.mrixs.me/Mrixs/yandex-music-api-go/internal/utils" "gitea.mrixs.me/Mrixs/yandex-music-api-go/internal/utils"
) )
// DeviceCode represents the device authorization response // DeviceCode represents the device authorization response from the Yandex OAuth device flow.
type DeviceCode struct { type DeviceCode struct {
DeviceCode string `json:"device_code"` DeviceCode string `json:"device_code"`
UserCode string `json:"user_code"` UserCode string `json:"user_code"`
@@ -22,7 +22,7 @@ type DeviceCode struct {
Interval int `json:"interval"` Interval int `json:"interval"`
} }
// OAuthToken represents an OAuth token response // OAuthToken represents an OAuth token response from the Yandex OAuth token endpoint.
type OAuthToken struct { type OAuthToken struct {
AccessToken string `json:"access_token"` AccessToken string `json:"access_token"`
RefreshToken string `json:"refresh_token"` RefreshToken string `json:"refresh_token"`
@@ -30,7 +30,9 @@ type OAuthToken struct {
ExpiresIn int `json:"expires_in"` ExpiresIn int `json:"expires_in"`
} }
// DeviceAuth performs OAuth Device Flow authentication // DeviceAuth performs OAuth Device Flow authentication.
// It requests a device code, invokes the onCode callback with it, then polls for the token.
// The onCode callback receives the DeviceCode which contains the user_code and verification URL.
func (r *Request) DeviceAuth(ctx context.Context, onCode func(*DeviceCode)) (*OAuthToken, error) { func (r *Request) DeviceAuth(ctx context.Context, onCode func(*DeviceCode)) (*OAuthToken, error) {
// Step 1: Request device code // Step 1: Request device code
deviceCode, err := r.requestDeviceCode(ctx) deviceCode, err := r.requestDeviceCode(ctx)
@@ -47,7 +49,7 @@ func (r *Request) DeviceAuth(ctx context.Context, onCode func(*DeviceCode)) (*OA
return r.pollForToken(ctx, deviceCode) return r.pollForToken(ctx, deviceCode)
} }
// requestDeviceCode requests a device code from Yandex OAuth // requestDeviceCode requests a device code from the Yandex OAuth device code endpoint.
func (r *Request) requestDeviceCode(ctx context.Context) (*DeviceCode, error) { func (r *Request) requestDeviceCode(ctx context.Context) (*DeviceCode, error) {
// Use Yandex OAuth endpoint for device auth // Use Yandex OAuth endpoint for device auth
data := url.Values{} data := url.Values{}
@@ -85,7 +87,8 @@ func (r *Request) requestDeviceCode(ctx context.Context) (*DeviceCode, error) {
return &deviceCode, nil return &deviceCode, nil
} }
// pollForToken polls for the OAuth token // pollForToken polls the Yandex OAuth token endpoint until the user authorizes the device code.
// It returns the OAuthToken once authorization is complete, or an error if the code expires or is denied.
func (r *Request) pollForToken(ctx context.Context, deviceCode *DeviceCode) (*OAuthToken, error) { func (r *Request) pollForToken(ctx context.Context, deviceCode *DeviceCode) (*OAuthToken, error) {
interval := deviceCode.Interval interval := deviceCode.Interval
if interval == 0 { if interval == 0 {
@@ -155,7 +158,8 @@ func (r *Request) pollForToken(ctx context.Context, deviceCode *DeviceCode) (*OA
} }
} }
// RefreshToken refreshes an access token using a refresh token // RefreshToken refreshes an access token using the provided refresh token.
// It makes a POST request to the Yandex OAuth token endpoint with grant_type=refresh_token.
func (r *Request) RefreshToken(ctx context.Context, refreshToken string) (*OAuthToken, error) { func (r *Request) RefreshToken(ctx context.Context, refreshToken string) (*OAuthToken, error) {
data := url.Values{} data := url.Values{}
data.Set("grant_type", "refresh_token") data.Set("grant_type", "refresh_token")
+5 -5
View File
@@ -1,3 +1,4 @@
// Package client provides methods for interacting with Yandex Music API endpoints.
package client package client
import ( import (
@@ -7,7 +8,7 @@ import (
"gitea.mrixs.me/Mrixs/yandex-music-api-go/internal/models" "gitea.mrixs.me/Mrixs/yandex-music-api-go/internal/models"
) )
// GetClips gets clips // GetClips gets clips with pagination (GET /clips).
func (c *Client) GetClips(ctx context.Context, page, pageSize int) ([]*models.Clip, error) { func (c *Client) GetClips(ctx context.Context, page, pageSize int) ([]*models.Clip, error) {
params := map[string]string{ params := map[string]string{
"page": "1", "page": "1",
@@ -33,7 +34,7 @@ func (c *Client) GetClips(ctx context.Context, page, pageSize int) ([]*models.Cl
return clips, nil return clips, nil
} }
// GetClipsWillLike gets clips the user might like // GetClipsWillLike gets clips the user might like (GET /clips/will/like).
func (c *Client) GetClipsWillLike(ctx context.Context) (*models.ClipsWillLike, error) { func (c *Client) GetClipsWillLike(ctx context.Context) (*models.ClipsWillLike, error) {
var result models.ClipsWillLike var result models.ClipsWillLike
if err := c.request.Get(ctx, "/clips/will/like", nil, &result); err != nil { if err := c.request.Get(ctx, "/clips/will/like", nil, &result); err != nil {
@@ -42,8 +43,7 @@ func (c *Client) GetClipsWillLike(ctx context.Context) (*models.ClipsWillLike, e
return &result, nil return &result, nil
} }
// GetArtistClips gets clips by an artist // GetArtistClips gets clips by an artist (GET /artists/{artistID}/blocks/artist-clips).
// GET /artists/{artistID}/blocks/artist-clips
func (c *Client) GetArtistClips(ctx context.Context, artistID string) (*models.ArtistClipData, error) { func (c *Client) GetArtistClips(ctx context.Context, artistID string) (*models.ArtistClipData, error) {
var result models.ArtistClipData var result models.ArtistClipData
if err := c.request.Get(ctx, fmt.Sprintf("/artists/%s/blocks/artist-clips", artistID), nil, &result); err != nil { if err := c.request.Get(ctx, fmt.Sprintf("/artists/%s/blocks/artist-clips", artistID), nil, &result); err != nil {
@@ -52,7 +52,7 @@ func (c *Client) GetArtistClips(ctx context.Context, artistID string) (*models.A
return &result, nil return &result, nil
} }
// GetShots gets shots // GetShots gets shots with pagination (GET /shots).
func (c *Client) GetShots(ctx context.Context, page, pageSize int) ([]*models.Shot, error) { func (c *Client) GetShots(ctx context.Context, page, pageSize int) ([]*models.Shot, error) {
params := map[string]string{ params := map[string]string{
"page": "1", "page": "1",
+6 -7
View File
@@ -1,3 +1,4 @@
// Package client provides methods for interacting with Yandex Music API endpoints.
package client package client
import ( import (
@@ -7,7 +8,7 @@ import (
"gitea.mrixs.me/Mrixs/yandex-music-api-go/internal/models" "gitea.mrixs.me/Mrixs/yandex-music-api-go/internal/models"
) )
// GetConcerts gets concerts // GetConcerts gets concerts with pagination (GET /concerts).
func (c *Client) GetConcerts(ctx context.Context, page, pageSize int) (*models.ConcertFeed, error) { func (c *Client) GetConcerts(ctx context.Context, page, pageSize int) (*models.ConcertFeed, error) {
params := map[string]string{ params := map[string]string{
"page": "1", "page": "1",
@@ -27,7 +28,7 @@ func (c *Client) GetConcerts(ctx context.Context, page, pageSize int) (*models.C
return &result, nil return &result, nil
} }
// GetConcertFeed gets concert feed // GetConcertFeed gets the concert feed (GET /concerts/feed).
func (c *Client) GetConcertFeed(ctx context.Context) (*models.ConcertFeed, error) { func (c *Client) GetConcertFeed(ctx context.Context) (*models.ConcertFeed, error) {
var result models.ConcertFeed var result models.ConcertFeed
if err := c.request.Get(ctx, "/concerts/feed", nil, &result); err != nil { if err := c.request.Get(ctx, "/concerts/feed", nil, &result); err != nil {
@@ -36,8 +37,7 @@ func (c *Client) GetConcertFeed(ctx context.Context) (*models.ConcertFeed, error
return &result, nil return &result, nil
} }
// GetConcertInfo gets concert info // GetConcertInfo gets concert info by ID (GET /concerts/{concertID}/info).
// GET /concerts/{concertID}/info
func (c *Client) GetConcertInfo(ctx context.Context, concertID string) (*models.ConcertInfo, error) { func (c *Client) GetConcertInfo(ctx context.Context, concertID string) (*models.ConcertInfo, error) {
var result models.ConcertInfo var result models.ConcertInfo
if err := c.request.Get(ctx, fmt.Sprintf("/concerts/%s/info", concertID), nil, &result); err != nil { if err := c.request.Get(ctx, fmt.Sprintf("/concerts/%s/info", concertID), nil, &result); err != nil {
@@ -46,7 +46,7 @@ func (c *Client) GetConcertInfo(ctx context.Context, concertID string) (*models.
return &result, nil return &result, nil
} }
// GetConcertLocations gets concert locations // GetConcertLocations gets concert locations (GET /concerts/locations).
func (c *Client) GetConcertLocations(ctx context.Context) (*models.ConcertLocations, error) { func (c *Client) GetConcertLocations(ctx context.Context) (*models.ConcertLocations, error) {
var result models.ConcertLocations var result models.ConcertLocations
if err := c.request.Get(ctx, "/concerts/locations", nil, &result); err != nil { if err := c.request.Get(ctx, "/concerts/locations", nil, &result); err != nil {
@@ -55,8 +55,7 @@ func (c *Client) GetConcertLocations(ctx context.Context) (*models.ConcertLocati
return &result, nil return &result, nil
} }
// GetConcertTabs gets concert tabs // GetConcertTabs gets concert tab configuration (GET /concerts/tab-config).
// GET /concerts/tab-config
func (c *Client) GetConcertTabs(ctx context.Context) (*models.ConcertTabConfig, error) { func (c *Client) GetConcertTabs(ctx context.Context) (*models.ConcertTabConfig, error) {
var result models.ConcertTabConfig var result models.ConcertTabConfig
if err := c.request.Get(ctx, "/concerts/tab-config", nil, &result); err != nil { if err := c.request.Get(ctx, "/concerts/tab-config", nil, &result); err != nil {
+9 -9
View File
@@ -1,3 +1,4 @@
// Package client provides methods for interacting with Yandex Music API endpoints.
package client package client
import ( import (
@@ -7,7 +8,7 @@ import (
"gitea.mrixs.me/Mrixs/yandex-music-api-go/internal/models" "gitea.mrixs.me/Mrixs/yandex-music-api-go/internal/models"
) )
// GetFeed gets the main feed // GetFeed gets the main feed (GET /feed).
func (c *Client) GetFeed(ctx context.Context) (*models.Feed, error) { func (c *Client) GetFeed(ctx context.Context) (*models.Feed, error) {
var result models.Feed var result models.Feed
if err := c.request.Get(ctx, "/feed", nil, &result); err != nil { if err := c.request.Get(ctx, "/feed", nil, &result); err != nil {
@@ -16,7 +17,7 @@ func (c *Client) GetFeed(ctx context.Context) (*models.Feed, error) {
return &result, nil return &result, nil
} }
// GetFeedBlocks gets feed blocks // GetFeedBlocks gets feed blocks (GET /feed/blocks).
func (c *Client) GetFeedBlocks(ctx context.Context) ([]*models.DayBlock, error) { func (c *Client) GetFeedBlocks(ctx context.Context) ([]*models.DayBlock, error) {
var result []models.DayBlock var result []models.DayBlock
if err := c.request.Get(ctx, "/feed/blocks", nil, &result); err != nil { if err := c.request.Get(ctx, "/feed/blocks", nil, &result); err != nil {
@@ -31,7 +32,7 @@ func (c *Client) GetFeedBlocks(ctx context.Context) ([]*models.DayBlock, error)
return blocks, nil return blocks, nil
} }
// GetFeedGeneratedPlaylist gets a generated playlist by ID from feed // GetFeedGeneratedPlaylist gets a generated playlist by ID from the feed (GET /feed/generated-playlist).
func (c *Client) GetFeedGeneratedPlaylist(ctx context.Context, playlistID string) (*models.GeneratedPlaylist, error) { func (c *Client) GetFeedGeneratedPlaylist(ctx context.Context, playlistID string) (*models.GeneratedPlaylist, error) {
params := map[string]string{ params := map[string]string{
"playlist_id": playlistID, "playlist_id": playlistID,
@@ -45,7 +46,7 @@ func (c *Client) GetFeedGeneratedPlaylist(ctx context.Context, playlistID string
return &result, nil return &result, nil
} }
// GetFeedDay gets a specific day from the feed // GetFeedDay gets a specific day from the feed by date (GET /feed/day).
func (c *Client) GetFeedDay(ctx context.Context, date string) (*models.Day, error) { func (c *Client) GetFeedDay(ctx context.Context, date string) (*models.Day, error) {
params := map[string]string{ params := map[string]string{
"date": date, "date": date,
@@ -58,7 +59,7 @@ func (c *Client) GetFeedDay(ctx context.Context, date string) (*models.Day, erro
return &result, nil return &result, nil
} }
// GetGeneratedPlaylists gets generated playlists // GetGeneratedPlaylists gets generated playlists (GET /generated-playlists).
func (c *Client) GetGeneratedPlaylists(ctx context.Context) ([]*models.GeneratedPlaylist, error) { func (c *Client) GetGeneratedPlaylists(ctx context.Context) ([]*models.GeneratedPlaylist, error) {
var result []models.GeneratedPlaylist var result []models.GeneratedPlaylist
if err := c.request.Get(ctx, "/generated-playlists", nil, &result); err != nil { if err := c.request.Get(ctx, "/generated-playlists", nil, &result); err != nil {
@@ -73,8 +74,7 @@ func (c *Client) GetGeneratedPlaylists(ctx context.Context) ([]*models.Generated
return playlists, nil return playlists, nil
} }
// GetLanding gets a landing page // GetLanding gets a landing page by ID (GET /landing3/{landingID}).
// GET /landing3/{landingID}
func (c *Client) GetLanding(ctx context.Context, landingID string) (*models.Landing, error) { func (c *Client) GetLanding(ctx context.Context, landingID string) (*models.Landing, error) {
params := map[string]string{ params := map[string]string{
"landing_id": landingID, "landing_id": landingID,
@@ -87,7 +87,7 @@ func (c *Client) GetLanding(ctx context.Context, landingID string) (*models.Land
return &result, nil return &result, nil
} }
// GetLandingList gets a list of landings // GetLandingList gets a list of landings (GET /landing3/list).
func (c *Client) GetLandingList(ctx context.Context) (*models.LandingList, error) { func (c *Client) GetLandingList(ctx context.Context) (*models.LandingList, error) {
var result models.LandingList var result models.LandingList
if err := c.request.Get(ctx, "/landing3/list", nil, &result); err != nil { if err := c.request.Get(ctx, "/landing3/list", nil, &result); err != nil {
@@ -96,7 +96,7 @@ func (c *Client) GetLandingList(ctx context.Context) (*models.LandingList, error
return &result, nil return &result, nil
} }
// GetLandingBlocks gets landing blocks by block IDs // GetLandingBlocks gets landing blocks by block IDs (GET /landing3/blocks).
func (c *Client) GetLandingBlocks(ctx context.Context, blockIDs []string) ([]*models.LandingBlock, error) { func (c *Client) GetLandingBlocks(ctx context.Context, blockIDs []string) ([]*models.LandingBlock, error) {
params := map[string]string{ params := map[string]string{
"blocks": joinStrings(blockIDs, ","), "blocks": joinStrings(blockIDs, ","),
+4 -3
View File
@@ -1,3 +1,4 @@
// Package client provides methods for interacting with Yandex Music API endpoints.
package client package client
import ( import (
@@ -7,7 +8,7 @@ import (
"gitea.mrixs.me/Mrixs/yandex-music-api-go/internal/models" "gitea.mrixs.me/Mrixs/yandex-music-api-go/internal/models"
) )
// GetMusicHistory gets music history // GetMusicHistory gets the user's music history (GET /music-history).
func (c *Client) GetMusicHistory(ctx context.Context) (*models.MusicHistory, error) { func (c *Client) GetMusicHistory(ctx context.Context) (*models.MusicHistory, error) {
var result models.MusicHistory var result models.MusicHistory
if err := c.request.Get(ctx, "/music-history", nil, &result); err != nil { if err := c.request.Get(ctx, "/music-history", nil, &result); err != nil {
@@ -16,7 +17,7 @@ func (c *Client) GetMusicHistory(ctx context.Context) (*models.MusicHistory, err
return &result, nil return &result, nil
} }
// GetMusicHistoryTabs gets music history tabs // GetMusicHistoryTabs gets music history tabs (GET /music-history/tabs).
func (c *Client) GetMusicHistoryTabs(ctx context.Context) ([]*models.MusicHistoryTab, error) { func (c *Client) GetMusicHistoryTabs(ctx context.Context) ([]*models.MusicHistoryTab, error) {
var result []models.MusicHistoryTab var result []models.MusicHistoryTab
if err := c.request.Get(ctx, "/music-history/tabs", nil, &result); err != nil { if err := c.request.Get(ctx, "/music-history/tabs", nil, &result); err != nil {
@@ -31,7 +32,7 @@ func (c *Client) GetMusicHistoryTabs(ctx context.Context) ([]*models.MusicHistor
return tabs, nil return tabs, nil
} }
// GetMusicHistoryItems gets music history items // GetMusicHistoryItems gets music history items for a tab (GET /music-history/items).
func (c *Client) GetMusicHistoryItems(ctx context.Context, tabID string, page, pageSize int) (*models.MusicHistoryItems, error) { func (c *Client) GetMusicHistoryItems(ctx context.Context, tabID string, page, pageSize int) (*models.MusicHistoryItems, error) {
params := map[string]string{} params := map[string]string{}
if tabID != "" { if tabID != "" {
+5 -7
View File
@@ -1,3 +1,4 @@
// Package client provides methods for interacting with Yandex Music API endpoints.
package client package client
import ( import (
@@ -7,7 +8,7 @@ import (
"gitea.mrixs.me/Mrixs/yandex-music-api-go/internal/models" "gitea.mrixs.me/Mrixs/yandex-music-api-go/internal/models"
) )
// GetLabels gets all labels // GetLabels gets all labels (GET /labels).
func (c *Client) GetLabels(ctx context.Context) ([]*models.Label, error) { func (c *Client) GetLabels(ctx context.Context) ([]*models.Label, error) {
var result []models.Label var result []models.Label
if err := c.request.Get(ctx, "/labels", nil, &result); err != nil { if err := c.request.Get(ctx, "/labels", nil, &result); err != nil {
@@ -22,8 +23,7 @@ func (c *Client) GetLabels(ctx context.Context) ([]*models.Label, error) {
return labels, nil return labels, nil
} }
// GetLabel gets a label by ID // GetLabel gets a label by ID (GET /labels/{labelID}).
// GET /labels/{labelID}
func (c *Client) GetLabel(ctx context.Context, labelID string) (*models.Label, error) { func (c *Client) GetLabel(ctx context.Context, labelID string) (*models.Label, error) {
var result models.Label var result models.Label
if err := c.request.Get(ctx, fmt.Sprintf("/labels/%s", labelID), nil, &result); err != nil { if err := c.request.Get(ctx, fmt.Sprintf("/labels/%s", labelID), nil, &result); err != nil {
@@ -33,8 +33,7 @@ func (c *Client) GetLabel(ctx context.Context, labelID string) (*models.Label, e
return &result, nil return &result, nil
} }
// GetLabelAlbums gets albums for a label // GetLabelAlbums gets albums for a label (GET /labels/{labelID}/albums).
// GET /labels/{labelID}/albums
func (c *Client) GetLabelAlbums(ctx context.Context, labelID string, page, pageSize int) (*models.LabelAlbums, error) { func (c *Client) GetLabelAlbums(ctx context.Context, labelID string, page, pageSize int) (*models.LabelAlbums, error) {
params := map[string]string{} params := map[string]string{}
if page > 0 { if page > 0 {
@@ -51,8 +50,7 @@ func (c *Client) GetLabelAlbums(ctx context.Context, labelID string, page, pageS
return &result, nil return &result, nil
} }
// GetLabelArtists gets artists for a label // GetLabelArtists gets artists for a label (GET /labels/{labelID}/artists).
// GET /labels/{labelID}/artists
func (c *Client) GetLabelArtists(ctx context.Context, labelID string, page, pageSize int) (*models.LabelArtists, error) { func (c *Client) GetLabelArtists(ctx context.Context, labelID string, page, pageSize int) (*models.LabelArtists, error) {
params := map[string]string{} params := map[string]string{}
if page > 0 { if page > 0 {
+13 -24
View File
@@ -1,3 +1,4 @@
// Package client provides methods for interacting with Yandex Music API endpoints.
package client package client
import ( import (
@@ -7,8 +8,7 @@ import (
"gitea.mrixs.me/Mrixs/yandex-music-api-go/internal/models" "gitea.mrixs.me/Mrixs/yandex-music-api-go/internal/models"
) )
// LikeTrack likes a track // LikeTrack likes a track (POST /users/me/likes/tracks/add-multiple).
// POST /users/me/likes/tracks/add-multiple
func (c *Client) LikeTrack(ctx context.Context, trackID string) error { func (c *Client) LikeTrack(ctx context.Context, trackID string) error {
params := map[string]string{ params := map[string]string{
"track-ids": trackID, "track-ids": trackID,
@@ -17,8 +17,7 @@ func (c *Client) LikeTrack(ctx context.Context, trackID string) error {
return c.request.Post(ctx, "/users/me/likes/tracks/add-multiple", params, &result) return c.request.Post(ctx, "/users/me/likes/tracks/add-multiple", params, &result)
} }
// UnlikeTrack unlikes a track // UnlikeTrack unlikes a track (POST /users/me/likes/tracks/remove).
// POST /users/me/likes/tracks/remove
func (c *Client) UnlikeTrack(ctx context.Context, trackID string) error { func (c *Client) UnlikeTrack(ctx context.Context, trackID string) error {
params := map[string]string{ params := map[string]string{
"track-ids": trackID, "track-ids": trackID,
@@ -27,8 +26,7 @@ func (c *Client) UnlikeTrack(ctx context.Context, trackID string) error {
return c.request.Post(ctx, "/users/me/likes/tracks/remove", params, &result) return c.request.Post(ctx, "/users/me/likes/tracks/remove", params, &result)
} }
// LikeAlbum likes an album // LikeAlbum likes an album (POST /users/me/likes/albums/add-multiple).
// POST /users/me/likes/albums/add-multiple
func (c *Client) LikeAlbum(ctx context.Context, albumID string) error { func (c *Client) LikeAlbum(ctx context.Context, albumID string) error {
params := map[string]string{ params := map[string]string{
"album-ids": albumID, "album-ids": albumID,
@@ -37,8 +35,7 @@ func (c *Client) LikeAlbum(ctx context.Context, albumID string) error {
return c.request.Post(ctx, "/users/me/likes/albums/add-multiple", params, &result) return c.request.Post(ctx, "/users/me/likes/albums/add-multiple", params, &result)
} }
// UnlikeAlbum unlikes an album // UnlikeAlbum unlikes an album (POST /users/me/likes/albums/remove).
// POST /users/me/likes/albums/remove
func (c *Client) UnlikeAlbum(ctx context.Context, albumID string) error { func (c *Client) UnlikeAlbum(ctx context.Context, albumID string) error {
params := map[string]string{ params := map[string]string{
"album-ids": albumID, "album-ids": albumID,
@@ -47,8 +44,7 @@ func (c *Client) UnlikeAlbum(ctx context.Context, albumID string) error {
return c.request.Post(ctx, "/users/me/likes/albums/remove", params, &result) return c.request.Post(ctx, "/users/me/likes/albums/remove", params, &result)
} }
// LikeArtist likes an artist // LikeArtist likes an artist (POST /users/me/likes/artists/add-multiple).
// POST /users/me/likes/artists/add-multiple
func (c *Client) LikeArtist(ctx context.Context, artistID string) error { func (c *Client) LikeArtist(ctx context.Context, artistID string) error {
params := map[string]string{ params := map[string]string{
"artist-ids": artistID, "artist-ids": artistID,
@@ -57,8 +53,7 @@ func (c *Client) LikeArtist(ctx context.Context, artistID string) error {
return c.request.Post(ctx, "/users/me/likes/artists/add-multiple", params, &result) return c.request.Post(ctx, "/users/me/likes/artists/add-multiple", params, &result)
} }
// UnlikeArtist unlikes an artist // UnlikeArtist unlikes an artist (POST /users/me/likes/artists/remove).
// POST /users/me/likes/artists/remove
func (c *Client) UnlikeArtist(ctx context.Context, artistID string) error { func (c *Client) UnlikeArtist(ctx context.Context, artistID string) error {
params := map[string]string{ params := map[string]string{
"artist-ids": artistID, "artist-ids": artistID,
@@ -67,8 +62,7 @@ func (c *Client) UnlikeArtist(ctx context.Context, artistID string) error {
return c.request.Post(ctx, "/users/me/likes/artists/remove", params, &result) return c.request.Post(ctx, "/users/me/likes/artists/remove", params, &result)
} }
// LikePlaylist likes a playlist // LikePlaylist likes a playlist (POST /users/me/likes/playlists/add-multiple).
// POST /users/me/likes/playlists/add-multiple
func (c *Client) LikePlaylist(ctx context.Context, kind int) error { func (c *Client) LikePlaylist(ctx context.Context, kind int) error {
params := map[string]string{ params := map[string]string{
"playlist-ids": fmt.Sprintf("%d", kind), "playlist-ids": fmt.Sprintf("%d", kind),
@@ -77,8 +71,7 @@ func (c *Client) LikePlaylist(ctx context.Context, kind int) error {
return c.request.Post(ctx, "/users/me/likes/playlists/add-multiple", params, &result) return c.request.Post(ctx, "/users/me/likes/playlists/add-multiple", params, &result)
} }
// UnlikePlaylist unlikes a playlist // UnlikePlaylist unlikes a playlist (POST /users/me/likes/playlists/remove).
// POST /users/me/likes/playlists/remove
func (c *Client) UnlikePlaylist(ctx context.Context, kind int) error { func (c *Client) UnlikePlaylist(ctx context.Context, kind int) error {
params := map[string]string{ params := map[string]string{
"playlist-ids": fmt.Sprintf("%d", kind), "playlist-ids": fmt.Sprintf("%d", kind),
@@ -87,8 +80,7 @@ func (c *Client) UnlikePlaylist(ctx context.Context, kind int) error {
return c.request.Post(ctx, "/users/me/likes/playlists/remove", params, &result) return c.request.Post(ctx, "/users/me/likes/playlists/remove", params, &result)
} }
// GetLikedTracks gets user's liked tracks // GetLikedTracks gets the user's liked tracks (GET /users/me/likes/tracks).
// GET /users/me/likes/tracks
func (c *Client) GetLikedTracks(ctx context.Context) ([]*models.Track, error) { func (c *Client) GetLikedTracks(ctx context.Context) ([]*models.Track, error) {
var result []models.Track var result []models.Track
if err := c.request.Get(ctx, "/users/me/likes/tracks", nil, &result); err != nil { if err := c.request.Get(ctx, "/users/me/likes/tracks", nil, &result); err != nil {
@@ -103,8 +95,7 @@ func (c *Client) GetLikedTracks(ctx context.Context) ([]*models.Track, error) {
return tracks, nil return tracks, nil
} }
// GetLikedAlbums gets user's liked albums // GetLikedAlbums gets the user's liked albums (GET /users/me/likes/albums).
// GET /users/me/likes/albums
func (c *Client) GetLikedAlbums(ctx context.Context) ([]*models.Album, error) { func (c *Client) GetLikedAlbums(ctx context.Context) ([]*models.Album, error) {
var result []models.Album var result []models.Album
if err := c.request.Get(ctx, "/users/me/likes/albums", nil, &result); err != nil { if err := c.request.Get(ctx, "/users/me/likes/albums", nil, &result); err != nil {
@@ -119,8 +110,7 @@ func (c *Client) GetLikedAlbums(ctx context.Context) ([]*models.Album, error) {
return albums, nil return albums, nil
} }
// GetLikedArtists gets user's liked artists // GetLikedArtists gets the user's liked artists (GET /users/me/likes/artists).
// GET /users/me/likes/artists
func (c *Client) GetLikedArtists(ctx context.Context) ([]*models.Artist, error) { func (c *Client) GetLikedArtists(ctx context.Context) ([]*models.Artist, error) {
var result []models.Artist var result []models.Artist
if err := c.request.Get(ctx, "/users/me/likes/artists", nil, &result); err != nil { if err := c.request.Get(ctx, "/users/me/likes/artists", nil, &result); err != nil {
@@ -135,8 +125,7 @@ func (c *Client) GetLikedArtists(ctx context.Context) ([]*models.Artist, error)
return artists, nil return artists, nil
} }
// GetLikedPlaylists gets user's liked playlists // GetLikedPlaylists gets the user's liked playlists (GET /users/me/likes/playlists).
// GET /users/me/likes/playlists
func (c *Client) GetLikedPlaylists(ctx context.Context) ([]*models.Playlist, error) { func (c *Client) GetLikedPlaylists(ctx context.Context) ([]*models.Playlist, error) {
var result []models.Playlist var result []models.Playlist
if err := c.request.Get(ctx, "/users/me/likes/playlists", nil, &result); err != nil { if err := c.request.Get(ctx, "/users/me/likes/playlists", nil, &result); err != nil {
+11 -10
View File
@@ -1,3 +1,4 @@
// Package client provides methods for interacting with Yandex Music API endpoints.
package client package client
import ( import (
@@ -7,7 +8,7 @@ import (
"gitea.mrixs.me/Mrixs/yandex-music-api-go/internal/models" "gitea.mrixs.me/Mrixs/yandex-music-api-go/internal/models"
) )
// GetMetatags gets all metatags // GetMetatags gets all metatags (GET /metatags).
func (c *Client) GetMetatags(ctx context.Context) ([]*models.Metatag, error) { func (c *Client) GetMetatags(ctx context.Context) ([]*models.Metatag, error) {
var result []models.Metatag var result []models.Metatag
if err := c.request.Get(ctx, "/metatags", nil, &result); err != nil { if err := c.request.Get(ctx, "/metatags", nil, &result); err != nil {
@@ -22,7 +23,7 @@ func (c *Client) GetMetatags(ctx context.Context) ([]*models.Metatag, error) {
return metatags, nil return metatags, nil
} }
// GetMetatagTree gets metatag tree // GetMetatagTree gets the metatag tree (GET /metatags/tree).
func (c *Client) GetMetatagTree(ctx context.Context) (*models.MetatagTree, error) { func (c *Client) GetMetatagTree(ctx context.Context) (*models.MetatagTree, error) {
var result models.MetatagTree var result models.MetatagTree
if err := c.request.Get(ctx, "/metatags/tree", nil, &result); err != nil { if err := c.request.Get(ctx, "/metatags/tree", nil, &result); err != nil {
@@ -31,7 +32,7 @@ func (c *Client) GetMetatagTree(ctx context.Context) (*models.MetatagTree, error
return &result, nil return &result, nil
} }
// GetMetatagArtists gets artists for a metatag // GetMetatagArtists gets artists for a metatag (GET /metatags/artists).
func (c *Client) GetMetatagArtists(ctx context.Context, metatagID string, page, pageSize int) (*models.MetatagArtists, error) { func (c *Client) GetMetatagArtists(ctx context.Context, metatagID string, page, pageSize int) (*models.MetatagArtists, error) {
params := map[string]string{ params := map[string]string{
"metatag_id": metatagID, "metatag_id": metatagID,
@@ -50,7 +51,7 @@ func (c *Client) GetMetatagArtists(ctx context.Context, metatagID string, page,
return &result, nil return &result, nil
} }
// GetMetatagAlbums gets albums for a metatag // GetMetatagAlbums gets albums for a metatag (GET /metatags/albums).
func (c *Client) GetMetatagAlbums(ctx context.Context, metatagID string, page, pageSize int) (*models.MetatagAlbums, error) { func (c *Client) GetMetatagAlbums(ctx context.Context, metatagID string, page, pageSize int) (*models.MetatagAlbums, error) {
params := map[string]string{ params := map[string]string{
"metatag_id": metatagID, "metatag_id": metatagID,
@@ -69,7 +70,7 @@ func (c *Client) GetMetatagAlbums(ctx context.Context, metatagID string, page, p
return &result, nil return &result, nil
} }
// GetMetatagPlaylists gets playlists for a metatag // GetMetatagPlaylists gets playlists for a metatag (GET /metatags/playlists).
func (c *Client) GetMetatagPlaylists(ctx context.Context, metatagID string, page, pageSize int) (*models.MetatagPlaylists, error) { func (c *Client) GetMetatagPlaylists(ctx context.Context, metatagID string, page, pageSize int) (*models.MetatagPlaylists, error) {
params := map[string]string{ params := map[string]string{
"metatag_id": metatagID, "metatag_id": metatagID,
@@ -88,7 +89,7 @@ func (c *Client) GetMetatagPlaylists(ctx context.Context, metatagID string, page
return &result, nil return &result, nil
} }
// GetGenres gets all genres // GetGenres gets all genres (GET /genres).
func (c *Client) GetGenres(ctx context.Context) ([]*models.Genre, error) { func (c *Client) GetGenres(ctx context.Context) ([]*models.Genre, error) {
var result []models.Genre var result []models.Genre
if err := c.request.Get(ctx, "/genres", nil, &result); err != nil { if err := c.request.Get(ctx, "/genres", nil, &result); err != nil {
@@ -103,7 +104,7 @@ func (c *Client) GetGenres(ctx context.Context) ([]*models.Genre, error) {
return genres, nil return genres, nil
} }
// GetCharts gets charts // GetCharts gets all charts (GET /charts).
func (c *Client) GetCharts(ctx context.Context) ([]*models.Chart, error) { func (c *Client) GetCharts(ctx context.Context) ([]*models.Chart, error) {
var result []models.Chart var result []models.Chart
if err := c.request.Get(ctx, "/charts", nil, &result); err != nil { if err := c.request.Get(ctx, "/charts", nil, &result); err != nil {
@@ -118,7 +119,7 @@ func (c *Client) GetCharts(ctx context.Context) ([]*models.Chart, error) {
return charts, nil return charts, nil
} }
// GetChartInfo gets chart info // GetChartInfo gets chart info for a chart ID (GET /charts/info).
func (c *Client) GetChartInfo(ctx context.Context, chartID string) (*models.ChartInfo, error) { func (c *Client) GetChartInfo(ctx context.Context, chartID string) (*models.ChartInfo, error) {
params := map[string]string{ params := map[string]string{
"chart_id": chartID, "chart_id": chartID,
@@ -131,7 +132,7 @@ func (c *Client) GetChartInfo(ctx context.Context, chartID string) (*models.Char
return &result, nil return &result, nil
} }
// GetChartItems gets chart items // GetChartItems gets chart items for a chart ID (GET /charts/items).
func (c *Client) GetChartItems(ctx context.Context, chartID string, page, pageSize int) (*models.ChartItems, error) { func (c *Client) GetChartItems(ctx context.Context, chartID string, page, pageSize int) (*models.ChartItems, error) {
params := map[string]string{ params := map[string]string{
"chart_id": chartID, "chart_id": chartID,
@@ -150,7 +151,7 @@ func (c *Client) GetChartItems(ctx context.Context, chartID string, page, pageSi
return &result, nil return &result, nil
} }
// GetChartMenu gets chart menu // GetChartMenu gets chart menu for a chart ID (GET /charts/menu).
func (c *Client) GetChartMenu(ctx context.Context, chartID string) (*models.ChartInfoMenu, error) { func (c *Client) GetChartMenu(ctx context.Context, chartID string) (*models.ChartInfoMenu, error) {
params := map[string]string{ params := map[string]string{
"chart_id": chartID, "chart_id": chartID,
+5 -4
View File
@@ -1,3 +1,4 @@
// Package client provides methods for interacting with Yandex Music API endpoints.
package client package client
import ( import (
@@ -6,7 +7,7 @@ import (
"gitea.mrixs.me/Mrixs/yandex-music-api-go/internal/models" "gitea.mrixs.me/Mrixs/yandex-music-api-go/internal/models"
) )
// GetPins gets user's pins // GetPins gets user's pins (GET /pins).
func (c *Client) GetPins(ctx context.Context) (*models.PinsList, error) { func (c *Client) GetPins(ctx context.Context) (*models.PinsList, error) {
var result models.PinsList var result models.PinsList
if err := c.request.Get(ctx, "/pins", nil, &result); err != nil { if err := c.request.Get(ctx, "/pins", nil, &result); err != nil {
@@ -15,7 +16,7 @@ func (c *Client) GetPins(ctx context.Context) (*models.PinsList, error) {
return &result, nil return &result, nil
} }
// AddPin adds a pin // AddPin adds a pin (POST /pins).
func (c *Client) AddPin(ctx context.Context, pinType, entityID string) (*models.Pin, error) { func (c *Client) AddPin(ctx context.Context, pinType, entityID string) (*models.Pin, error) {
params := map[string]string{ params := map[string]string{
"type": pinType, "type": pinType,
@@ -29,7 +30,7 @@ func (c *Client) AddPin(ctx context.Context, pinType, entityID string) (*models.
return &result, nil return &result, nil
} }
// RemovePin removes a pin // RemovePin removes a pin by ID (DELETE /pins).
func (c *Client) RemovePin(ctx context.Context, pinID string) error { func (c *Client) RemovePin(ctx context.Context, pinID string) error {
params := map[string]string{ params := map[string]string{
"pin_id": pinID, "pin_id": pinID,
@@ -38,7 +39,7 @@ func (c *Client) RemovePin(ctx context.Context, pinID string) error {
return c.request.Delete(ctx, "/pins", params, &result) return c.request.Delete(ctx, "/pins", params, &result)
} }
// GetPresaves gets user's presaves // GetPresaves gets user's presaves (GET /presaves).
func (c *Client) GetPresaves(ctx context.Context) (*models.Presaves, error) { func (c *Client) GetPresaves(ctx context.Context) (*models.Presaves, error) {
var result models.Presaves var result models.Presaves
if err := c.request.Get(ctx, "/presaves", nil, &result); err != nil { if err := c.request.Get(ctx, "/presaves", nil, &result); err != nil {
+18 -11
View File
@@ -1,3 +1,4 @@
// Package client provides methods for interacting with Yandex Music API endpoints.
package client package client
import ( import (
@@ -8,7 +9,8 @@ import (
"gitea.mrixs.me/Mrixs/yandex-music-api-go/internal/utils" "gitea.mrixs.me/Mrixs/yandex-music-api-go/internal/utils"
) )
// GetPlaylists gets playlists by IDs (kinds) // GetPlaylists gets playlists by their kind IDs (GET /playlists).
// Returns a slice of Playlist pointers, or nil if no kinds are provided.
func (c *Client) GetPlaylists(ctx context.Context, kinds []int) ([]*models.Playlist, error) { func (c *Client) GetPlaylists(ctx context.Context, kinds []int) ([]*models.Playlist, error) {
if len(kinds) == 0 { if len(kinds) == 0 {
return nil, nil return nil, nil
@@ -40,7 +42,8 @@ func (c *Client) GetPlaylists(ctx context.Context, kinds []int) ([]*models.Playl
return playlists, nil return playlists, nil
} }
// GetPlaylist gets a single playlist by kind // GetPlaylist gets a single playlist by kind using GetPlaylists.
// Returns an error if no playlist is found with the given kind.
func (c *Client) GetPlaylist(ctx context.Context, kind int) (*models.Playlist, error) { func (c *Client) GetPlaylist(ctx context.Context, kind int) (*models.Playlist, error) {
playlists, err := c.GetPlaylists(ctx, []int{kind}) playlists, err := c.GetPlaylists(ctx, []int{kind})
if err != nil { if err != nil {
@@ -52,8 +55,7 @@ func (c *Client) GetPlaylist(ctx context.Context, kind int) (*models.Playlist, e
return playlists[0], nil return playlists[0], nil
} }
// GetUserPlaylists gets playlists for a user // GetUserPlaylists gets playlists for a user (GET /users/{userID}/playlists).
// GET /users/{userID}/playlists
func (c *Client) GetUserPlaylists(ctx context.Context, userID string) ([]*models.Playlist, error) { func (c *Client) GetUserPlaylists(ctx context.Context, userID string) ([]*models.Playlist, error) {
var result []models.Playlist var result []models.Playlist
if err := c.request.Get(ctx, fmt.Sprintf("/users/%s/playlists", userID), nil, &result); err != nil { if err := c.request.Get(ctx, fmt.Sprintf("/users/%s/playlists", userID), nil, &result); err != nil {
@@ -68,7 +70,8 @@ func (c *Client) GetUserPlaylists(ctx context.Context, userID string) ([]*models
return playlists, nil return playlists, nil
} }
// CreatePlaylist creates a new playlist // CreatePlaylist creates a new playlist (POST /users/me/playlists).
// The visibility parameter should be "public" or "private".
func (c *Client) CreatePlaylist(ctx context.Context, title string, visibility string) (*models.Playlist, error) { func (c *Client) CreatePlaylist(ctx context.Context, title string, visibility string) (*models.Playlist, error) {
params := map[string]string{ params := map[string]string{
"title": title, "title": title,
@@ -83,7 +86,8 @@ func (c *Client) CreatePlaylist(ctx context.Context, title string, visibility st
return &result, nil return &result, nil
} }
// EditPlaylist edits an existing playlist // EditPlaylist edits an existing playlist (PUT /users/me/playlists).
// Only non-empty parameters are updated.
func (c *Client) EditPlaylist(ctx context.Context, kind int, title, description, visibility string) (*models.Playlist, error) { func (c *Client) EditPlaylist(ctx context.Context, kind int, title, description, visibility string) (*models.Playlist, error) {
params := map[string]string{ params := map[string]string{
"kind": fmt.Sprintf("%d", kind), "kind": fmt.Sprintf("%d", kind),
@@ -106,7 +110,7 @@ func (c *Client) EditPlaylist(ctx context.Context, kind int, title, description,
return &result, nil return &result, nil
} }
// DeletePlaylist deletes a playlist // DeletePlaylist deletes a playlist (DELETE /users/me/playlists).
func (c *Client) DeletePlaylist(ctx context.Context, kind int) error { func (c *Client) DeletePlaylist(ctx context.Context, kind int) error {
params := map[string]string{ params := map[string]string{
"kind": fmt.Sprintf("%d", kind), "kind": fmt.Sprintf("%d", kind),
@@ -115,7 +119,8 @@ func (c *Client) DeletePlaylist(ctx context.Context, kind int) error {
return c.request.Delete(ctx, "/users/me/playlists", params, &result) return c.request.Delete(ctx, "/users/me/playlists", params, &result)
} }
// AddTracksToPlaylist adds tracks to a playlist // AddTracksToPlaylist adds tracks to a playlist (POST /users/me/playlists/tracks).
// The revision parameter is the current playlist revision for optimistic concurrency.
func (c *Client) AddTracksToPlaylist(ctx context.Context, kind int, trackIDs []string, revision int) (*models.Playlist, error) { func (c *Client) AddTracksToPlaylist(ctx context.Context, kind int, trackIDs []string, revision int) (*models.Playlist, error) {
if len(trackIDs) == 0 { if len(trackIDs) == 0 {
return nil, utils.NewYandexMusicError("no tracks provided", utils.ErrBadRequest) return nil, utils.NewYandexMusicError("no tracks provided", utils.ErrBadRequest)
@@ -143,7 +148,8 @@ func (c *Client) AddTracksToPlaylist(ctx context.Context, kind int, trackIDs []s
return &result, nil return &result, nil
} }
// RemoveTracksFromPlaylist removes tracks from a playlist // RemoveTracksFromPlaylist removes tracks from a playlist (DELETE /users/me/playlists/tracks).
// The revision parameter is the current playlist revision for optimistic concurrency.
func (c *Client) RemoveTracksFromPlaylist(ctx context.Context, kind int, trackIDs []string, revision int) (*models.Playlist, error) { func (c *Client) RemoveTracksFromPlaylist(ctx context.Context, kind int, trackIDs []string, revision int) (*models.Playlist, error) {
if len(trackIDs) == 0 { if len(trackIDs) == 0 {
return nil, utils.NewYandexMusicError("no tracks provided", utils.ErrBadRequest) return nil, utils.NewYandexMusicError("no tracks provided", utils.ErrBadRequest)
@@ -171,7 +177,8 @@ func (c *Client) RemoveTracksFromPlaylist(ctx context.Context, kind int, trackID
return &result, nil return &result, nil
} }
// ReorderPlaylistTracks reorders tracks in a playlist // ReorderPlaylistTracks reorders tracks in a playlist (PUT /users/me/playlists/tracks/reorder).
// The from and to parameters specify the position range to move.
func (c *Client) ReorderPlaylistTracks(ctx context.Context, kind int, from, to, revision int) (*models.Playlist, error) { func (c *Client) ReorderPlaylistTracks(ctx context.Context, kind int, from, to, revision int) (*models.Playlist, error) {
params := map[string]string{ params := map[string]string{
"kind": fmt.Sprintf("%d", kind), "kind": fmt.Sprintf("%d", kind),
@@ -188,7 +195,7 @@ func (c *Client) ReorderPlaylistTracks(ctx context.Context, kind int, from, to,
return &result, nil return &result, nil
} }
// GetPlaylistRecommendations gets playlist recommendations // GetPlaylistRecommendations gets playlist recommendations based on a playlist kind (GET /playlists/recommendations).
func (c *Client) GetPlaylistRecommendations(ctx context.Context, kind int) ([]*models.Playlist, error) { func (c *Client) GetPlaylistRecommendations(ctx context.Context, kind int) ([]*models.Playlist, error) {
params := map[string]string{ params := map[string]string{
"kind": fmt.Sprintf("%d", kind), "kind": fmt.Sprintf("%d", kind),
+20 -30
View File
@@ -17,7 +17,8 @@ func (c *Client) GetQueue(ctx context.Context) (*models.Queue, error) {
return &result, nil return &result, nil
} }
// CreateQueue creates a new queue // CreateQueue creates a new playback queue (POST /queues).
// The queueType parameter specifies the type of queue (e.g., "radio", "album", "playlist").
func (c *Client) CreateQueue(ctx context.Context, trackID string, queueType string) (*models.Queue, error) { func (c *Client) CreateQueue(ctx context.Context, trackID string, queueType string) (*models.Queue, error) {
params := map[string]string{ params := map[string]string{
"track_id": trackID, "track_id": trackID,
@@ -32,8 +33,7 @@ func (c *Client) CreateQueue(ctx context.Context, trackID string, queueType stri
return &result, nil return &result, nil
} }
// GetQueueItem gets a queue item // GetQueueItem gets a queue item by queue ID (GET /queues/{queue_id}).
// GET /queues/{queue_id}
func (c *Client) GetQueueItem(ctx context.Context, queueID string) (*models.QueueItem, error) { func (c *Client) GetQueueItem(ctx context.Context, queueID string) (*models.QueueItem, error) {
var result models.QueueItem var result models.QueueItem
if err := c.request.Get(ctx, fmt.Sprintf("/queues/%s", queueID), nil, &result); err != nil { if err := c.request.Get(ctx, fmt.Sprintf("/queues/%s", queueID), nil, &result); err != nil {
@@ -43,8 +43,7 @@ func (c *Client) GetQueueItem(ctx context.Context, queueID string) (*models.Queu
return &result, nil return &result, nil
} }
// AddToQueue adds a track to the queue // AddToQueue adds a track to the queue at the given position (POST /queues/{queue_id}/add).
// POST /queues/{queue_id}/add
func (c *Client) AddToQueue(ctx context.Context, queueID, trackID string, position int) (*models.Queue, error) { func (c *Client) AddToQueue(ctx context.Context, queueID, trackID string, position int) (*models.Queue, error) {
params := map[string]string{ params := map[string]string{
"track_id": trackID, "track_id": trackID,
@@ -59,8 +58,7 @@ func (c *Client) AddToQueue(ctx context.Context, queueID, trackID string, positi
return &result, nil return &result, nil
} }
// RemoveFromQueue removes a track from the queue // RemoveFromQueue removes a track from the queue (DELETE /queues/{queue_id}/remove).
// DELETE /queues/{queue_id}/remove
func (c *Client) RemoveFromQueue(ctx context.Context, queueID, trackID string) (*models.Queue, error) { func (c *Client) RemoveFromQueue(ctx context.Context, queueID, trackID string) (*models.Queue, error) {
params := map[string]string{ params := map[string]string{
"track_id": trackID, "track_id": trackID,
@@ -74,8 +72,7 @@ func (c *Client) RemoveFromQueue(ctx context.Context, queueID, trackID string) (
return &result, nil return &result, nil
} }
// ReorderQueue reorders the queue // ReorderQueue reorders items in the queue from one position to another (PUT /queues/{queue_id}/reorder).
// PUT /queues/{queue_id}/reorder
func (c *Client) ReorderQueue(ctx context.Context, queueID string, from, to int) (*models.Queue, error) { func (c *Client) ReorderQueue(ctx context.Context, queueID string, from, to int) (*models.Queue, error) {
params := map[string]string{ params := map[string]string{
"from": fmt.Sprintf("%d", from), "from": fmt.Sprintf("%d", from),
@@ -90,15 +87,13 @@ func (c *Client) ReorderQueue(ctx context.Context, queueID string, from, to int)
return &result, nil return &result, nil
} }
// ClearQueue clears the queue // ClearQueue clears the queue (DELETE /queues/{queue_id}/clear).
// DELETE /queues/{queue_id}/clear
func (c *Client) ClearQueue(ctx context.Context, queueID string) error { func (c *Client) ClearQueue(ctx context.Context, queueID string) error {
var result map[string]any var result map[string]any
return c.request.Delete(ctx, fmt.Sprintf("/queues/%s/clear", queueID), nil, &result) return c.request.Delete(ctx, fmt.Sprintf("/queues/%s/clear", queueID), nil, &result)
} }
// NextTrack moves to the next track in the queue // NextTrack moves to the next track in the queue (POST /queues/{queue_id}/next).
// POST /queues/{queue_id}/next
func (c *Client) NextTrack(ctx context.Context, queueID string) (*models.Queue, error) { func (c *Client) NextTrack(ctx context.Context, queueID string) (*models.Queue, error) {
var result models.Queue var result models.Queue
if err := c.request.Post(ctx, fmt.Sprintf("/queues/%s/next", queueID), nil, &result); err != nil { if err := c.request.Post(ctx, fmt.Sprintf("/queues/%s/next", queueID), nil, &result); err != nil {
@@ -108,8 +103,7 @@ func (c *Client) NextTrack(ctx context.Context, queueID string) (*models.Queue,
return &result, nil return &result, nil
} }
// PreviousTrack moves to the previous track in the queue // PreviousTrack moves to the previous track in the queue (POST /queues/{queue_id}/prev).
// POST /queues/{queue_id}/prev
func (c *Client) PreviousTrack(ctx context.Context, queueID string) (*models.Queue, error) { func (c *Client) PreviousTrack(ctx context.Context, queueID string) (*models.Queue, error) {
var result models.Queue var result models.Queue
if err := c.request.Post(ctx, fmt.Sprintf("/queues/%s/prev", queueID), nil, &result); err != nil { if err := c.request.Post(ctx, fmt.Sprintf("/queues/%s/prev", queueID), nil, &result); err != nil {
@@ -119,8 +113,8 @@ func (c *Client) PreviousTrack(ctx context.Context, queueID string) (*models.Que
return &result, nil return &result, nil
} }
// Seek seeks to a specific position in the current track (in milliseconds) // Seek seeks to a specific position in the current track (POST /queues/{queue_id}/seek).
// POST /queues/{queue_id}/seek // The positionMs parameter is the position in milliseconds.
func (c *Client) Seek(ctx context.Context, queueID string, positionMs int) (*models.Queue, error) { func (c *Client) Seek(ctx context.Context, queueID string, positionMs int) (*models.Queue, error) {
params := map[string]string{ params := map[string]string{
"position": fmt.Sprintf("%d", positionMs), "position": fmt.Sprintf("%d", positionMs),
@@ -134,9 +128,8 @@ func (c *Client) Seek(ctx context.Context, queueID string, positionMs int) (*mod
return &result, nil return &result, nil
} }
// SetRepeatMode sets the repeat mode for the queue // SetRepeatMode sets the repeat mode for the queue (POST /queues/{queue_id}/repeat).
// mode can be "off", "one", or "all" // The mode parameter can be "off", "one", or "all".
// POST /queues/{queue_id}/repeat
func (c *Client) SetRepeatMode(ctx context.Context, queueID, mode string) (*models.Queue, error) { func (c *Client) SetRepeatMode(ctx context.Context, queueID, mode string) (*models.Queue, error) {
params := map[string]string{ params := map[string]string{
"mode": mode, "mode": mode,
@@ -150,8 +143,7 @@ func (c *Client) SetRepeatMode(ctx context.Context, queueID, mode string) (*mode
return &result, nil return &result, nil
} }
// SetShuffle enables or disables shuffle for the queue // SetShuffle enables or disables shuffle for the queue (POST /queues/{queue_id}/shuffle).
// POST /queues/{queue_id}/shuffle
func (c *Client) SetShuffle(ctx context.Context, queueID string, enabled bool) (*models.Queue, error) { func (c *Client) SetShuffle(ctx context.Context, queueID string, enabled bool) (*models.Queue, error) {
params := map[string]string{ params := map[string]string{
"enabled": fmt.Sprintf("%t", enabled), "enabled": fmt.Sprintf("%t", enabled),
@@ -165,8 +157,8 @@ func (c *Client) SetShuffle(ctx context.Context, queueID string, enabled bool) (
return &result, nil return &result, nil
} }
// SetVolume sets the volume for the queue (0-100) // SetVolume sets the volume for the queue (POST /queues/{queue_id}/volume).
// POST /queues/{queue_id}/volume // The volume parameter should be between 0 and 100.
func (c *Client) SetVolume(ctx context.Context, queueID string, volume int) (*models.Queue, error) { func (c *Client) SetVolume(ctx context.Context, queueID string, volume int) (*models.Queue, error) {
params := map[string]string{ params := map[string]string{
"volume": fmt.Sprintf("%d", volume), "volume": fmt.Sprintf("%d", volume),
@@ -180,8 +172,7 @@ func (c *Client) SetVolume(ctx context.Context, queueID string, volume int) (*mo
return &result, nil return &result, nil
} }
// GetCurrentTrack gets the currently playing track from the queue // GetCurrentTrack gets the currently playing track from the queue (GET /queues/{queue_id}/current).
// GET /queues/{queue_id}/current
func (c *Client) GetCurrentTrack(ctx context.Context, queueID string) (*models.QueueItem, error) { func (c *Client) GetCurrentTrack(ctx context.Context, queueID string) (*models.QueueItem, error) {
var result models.QueueItem var result models.QueueItem
if err := c.request.Get(ctx, fmt.Sprintf("/queues/%s/current", queueID), nil, &result); err != nil { if err := c.request.Get(ctx, fmt.Sprintf("/queues/%s/current", queueID), nil, &result); err != nil {
@@ -191,8 +182,7 @@ func (c *Client) GetCurrentTrack(ctx context.Context, queueID string) (*models.Q
return &result, nil return &result, nil
} }
// GetQueueHistory gets the queue history (recently played tracks) // GetQueueHistory gets the queue history (recently played tracks) (GET /queues/{queue_id}/history).
// GET /queues/{queue_id}/history
func (c *Client) GetQueueHistory(ctx context.Context, queueID string, limit int) ([]*models.QueueItem, error) { func (c *Client) GetQueueHistory(ctx context.Context, queueID string, limit int) ([]*models.QueueItem, error) {
params := map[string]string{ params := map[string]string{
"limit": fmt.Sprintf("%d", limit), "limit": fmt.Sprintf("%d", limit),
@@ -211,7 +201,7 @@ func (c *Client) GetQueueHistory(ctx context.Context, queueID string, limit int)
return items, nil return items, nil
} }
// GetPlayContexts gets play contexts // GetPlayContexts gets play contexts (GET /play-contexts).
func (c *Client) GetPlayContexts(ctx context.Context) ([]*models.PlayContext, error) { func (c *Client) GetPlayContexts(ctx context.Context) ([]*models.PlayContext, error) {
var result []models.PlayContext var result []models.PlayContext
if err := c.request.Get(ctx, "/play-contexts", nil, &result); err != nil { if err := c.request.Get(ctx, "/play-contexts", nil, &result); err != nil {
@@ -226,7 +216,7 @@ func (c *Client) GetPlayContexts(ctx context.Context) ([]*models.PlayContext, er
return contexts, nil return contexts, nil
} }
// GetPlayContextsData gets play contexts data // GetPlayContextsData gets play contexts data (GET /play-contexts/data).
func (c *Client) GetPlayContextsData(ctx context.Context) (*models.PlayContextsData, error) { func (c *Client) GetPlayContextsData(ctx context.Context) (*models.PlayContextsData, error) {
var result models.PlayContextsData var result models.PlayContextsData
if err := c.request.Get(ctx, "/play-contexts/data", nil, &result); err != nil { if err := c.request.Get(ctx, "/play-contexts/data", nil, &result); err != nil {
+11 -16
View File
@@ -1,3 +1,4 @@
// Package client provides methods for interacting with Yandex Music API endpoints.
package client package client
import ( import (
@@ -7,7 +8,7 @@ import (
"gitea.mrixs.me/Mrixs/yandex-music-api-go/internal/models" "gitea.mrixs.me/Mrixs/yandex-music-api-go/internal/models"
) )
// GetRadioStations gets radio stations // GetRadioStations gets radio stations (GET /radio/stations).
func (c *Client) GetRadioStations(ctx context.Context) ([]*models.RadioStation, error) { func (c *Client) GetRadioStations(ctx context.Context) ([]*models.RadioStation, error) {
var result []models.RadioStation var result []models.RadioStation
if err := c.request.Get(ctx, "/radio/stations", nil, &result); err != nil { if err := c.request.Get(ctx, "/radio/stations", nil, &result); err != nil {
@@ -22,8 +23,7 @@ func (c *Client) GetRadioStations(ctx context.Context) ([]*models.RadioStation,
return stations, nil return stations, nil
} }
// GetRadioStation gets a radio station by ID // GetRadioStation gets a radio station by ID (GET /rotor/station/{stationID}/info).
// GET /rotor/station/{stationID}/info
func (c *Client) GetRadioStation(ctx context.Context, stationID string) (*models.RadioStation, error) { func (c *Client) GetRadioStation(ctx context.Context, stationID string) (*models.RadioStation, error) {
var result models.RadioStation var result models.RadioStation
if err := c.request.Get(ctx, fmt.Sprintf("/rotor/station/%s/info", stationID), nil, &result); err != nil { if err := c.request.Get(ctx, fmt.Sprintf("/rotor/station/%s/info", stationID), nil, &result); err != nil {
@@ -33,8 +33,7 @@ func (c *Client) GetRadioStation(ctx context.Context, stationID string) (*models
return &result, nil return &result, nil
} }
// GetStationTracks gets tracks for a radio station // GetStationTracks gets tracks for a radio station (GET /rotor/station/{stationID}/tracks).
// GET /rotor/station/{stationID}/tracks
func (c *Client) GetStationTracks(ctx context.Context, stationID string, limit int) (*models.StationTracksResult, error) { func (c *Client) GetStationTracks(ctx context.Context, stationID string, limit int) (*models.StationTracksResult, error) {
params := map[string]string{} params := map[string]string{}
if limit > 0 { if limit > 0 {
@@ -48,7 +47,7 @@ func (c *Client) GetStationTracks(ctx context.Context, stationID string, limit i
return &result, nil return &result, nil
} }
// GetRotorStations gets rotor stations (generative) // GetRotorStations gets rotor stations (generative stations) (GET /rotor/stations).
func (c *Client) GetRotorStations(ctx context.Context) ([]*models.RotorStation, error) { func (c *Client) GetRotorStations(ctx context.Context) ([]*models.RotorStation, error) {
var result []models.RotorStation var result []models.RotorStation
if err := c.request.Get(ctx, "/rotor/stations", nil, &result); err != nil { if err := c.request.Get(ctx, "/rotor/stations", nil, &result); err != nil {
@@ -63,8 +62,7 @@ func (c *Client) GetRotorStations(ctx context.Context) ([]*models.RotorStation,
return stations, nil return stations, nil
} }
// GetRotorStation gets a rotor station by ID // GetRotorStation gets a rotor station by ID (GET /rotor/station/{stationID}/info).
// GET /rotor/station/{stationID}/info
func (c *Client) GetRotorStation(ctx context.Context, stationID string) (*models.RotorStation, error) { func (c *Client) GetRotorStation(ctx context.Context, stationID string) (*models.RotorStation, error) {
var result models.RotorStation var result models.RotorStation
if err := c.request.Get(ctx, fmt.Sprintf("/rotor/station/%s/info", stationID), nil, &result); err != nil { if err := c.request.Get(ctx, fmt.Sprintf("/rotor/station/%s/info", stationID), nil, &result); err != nil {
@@ -74,8 +72,7 @@ func (c *Client) GetRotorStation(ctx context.Context, stationID string) (*models
return &result, nil return &result, nil
} }
// GetRotorStationTracks gets tracks for a rotor station // GetRotorStationTracks gets tracks for a rotor station (GET /rotor/station/{stationID}/tracks).
// GET /rotor/station/{stationID}/tracks
func (c *Client) GetRotorStationTracks(ctx context.Context, stationID string, limit int) (*models.RotorStationTracksResult, error) { func (c *Client) GetRotorStationTracks(ctx context.Context, stationID string, limit int) (*models.RotorStationTracksResult, error) {
params := map[string]string{} params := map[string]string{}
if limit > 0 { if limit > 0 {
@@ -89,8 +86,7 @@ func (c *Client) GetRotorStationTracks(ctx context.Context, stationID string, li
return &result, nil return &result, nil
} }
// StartRotorSession starts a rotor session // StartRotorSession starts a rotor session (POST /rotor/station/{stationID}/session/start).
// POST /rotor/station/{stationID}/session/start
func (c *Client) StartRotorSession(ctx context.Context, stationID string) (*models.RotorSession, error) { func (c *Client) StartRotorSession(ctx context.Context, stationID string) (*models.RotorSession, error) {
var result models.RotorSession var result models.RotorSession
if err := c.request.Post(ctx, fmt.Sprintf("/rotor/station/%s/session/start", stationID), nil, &result); err != nil { if err := c.request.Post(ctx, fmt.Sprintf("/rotor/station/%s/session/start", stationID), nil, &result); err != nil {
@@ -100,8 +96,7 @@ func (c *Client) StartRotorSession(ctx context.Context, stationID string) (*mode
return &result, nil return &result, nil
} }
// GetRotorSession gets rotor session info // GetRotorSession gets rotor session info by session ID (GET /rotor/session).
// GET /rotor/session?session_id={sessionID}
func (c *Client) GetRotorSession(ctx context.Context, sessionID string) (*models.RotorSession, error) { func (c *Client) GetRotorSession(ctx context.Context, sessionID string) (*models.RotorSession, error) {
params := map[string]string{ params := map[string]string{
"session_id": sessionID, "session_id": sessionID,
@@ -115,8 +110,8 @@ func (c *Client) GetRotorSession(ctx context.Context, sessionID string) (*models
return &result, nil return &result, nil
} }
// RotorSessionFeedback sends feedback for a rotor session track // RotorSessionFeedback sends feedback for a rotor session track (POST /rotor/station/{stationID}/feedback).
// POST /rotor/station/{stationID}/feedback // The feedbackType parameter can be "like", "dislike", or "skip".
func (c *Client) RotorSessionFeedback(ctx context.Context, sessionID, trackID, feedbackType string) error { func (c *Client) RotorSessionFeedback(ctx context.Context, sessionID, trackID, feedbackType string) error {
params := map[string]string{ params := map[string]string{
"track_id": trackID, "track_id": trackID,
+22 -13
View File
@@ -13,7 +13,7 @@ import (
"gitea.mrixs.me/Mrixs/yandex-music-api-go/internal/utils" "gitea.mrixs.me/Mrixs/yandex-music-api-go/internal/utils"
) )
// Default values // Default values for the Yandex Music API client.
const ( const (
DefaultBaseURL = "https://api.music.yandex.net" DefaultBaseURL = "https://api.music.yandex.net"
DefaultTimeout = 5 * time.Second DefaultTimeout = 5 * time.Second
@@ -21,7 +21,7 @@ const (
DefaultClientHeader = "YandexMusicAndroid/24023621" DefaultClientHeader = "YandexMusicAndroid/24023621"
) )
// RequestConfig holds configuration for the request client // RequestConfig holds configuration for the request client.
type RequestConfig struct { type RequestConfig struct {
BaseURL string BaseURL string
Token string Token string
@@ -36,14 +36,16 @@ type RequestConfig struct {
OnSchemaMismatch utils.SchemaMismatchHandler OnSchemaMismatch utils.SchemaMismatchHandler
} }
// Request handles HTTP requests to Yandex Music API // Request handles HTTP requests to the Yandex Music API.
// It manages the HTTP client, authentication headers, and request signing.
type Request struct { type Request struct {
config RequestConfig config RequestConfig
client *http.Client client *http.Client
schemaTracker *utils.SchemaMismatchTracker schemaTracker *utils.SchemaMismatchTracker
} }
// NewRequest creates a new Request instance // NewRequest creates a new Request instance with the given configuration.
// It sets up the HTTP client, default headers, and authentication if a token is provided.
func NewRequest(config RequestConfig) *Request { func NewRequest(config RequestConfig) *Request {
if config.BaseURL == "" { if config.BaseURL == "" {
config.BaseURL = DefaultBaseURL config.BaseURL = DefaultBaseURL
@@ -92,7 +94,8 @@ func NewRequest(config RequestConfig) *Request {
return r return r
} }
// SetToken updates the authorization token // SetToken updates the authorization token used for API requests.
// When a token is provided, it sets the Authorization header to "OAuth <token>".
func (r *Request) SetToken(token string) { func (r *Request) SetToken(token string) {
r.config.Token = token r.config.Token = token
if token != "" { if token != "" {
@@ -102,33 +105,38 @@ func (r *Request) SetToken(token string) {
} }
} }
// SetLanguage sets the Accept-Language header // SetLanguage sets the Accept-Language header for API requests.
func (r *Request) SetLanguage(lang string) { func (r *Request) SetLanguage(lang string) {
r.config.Language = lang r.config.Language = lang
r.config.Headers["Accept-Language"] = lang r.config.Headers["Accept-Language"] = lang
} }
// Get performs a GET request // Get performs a GET request to the given path with query parameters.
// The response is unmarshaled into the result pointer.
func (r *Request) Get(ctx context.Context, path string, params map[string]string, result any) error { func (r *Request) Get(ctx context.Context, path string, params map[string]string, result any) error {
return r.doRequest(ctx, "GET", path, params, nil, result) return r.doRequest(ctx, "GET", path, params, nil, result)
} }
// Post performs a POST request // Post performs a POST request to the given path with a JSON body.
// The response is unmarshaled into the result pointer.
func (r *Request) Post(ctx context.Context, path string, body any, result any) error { func (r *Request) Post(ctx context.Context, path string, body any, result any) error {
return r.doRequest(ctx, "POST", path, nil, body, result) return r.doRequest(ctx, "POST", path, nil, body, result)
} }
// Put performs a PUT request // Put performs a PUT request to the given path with a JSON body.
// The response is unmarshaled into the result pointer.
func (r *Request) Put(ctx context.Context, path string, body any, result any) error { func (r *Request) Put(ctx context.Context, path string, body any, result any) error {
return r.doRequest(ctx, "PUT", path, nil, body, result) return r.doRequest(ctx, "PUT", path, nil, body, result)
} }
// Delete performs a DELETE request // Delete performs a DELETE request to the given path with an optional JSON body.
// The response is unmarshaled into the result pointer.
func (r *Request) Delete(ctx context.Context, path string, body any, result any) error { func (r *Request) Delete(ctx context.Context, path string, body any, result any) error {
return r.doRequest(ctx, "DELETE", path, nil, body, result) return r.doRequest(ctx, "DELETE", path, nil, body, result)
} }
// doRequest performs the actual HTTP request // doRequest performs the actual HTTP request to the Yandex Music API.
// It handles URL building, request signing, response parsing, and error handling.
func (r *Request) doRequest(ctx context.Context, method, path string, params map[string]string, body any, result any) error { func (r *Request) doRequest(ctx context.Context, method, path string, params map[string]string, body any, result any) error {
// Build URL // Build URL
fullURL := r.config.BaseURL + path fullURL := r.config.BaseURL + path
@@ -209,7 +217,7 @@ func (r *Request) doRequest(ctx context.Context, method, path string, params map
return nil return nil
} }
// handleErrorResponse handles HTTP error responses // handleErrorResponse handles HTTP error responses by mapping status codes to typed errors.
func (r *Request) handleErrorResponse(statusCode int, body []byte) error { func (r *Request) handleErrorResponse(statusCode int, body []byte) error {
var msg string var msg string
apiResp, err := utils.DeJSON(body) apiResp, err := utils.DeJSON(body)
@@ -235,7 +243,8 @@ func (r *Request) handleErrorResponse(statusCode int, body []byte) error {
} }
} }
// Download downloads a file from a URL // Download downloads a file from the given URL and returns the raw response body.
// It is used for downloading track files and lyrics text.
func (r *Request) Download(ctx context.Context, urlStr string) ([]byte, error) { func (r *Request) Download(ctx context.Context, urlStr string) ([]byte, error) {
req, err := http.NewRequestWithContext(ctx, "GET", urlStr, nil) req, err := http.NewRequestWithContext(ctx, "GET", urlStr, nil)
if err != nil { if err != nil {
+12 -10
View File
@@ -1,3 +1,4 @@
// Package client provides methods for interacting with Yandex Music API endpoints.
package client package client
import ( import (
@@ -7,7 +8,8 @@ import (
"gitea.mrixs.me/Mrixs/yandex-music-api-go/internal/models" "gitea.mrixs.me/Mrixs/yandex-music-api-go/internal/models"
) )
// Search performs a multi-type search // Search performs a multi-type search (GET /search).
// The searchType parameter specifies what to search for (e.g., "track", "album", "artist").
func (c *Client) Search(ctx context.Context, query string, searchType string, page, pageSize int) (*models.SearchResult, error) { func (c *Client) Search(ctx context.Context, query string, searchType string, page, pageSize int) (*models.SearchResult, error) {
params := map[string]string{ params := map[string]string{
"text": query, "text": query,
@@ -46,7 +48,7 @@ func (c *Client) Search(ctx context.Context, query string, searchType string, pa
return &result, nil return &result, nil
} }
// SearchTracks searches for tracks // SearchTracks searches for tracks using Search with type "track".
func (c *Client) SearchTracks(ctx context.Context, query string, page, pageSize int) (*models.SearchTracksResult, error) { func (c *Client) SearchTracks(ctx context.Context, query string, page, pageSize int) (*models.SearchTracksResult, error) {
result, err := c.Search(ctx, query, "track", page, pageSize) result, err := c.Search(ctx, query, "track", page, pageSize)
if err != nil { if err != nil {
@@ -55,7 +57,7 @@ func (c *Client) SearchTracks(ctx context.Context, query string, page, pageSize
return result.Tracks, nil return result.Tracks, nil
} }
// SearchAlbums searches for albums // SearchAlbums searches for albums using Search with type "album".
func (c *Client) SearchAlbums(ctx context.Context, query string, page, pageSize int) (*models.SearchAlbumsResult, error) { func (c *Client) SearchAlbums(ctx context.Context, query string, page, pageSize int) (*models.SearchAlbumsResult, error) {
result, err := c.Search(ctx, query, "album", page, pageSize) result, err := c.Search(ctx, query, "album", page, pageSize)
if err != nil { if err != nil {
@@ -64,7 +66,7 @@ func (c *Client) SearchAlbums(ctx context.Context, query string, page, pageSize
return result.Albums, nil return result.Albums, nil
} }
// SearchArtists searches for artists // SearchArtists searches for artists using Search with type "artist".
func (c *Client) SearchArtists(ctx context.Context, query string, page, pageSize int) (*models.SearchArtistsResult, error) { func (c *Client) SearchArtists(ctx context.Context, query string, page, pageSize int) (*models.SearchArtistsResult, error) {
result, err := c.Search(ctx, query, "artist", page, pageSize) result, err := c.Search(ctx, query, "artist", page, pageSize)
if err != nil { if err != nil {
@@ -73,7 +75,7 @@ func (c *Client) SearchArtists(ctx context.Context, query string, page, pageSize
return result.Artists, nil return result.Artists, nil
} }
// SearchPlaylists searches for playlists // SearchPlaylists searches for playlists using Search with type "playlist".
func (c *Client) SearchPlaylists(ctx context.Context, query string, page, pageSize int) (*models.SearchPlaylistsResult, error) { func (c *Client) SearchPlaylists(ctx context.Context, query string, page, pageSize int) (*models.SearchPlaylistsResult, error) {
result, err := c.Search(ctx, query, "playlist", page, pageSize) result, err := c.Search(ctx, query, "playlist", page, pageSize)
if err != nil { if err != nil {
@@ -82,7 +84,7 @@ func (c *Client) SearchPlaylists(ctx context.Context, query string, page, pageSi
return result.Playlists, nil return result.Playlists, nil
} }
// SearchVideos searches for videos // SearchVideos searches for videos using Search with type "video".
func (c *Client) SearchVideos(ctx context.Context, query string, page, pageSize int) (*models.SearchVideosResult, error) { func (c *Client) SearchVideos(ctx context.Context, query string, page, pageSize int) (*models.SearchVideosResult, error) {
result, err := c.Search(ctx, query, "video", page, pageSize) result, err := c.Search(ctx, query, "video", page, pageSize)
if err != nil { if err != nil {
@@ -91,7 +93,7 @@ func (c *Client) SearchVideos(ctx context.Context, query string, page, pageSize
return result.Videos, nil return result.Videos, nil
} }
// SearchUsers searches for users // SearchUsers searches for users using Search with type "user".
func (c *Client) SearchUsers(ctx context.Context, query string, page, pageSize int) (*models.SearchUsersResult, error) { func (c *Client) SearchUsers(ctx context.Context, query string, page, pageSize int) (*models.SearchUsersResult, error) {
result, err := c.Search(ctx, query, "user", page, pageSize) result, err := c.Search(ctx, query, "user", page, pageSize)
if err != nil { if err != nil {
@@ -100,7 +102,7 @@ func (c *Client) SearchUsers(ctx context.Context, query string, page, pageSize i
return result.Users, nil return result.Users, nil
} }
// SearchSuggestions gets search suggestions // SearchSuggestions gets search suggestions for a query (GET /search/suggest?type=suggest).
func (c *Client) SearchSuggestions(ctx context.Context, query string) ([]string, error) { func (c *Client) SearchSuggestions(ctx context.Context, query string) ([]string, error) {
params := map[string]string{ params := map[string]string{
"text": query, "text": query,
@@ -116,7 +118,7 @@ func (c *Client) SearchSuggestions(ctx context.Context, query string) ([]string,
return result.Suggestions, nil return result.Suggestions, nil
} }
// SearchBanners gets search banners // SearchBanners gets search banners for a query (GET /search/banner?type=banner).
func (c *Client) SearchBanners(ctx context.Context, query string) ([]models.SearchBanner, error) { func (c *Client) SearchBanners(ctx context.Context, query string) ([]models.SearchBanner, error) {
params := map[string]string{ params := map[string]string{
"text": query, "text": query,
@@ -132,7 +134,7 @@ func (c *Client) SearchBanners(ctx context.Context, query string) ([]models.Sear
return result.Banners, nil return result.Banners, nil
} }
// SearchTags gets search tags // SearchTags gets search tags for a query (GET /search/tag?type=tag).
func (c *Client) SearchTags(ctx context.Context, query string) ([]models.Tag, error) { func (c *Client) SearchTags(ctx context.Context, query string) ([]models.Tag, error) {
params := map[string]string{ params := map[string]string{
"text": query, "text": query,
+8 -7
View File
@@ -1,3 +1,4 @@
// Package client provides methods for interacting with Yandex Music API endpoints.
package client package client
import ( import (
@@ -6,7 +7,7 @@ import (
"gitea.mrixs.me/Mrixs/yandex-music-api-go/internal/models" "gitea.mrixs.me/Mrixs/yandex-music-api-go/internal/models"
) )
// GetSettings gets user settings // GetSettings gets user settings (GET /account/settings).
func (c *Client) GetSettings(ctx context.Context) (*models.AccountSettings, error) { func (c *Client) GetSettings(ctx context.Context) (*models.AccountSettings, error) {
var result models.AccountSettings var result models.AccountSettings
if err := c.request.Get(ctx, "/account/settings", nil, &result); err != nil { if err := c.request.Get(ctx, "/account/settings", nil, &result); err != nil {
@@ -15,7 +16,7 @@ func (c *Client) GetSettings(ctx context.Context) (*models.AccountSettings, erro
return &result, nil return &result, nil
} }
// UpdateSettings updates user settings // UpdateSettings updates user settings (PUT /account/settings).
func (c *Client) UpdateSettings(ctx context.Context, settings *models.AccountSettings) (*models.AccountSettings, error) { func (c *Client) UpdateSettings(ctx context.Context, settings *models.AccountSettings) (*models.AccountSettings, error) {
var result models.AccountSettings var result models.AccountSettings
if err := c.request.Put(ctx, "/account/settings", settings, &result); err != nil { if err := c.request.Put(ctx, "/account/settings", settings, &result); err != nil {
@@ -24,7 +25,7 @@ func (c *Client) UpdateSettings(ctx context.Context, settings *models.AccountSet
return &result, nil return &result, nil
} }
// GetExperiments gets experiments // GetExperiments gets experiments (GET /experiments).
func (c *Client) GetExperiments(ctx context.Context) (*models.Experiments, error) { func (c *Client) GetExperiments(ctx context.Context) (*models.Experiments, error) {
var result models.Experiments var result models.Experiments
if err := c.request.Get(ctx, "/experiments", nil, &result); err != nil { if err := c.request.Get(ctx, "/experiments", nil, &result); err != nil {
@@ -33,7 +34,7 @@ func (c *Client) GetExperiments(ctx context.Context) (*models.Experiments, error
return &result, nil return &result, nil
} }
// GetExperimentDetails gets experiment details // GetExperimentDetails gets experiment details for the given experiment ID (GET /experiments/details).
func (c *Client) GetExperimentDetails(ctx context.Context, experimentID string) (*models.ExperimentDetail, error) { func (c *Client) GetExperimentDetails(ctx context.Context, experimentID string) (*models.ExperimentDetail, error) {
params := map[string]string{ params := map[string]string{
"experiment_id": experimentID, "experiment_id": experimentID,
@@ -45,7 +46,7 @@ func (c *Client) GetExperimentDetails(ctx context.Context, experimentID string)
return &result, nil return &result, nil
} }
// GetPermissions gets user permissions // GetPermissions gets user permissions (GET /permissions).
func (c *Client) GetPermissions(ctx context.Context) (*models.Permissions, error) { func (c *Client) GetPermissions(ctx context.Context) (*models.Permissions, error) {
var result models.Permissions var result models.Permissions
if err := c.request.Get(ctx, "/permissions", nil, &result); err != nil { if err := c.request.Get(ctx, "/permissions", nil, &result); err != nil {
@@ -54,7 +55,7 @@ func (c *Client) GetPermissions(ctx context.Context) (*models.Permissions, error
return &result, nil return &result, nil
} }
// GetPermissionAlerts gets permission alerts // GetPermissionAlerts gets permission alerts (GET /permission-alerts).
func (c *Client) GetPermissionAlerts(ctx context.Context) (*models.PermissionAlerts, error) { func (c *Client) GetPermissionAlerts(ctx context.Context) (*models.PermissionAlerts, error) {
var result models.PermissionAlerts var result models.PermissionAlerts
if err := c.request.Get(ctx, "/permission-alerts", nil, &result); err != nil { if err := c.request.Get(ctx, "/permission-alerts", nil, &result); err != nil {
@@ -63,7 +64,7 @@ func (c *Client) GetPermissionAlerts(ctx context.Context) (*models.PermissionAle
return &result, nil return &result, nil
} }
// GetContentRestrictions gets content restrictions // GetContentRestrictions gets content restrictions (GET /content-restrictions).
func (c *Client) GetContentRestrictions(ctx context.Context) (*models.ContentRestrictions, error) { func (c *Client) GetContentRestrictions(ctx context.Context) (*models.ContentRestrictions, error) {
var result models.ContentRestrictions var result models.ContentRestrictions
if err := c.request.Get(ctx, "/content-restrictions", nil, &result); err != nil { if err := c.request.Get(ctx, "/content-restrictions", nil, &result); err != nil {
+20 -21
View File
@@ -1,3 +1,4 @@
// Package client provides methods for interacting with Yandex Music API endpoints.
package client package client
import ( import (
@@ -9,8 +10,7 @@ import (
"gitea.mrixs.me/Mrixs/yandex-music-api-go/internal/utils" "gitea.mrixs.me/Mrixs/yandex-music-api-go/internal/utils"
) )
// GetTrackSupplement gets supplement for a track // GetTrackSupplement gets supplement for a track (GET /tracks/{track_id}/supplement).
// GET /tracks/{track_id}/supplement
func (c *Client) GetTrackSupplement(ctx context.Context, trackID string) (*models.Supplement, error) { func (c *Client) GetTrackSupplement(ctx context.Context, trackID string) (*models.Supplement, error) {
path := fmt.Sprintf("/tracks/%s/supplement", trackID) path := fmt.Sprintf("/tracks/%s/supplement", trackID)
@@ -21,8 +21,9 @@ func (c *Client) GetTrackSupplement(ctx context.Context, trackID string) (*model
return &result, nil return &result, nil
} }
// GetTrackLyrics gets lyrics for a track (new endpoint with signing) // GetTrackLyrics gets lyrics for a track (GET /tracks/{track_id}/lyrics).
// GET /tracks/{track_id}/lyrics // The format parameter specifies the lyrics format (e.g., "TEXT" or "LRC").
// The request is signed using the default signing key.
func (c *Client) GetTrackLyrics(ctx context.Context, trackID string, format string) (*models.TrackLyrics, error) { func (c *Client) GetTrackLyrics(ctx context.Context, trackID string, format string) (*models.TrackLyrics, error) {
path := fmt.Sprintf("/tracks/%s/lyrics", trackID) path := fmt.Sprintf("/tracks/%s/lyrics", trackID)
@@ -42,7 +43,7 @@ func (c *Client) GetTrackLyrics(ctx context.Context, trackID string, format stri
return &result, nil return &result, nil
} }
// GetTrackLyricsText fetches the full lyrics text from the download URL // GetTrackLyricsText fetches the full lyrics text from the download URL provided in TrackLyrics.
func (c *Client) GetTrackLyricsText(ctx context.Context, trackLyrics *models.TrackLyrics) (string, error) { func (c *Client) GetTrackLyricsText(ctx context.Context, trackLyrics *models.TrackLyrics) (string, error) {
data, err := c.request.Download(ctx, trackLyrics.DownloadURL) data, err := c.request.Download(ctx, trackLyrics.DownloadURL)
if err != nil { if err != nil {
@@ -51,8 +52,7 @@ func (c *Client) GetTrackLyricsText(ctx context.Context, trackLyrics *models.Tra
return string(data), nil return string(data), nil
} }
// GetLyrics gets lyrics info for a track (legacy endpoint) // GetLyrics gets lyrics info for a track using the legacy endpoint (GET /tracks/lyrics).
// GET /tracks/lyrics?track_id={track_id}
func (c *Client) GetLyrics(ctx context.Context, trackID string) (*models.LyricsInfo, error) { func (c *Client) GetLyrics(ctx context.Context, trackID string) (*models.LyricsInfo, error) {
params := map[string]string{ params := map[string]string{
"track_id": trackID, "track_id": trackID,
@@ -65,8 +65,7 @@ func (c *Client) GetLyrics(ctx context.Context, trackID string) (*models.LyricsI
return &result, nil return &result, nil
} }
// GetVideoSupplement gets video supplement for a track (legacy endpoint) // GetVideoSupplement gets video supplement for a track using the legacy endpoint (GET /tracks/video-supplement).
// GET /tracks/video-supplement?track_id={track_id}
func (c *Client) GetVideoSupplement(ctx context.Context, trackID string) (*models.VideoSupplement, error) { func (c *Client) GetVideoSupplement(ctx context.Context, trackID string) (*models.VideoSupplement, error) {
params := map[string]string{ params := map[string]string{
"track_id": trackID, "track_id": trackID,
@@ -79,44 +78,43 @@ func (c *Client) GetVideoSupplement(ctx context.Context, trackID string) (*model
return &result, nil return &result, nil
} }
// GetLyricsByTrackID is an alias for GetTrackLyrics for backward compatibility // GetLyricsByTrackID is an alias for GetTrackLyrics for backward compatibility (GET /tracks/{track_id}/lyrics).
// GET /tracks/{track_id}/lyrics
func (c *Client) GetLyricsByTrackID(ctx context.Context, trackID string, format string) (*models.TrackLyrics, error) { func (c *Client) GetLyricsByTrackID(ctx context.Context, trackID string, format string) (*models.TrackLyrics, error) {
return c.GetTrackLyrics(ctx, trackID, format) return c.GetTrackLyrics(ctx, trackID, format)
} }
// LyricsFormat represents the lyrics format // LyricsFormat represents the lyrics format.
type LyricsFormat string type LyricsFormat string
const ( const (
// LyricsFormatText is plain text format // LyricsFormatText is plain text lyrics format.
LyricsFormatText LyricsFormat = "TEXT" LyricsFormatText LyricsFormat = "TEXT"
// LyricsFormatLRC is LRC format with timestamps // LyricsFormatLRC is LRC format lyrics with timestamps.
LyricsFormatLRC LyricsFormat = "LRC" LyricsFormatLRC LyricsFormat = "LRC"
) )
// GetTrackLyricsWithOptions gets lyrics with options // GetTrackLyricsWithOptions gets lyrics with options using a LyricsFormat value.
func (c *Client) GetTrackLyricsWithOptions(ctx context.Context, trackID string, format LyricsFormat) (*models.TrackLyrics, error) { func (c *Client) GetTrackLyricsWithOptions(ctx context.Context, trackID string, format LyricsFormat) (*models.TrackLyrics, error) {
return c.GetTrackLyrics(ctx, trackID, string(format)) return c.GetTrackLyrics(ctx, trackID, string(format))
} }
// SupplementOptions holds options for supplement requests // SupplementOptions holds options for supplement requests.
type SupplementOptions struct { type SupplementOptions struct {
TrackID string TrackID string
} }
// GetSupplement gets track supplement with options // GetSupplement gets track supplement with options.
func (c *Client) GetSupplement(ctx context.Context, opts SupplementOptions) (*models.Supplement, error) { func (c *Client) GetSupplement(ctx context.Context, opts SupplementOptions) (*models.Supplement, error) {
return c.GetTrackSupplement(ctx, opts.TrackID) return c.GetTrackSupplement(ctx, opts.TrackID)
} }
// LyricsOptions holds options for lyrics requests // LyricsOptions holds options for lyrics requests.
type LyricsOptions struct { type LyricsOptions struct {
TrackID string TrackID string
Format LyricsFormat Format LyricsFormat
} }
// GetLyricsWithOptions gets track lyrics with options // GetLyricsWithOptions gets track lyrics with options.
func (c *Client) GetLyricsWithOptions(ctx context.Context, opts LyricsOptions) (*models.TrackLyrics, error) { func (c *Client) GetLyricsWithOptions(ctx context.Context, opts LyricsOptions) (*models.TrackLyrics, error) {
format := string(opts.Format) format := string(opts.Format)
if format == "" { if format == "" {
@@ -125,13 +123,14 @@ func (c *Client) GetLyricsWithOptions(ctx context.Context, opts LyricsOptions) (
return c.GetTrackLyrics(ctx, opts.TrackID, format) return c.GetTrackLyrics(ctx, opts.TrackID, format)
} }
// Sign represents a request signature // Sign represents a request signature for signed API requests.
type Sign struct { type Sign struct {
Timestamp int64 Timestamp int64
Value string Value string
} }
// GetSignRequest creates a signature for a track request (exported for external use) // GetSignRequest creates a signature for a track request (exported for external use).
// It delegates to utils.GetSignRequest with the default signing key.
func GetSignRequest(trackID string) Sign { func GetSignRequest(trackID string) Sign {
h := utils.GetSignRequest(trackID, utils.DefaultSignKey) h := utils.GetSignRequest(trackID, utils.DefaultSignKey)
+11 -6
View File
@@ -1,3 +1,4 @@
// Package client provides methods for interacting with Yandex Music API endpoints.
package client package client
import ( import (
@@ -8,7 +9,8 @@ import (
"gitea.mrixs.me/Mrixs/yandex-music-api-go/internal/utils" "gitea.mrixs.me/Mrixs/yandex-music-api-go/internal/utils"
) )
// GetTracks gets tracks by IDs // GetTracks gets tracks by their IDs (GET /tracks).
// Returns a slice of Track pointers, or nil if no IDs are provided.
func (c *Client) GetTracks(ctx context.Context, trackIDs []string) ([]*models.Track, error) { func (c *Client) GetTracks(ctx context.Context, trackIDs []string) ([]*models.Track, error) {
if len(trackIDs) == 0 { if len(trackIDs) == 0 {
return nil, nil return nil, nil
@@ -31,7 +33,8 @@ func (c *Client) GetTracks(ctx context.Context, trackIDs []string) ([]*models.Tr
return tracks, nil return tracks, nil
} }
// GetTrack gets a single track by ID // GetTrack gets a single track by ID using GetTracks.
// Returns an error if no track is found with the given ID.
func (c *Client) GetTrack(ctx context.Context, trackID string) (*models.Track, error) { func (c *Client) GetTrack(ctx context.Context, trackID string) (*models.Track, error) {
tracks, err := c.GetTracks(ctx, []string{trackID}) tracks, err := c.GetTracks(ctx, []string{trackID})
if err != nil { if err != nil {
@@ -43,7 +46,8 @@ func (c *Client) GetTrack(ctx context.Context, trackID string) (*models.Track, e
return tracks[0], nil return tracks[0], nil
} }
// GetTrackDownloadInfo gets download info for a track // GetTrackDownloadInfo gets download info for a track (GET /tracks/{track_id}/download-info).
// The quality parameter specifies the desired audio quality (e.g., "mp3").
func (c *Client) GetTrackDownloadInfo(ctx context.Context, trackID, quality string) ([]models.DownloadInfo, error) { func (c *Client) GetTrackDownloadInfo(ctx context.Context, trackID, quality string) ([]models.DownloadInfo, error) {
// This requires signing - use the sign utility // This requires signing - use the sign utility
// For now, return basic implementation // For now, return basic implementation
@@ -58,7 +62,8 @@ func (c *Client) GetTrackDownloadInfo(ctx context.Context, trackID, quality stri
return result, nil return result, nil
} }
// DownloadTrack downloads a track // DownloadTrack downloads a track by ID.
// It first fetches download info, finds a matching format/bitrate, then downloads the file content.
func (c *Client) DownloadTrack(ctx context.Context, trackID, format string, bitrate int) ([]byte, error) { func (c *Client) DownloadTrack(ctx context.Context, trackID, format string, bitrate int) ([]byte, error) {
info, err := c.GetTrackDownloadInfo(ctx, trackID, format) info, err := c.GetTrackDownloadInfo(ctx, trackID, format)
if err != nil { if err != nil {
@@ -85,12 +90,12 @@ func (c *Client) DownloadTrack(ctx context.Context, trackID, format string, bitr
return c.request.Download(ctx, url) return c.request.Download(ctx, url)
} }
// SearchResult represents search results // SearchResult represents search results containing tracks.
type SearchResult struct { type SearchResult struct {
Tracks *SearchTracksResult `json:"tracks"` Tracks *SearchTracksResult `json:"tracks"`
} }
// SearchTracksResult represents track search results // SearchTracksResult represents track search results with total count and results list.
type SearchTracksResult struct { type SearchTracksResult struct {
Total int `json:"total"` Total int `json:"total"`
Results []models.Track `json:"results"` Results []models.Track `json:"results"`
+13 -12
View File
@@ -1,10 +1,11 @@
// Package models provides data models for the Yandex Music API.
package models package models
import ( import (
"encoding/json" "encoding/json"
) )
// AccountSettings represents account settings // AccountSettings represents account settings from the Yandex Music API.
type AccountSettings struct { type AccountSettings struct {
BaseModel BaseModel
Language string `json:"language"` Language string `json:"language"`
@@ -26,7 +27,7 @@ type AccountSettings struct {
DownloadOnWifiOnly bool `json:"download_on_wifi_only"` DownloadOnWifiOnly bool `json:"download_on_wifi_only"`
} }
// DeJSON deserializes AccountSettings from JSON // DeJSON deserializes AccountSettings from JSON data.
func (a *AccountSettings) DeJSON(data []byte, c ClientInterface) (Model, error) { func (a *AccountSettings) DeJSON(data []byte, c ClientInterface) (Model, error) {
var raw map[string]json.RawMessage var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil { if err := json.Unmarshal(data, &raw); err != nil {
@@ -90,7 +91,7 @@ func (a *AccountSettings) DeJSON(data []byte, c ClientInterface) (Model, error)
return settings, nil return settings, nil
} }
// DeList deserializes a list of AccountSettings // DeList deserializes a list of AccountSettings from JSON data.
func (a *AccountSettings) DeList(data []byte, c ClientInterface) ([]Model, error) { func (a *AccountSettings) DeList(data []byte, c ClientInterface) ([]Model, error) {
var rawList []json.RawMessage var rawList []json.RawMessage
if err := json.Unmarshal(data, &rawList); err != nil { if err := json.Unmarshal(data, &rawList); err != nil {
@@ -108,7 +109,7 @@ func (a *AccountSettings) DeList(data []byte, c ClientInterface) ([]Model, error
return result, nil return result, nil
} }
// Subscription represents subscription info // Subscription represents subscription info.
type Subscription struct { type Subscription struct {
BaseModel BaseModel
ID string `json:"id"` ID string `json:"id"`
@@ -127,7 +128,7 @@ type Subscription struct {
TrialUsed bool `json:"trial_used"` TrialUsed bool `json:"trial_used"`
} }
// DeJSON deserializes Subscription from JSON // DeJSON deserializes Subscription from JSON data.
func (s *Subscription) DeJSON(data []byte, c ClientInterface) (Model, error) { func (s *Subscription) DeJSON(data []byte, c ClientInterface) (Model, error) {
var raw map[string]json.RawMessage var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil { if err := json.Unmarshal(data, &raw); err != nil {
@@ -182,7 +183,7 @@ func (s *Subscription) DeJSON(data []byte, c ClientInterface) (Model, error) {
return sub, nil return sub, nil
} }
// DeList deserializes a list of Subscriptions // DeList deserializes a list of Subscriptions from JSON data.
func (s *Subscription) DeList(data []byte, c ClientInterface) ([]Model, error) { func (s *Subscription) DeList(data []byte, c ClientInterface) ([]Model, error) {
var rawList []json.RawMessage var rawList []json.RawMessage
if err := json.Unmarshal(data, &rawList); err != nil { if err := json.Unmarshal(data, &rawList); err != nil {
@@ -200,7 +201,7 @@ func (s *Subscription) DeList(data []byte, c ClientInterface) ([]Model, error) {
return result, nil return result, nil
} }
// PlusInfo represents Plus subscription info (from /account/plus or account status) // PlusInfo represents Plus subscription info.
type PlusInfo struct { type PlusInfo struct {
BaseModel BaseModel
HasPlus bool `json:"has_plus"` HasPlus bool `json:"has_plus"`
@@ -208,7 +209,7 @@ type PlusInfo struct {
Migrated *bool `json:"migrated,omitempty"` Migrated *bool `json:"migrated,omitempty"`
} }
// DeJSON deserializes PlusInfo from JSON // DeJSON deserializes PlusInfo from JSON data.
func (p *PlusInfo) DeJSON(data []byte, c ClientInterface) (Model, error) { func (p *PlusInfo) DeJSON(data []byte, c ClientInterface) (Model, error) {
var raw map[string]json.RawMessage var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil { if err := json.Unmarshal(data, &raw); err != nil {
@@ -232,7 +233,7 @@ func (p *PlusInfo) DeJSON(data []byte, c ClientInterface) (Model, error) {
return plus, nil return plus, nil
} }
// DeList deserializes a list of PlusInfo // DeList deserializes a list of PlusInfo from JSON data.
func (p *PlusInfo) DeList(data []byte, c ClientInterface) ([]Model, error) { func (p *PlusInfo) DeList(data []byte, c ClientInterface) ([]Model, error) {
var rawList []json.RawMessage var rawList []json.RawMessage
if err := json.Unmarshal(data, &rawList); err != nil { if err := json.Unmarshal(data, &rawList); err != nil {
@@ -250,7 +251,7 @@ func (p *PlusInfo) DeList(data []byte, c ClientInterface) ([]Model, error) {
return result, nil return result, nil
} }
// PromoCodeStatus represents promo code status // PromoCodeStatus represents promo code status.
type PromoCodeStatus struct { type PromoCodeStatus struct {
BaseModel BaseModel
Code string `json:"code"` Code string `json:"code"`
@@ -262,7 +263,7 @@ type PromoCodeStatus struct {
Activated bool `json:"activated"` Activated bool `json:"activated"`
} }
// DeJSON deserializes PromoCodeStatus from JSON // DeJSON deserializes PromoCodeStatus from JSON data.
func (p *PromoCodeStatus) DeJSON(data []byte, c ClientInterface) (Model, error) { func (p *PromoCodeStatus) DeJSON(data []byte, c ClientInterface) (Model, error) {
var raw map[string]json.RawMessage var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil { if err := json.Unmarshal(data, &raw); err != nil {
@@ -296,7 +297,7 @@ func (p *PromoCodeStatus) DeJSON(data []byte, c ClientInterface) (Model, error)
return promo, nil return promo, nil
} }
// DeList deserializes a list of PromoCodeStatus // DeList deserializes a list of PromoCodeStatus from JSON data.
func (p *PromoCodeStatus) DeList(data []byte, c ClientInterface) ([]Model, error) { func (p *PromoCodeStatus) DeList(data []byte, c ClientInterface) ([]Model, error) {
var rawList []json.RawMessage var rawList []json.RawMessage
if err := json.Unmarshal(data, &rawList); err != nil { if err := json.Unmarshal(data, &rawList); err != nil {
+13 -12
View File
@@ -1,10 +1,11 @@
// Package models provides data models for the Yandex Music API.
package models package models
import ( import (
"encoding/json" "encoding/json"
) )
// Album represents a full album // Album represents a full album from the Yandex Music API.
type Album struct { type Album struct {
BaseModel BaseModel
ID string `json:"id"` ID string `json:"id"`
@@ -34,7 +35,7 @@ type Album struct {
Trailer *TrailerInfo `json:"trailer"` Trailer *TrailerInfo `json:"trailer"`
} }
// DeJSON deserializes an Album from JSON // DeJSON deserializes an Album from JSON data.
func (a *Album) DeJSON(data []byte, c ClientInterface) (Model, error) { func (a *Album) DeJSON(data []byte, c ClientInterface) (Model, error) {
var raw map[string]json.RawMessage var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil { if err := json.Unmarshal(data, &raw); err != nil {
@@ -138,7 +139,7 @@ func (a *Album) DeJSON(data []byte, c ClientInterface) (Model, error) {
return album, nil return album, nil
} }
// DeList deserializes a list of Albums // DeList deserializes a list of Albums from JSON data.
func (a *Album) DeList(data []byte, c ClientInterface) ([]Model, error) { func (a *Album) DeList(data []byte, c ClientInterface) ([]Model, error) {
var rawList []json.RawMessage var rawList []json.RawMessage
if err := json.Unmarshal(data, &rawList); err != nil { if err := json.Unmarshal(data, &rawList); err != nil {
@@ -156,14 +157,14 @@ func (a *Album) DeList(data []byte, c ClientInterface) ([]Model, error) {
return result, nil return result, nil
} }
// AlbumMeta represents album metadata // AlbumMeta represents album metadata.
type AlbumMeta struct { type AlbumMeta struct {
BaseModel BaseModel
Availability *Availability `json:"availability"` Availability *Availability `json:"availability"`
Upsell *Upsell `json:"upsell"` Upsell *Upsell `json:"upsell"`
} }
// DeJSON deserializes an AlbumMeta from JSON // DeJSON deserializes an AlbumMeta from JSON data.
func (am *AlbumMeta) DeJSON(data []byte, c ClientInterface) (Model, error) { func (am *AlbumMeta) DeJSON(data []byte, c ClientInterface) (Model, error) {
var raw map[string]json.RawMessage var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil { if err := json.Unmarshal(data, &raw); err != nil {
@@ -186,7 +187,7 @@ func (am *AlbumMeta) DeJSON(data []byte, c ClientInterface) (Model, error) {
return meta, nil return meta, nil
} }
// DeList deserializes a list of AlbumMeta // DeList deserializes a list of AlbumMeta from JSON data.
func (am *AlbumMeta) DeList(data []byte, c ClientInterface) ([]Model, error) { func (am *AlbumMeta) DeList(data []byte, c ClientInterface) ([]Model, error) {
var rawList []json.RawMessage var rawList []json.RawMessage
if err := json.Unmarshal(data, &rawList); err != nil { if err := json.Unmarshal(data, &rawList); err != nil {
@@ -204,24 +205,24 @@ func (am *AlbumMeta) DeList(data []byte, c ClientInterface) ([]Model, error) {
return result, nil return result, nil
} }
// Availability represents availability info // Availability represents availability info for an album.
type Availability struct { type Availability struct {
AvailableForPremiumUsers bool `json:"available_for_premium_users"` AvailableForPremiumUsers bool `json:"available_for_premium_users"`
Territories []string `json:"territories"` Territories []string `json:"territories"`
} }
// Upsell represents upsell info // Upsell represents upsell info for an album.
type Upsell struct { type Upsell struct {
Type string `json:"type"` Type string `json:"type"`
Description string `json:"description"` Description string `json:"description"`
} }
// Best represents best tracks info // Best represents best tracks info for an album.
type Best struct { type Best struct {
Tracks []Track `json:"tracks"` Tracks []Track `json:"tracks"`
} }
// TrailerInfo represents album/track trailer info // TrailerInfo represents album/track trailer info.
type TrailerInfo struct { type TrailerInfo struct {
BaseModel BaseModel
PreviewURI string `json:"preview_uri"` PreviewURI string `json:"preview_uri"`
@@ -230,7 +231,7 @@ type TrailerInfo struct {
Duration int `json:"duration"` Duration int `json:"duration"`
} }
// DeJSON deserializes a TrailerInfo from JSON // DeJSON deserializes a TrailerInfo from JSON data.
func (ti *TrailerInfo) DeJSON(data []byte, c ClientInterface) (Model, error) { func (ti *TrailerInfo) DeJSON(data []byte, c ClientInterface) (Model, error) {
var raw map[string]json.RawMessage var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil { if err := json.Unmarshal(data, &raw); err != nil {
@@ -255,7 +256,7 @@ func (ti *TrailerInfo) DeJSON(data []byte, c ClientInterface) (Model, error) {
return trailer, nil return trailer, nil
} }
// DeList deserializes a list of TrailerInfo // DeList deserializes a list of TrailerInfo from JSON data.
func (ti *TrailerInfo) DeList(data []byte, c ClientInterface) ([]Model, error) { func (ti *TrailerInfo) DeList(data []byte, c ClientInterface) ([]Model, error) {
var rawList []json.RawMessage var rawList []json.RawMessage
if err := json.Unmarshal(data, &rawList); err != nil { if err := json.Unmarshal(data, &rawList); err != nil {
+17 -16
View File
@@ -1,10 +1,11 @@
// Package models provides data models for the Yandex Music API.
package models package models
import ( import (
"encoding/json" "encoding/json"
) )
// Artist represents a full artist // Artist represents a full artist from the Yandex Music API.
type Artist struct { type Artist struct {
BaseModel BaseModel
ID string `json:"id"` ID string `json:"id"`
@@ -34,7 +35,7 @@ type Artist struct {
TracksData []Track `json:"tracks_data"` TracksData []Track `json:"tracks_data"`
} }
// DeJSON deserializes an Artist from JSON // DeJSON deserializes an Artist from JSON data.
func (a *Artist) DeJSON(data []byte, c ClientInterface) (Model, error) { func (a *Artist) DeJSON(data []byte, c ClientInterface) (Model, error) {
var raw map[string]json.RawMessage var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil { if err := json.Unmarshal(data, &raw); err != nil {
@@ -146,7 +147,7 @@ func (a *Artist) DeJSON(data []byte, c ClientInterface) (Model, error) {
return artist, nil return artist, nil
} }
// DeList deserializes a list of Artists // DeList deserializes a list of Artists from JSON data.
func (a *Artist) DeList(data []byte, c ClientInterface) ([]Model, error) { func (a *Artist) DeList(data []byte, c ClientInterface) ([]Model, error) {
var rawList []json.RawMessage var rawList []json.RawMessage
if err := json.Unmarshal(data, &rawList); err != nil { if err := json.Unmarshal(data, &rawList); err != nil {
@@ -164,27 +165,27 @@ func (a *Artist) DeList(data []byte, c ClientInterface) ([]Model, error) {
return result, nil return result, nil
} }
// Ratings represents artist ratings // Ratings represents artist ratings.
type Ratings struct { type Ratings struct {
Rating float64 `json:"rating"` Rating float64 `json:"rating"`
Votes int `json:"votes"` Votes int `json:"votes"`
} }
// Counts represents artist counts // Counts represents artist counts.
type Counts struct { type Counts struct {
Tracks int `json:"tracks"` Tracks int `json:"tracks"`
Albums int `json:"albums"` Albums int `json:"albums"`
Folders int `json:"folders"` Folders int `json:"folders"`
} }
// SocialLink represents a social media link // SocialLink represents a social media link.
type SocialLink struct { type SocialLink struct {
URL string `json:"url"` URL string `json:"url"`
Title string `json:"title"` Title string `json:"title"`
Type string `json:"type"` Type string `json:"type"`
} }
// Cover represents cover image info // Cover represents cover image info.
type Cover struct { type Cover struct {
URI string `json:"uri"` URI string `json:"uri"`
Type string `json:"type"` Type string `json:"type"`
@@ -193,13 +194,13 @@ type Cover struct {
Background string `json:"background"` Background string `json:"background"`
} }
// ArtistBriefInfo represents brief artist info // ArtistBriefInfo represents brief artist info.
type ArtistBriefInfo struct { type ArtistBriefInfo struct {
Description string `json:"description"` Description string `json:"description"`
Available bool `json:"available"` Available bool `json:"available"`
} }
// ArtistDonations represents artist donations info // ArtistDonations represents artist donations info.
type ArtistDonations struct { type ArtistDonations struct {
Items []DonationItem `json:"items"` Items []DonationItem `json:"items"`
Total int `json:"total"` Total int `json:"total"`
@@ -207,7 +208,7 @@ type ArtistDonations struct {
Raised int `json:"raised"` Raised int `json:"raised"`
} }
// DonationItem represents a donation item // DonationItem represents a donation item.
type DonationItem struct { type DonationItem struct {
ID string `json:"id"` ID string `json:"id"`
Title string `json:"title"` Title string `json:"title"`
@@ -218,7 +219,7 @@ type DonationItem struct {
Currency string `json:"currency"` Currency string `json:"currency"`
} }
// ConcertShort represents a concert (minimal for artist) // ConcertShort represents a concert (minimal for artist).
type ConcertShort struct { type ConcertShort struct {
BaseModel BaseModel
ID string `json:"id"` ID string `json:"id"`
@@ -233,7 +234,7 @@ type ConcertShort struct {
Available bool `json:"available"` Available bool `json:"available"`
} }
// DeJSON deserializes a ConcertShort from JSON // DeJSON deserializes a ConcertShort from JSON data.
func (c *ConcertShort) DeJSON(data []byte, client ClientInterface) (Model, error) { func (c *ConcertShort) DeJSON(data []byte, client ClientInterface) (Model, error) {
var raw map[string]json.RawMessage var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil { if err := json.Unmarshal(data, &raw); err != nil {
@@ -276,7 +277,7 @@ func (c *ConcertShort) DeJSON(data []byte, client ClientInterface) (Model, error
return concert, nil return concert, nil
} }
// DeList deserializes a list of ConcertShort // DeList deserializes a list of ConcertShort from JSON data.
func (c *ConcertShort) DeList(data []byte, client ClientInterface) ([]Model, error) { func (c *ConcertShort) DeList(data []byte, client ClientInterface) ([]Model, error) {
var rawList []json.RawMessage var rawList []json.RawMessage
if err := json.Unmarshal(data, &rawList); err != nil { if err := json.Unmarshal(data, &rawList); err != nil {
@@ -294,7 +295,7 @@ func (c *ConcertShort) DeList(data []byte, client ClientInterface) ([]Model, err
return result, nil return result, nil
} }
// ClipShort represents a clip (minimal for artist) // ClipShort represents a clip (minimal for artist).
type ClipShort struct { type ClipShort struct {
BaseModel BaseModel
ID string `json:"id"` ID string `json:"id"`
@@ -308,7 +309,7 @@ type ClipShort struct {
CreatedAt string `json:"created_at"` CreatedAt string `json:"created_at"`
} }
// DeJSON deserializes a ClipShort from JSON // DeJSON deserializes a ClipShort from JSON data.
func (c *ClipShort) DeJSON(data []byte, client ClientInterface) (Model, error) { func (c *ClipShort) DeJSON(data []byte, client ClientInterface) (Model, error) {
var raw map[string]json.RawMessage var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil { if err := json.Unmarshal(data, &raw); err != nil {
@@ -348,7 +349,7 @@ func (c *ClipShort) DeJSON(data []byte, client ClientInterface) (Model, error) {
return clip, nil return clip, nil
} }
// DeList deserializes a list of ClipShort // DeList deserializes a list of ClipShort from JSON data.
func (c *ClipShort) DeList(data []byte, client ClientInterface) ([]Model, error) { func (c *ClipShort) DeList(data []byte, client ClientInterface) ([]Model, error) {
var rawList []json.RawMessage var rawList []json.RawMessage
if err := json.Unmarshal(data, &rawList); err != nil { if err := json.Unmarshal(data, &rawList); err != nil {
+4 -3
View File
@@ -1,17 +1,18 @@
// Package models provides data models for the Yandex Music API.
package models package models
import ( import (
"encoding/json" "encoding/json"
) )
// ArtistAlbums represents a page of albums by an artist // ArtistAlbums represents a page of albums by an artist.
type ArtistAlbums struct { type ArtistAlbums struct {
BaseModel BaseModel
Albums []Album `json:"albums"` Albums []Album `json:"albums"`
Pager *Pager `json:"pager"` Pager *Pager `json:"pager"`
} }
// DeJSON deserializes an ArtistAlbums from JSON // DeJSON deserializes an ArtistAlbums from JSON data.
func (aa *ArtistAlbums) DeJSON(data []byte, c ClientInterface) (Model, error) { func (aa *ArtistAlbums) DeJSON(data []byte, c ClientInterface) (Model, error) {
var raw map[string]json.RawMessage var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil { if err := json.Unmarshal(data, &raw); err != nil {
@@ -36,7 +37,7 @@ func (aa *ArtistAlbums) DeJSON(data []byte, c ClientInterface) (Model, error) {
return albums, nil return albums, nil
} }
// DeList deserializes a list of ArtistAlbums // DeList deserializes a list of ArtistAlbums from JSON data.
func (aa *ArtistAlbums) DeList(data []byte, c ClientInterface) ([]Model, error) { func (aa *ArtistAlbums) DeList(data []byte, c ClientInterface) ([]Model, error) {
var rawList []json.RawMessage var rawList []json.RawMessage
if err := json.Unmarshal(data, &rawList); err != nil { if err := json.Unmarshal(data, &rawList); err != nil {
+4 -3
View File
@@ -1,17 +1,18 @@
// Package models provides data models for the Yandex Music API.
package models package models
import ( import (
"encoding/json" "encoding/json"
) )
// ArtistTracks represents a page of tracks by an artist // ArtistTracks represents a page of tracks by an artist.
type ArtistTracks struct { type ArtistTracks struct {
BaseModel BaseModel
Tracks []Track `json:"tracks"` Tracks []Track `json:"tracks"`
Pager *Pager `json:"pager"` Pager *Pager `json:"pager"`
} }
// DeJSON deserializes an ArtistTracks from JSON // DeJSON deserializes an ArtistTracks from JSON data.
func (at *ArtistTracks) DeJSON(data []byte, c ClientInterface) (Model, error) { func (at *ArtistTracks) DeJSON(data []byte, c ClientInterface) (Model, error) {
var raw map[string]json.RawMessage var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil { if err := json.Unmarshal(data, &raw); err != nil {
@@ -36,7 +37,7 @@ func (at *ArtistTracks) DeJSON(data []byte, c ClientInterface) (Model, error) {
return tracks, nil return tracks, nil
} }
// DeList deserializes a list of ArtistTracks // DeList deserializes a list of ArtistTracks from JSON data.
func (at *ArtistTracks) DeList(data []byte, c ClientInterface) ([]Model, error) { func (at *ArtistTracks) DeList(data []byte, c ClientInterface) ([]Model, error) {
var rawList []json.RawMessage var rawList []json.RawMessage
if err := json.Unmarshal(data, &rawList); err != nil { if err := json.Unmarshal(data, &rawList); err != nil {
+16 -13
View File
@@ -8,35 +8,38 @@ import (
"gitea.mrixs.me/Mrixs/yandex-music-api-go/internal/utils" "gitea.mrixs.me/Mrixs/yandex-music-api-go/internal/utils"
) )
// Model is the base interface for all models // Model is the base interface for all models.
// All model types implement this interface for JSON deserialization and serialization.
type Model interface { type Model interface {
// DeJSON deserializes from JSON // DeJSON deserializes a model from JSON data.
DeJSON(data []byte, c ClientInterface) (Model, error) DeJSON(data []byte, c ClientInterface) (Model, error)
// DeList deserializes a list of models // DeList deserializes a list of models from JSON data.
DeList(data []byte, c ClientInterface) ([]Model, error) DeList(data []byte, c ClientInterface) ([]Model, error)
// ToJSON serializes to JSON // ToJSON serializes the model to JSON.
ToJSON() ([]byte, error) ToJSON() ([]byte, error)
// ToMap converts to map // ToMap converts the model to a map.
ToMap() (map[string]any, error) ToMap() (map[string]any, error)
} }
// BaseModel provides common functionality for models // BaseModel provides common functionality for models, including a client reference.
type BaseModel struct { type BaseModel struct {
Client ClientInterface `json:"-"` Client ClientInterface `json:"-"`
} }
// NewBaseModel creates a new BaseModel // NewBaseModel creates a new BaseModel with the given client interface.
func NewBaseModel(c ClientInterface) *BaseModel { func NewBaseModel(c ClientInterface) *BaseModel {
return &BaseModel{Client: c} return &BaseModel{Client: c}
} }
// DeJSON implements Model.DeJSON for basic models // DeJSON implements Model.DeJSON for basic models.
// This should be overridden by concrete types.
func (b *BaseModel) DeJSON(data []byte, c ClientInterface) (Model, error) { func (b *BaseModel) DeJSON(data []byte, c ClientInterface) (Model, error) {
// This should be overridden by concrete types // This should be overridden by concrete types
return nil, nil return nil, nil
} }
// DeList implements Model.DeList for basic models // DeList implements Model.DeList for basic models.
// This should be overridden by concrete types.
func (b *BaseModel) DeList(data []byte, c ClientInterface) ([]Model, error) { func (b *BaseModel) DeList(data []byte, c ClientInterface) ([]Model, error) {
var rawList []json.RawMessage var rawList []json.RawMessage
if err := json.Unmarshal(data, &rawList); err != nil { if err := json.Unmarshal(data, &rawList); err != nil {
@@ -51,12 +54,12 @@ func (b *BaseModel) DeList(data []byte, c ClientInterface) ([]Model, error) {
return result, nil return result, nil
} }
// ToJSON serializes the model to JSON // ToJSON serializes the model to JSON using the default JSON backend.
func (b *BaseModel) ToJSON() ([]byte, error) { func (b *BaseModel) ToJSON() ([]byte, error) {
return utils.Marshal(b) return utils.Marshal(b)
} }
// ToMap converts the model to a map // ToMap converts the model to a map by serializing to JSON and unmarshaling into a map.
func (b *BaseModel) ToMap() (map[string]any, error) { func (b *BaseModel) ToMap() (map[string]any, error) {
data, err := b.ToJSON() data, err := b.ToJSON()
if err != nil { if err != nil {
@@ -69,12 +72,12 @@ func (b *BaseModel) ToMap() (map[string]any, error) {
return result, nil return result, nil
} }
// SetClient sets the client on the model // SetClient sets the client interface on the model.
func (b *BaseModel) SetClient(c ClientInterface) { func (b *BaseModel) SetClient(c ClientInterface) {
b.Client = c b.Client = c
} }
// GetClient returns the client // GetClient returns the client interface associated with the model.
func (b *BaseModel) GetClient() ClientInterface { func (b *BaseModel) GetClient() ClientInterface {
return b.Client return b.Client
} }
+11 -2
View File
@@ -1,19 +1,28 @@
// Package models provides data models for the Yandex Music API.
package models package models
import ( import (
"context" "context"
) )
// ClientInterface defines the minimal client interface needed by models // ClientInterface defines the minimal client interface needed by models.
// Models use this to access the underlying request handler.
type ClientInterface interface { type ClientInterface interface {
// GetRequest returns the underlying request handler.
GetRequest() RequestInterface GetRequest() RequestInterface
} }
// RequestInterface defines the minimal request interface needed by models // RequestInterface defines the minimal request interface needed by models.
// It provides methods for making HTTP requests to the Yandex Music API.
type RequestInterface interface { type RequestInterface interface {
// Get performs a GET request to the given path with query parameters.
Get(ctx context.Context, path string, params map[string]string, result any) error Get(ctx context.Context, path string, params map[string]string, result any) error
// Post performs a POST request to the given path with a JSON body.
Post(ctx context.Context, path string, body any, result any) error Post(ctx context.Context, path string, body any, result any) error
// Put performs a PUT request to the given path with a JSON body.
Put(ctx context.Context, path string, body any, result any) error Put(ctx context.Context, path string, body any, result any) error
// Delete performs a DELETE request to the given path with an optional JSON body.
Delete(ctx context.Context, path string, body any, result any) error Delete(ctx context.Context, path string, body any, result any) error
// Download downloads a file from the given URL and returns the raw response body.
Download(ctx context.Context, url string) ([]byte, error) Download(ctx context.Context, url string) ([]byte, error)
} }
+13 -12
View File
@@ -1,10 +1,11 @@
// Package models provides data models for the Yandex Music API.
package models package models
import ( import (
"encoding/json" "encoding/json"
) )
// Clip represents a clip (short video) // Clip represents a clip (short video) from the Yandex Music API.
type Clip struct { type Clip struct {
BaseModel BaseModel
ID string `json:"id"` ID string `json:"id"`
@@ -24,7 +25,7 @@ type Clip struct {
AspectRatio string `json:"aspect_ratio"` AspectRatio string `json:"aspect_ratio"`
} }
// DeJSON deserializes a Clip from JSON // DeJSON deserializes a Clip from JSON data.
func (c *Clip) DeJSON(data []byte, client ClientInterface) (Model, error) { func (c *Clip) DeJSON(data []byte, client ClientInterface) (Model, error) {
var raw map[string]json.RawMessage var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil { if err := json.Unmarshal(data, &raw); err != nil {
@@ -89,7 +90,7 @@ func (c *Clip) DeJSON(data []byte, client ClientInterface) (Model, error) {
return clip, nil return clip, nil
} }
// DeList deserializes a list of Clips // DeList deserializes a list of Clips from JSON data.
func (c *Clip) DeList(data []byte, client ClientInterface) ([]Model, error) { func (c *Clip) DeList(data []byte, client ClientInterface) ([]Model, error) {
var rawList []json.RawMessage var rawList []json.RawMessage
if err := json.Unmarshal(data, &rawList); err != nil { if err := json.Unmarshal(data, &rawList); err != nil {
@@ -107,28 +108,28 @@ func (c *Clip) DeList(data []byte, client ClientInterface) ([]Model, error) {
return result, nil return result, nil
} }
// ClipsWillLike represents clips the user might like // ClipsWillLike represents clips the user might like.
type ClipsWillLike struct { type ClipsWillLike struct {
BaseModel BaseModel
Clips []Clip `json:"clips"` Clips []Clip `json:"clips"`
Total int `json:"total"` Total int `json:"total"`
} }
// ArtistClipData represents artist clip data // ArtistClipData represents artist clip data.
type ArtistClipData struct { type ArtistClipData struct {
BaseModel BaseModel
Clips []Clip `json:"clips"` Clips []Clip `json:"clips"`
Total int `json:"total"` Total int `json:"total"`
} }
// ArtistClipItem represents an artist clip item // ArtistClipItem represents an artist clip item.
type ArtistClipItem struct { type ArtistClipItem struct {
BaseModel BaseModel
Clip *Clip `json:"clip"` Clip *Clip `json:"clip"`
Index int `json:"index"` Index int `json:"index"`
} }
// Shot represents a shot (short video) // Shot represents a shot (short video).
type Shot struct { type Shot struct {
BaseModel BaseModel
ID string `json:"id"` ID string `json:"id"`
@@ -150,7 +151,7 @@ type Shot struct {
AspectRatio string `json:"aspect_ratio"` AspectRatio string `json:"aspect_ratio"`
} }
// DeJSON deserializes a Shot from JSON // DeJSON deserializes a Shot from JSON data.
func (s *Shot) DeJSON(data []byte, client ClientInterface) (Model, error) { func (s *Shot) DeJSON(data []byte, client ClientInterface) (Model, error) {
var raw map[string]json.RawMessage var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil { if err := json.Unmarshal(data, &raw); err != nil {
@@ -219,7 +220,7 @@ func (s *Shot) DeJSON(data []byte, client ClientInterface) (Model, error) {
return shot, nil return shot, nil
} }
// DeList deserializes a list of Shots // DeList deserializes a list of Shots from JSON data.
func (s *Shot) DeList(data []byte, client ClientInterface) ([]Model, error) { func (s *Shot) DeList(data []byte, client ClientInterface) ([]Model, error) {
var rawList []json.RawMessage var rawList []json.RawMessage
if err := json.Unmarshal(data, &rawList); err != nil { if err := json.Unmarshal(data, &rawList); err != nil {
@@ -237,14 +238,14 @@ func (s *Shot) DeList(data []byte, client ClientInterface) ([]Model, error) {
return result, nil return result, nil
} }
// ShotData represents shot data // ShotData represents shot data.
type ShotData struct { type ShotData struct {
BaseModel BaseModel
Shots []Shot `json:"shots"` Shots []Shot `json:"shots"`
Total int `json:"total"` Total int `json:"total"`
} }
// ShotEvent represents a shot event // ShotEvent represents a shot event.
type ShotEvent struct { type ShotEvent struct {
BaseModel BaseModel
EventID string `json:"event_id"` EventID string `json:"event_id"`
@@ -254,7 +255,7 @@ type ShotEvent struct {
Action string `json:"action"` Action string `json:"action"`
} }
// ShotType represents a shot type // ShotType represents a shot type.
type ShotType struct { type ShotType struct {
BaseModel BaseModel
ID string `json:"id"` ID string `json:"id"`
+17 -16
View File
@@ -1,10 +1,11 @@
// Package models provides data models for the Yandex Music API.
package models package models
import ( import (
"encoding/json" "encoding/json"
) )
// Concert represents a concert // Concert represents a concert from the Yandex Music API.
type Concert struct { type Concert struct {
BaseModel BaseModel
ID string `json:"id"` ID string `json:"id"`
@@ -28,7 +29,7 @@ type Concert struct {
Skeleton *ConcertSkeleton `json:"skeleton"` Skeleton *ConcertSkeleton `json:"skeleton"`
} }
// DeJSON deserializes a Concert from JSON // DeJSON deserializes a Concert from JSON data.
func (c *Concert) DeJSON(data []byte, client ClientInterface) (Model, error) { func (c *Concert) DeJSON(data []byte, client ClientInterface) (Model, error) {
var raw map[string]json.RawMessage var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil { if err := json.Unmarshal(data, &raw); err != nil {
@@ -111,7 +112,7 @@ func (c *Concert) DeJSON(data []byte, client ClientInterface) (Model, error) {
return concert, nil return concert, nil
} }
// DeList deserializes a list of Concerts // DeList deserializes a list of Concerts from JSON data.
func (c *Concert) DeList(data []byte, client ClientInterface) ([]Model, error) { func (c *Concert) DeList(data []byte, client ClientInterface) ([]Model, error) {
var rawList []json.RawMessage var rawList []json.RawMessage
if err := json.Unmarshal(data, &rawList); err != nil { if err := json.Unmarshal(data, &rawList); err != nil {
@@ -129,7 +130,7 @@ func (c *Concert) DeList(data []byte, client ClientInterface) ([]Model, error) {
return result, nil return result, nil
} }
// ConcertVenue represents a concert venue // ConcertVenue represents a concert venue.
type ConcertVenue struct { type ConcertVenue struct {
BaseModel BaseModel
ID string `json:"id"` ID string `json:"id"`
@@ -141,7 +142,7 @@ type ConcertVenue struct {
ImageURI string `json:"image_uri"` ImageURI string `json:"image_uri"`
} }
// ConcertLocation represents a concert location // ConcertLocation represents a concert location.
type ConcertLocation struct { type ConcertLocation struct {
BaseModel BaseModel
ID string `json:"id"` ID string `json:"id"`
@@ -152,7 +153,7 @@ type ConcertLocation struct {
Venues []ConcertVenue `json:"venues"` Venues []ConcertVenue `json:"venues"`
} }
// ConcertLocations represents concert locations // ConcertLocations represents concert locations.
type ConcertLocations struct { type ConcertLocations struct {
BaseModel BaseModel
Locations []ConcertLocation `json:"locations"` Locations []ConcertLocation `json:"locations"`
@@ -161,7 +162,7 @@ type ConcertLocations struct {
PageSize int `json:"page_size"` PageSize int `json:"page_size"`
} }
// ConcertFeed represents a concert feed // ConcertFeed represents a concert feed.
type ConcertFeed struct { type ConcertFeed struct {
BaseModel BaseModel
Concerts []Concert `json:"concerts"` Concerts []Concert `json:"concerts"`
@@ -170,14 +171,14 @@ type ConcertFeed struct {
PageSize int `json:"page_size"` PageSize int `json:"page_size"`
} }
// ConcertInfo represents concert info // ConcertInfo represents concert info.
type ConcertInfo struct { type ConcertInfo struct {
BaseModel BaseModel
Concert *Concert `json:"concert"` Concert *Concert `json:"concert"`
Related []Concert `json:"related"` Related []Concert `json:"related"`
} }
// ConcertEventInfo represents concert event info // ConcertEventInfo represents concert event info.
type ConcertEventInfo struct { type ConcertEventInfo struct {
BaseModel BaseModel
EventID string `json:"event_id"` EventID string `json:"event_id"`
@@ -186,7 +187,7 @@ type ConcertEventInfo struct {
Data json.RawMessage `json:"data"` Data json.RawMessage `json:"data"`
} }
// ConcertDescription represents concert description // ConcertDescription represents concert description.
type ConcertDescription struct { type ConcertDescription struct {
BaseModel BaseModel
Text string `json:"text"` Text string `json:"text"`
@@ -194,7 +195,7 @@ type ConcertDescription struct {
ShortText string `json:"short_text"` ShortText string `json:"short_text"`
} }
// ConcertCashback represents concert cashback // ConcertCashback represents concert cashback.
type ConcertCashback struct { type ConcertCashback struct {
BaseModel BaseModel
Amount int `json:"amount"` Amount int `json:"amount"`
@@ -203,14 +204,14 @@ type ConcertCashback struct {
Expires string `json:"expires"` Expires string `json:"expires"`
} }
// ConcertMinPrice represents concert min price // ConcertMinPrice represents concert min price.
type ConcertMinPrice struct { type ConcertMinPrice struct {
BaseModel BaseModel
Price int `json:"price"` Price int `json:"price"`
Currency string `json:"currency"` Currency string `json:"currency"`
} }
// ConcertTabConfig represents concert tab config // ConcertTabConfig represents concert tab config.
type ConcertTabConfig struct { type ConcertTabConfig struct {
BaseModel BaseModel
ID string `json:"id"` ID string `json:"id"`
@@ -220,20 +221,20 @@ type ConcertTabConfig struct {
Range *ConcertTabRange `json:"range"` Range *ConcertTabRange `json:"range"`
} }
// ConcertTabRange represents concert tab range // ConcertTabRange represents concert tab range.
type ConcertTabRange struct { type ConcertTabRange struct {
BaseModel BaseModel
From string `json:"from"` From string `json:"from"`
To string `json:"to"` To string `json:"to"`
} }
// ConcertSkeleton represents concert skeleton // ConcertSkeleton represents concert skeleton.
type ConcertSkeleton struct { type ConcertSkeleton struct {
BaseModel BaseModel
Blocks []ConcertSkeletonBlock `json:"blocks"` Blocks []ConcertSkeletonBlock `json:"blocks"`
} }
// ConcertSkeletonBlock represents a concert skeleton block // ConcertSkeletonBlock represents a concert skeleton block.
type ConcertSkeletonBlock struct { type ConcertSkeletonBlock struct {
BaseModel BaseModel
ID string `json:"id"` ID string `json:"id"`
+9 -8
View File
@@ -1,17 +1,18 @@
// Package models provides data models for the Yandex Music API.
package models package models
import ( import (
"encoding/json" "encoding/json"
) )
// Credits represents track credits // Credits represents track credits from the Yandex Music API.
type Credits struct { type Credits struct {
BaseModel BaseModel
Items []Credit `json:"items"` Items []Credit `json:"items"`
Total int `json:"total"` Total int `json:"total"`
} }
// DeJSON deserializes Credits from JSON // DeJSON deserializes Credits from JSON data.
func (c *Credits) DeJSON(data []byte, client ClientInterface) (Model, error) { func (c *Credits) DeJSON(data []byte, client ClientInterface) (Model, error) {
var raw map[string]json.RawMessage var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil { if err := json.Unmarshal(data, &raw); err != nil {
@@ -32,7 +33,7 @@ func (c *Credits) DeJSON(data []byte, client ClientInterface) (Model, error) {
return credits, nil return credits, nil
} }
// DeList deserializes a list of Credits // DeList deserializes a list of Credits from JSON data. from JSON data.
func (c *Credits) DeList(data []byte, client ClientInterface) ([]Model, error) { func (c *Credits) DeList(data []byte, client ClientInterface) ([]Model, error) {
var rawList []json.RawMessage var rawList []json.RawMessage
if err := json.Unmarshal(data, &rawList); err != nil { if err := json.Unmarshal(data, &rawList); err != nil {
@@ -50,7 +51,7 @@ func (c *Credits) DeList(data []byte, client ClientInterface) ([]Model, error) {
return result, nil return result, nil
} }
// Credit represents a credit // Credit represents a credit.
type Credit struct { type Credit struct {
BaseModel BaseModel
Role string `json:"role"` Role string `json:"role"`
@@ -62,7 +63,7 @@ type Credit struct {
AlbumID string `json:"album_id"` AlbumID string `json:"album_id"`
} }
// DeJSON deserializes a Credit from JSON // DeJSON deserializes a Credit from JSON data.
func (c *Credit) DeJSON(data []byte, client ClientInterface) (Model, error) { func (c *Credit) DeJSON(data []byte, client ClientInterface) (Model, error) {
var raw map[string]json.RawMessage var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil { if err := json.Unmarshal(data, &raw); err != nil {
@@ -114,7 +115,7 @@ func (c *Credit) DeList(data []byte, client ClientInterface) ([]Model, error) {
return result, nil return result, nil
} }
// LicenceTextPart represents a licence text part // LicenceTextPart represents a licence text part.
type LicenceTextPart struct { type LicenceTextPart struct {
BaseModel BaseModel
Text string `json:"text"` Text string `json:"text"`
@@ -124,7 +125,7 @@ type LicenceTextPart struct {
IsMain bool `json:"is_main"` IsMain bool `json:"is_main"`
} }
// DeJSON deserializes a LicenceTextPart from JSON // DeJSON deserializes a LicenceTextPart from JSON data.
func (ltp *LicenceTextPart) DeJSON(data []byte, client ClientInterface) (Model, error) { func (ltp *LicenceTextPart) DeJSON(data []byte, client ClientInterface) (Model, error) {
var raw map[string]json.RawMessage var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil { if err := json.Unmarshal(data, &raw); err != nil {
@@ -152,7 +153,7 @@ func (ltp *LicenceTextPart) DeJSON(data []byte, client ClientInterface) (Model,
return part, nil return part, nil
} }
// DeList deserializes a list of LicenceTextPart // DeList deserializes a list of LicenceTextPart from JSON data.
func (ltp *LicenceTextPart) DeList(data []byte, client ClientInterface) ([]Model, error) { func (ltp *LicenceTextPart) DeList(data []byte, client ClientInterface) ([]Model, error) {
var rawList []json.RawMessage var rawList []json.RawMessage
if err := json.Unmarshal(data, &rawList); err != nil { if err := json.Unmarshal(data, &rawList); err != nil {
+18 -17
View File
@@ -1,10 +1,11 @@
// Package models provides data models for the Yandex Music API.
package models package models
import ( import (
"encoding/json" "encoding/json"
) )
// Feed represents the main feed // Feed represents the main feed from the Yandex Music API.
type Feed struct { type Feed struct {
BaseModel BaseModel
Days []Day `json:"days"` Days []Day `json:"days"`
@@ -12,7 +13,7 @@ type Feed struct {
PlayContexts []PlayContext `json:"play_contexts"` PlayContexts []PlayContext `json:"play_contexts"`
} }
// DeJSON deserializes a Feed from JSON // DeJSON deserializes a Feed from JSON data.
func (f *Feed) DeJSON(data []byte, c ClientInterface) (Model, error) { func (f *Feed) DeJSON(data []byte, c ClientInterface) (Model, error) {
var raw map[string]json.RawMessage var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil { if err := json.Unmarshal(data, &raw); err != nil {
@@ -40,7 +41,7 @@ func (f *Feed) DeJSON(data []byte, c ClientInterface) (Model, error) {
return feed, nil return feed, nil
} }
// DeList deserializes a list of Feeds // DeList deserializes a list of Feeds from JSON data.
func (f *Feed) DeList(data []byte, c ClientInterface) ([]Model, error) { func (f *Feed) DeList(data []byte, c ClientInterface) ([]Model, error) {
var rawList []json.RawMessage var rawList []json.RawMessage
if err := json.Unmarshal(data, &rawList); err != nil { if err := json.Unmarshal(data, &rawList); err != nil {
@@ -58,7 +59,7 @@ func (f *Feed) DeList(data []byte, c ClientInterface) ([]Model, error) {
return result, nil return result, nil
} }
// Day represents a day in the feed // Day represents a day in the feed.
type Day struct { type Day struct {
BaseModel BaseModel
Date string `json:"date"` Date string `json:"date"`
@@ -68,7 +69,7 @@ type Day struct {
GeneratedPlaylists []GeneratedPlaylist `json:"generated_playlists"` GeneratedPlaylists []GeneratedPlaylist `json:"generated_playlists"`
} }
// DeJSON deserializes a Day from JSON // DeJSON deserializes a Day from JSON data.
func (d *Day) DeJSON(data []byte, c ClientInterface) (Model, error) { func (d *Day) DeJSON(data []byte, c ClientInterface) (Model, error) {
var raw map[string]json.RawMessage var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil { if err := json.Unmarshal(data, &raw); err != nil {
@@ -100,7 +101,7 @@ func (d *Day) DeJSON(data []byte, c ClientInterface) (Model, error) {
return day, nil return day, nil
} }
// DeList deserializes a list of Days // DeList deserializes a list of Days from JSON data.
func (d *Day) DeList(data []byte, c ClientInterface) ([]Model, error) { func (d *Day) DeList(data []byte, c ClientInterface) ([]Model, error) {
var rawList []json.RawMessage var rawList []json.RawMessage
if err := json.Unmarshal(data, &rawList); err != nil { if err := json.Unmarshal(data, &rawList); err != nil {
@@ -118,7 +119,7 @@ func (d *Day) DeList(data []byte, c ClientInterface) ([]Model, error) {
return result, nil return result, nil
} }
// DayBlock represents a block in a day // DayBlock represents a block in a day.
type DayBlock struct { type DayBlock struct {
BaseModel BaseModel
ID string `json:"id"` ID string `json:"id"`
@@ -128,7 +129,7 @@ type DayBlock struct {
Data *DayBlockData `json:"data"` Data *DayBlockData `json:"data"`
} }
// DayBlockData represents data in a day block // DayBlockData represents data in a day block.
type DayBlockData struct { type DayBlockData struct {
Tracks []Track `json:"tracks"` Tracks []Track `json:"tracks"`
Playlists []Playlist `json:"playlists"` Playlists []Playlist `json:"playlists"`
@@ -137,7 +138,7 @@ type DayBlockData struct {
GeneratedPlaylist *GeneratedPlaylist `json:"generated_playlist"` GeneratedPlaylist *GeneratedPlaylist `json:"generated_playlist"`
} }
// GeneratedPlaylist represents a generated playlist // GeneratedPlaylist represents a generated playlist.
type GeneratedPlaylist struct { type GeneratedPlaylist struct {
BaseModel BaseModel
ID string `json:"id"` ID string `json:"id"`
@@ -153,7 +154,7 @@ type GeneratedPlaylist struct {
Tracks []Track `json:"tracks"` Tracks []Track `json:"tracks"`
} }
// DeJSON deserializes a GeneratedPlaylist from JSON // DeJSON deserializes a GeneratedPlaylist from JSON data.
func (gp *GeneratedPlaylist) DeJSON(data []byte, c ClientInterface) (Model, error) { func (gp *GeneratedPlaylist) DeJSON(data []byte, c ClientInterface) (Model, error) {
var raw map[string]json.RawMessage var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil { if err := json.Unmarshal(data, &raw); err != nil {
@@ -201,7 +202,7 @@ func (gp *GeneratedPlaylist) DeJSON(data []byte, c ClientInterface) (Model, erro
return playlist, nil return playlist, nil
} }
// DeList deserializes a list of GeneratedPlaylists // DeList deserializes a list of GeneratedPlaylists from JSON data.
func (gp *GeneratedPlaylist) DeList(data []byte, c ClientInterface) ([]Model, error) { func (gp *GeneratedPlaylist) DeList(data []byte, c ClientInterface) ([]Model, error) {
var rawList []json.RawMessage var rawList []json.RawMessage
if err := json.Unmarshal(data, &rawList); err != nil { if err := json.Unmarshal(data, &rawList); err != nil {
@@ -219,7 +220,7 @@ func (gp *GeneratedPlaylist) DeList(data []byte, c ClientInterface) ([]Model, er
return result, nil return result, nil
} }
// Event represents a feed event // Event represents a feed event.
type Event struct { type Event struct {
BaseModel BaseModel
Timestamp string `json:"timestamp"` Timestamp string `json:"timestamp"`
@@ -231,7 +232,7 @@ type Event struct {
Action string `json:"action"` Action string `json:"action"`
} }
// AlbumEvent represents an album event // AlbumEvent represents an album event.
type AlbumEvent struct { type AlbumEvent struct {
BaseModel BaseModel
Album *Album `json:"album"` Album *Album `json:"album"`
@@ -240,7 +241,7 @@ type AlbumEvent struct {
Action string `json:"action"` Action string `json:"action"`
} }
// ArtistEvent represents an artist event // ArtistEvent represents an artist event.
type ArtistEvent struct { type ArtistEvent struct {
BaseModel BaseModel
Artist *Artist `json:"artist"` Artist *Artist `json:"artist"`
@@ -249,7 +250,7 @@ type ArtistEvent struct {
Action string `json:"action"` Action string `json:"action"`
} }
// TrackWithAds represents a track with ads // TrackWithAds represents a track with ads.
type TrackWithAds struct { type TrackWithAds struct {
BaseModel BaseModel
Track *Track `json:"track"` Track *Track `json:"track"`
@@ -257,7 +258,7 @@ type TrackWithAds struct {
AdParams *AdParams `json:"ad_params"` AdParams *AdParams `json:"ad_params"`
} }
// Ad represents an ad // Ad represents an ad.
type Ad struct { type Ad struct {
BaseModel BaseModel
ID string `json:"id"` ID string `json:"id"`
@@ -269,7 +270,7 @@ type Ad struct {
Duration int `json:"duration"` Duration int `json:"duration"`
} }
// AdParams represents ad parameters // AdParams represents ad parameters.
type AdParams struct { type AdParams struct {
BaseModel BaseModel
Frequency int `json:"frequency"` Frequency int `json:"frequency"`
+6 -5
View File
@@ -1,10 +1,11 @@
// Package models provides data models for the Yandex Music API.
package models package models
import ( import (
"encoding/json" "encoding/json"
) )
// Label represents a label // Label represents a label from the Yandex Music API.
type Label struct { type Label struct {
BaseModel BaseModel
ID string `json:"id"` ID string `json:"id"`
@@ -17,7 +18,7 @@ type Label struct {
Owner *User `json:"owner"` Owner *User `json:"owner"`
} }
// DeJSON deserializes a Label from JSON // DeJSON deserializes a Label from JSON data.
func (l *Label) DeJSON(data []byte, client ClientInterface) (Model, error) { func (l *Label) DeJSON(data []byte, client ClientInterface) (Model, error) {
var raw map[string]json.RawMessage var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil { if err := json.Unmarshal(data, &raw); err != nil {
@@ -58,7 +59,7 @@ func (l *Label) DeJSON(data []byte, client ClientInterface) (Model, error) {
return label, nil return label, nil
} }
// DeList deserializes a list of Labels // DeList deserializes a list of Labels from JSON data.
func (l *Label) DeList(data []byte, client ClientInterface) ([]Model, error) { func (l *Label) DeList(data []byte, client ClientInterface) ([]Model, error) {
var rawList []json.RawMessage var rawList []json.RawMessage
if err := json.Unmarshal(data, &rawList); err != nil { if err := json.Unmarshal(data, &rawList); err != nil {
@@ -76,7 +77,7 @@ func (l *Label) DeList(data []byte, client ClientInterface) ([]Model, error) {
return result, nil return result, nil
} }
// LabelAlbums represents label albums // LabelAlbums represents label albums.
type LabelAlbums struct { type LabelAlbums struct {
BaseModel BaseModel
Albums []Album `json:"albums"` Albums []Album `json:"albums"`
@@ -85,7 +86,7 @@ type LabelAlbums struct {
PageSize int `json:"page_size"` PageSize int `json:"page_size"`
} }
// LabelArtists represents label artists // LabelArtists represents label artists.
type LabelArtists struct { type LabelArtists struct {
BaseModel BaseModel
Artists []Artist `json:"artists"` Artists []Artist `json:"artists"`
+9 -8
View File
@@ -1,10 +1,11 @@
// Package models provides data models for the Yandex Music API.
package models package models
import ( import (
"encoding/json" "encoding/json"
) )
// Landing represents a landing page // Landing represents a landing page from the Yandex Music API.
type Landing struct { type Landing struct {
BaseModel BaseModel
ID string `json:"id"` ID string `json:"id"`
@@ -16,7 +17,7 @@ type Landing struct {
Available bool `json:"available"` Available bool `json:"available"`
} }
// DeJSON deserializes a Landing from JSON // DeJSON deserializes a Landing from JSON data.
func (l *Landing) DeJSON(data []byte, c ClientInterface) (Model, error) { func (l *Landing) DeJSON(data []byte, c ClientInterface) (Model, error) {
var raw map[string]json.RawMessage var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil { if err := json.Unmarshal(data, &raw); err != nil {
@@ -53,7 +54,7 @@ func (l *Landing) DeJSON(data []byte, c ClientInterface) (Model, error) {
return landing, nil return landing, nil
} }
// DeList deserializes a list of Landings // DeList deserializes a list of Landings from JSON data.
func (l *Landing) DeList(data []byte, c ClientInterface) ([]Model, error) { func (l *Landing) DeList(data []byte, c ClientInterface) ([]Model, error) {
var rawList []json.RawMessage var rawList []json.RawMessage
if err := json.Unmarshal(data, &rawList); err != nil { if err := json.Unmarshal(data, &rawList); err != nil {
@@ -71,7 +72,7 @@ func (l *Landing) DeList(data []byte, c ClientInterface) ([]Model, error) {
return result, nil return result, nil
} }
// LandingBlock represents a block in a landing // LandingBlock represents a block in a landing.
type LandingBlock struct { type LandingBlock struct {
BaseModel BaseModel
ID string `json:"id"` ID string `json:"id"`
@@ -81,7 +82,7 @@ type LandingBlock struct {
Data *LandingBlockData `json:"data"` Data *LandingBlockData `json:"data"`
} }
// LandingBlockData represents data in a landing block // LandingBlockData represents data in a landing block.
type LandingBlockData struct { type LandingBlockData struct {
Tracks []Track `json:"tracks"` Tracks []Track `json:"tracks"`
Playlists []Playlist `json:"playlists"` Playlists []Playlist `json:"playlists"`
@@ -90,7 +91,7 @@ type LandingBlockData struct {
GeneratedPlaylist *GeneratedPlaylist `json:"generated_playlist"` GeneratedPlaylist *GeneratedPlaylist `json:"generated_playlist"`
} }
// LandingList represents a list of landings // LandingList represents a list of landings.
type LandingList struct { type LandingList struct {
BaseModel BaseModel
Landings []Landing `json:"landings"` Landings []Landing `json:"landings"`
@@ -99,7 +100,7 @@ type LandingList struct {
PageSize int `json:"page_size"` PageSize int `json:"page_size"`
} }
// DeJSON deserializes a LandingList from JSON // DeJSON deserializes a LandingList from JSON data.
func (ll *LandingList) DeJSON(data []byte, c ClientInterface) (Model, error) { func (ll *LandingList) DeJSON(data []byte, c ClientInterface) (Model, error) {
var raw map[string]json.RawMessage var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil { if err := json.Unmarshal(data, &raw); err != nil {
@@ -126,7 +127,7 @@ func (ll *LandingList) DeJSON(data []byte, c ClientInterface) (Model, error) {
return list, nil return list, nil
} }
// DeList deserializes a list of LandingLists // DeList deserializes a list of LandingLists from JSON data.
func (ll *LandingList) DeList(data []byte, c ClientInterface) ([]Model, error) { func (ll *LandingList) DeList(data []byte, c ClientInterface) ([]Model, error) {
var rawList []json.RawMessage var rawList []json.RawMessage
if err := json.Unmarshal(data, &rawList); err != nil { if err := json.Unmarshal(data, &rawList); err != nil {
+23 -22
View File
@@ -1,10 +1,11 @@
// Package models provides data models for the Yandex Music API.
package models package models
import ( import (
"encoding/json" "encoding/json"
) )
// Metatag represents a metatag // Metatag represents a metatag from the Yandex Music API.
type Metatag struct { type Metatag struct {
BaseModel BaseModel
ID string `json:"id"` ID string `json:"id"`
@@ -16,7 +17,7 @@ type Metatag struct {
Children []Metatag `json:"children"` Children []Metatag `json:"children"`
} }
// DeJSON deserializes a Metatag from JSON // DeJSON deserializes a Metatag from JSON data.
func (m *Metatag) DeJSON(data []byte, client ClientInterface) (Model, error) { func (m *Metatag) DeJSON(data []byte, client ClientInterface) (Model, error) {
var raw map[string]json.RawMessage var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil { if err := json.Unmarshal(data, &raw); err != nil {
@@ -52,7 +53,7 @@ func (m *Metatag) DeJSON(data []byte, client ClientInterface) (Model, error) {
return metatag, nil return metatag, nil
} }
// DeList deserializes a list of Metatags // DeList deserializes a list of Metatags from JSON data.
func (m *Metatag) DeList(data []byte, client ClientInterface) ([]Model, error) { func (m *Metatag) DeList(data []byte, client ClientInterface) ([]Model, error) {
var rawList []json.RawMessage var rawList []json.RawMessage
if err := json.Unmarshal(data, &rawList); err != nil { if err := json.Unmarshal(data, &rawList); err != nil {
@@ -70,14 +71,14 @@ func (m *Metatag) DeList(data []byte, client ClientInterface) ([]Model, error) {
return result, nil return result, nil
} }
// MetatagTree represents a metatag tree // MetatagTree represents a metatag tree.
type MetatagTree struct { type MetatagTree struct {
BaseModel BaseModel
Root *Metatag `json:"root"` Root *Metatag `json:"root"`
Leaves []Metatag `json:"leaves"` Leaves []Metatag `json:"leaves"`
} }
// MetatagLeaf represents a metatag leaf // MetatagLeaf represents a metatag leaf.
type MetatagLeaf struct { type MetatagLeaf struct {
BaseModel BaseModel
ID string `json:"id"` ID string `json:"id"`
@@ -88,7 +89,7 @@ type MetatagLeaf struct {
Position int `json:"position"` Position int `json:"position"`
} }
// MetatagArtists represents metatag artists // MetatagArtists represents metatag artists.
type MetatagArtists struct { type MetatagArtists struct {
BaseModel BaseModel
Artists []Artist `json:"artists"` Artists []Artist `json:"artists"`
@@ -97,7 +98,7 @@ type MetatagArtists struct {
PageSize int `json:"page_size"` PageSize int `json:"page_size"`
} }
// MetatagAlbums represents metatag albums // MetatagAlbums represents metatag albums.
type MetatagAlbums struct { type MetatagAlbums struct {
BaseModel BaseModel
Albums []Album `json:"albums"` Albums []Album `json:"albums"`
@@ -106,7 +107,7 @@ type MetatagAlbums struct {
PageSize int `json:"page_size"` PageSize int `json:"page_size"`
} }
// MetatagPlaylists represents metatag playlists // MetatagPlaylists represents metatag playlists.
type MetatagPlaylists struct { type MetatagPlaylists struct {
BaseModel BaseModel
Playlists []Playlist `json:"playlists"` Playlists []Playlist `json:"playlists"`
@@ -115,27 +116,27 @@ type MetatagPlaylists struct {
PageSize int `json:"page_size"` PageSize int `json:"page_size"`
} }
// MetatagTitle represents a metatag title // MetatagTitle represents a metatag title.
type MetatagTitle struct { type MetatagTitle struct {
BaseModel BaseModel
Title string `json:"title"` Title string `json:"title"`
} }
// MetatagSortByValue represents metatag sort by value // MetatagSortByValue represents metatag sort by value.
type MetatagSortByValue struct { type MetatagSortByValue struct {
BaseModel BaseModel
Value string `json:"value"` Value string `json:"value"`
Label string `json:"label"` Label string `json:"label"`
} }
// MetatagArtistEntry represents a metatag artist entry // MetatagArtistEntry represents a metatag artist entry.
type MetatagArtistEntry struct { type MetatagArtistEntry struct {
BaseModel BaseModel
Artist *Artist `json:"artist"` Artist *Artist `json:"artist"`
Score float64 `json:"score"` Score float64 `json:"score"`
} }
// Genre represents a genre // Genre represents a genre from the Yandex Music API.
type Genre struct { type Genre struct {
BaseModel BaseModel
ID string `json:"id"` ID string `json:"id"`
@@ -147,7 +148,7 @@ type Genre struct {
Children []Genre `json:"children"` Children []Genre `json:"children"`
} }
// DeJSON deserializes a Genre from JSON // DeJSON deserializes a Genre from JSON data.
func (g *Genre) DeJSON(data []byte, client ClientInterface) (Model, error) { func (g *Genre) DeJSON(data []byte, client ClientInterface) (Model, error) {
var raw map[string]json.RawMessage var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil { if err := json.Unmarshal(data, &raw); err != nil {
@@ -183,7 +184,7 @@ func (g *Genre) DeJSON(data []byte, client ClientInterface) (Model, error) {
return genre, nil return genre, nil
} }
// DeList deserializes a list of Genres // DeList deserializes a list of Genres from JSON data.
func (g *Genre) DeList(data []byte, client ClientInterface) ([]Model, error) { func (g *Genre) DeList(data []byte, client ClientInterface) ([]Model, error) {
var rawList []json.RawMessage var rawList []json.RawMessage
if err := json.Unmarshal(data, &rawList); err != nil { if err := json.Unmarshal(data, &rawList); err != nil {
@@ -201,7 +202,7 @@ func (g *Genre) DeList(data []byte, client ClientInterface) ([]Model, error) {
return result, nil return result, nil
} }
// Chart represents a chart // Chart represents a chart from the Yandex Music API.
type Chart struct { type Chart struct {
BaseModel BaseModel
ID string `json:"id"` ID string `json:"id"`
@@ -212,7 +213,7 @@ type Chart struct {
Items []ChartItem `json:"items"` Items []ChartItem `json:"items"`
} }
// DeJSON deserializes a Chart from JSON // DeJSON deserializes a Chart from JSON data.
func (c *Chart) DeJSON(data []byte, client ClientInterface) (Model, error) { func (c *Chart) DeJSON(data []byte, client ClientInterface) (Model, error) {
var raw map[string]json.RawMessage var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil { if err := json.Unmarshal(data, &raw); err != nil {
@@ -245,7 +246,7 @@ func (c *Chart) DeJSON(data []byte, client ClientInterface) (Model, error) {
return chart, nil return chart, nil
} }
// DeList deserializes a list of Charts // DeList deserializes a list of Charts from JSON data.
func (c *Chart) DeList(data []byte, client ClientInterface) ([]Model, error) { func (c *Chart) DeList(data []byte, client ClientInterface) ([]Model, error) {
var rawList []json.RawMessage var rawList []json.RawMessage
if err := json.Unmarshal(data, &rawList); err != nil { if err := json.Unmarshal(data, &rawList); err != nil {
@@ -263,14 +264,14 @@ func (c *Chart) DeList(data []byte, client ClientInterface) ([]Model, error) {
return result, nil return result, nil
} }
// ChartInfo represents chart info // ChartInfo represents chart info.
type ChartInfo struct { type ChartInfo struct {
BaseModel BaseModel
Chart *Chart `json:"chart"` Chart *Chart `json:"chart"`
Menu []ChartInfoMenu `json:"menu"` Menu []ChartInfoMenu `json:"menu"`
} }
// ChartItem represents a chart item // ChartItem represents a chart item.
type ChartItem struct { type ChartItem struct {
BaseModel BaseModel
Position int `json:"position"` Position int `json:"position"`
@@ -282,7 +283,7 @@ type ChartItem struct {
Trend string `json:"trend"` Trend string `json:"trend"`
} }
// ChartInfoMenu represents a chart info menu // ChartInfoMenu represents a chart info menu.
type ChartInfoMenu struct { type ChartInfoMenu struct {
BaseModel BaseModel
ID string `json:"id"` ID string `json:"id"`
@@ -291,7 +292,7 @@ type ChartInfoMenu struct {
Items []ChartInfoMenuItem `json:"items"` Items []ChartInfoMenuItem `json:"items"`
} }
// ChartInfoMenuItem represents a chart info menu item // ChartInfoMenuItem represents a chart info menu item.
type ChartInfoMenuItem struct { type ChartInfoMenuItem struct {
BaseModel BaseModel
ID string `json:"id"` ID string `json:"id"`
@@ -300,7 +301,7 @@ type ChartInfoMenuItem struct {
Action string `json:"action"` Action string `json:"action"`
} }
// ChartItems represents chart items response // ChartItems represents chart items response.
type ChartItems struct { type ChartItems struct {
BaseModel BaseModel
Items []ChartItem `json:"items"` Items []ChartItem `json:"items"`
+11 -10
View File
@@ -1,10 +1,11 @@
// Package models provides data models for the Yandex Music API.
package models package models
import ( import (
"encoding/json" "encoding/json"
) )
// MusicHistory represents music history // MusicHistory represents music history from the Yandex Music API.
type MusicHistory struct { type MusicHistory struct {
BaseModel BaseModel
Tabs []MusicHistoryTab `json:"tabs"` Tabs []MusicHistoryTab `json:"tabs"`
@@ -13,7 +14,7 @@ type MusicHistory struct {
Context *MusicHistoryContextFullModel `json:"context"` Context *MusicHistoryContextFullModel `json:"context"`
} }
// DeJSON deserializes a MusicHistory from JSON // DeJSON deserializes a MusicHistory from JSON data.
func (mh *MusicHistory) DeJSON(data []byte, client ClientInterface) (Model, error) { func (mh *MusicHistory) DeJSON(data []byte, client ClientInterface) (Model, error) {
var raw map[string]json.RawMessage var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil { if err := json.Unmarshal(data, &raw); err != nil {
@@ -46,7 +47,7 @@ func (mh *MusicHistory) DeJSON(data []byte, client ClientInterface) (Model, erro
return history, nil return history, nil
} }
// DeList deserializes a list of MusicHistory // DeList deserializes a list of MusicHistory from JSON data.
func (mh *MusicHistory) DeList(data []byte, client ClientInterface) ([]Model, error) { func (mh *MusicHistory) DeList(data []byte, client ClientInterface) ([]Model, error) {
var rawList []json.RawMessage var rawList []json.RawMessage
if err := json.Unmarshal(data, &rawList); err != nil { if err := json.Unmarshal(data, &rawList); err != nil {
@@ -64,7 +65,7 @@ func (mh *MusicHistory) DeList(data []byte, client ClientInterface) ([]Model, er
return result, nil return result, nil
} }
// MusicHistoryTab represents a music history tab // MusicHistoryTab represents a music history tab.
type MusicHistoryTab struct { type MusicHistoryTab struct {
BaseModel BaseModel
ID string `json:"id"` ID string `json:"id"`
@@ -75,7 +76,7 @@ type MusicHistoryTab struct {
Position int `json:"position"` Position int `json:"position"`
} }
// MusicHistoryGroup represents a music history group // MusicHistoryGroup represents a music history group.
type MusicHistoryGroup struct { type MusicHistoryGroup struct {
BaseModel BaseModel
ID string `json:"id"` ID string `json:"id"`
@@ -85,7 +86,7 @@ type MusicHistoryGroup struct {
Total int `json:"total"` Total int `json:"total"`
} }
// MusicHistoryItem represents a music history item // MusicHistoryItem represents a music history item.
type MusicHistoryItem struct { type MusicHistoryItem struct {
BaseModel BaseModel
ID string `json:"id"` ID string `json:"id"`
@@ -100,7 +101,7 @@ type MusicHistoryItem struct {
Context *MusicHistoryItemData `json:"context"` Context *MusicHistoryItemData `json:"context"`
} }
// MusicHistoryItemData represents music history item data // MusicHistoryItemData represents music history item data.
type MusicHistoryItemData struct { type MusicHistoryItemData struct {
BaseModel BaseModel
Source string `json:"source"` Source string `json:"source"`
@@ -112,14 +113,14 @@ type MusicHistoryItemData struct {
Progress float64 `json:"progress"` Progress float64 `json:"progress"`
} }
// MusicHistoryItemID represents music history item ID // MusicHistoryItemID represents music history item ID.
type MusicHistoryItemID struct { type MusicHistoryItemID struct {
BaseModel BaseModel
ID string `json:"id"` ID string `json:"id"`
Type string `json:"type"` Type string `json:"type"`
} }
// MusicHistoryItems represents music history items // MusicHistoryItems represents music history items.
type MusicHistoryItems struct { type MusicHistoryItems struct {
BaseModel BaseModel
Items []MusicHistoryItem `json:"items"` Items []MusicHistoryItem `json:"items"`
@@ -128,7 +129,7 @@ type MusicHistoryItems struct {
PageSize int `json:"page_size"` PageSize int `json:"page_size"`
} }
// MusicHistoryContextFullModel represents music history context full model // MusicHistoryContextFullModel represents music history context full model.
type MusicHistoryContextFullModel struct { type MusicHistoryContextFullModel struct {
BaseModel BaseModel
DeviceID string `json:"device_id"` DeviceID string `json:"device_id"`
+10 -9
View File
@@ -1,10 +1,11 @@
// Package models provides data models for the Yandex Music API.
package models package models
import ( import (
"encoding/json" "encoding/json"
) )
// Pin represents a pin // Pin represents a pin from the Yandex Music API.
type Pin struct { type Pin struct {
BaseModel BaseModel
ID string `json:"id"` ID string `json:"id"`
@@ -22,7 +23,7 @@ type Pin struct {
Active bool `json:"active"` Active bool `json:"active"`
} }
// DeJSON deserializes a Pin from JSON // DeJSON deserializes a Pin from JSON data.
func (p *Pin) DeJSON(data []byte, client ClientInterface) (Model, error) { func (p *Pin) DeJSON(data []byte, client ClientInterface) (Model, error) {
var raw map[string]json.RawMessage var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil { if err := json.Unmarshal(data, &raw); err != nil {
@@ -83,7 +84,7 @@ func (p *Pin) DeJSON(data []byte, client ClientInterface) (Model, error) {
return pin, nil return pin, nil
} }
// DeList deserializes a list of Pins // DeList deserializes a list of Pins from JSON data.
func (p *Pin) DeList(data []byte, client ClientInterface) ([]Model, error) { func (p *Pin) DeList(data []byte, client ClientInterface) ([]Model, error) {
var rawList []json.RawMessage var rawList []json.RawMessage
if err := json.Unmarshal(data, &rawList); err != nil { if err := json.Unmarshal(data, &rawList); err != nil {
@@ -101,14 +102,14 @@ func (p *Pin) DeList(data []byte, client ClientInterface) ([]Model, error) {
return result, nil return result, nil
} }
// PinData represents pin data // PinData represents pin data.
type PinData struct { type PinData struct {
BaseModel BaseModel
Pins []Pin `json:"pins"` Pins []Pin `json:"pins"`
Total int `json:"total"` Total int `json:"total"`
} }
// PinsList represents a list of pins // PinsList represents a list of pins.
type PinsList struct { type PinsList struct {
BaseModel BaseModel
Pins []Pin `json:"pins"` Pins []Pin `json:"pins"`
@@ -117,7 +118,7 @@ type PinsList struct {
PageSize int `json:"page_size"` PageSize int `json:"page_size"`
} }
// Presaves represents presaves // Presaves represents presaves.
type Presaves struct { type Presaves struct {
BaseModel BaseModel
Presaves []Presave `json:"presaves"` Presaves []Presave `json:"presaves"`
@@ -126,7 +127,7 @@ type Presaves struct {
PageSize int `json:"page_size"` PageSize int `json:"page_size"`
} }
// Presave represents a presave // Presave represents a presave.
type Presave struct { type Presave struct {
BaseModel BaseModel
ID string `json:"id"` ID string `json:"id"`
@@ -142,7 +143,7 @@ type Presave struct {
UpdatedAt string `json:"updated_at"` UpdatedAt string `json:"updated_at"`
} }
// DeJSON deserializes a Presave from JSON // DeJSON deserializes a Presave from JSON data.
func (p *Presave) DeJSON(data []byte, client ClientInterface) (Model, error) { func (p *Presave) DeJSON(data []byte, client ClientInterface) (Model, error) {
var raw map[string]json.RawMessage var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil { if err := json.Unmarshal(data, &raw); err != nil {
@@ -195,7 +196,7 @@ func (p *Presave) DeJSON(data []byte, client ClientInterface) (Model, error) {
return presave, nil return presave, nil
} }
// DeList deserializes a list of Presaves // DeList deserializes a list of Presaves from JSON data.
func (p *Presave) DeList(data []byte, client ClientInterface) ([]Model, error) { func (p *Presave) DeList(data []byte, client ClientInterface) ([]Model, error) {
var rawList []json.RawMessage var rawList []json.RawMessage
if err := json.Unmarshal(data, &rawList); err != nil { if err := json.Unmarshal(data, &rawList); err != nil {
+12 -11
View File
@@ -1,10 +1,11 @@
// Package models provides data models for the Yandex Music API.
package models package models
import ( import (
"encoding/json" "encoding/json"
) )
// Playlist represents a playlist // Playlist represents a playlist from the Yandex Music API.
type Playlist struct { type Playlist struct {
BaseModel BaseModel
Kind int `json:"kind"` Kind int `json:"kind"`
@@ -36,7 +37,7 @@ type Playlist struct {
Trailer *TrailerInfo `json:"trailer"` Trailer *TrailerInfo `json:"trailer"`
} }
// DeJSON deserializes a Playlist from JSON // DeJSON deserializes a Playlist from JSON data.
func (p *Playlist) DeJSON(data []byte, c ClientInterface) (Model, error) { func (p *Playlist) DeJSON(data []byte, c ClientInterface) (Model, error) {
var raw map[string]json.RawMessage var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil { if err := json.Unmarshal(data, &raw); err != nil {
@@ -142,7 +143,7 @@ func (p *Playlist) DeJSON(data []byte, c ClientInterface) (Model, error) {
return playlist, nil return playlist, nil
} }
// DeList deserializes a list of Playlists // DeList deserializes a list of Playlists from JSON data.
func (p *Playlist) DeList(data []byte, c ClientInterface) ([]Model, error) { func (p *Playlist) DeList(data []byte, c ClientInterface) ([]Model, error) {
var rawList []json.RawMessage var rawList []json.RawMessage
if err := json.Unmarshal(data, &rawList); err != nil { if err := json.Unmarshal(data, &rawList); err != nil {
@@ -160,7 +161,7 @@ func (p *Playlist) DeList(data []byte, c ClientInterface) ([]Model, error) {
return result, nil return result, nil
} }
// User represents a user (playlist owner) // User represents a user (playlist owner) from the Yandex Music API.
type User struct { type User struct {
BaseModel BaseModel
UID int64 `json:"uid"` UID int64 `json:"uid"`
@@ -184,7 +185,7 @@ type User struct {
Counters *UserCounters `json:"counters"` Counters *UserCounters `json:"counters"`
} }
// DeJSON deserializes a User from JSON // DeJSON deserializes a User from JSON data.
func (u *User) DeJSON(data []byte, c ClientInterface) (Model, error) { func (u *User) DeJSON(data []byte, c ClientInterface) (Model, error) {
var raw map[string]json.RawMessage var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil { if err := json.Unmarshal(data, &raw); err != nil {
@@ -255,7 +256,7 @@ func (u *User) DeJSON(data []byte, c ClientInterface) (Model, error) {
return user, nil return user, nil
} }
// DeList deserializes a list of Users // DeList deserializes a list of Users from JSON data.
func (u *User) DeList(data []byte, c ClientInterface) ([]Model, error) { func (u *User) DeList(data []byte, c ClientInterface) ([]Model, error) {
var rawList []json.RawMessage var rawList []json.RawMessage
if err := json.Unmarshal(data, &rawList); err != nil { if err := json.Unmarshal(data, &rawList); err != nil {
@@ -273,7 +274,7 @@ func (u *User) DeList(data []byte, c ClientInterface) ([]Model, error) {
return result, nil return result, nil
} }
// UserSettings represents user settings (from /account/settings) // UserSettings represents user settings from /account/settings.
type UserSettings struct { type UserSettings struct {
BaseModel BaseModel
UID int64 `json:"uid"` UID int64 `json:"uid"`
@@ -295,7 +296,7 @@ type UserSettings struct {
ShowDiskTracksInLibrary *bool `json:"show_disk_tracks_in_library,omitempty"` ShowDiskTracksInLibrary *bool `json:"show_disk_tracks_in_library,omitempty"`
} }
// DeJSON deserializes UserSettings from JSON // DeJSON deserializes UserSettings from JSON data.
func (u *UserSettings) DeJSON(data []byte, c ClientInterface) (Model, error) { func (u *UserSettings) DeJSON(data []byte, c ClientInterface) (Model, error) {
var raw map[string]json.RawMessage var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil { if err := json.Unmarshal(data, &raw); err != nil {
@@ -365,7 +366,7 @@ func (u *UserSettings) DeJSON(data []byte, c ClientInterface) (Model, error) {
return settings, nil return settings, nil
} }
// DeList deserializes a list of UserSettings // DeList deserializes a list of UserSettings from JSON data.
func (u *UserSettings) DeList(data []byte, c ClientInterface) ([]Model, error) { func (u *UserSettings) DeList(data []byte, c ClientInterface) ([]Model, error) {
var rawList []json.RawMessage var rawList []json.RawMessage
if err := json.Unmarshal(data, &rawList); err != nil { if err := json.Unmarshal(data, &rawList); err != nil {
@@ -383,7 +384,7 @@ func (u *UserSettings) DeList(data []byte, c ClientInterface) ([]Model, error) {
return result, nil return result, nil
} }
// UserCounters represents user counters // UserCounters represents user counters.
type UserCounters struct { type UserCounters struct {
Tracks int `json:"tracks"` Tracks int `json:"tracks"`
Albums int `json:"albums"` Albums int `json:"albums"`
@@ -393,7 +394,7 @@ type UserCounters struct {
Likes int `json:"likes"` Likes int `json:"likes"`
} }
// Image represents an image with multiple sizes // Image represents an image with multiple sizes.
type Image struct { type Image struct {
URI string `json:"uri"` URI string `json:"uri"`
Type string `json:"type"` Type string `json:"type"`
+13 -12
View File
@@ -1,10 +1,11 @@
// Package models provides data models for the Yandex Music API.
package models package models
import ( import (
"encoding/json" "encoding/json"
) )
// Queue represents a playback queue // Queue represents a playback queue from the Yandex Music API.
type Queue struct { type Queue struct {
BaseModel BaseModel
ID string `json:"id"` ID string `json:"id"`
@@ -20,7 +21,7 @@ type Queue struct {
TotalDuration int `json:"total_duration_ms"` TotalDuration int `json:"total_duration_ms"`
} }
// DeJSON deserializes a Queue from JSON // DeJSON deserializes a Queue from JSON data.
func (q *Queue) DeJSON(data []byte, c ClientInterface) (Model, error) { func (q *Queue) DeJSON(data []byte, c ClientInterface) (Model, error) {
var raw map[string]json.RawMessage var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil { if err := json.Unmarshal(data, &raw); err != nil {
@@ -71,7 +72,7 @@ func (q *Queue) DeJSON(data []byte, c ClientInterface) (Model, error) {
return queue, nil return queue, nil
} }
// DeList deserializes a list of Queues // DeList deserializes a list of Queues from JSON data.
func (q *Queue) DeList(data []byte, c ClientInterface) ([]Model, error) { func (q *Queue) DeList(data []byte, c ClientInterface) ([]Model, error) {
var rawList []json.RawMessage var rawList []json.RawMessage
if err := json.Unmarshal(data, &rawList); err != nil { if err := json.Unmarshal(data, &rawList); err != nil {
@@ -89,7 +90,7 @@ func (q *Queue) DeList(data []byte, c ClientInterface) ([]Model, error) {
return result, nil return result, nil
} }
// QueueItem represents a queue item // QueueItem represents a queue item.
type QueueItem struct { type QueueItem struct {
BaseModel BaseModel
TrackID string `json:"track_id"` TrackID string `json:"track_id"`
@@ -101,7 +102,7 @@ type QueueItem struct {
PlayContext *PlayContext `json:"play_context"` PlayContext *PlayContext `json:"play_context"`
} }
// DeJSON deserializes a QueueItem from JSON // DeJSON deserializes a QueueItem from JSON data.
func (qi *QueueItem) DeJSON(data []byte, c ClientInterface) (Model, error) { func (qi *QueueItem) DeJSON(data []byte, c ClientInterface) (Model, error) {
var raw map[string]json.RawMessage var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil { if err := json.Unmarshal(data, &raw); err != nil {
@@ -140,7 +141,7 @@ func (qi *QueueItem) DeJSON(data []byte, c ClientInterface) (Model, error) {
return item, nil return item, nil
} }
// DeList deserializes a list of QueueItems // DeList deserializes a list of QueueItems from JSON data.
func (qi *QueueItem) DeList(data []byte, c ClientInterface) ([]Model, error) { func (qi *QueueItem) DeList(data []byte, c ClientInterface) ([]Model, error) {
var rawList []json.RawMessage var rawList []json.RawMessage
if err := json.Unmarshal(data, &rawList); err != nil { if err := json.Unmarshal(data, &rawList); err != nil {
@@ -158,7 +159,7 @@ func (qi *QueueItem) DeList(data []byte, c ClientInterface) ([]Model, error) {
return result, nil return result, nil
} }
// PlayContext represents a play context // PlayContext represents a play context.
type PlayContext struct { type PlayContext struct {
BaseModel BaseModel
ID string `json:"id"` ID string `json:"id"`
@@ -173,7 +174,7 @@ type PlayContext struct {
Available bool `json:"available"` Available bool `json:"available"`
} }
// DeJSON deserializes a PlayContext from JSON // DeJSON deserializes a PlayContext from JSON data.
func (pc *PlayContext) DeJSON(data []byte, c ClientInterface) (Model, error) { func (pc *PlayContext) DeJSON(data []byte, c ClientInterface) (Model, error) {
var raw map[string]json.RawMessage var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil { if err := json.Unmarshal(data, &raw); err != nil {
@@ -219,7 +220,7 @@ func (pc *PlayContext) DeJSON(data []byte, c ClientInterface) (Model, error) {
return ctx, nil return ctx, nil
} }
// DeList deserializes a list of PlayContexts // DeList deserializes a list of PlayContexts from JSON data.
func (pc *PlayContext) DeList(data []byte, c ClientInterface) ([]Model, error) { func (pc *PlayContext) DeList(data []byte, c ClientInterface) ([]Model, error) {
var rawList []json.RawMessage var rawList []json.RawMessage
if err := json.Unmarshal(data, &rawList); err != nil { if err := json.Unmarshal(data, &rawList); err != nil {
@@ -237,7 +238,7 @@ func (pc *PlayContext) DeList(data []byte, c ClientInterface) ([]Model, error) {
return result, nil return result, nil
} }
// PlayContextsData represents play contexts data // PlayContextsData represents play contexts data.
type PlayContextsData struct { type PlayContextsData struct {
BaseModel BaseModel
Contexts []PlayContext `json:"contexts"` Contexts []PlayContext `json:"contexts"`
@@ -246,7 +247,7 @@ type PlayContextsData struct {
PageSize int `json:"page_size"` PageSize int `json:"page_size"`
} }
// DeJSON deserializes PlayContextsData from JSON // DeJSON deserializes PlayContextsData from JSON data.
func (pcd *PlayContextsData) DeJSON(data []byte, c ClientInterface) (Model, error) { func (pcd *PlayContextsData) DeJSON(data []byte, c ClientInterface) (Model, error) {
var raw map[string]json.RawMessage var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil { if err := json.Unmarshal(data, &raw); err != nil {
@@ -273,7 +274,7 @@ func (pcd *PlayContextsData) DeJSON(data []byte, c ClientInterface) (Model, erro
return result, nil return result, nil
} }
// DeList deserializes a list of PlayContextsData // DeList deserializes a list of PlayContextsData from JSON data.
func (pcd *PlayContextsData) DeList(data []byte, c ClientInterface) ([]Model, error) { func (pcd *PlayContextsData) DeList(data []byte, c ClientInterface) ([]Model, error) {
var rawList []json.RawMessage var rawList []json.RawMessage
if err := json.Unmarshal(data, &rawList); err != nil { if err := json.Unmarshal(data, &rawList); err != nil {
+19 -18
View File
@@ -1,10 +1,11 @@
// Package models provides data models for the Yandex Music API.
package models package models
import ( import (
"encoding/json" "encoding/json"
) )
// RadioStation represents a radio station // RadioStation represents a radio station from the Yandex Music API.
type RadioStation struct { type RadioStation struct {
BaseModel BaseModel
ID string `json:"id"` ID string `json:"id"`
@@ -16,7 +17,7 @@ type RadioStation struct {
IsPersonal bool `json:"is_personal"` IsPersonal bool `json:"is_personal"`
} }
// DeJSON deserializes a RadioStation from JSON // DeJSON deserializes a RadioStation from JSON data.
func (r *RadioStation) DeJSON(data []byte, client ClientInterface) (Model, error) { func (r *RadioStation) DeJSON(data []byte, client ClientInterface) (Model, error) {
var raw map[string]json.RawMessage var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil { if err := json.Unmarshal(data, &raw); err != nil {
@@ -50,7 +51,7 @@ func (r *RadioStation) DeJSON(data []byte, client ClientInterface) (Model, error
return station, nil return station, nil
} }
// DeList deserializes a list of RadioStations // DeList deserializes a list of RadioStations from JSON data.
func (r *RadioStation) DeList(data []byte, client ClientInterface) ([]Model, error) { func (r *RadioStation) DeList(data []byte, client ClientInterface) ([]Model, error) {
var rawList []json.RawMessage var rawList []json.RawMessage
if err := json.Unmarshal(data, &rawList); err != nil { if err := json.Unmarshal(data, &rawList); err != nil {
@@ -68,7 +69,7 @@ func (r *RadioStation) DeList(data []byte, client ClientInterface) ([]Model, err
return result, nil return result, nil
} }
// StationTracksResult represents station tracks result // StationTracksResult represents station tracks result.
type StationTracksResult struct { type StationTracksResult struct {
BaseModel BaseModel
Tracks []Track `json:"tracks"` Tracks []Track `json:"tracks"`
@@ -76,7 +77,7 @@ type StationTracksResult struct {
Sequence string `json:"sequence"` Sequence string `json:"sequence"`
} }
// DeJSON deserializes StationTracksResult from JSON // DeJSON deserializes StationTracksResult from JSON data.
func (s *StationTracksResult) DeJSON(data []byte, client ClientInterface) (Model, error) { func (s *StationTracksResult) DeJSON(data []byte, client ClientInterface) (Model, error) {
var raw map[string]json.RawMessage var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil { if err := json.Unmarshal(data, &raw); err != nil {
@@ -100,7 +101,7 @@ func (s *StationTracksResult) DeJSON(data []byte, client ClientInterface) (Model
return result, nil return result, nil
} }
// DeList deserializes a list of StationTracksResult // DeList deserializes a list of StationTracksResult from JSON data.
func (s *StationTracksResult) DeList(data []byte, client ClientInterface) ([]Model, error) { func (s *StationTracksResult) DeList(data []byte, client ClientInterface) ([]Model, error) {
var rawList []json.RawMessage var rawList []json.RawMessage
if err := json.Unmarshal(data, &rawList); err != nil { if err := json.Unmarshal(data, &rawList); err != nil {
@@ -118,7 +119,7 @@ func (s *StationTracksResult) DeList(data []byte, client ClientInterface) ([]Mod
return result, nil return result, nil
} }
// RotorStation represents a rotor (generative) station // RotorStation represents a rotor (generative) station.
type RotorStation struct { type RotorStation struct {
BaseModel BaseModel
ID string `json:"id"` ID string `json:"id"`
@@ -131,7 +132,7 @@ type RotorStation struct {
Settings *RotorSettings `json:"settings"` Settings *RotorSettings `json:"settings"`
} }
// DeJSON deserializes a RotorStation from JSON // DeJSON deserializes a RotorStation from JSON data.
func (r *RotorStation) DeJSON(data []byte, client ClientInterface) (Model, error) { func (r *RotorStation) DeJSON(data []byte, client ClientInterface) (Model, error) {
var raw map[string]json.RawMessage var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil { if err := json.Unmarshal(data, &raw); err != nil {
@@ -170,7 +171,7 @@ func (r *RotorStation) DeJSON(data []byte, client ClientInterface) (Model, error
return station, nil return station, nil
} }
// DeList deserializes a list of RotorStations // DeList deserializes a list of RotorStations from JSON data.
func (r *RotorStation) DeList(data []byte, client ClientInterface) ([]Model, error) { func (r *RotorStation) DeList(data []byte, client ClientInterface) ([]Model, error) {
var rawList []json.RawMessage var rawList []json.RawMessage
if err := json.Unmarshal(data, &rawList); err != nil { if err := json.Unmarshal(data, &rawList); err != nil {
@@ -188,7 +189,7 @@ func (r *RotorStation) DeList(data []byte, client ClientInterface) ([]Model, err
return result, nil return result, nil
} }
// RotorSettings represents rotor station settings // RotorSettings represents rotor station settings.
type RotorSettings struct { type RotorSettings struct {
BaseModel BaseModel
Diversity float64 `json:"diversity"` Diversity float64 `json:"diversity"`
@@ -201,7 +202,7 @@ type RotorSettings struct {
Valence float64 `json:"valence"` Valence float64 `json:"valence"`
} }
// RotorStationTracksResult represents rotor station tracks result // RotorStationTracksResult represents rotor station tracks result.
type RotorStationTracksResult struct { type RotorStationTracksResult struct {
BaseModel BaseModel
Tracks []Track `json:"tracks"` Tracks []Track `json:"tracks"`
@@ -209,7 +210,7 @@ type RotorStationTracksResult struct {
Sequence string `json:"sequence"` Sequence string `json:"sequence"`
} }
// DeJSON deserializes RotorStationTracksResult from JSON // DeJSON deserializes RotorStationTracksResult from JSON data.
func (r *RotorStationTracksResult) DeJSON(data []byte, client ClientInterface) (Model, error) { func (r *RotorStationTracksResult) DeJSON(data []byte, client ClientInterface) (Model, error) {
var raw map[string]json.RawMessage var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil { if err := json.Unmarshal(data, &raw); err != nil {
@@ -233,7 +234,7 @@ func (r *RotorStationTracksResult) DeJSON(data []byte, client ClientInterface) (
return result, nil return result, nil
} }
// DeList deserializes a list of RotorStationTracksResult // DeList deserializes a list of RotorStationTracksResult from JSON data.
func (r *RotorStationTracksResult) DeList(data []byte, client ClientInterface) ([]Model, error) { func (r *RotorStationTracksResult) DeList(data []byte, client ClientInterface) ([]Model, error) {
var rawList []json.RawMessage var rawList []json.RawMessage
if err := json.Unmarshal(data, &rawList); err != nil { if err := json.Unmarshal(data, &rawList); err != nil {
@@ -251,7 +252,7 @@ func (r *RotorStationTracksResult) DeList(data []byte, client ClientInterface) (
return result, nil return result, nil
} }
// RotorSession represents a rotor session // RotorSession represents a rotor session.
type RotorSession struct { type RotorSession struct {
BaseModel BaseModel
SessionID string `json:"session_id"` SessionID string `json:"session_id"`
@@ -262,7 +263,7 @@ type RotorSession struct {
CreatedAt string `json:"created_at"` CreatedAt string `json:"created_at"`
} }
// DeJSON deserializes a RotorSession from JSON // DeJSON deserializes a RotorSession from JSON data.
func (r *RotorSession) DeJSON(data []byte, client ClientInterface) (Model, error) { func (r *RotorSession) DeJSON(data []byte, client ClientInterface) (Model, error) {
var raw map[string]json.RawMessage var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil { if err := json.Unmarshal(data, &raw); err != nil {
@@ -295,7 +296,7 @@ func (r *RotorSession) DeJSON(data []byte, client ClientInterface) (Model, error
return session, nil return session, nil
} }
// DeList deserializes a list of RotorSessions // DeList deserializes a list of RotorSessions from JSON data.
func (r *RotorSession) DeList(data []byte, client ClientInterface) ([]Model, error) { func (r *RotorSession) DeList(data []byte, client ClientInterface) ([]Model, error) {
var rawList []json.RawMessage var rawList []json.RawMessage
if err := json.Unmarshal(data, &rawList); err != nil { if err := json.Unmarshal(data, &rawList); err != nil {
@@ -313,7 +314,7 @@ func (r *RotorSession) DeList(data []byte, client ClientInterface) ([]Model, err
return result, nil return result, nil
} }
// SessionFeedback represents session feedback // SessionFeedback represents session feedback.
type SessionFeedback struct { type SessionFeedback struct {
BaseModel BaseModel
TrackID string `json:"track_id"` TrackID string `json:"track_id"`
@@ -321,7 +322,7 @@ type SessionFeedback struct {
Timestamp string `json:"timestamp"` Timestamp string `json:"timestamp"`
} }
// SessionFeedbacks represents multiple session feedbacks // SessionFeedbacks represents multiple session feedbacks.
type SessionFeedbacks struct { type SessionFeedbacks struct {
BaseModel BaseModel
Feedbacks []SessionFeedback `json:"feedbacks"` Feedbacks []SessionFeedback `json:"feedbacks"`
+11 -10
View File
@@ -1,6 +1,7 @@
// Package models provides data models for the Yandex Music API.
package models package models
// SearchResult represents search results // SearchResult represents search results from the Yandex Music API.
type SearchResult struct { type SearchResult struct {
Tracks *SearchTracksResult `json:"tracks"` Tracks *SearchTracksResult `json:"tracks"`
Albums *SearchAlbumsResult `json:"albums"` Albums *SearchAlbumsResult `json:"albums"`
@@ -10,43 +11,43 @@ type SearchResult struct {
Users *SearchUsersResult `json:"users"` Users *SearchUsersResult `json:"users"`
} }
// SearchTracksResult represents track search results // SearchTracksResult represents track search results.
type SearchTracksResult struct { type SearchTracksResult struct {
Total int `json:"total"` Total int `json:"total"`
Results []Track `json:"results"` Results []Track `json:"results"`
} }
// SearchAlbumsResult represents album search results // SearchAlbumsResult represents album search results.
type SearchAlbumsResult struct { type SearchAlbumsResult struct {
Total int `json:"total"` Total int `json:"total"`
Results []Album `json:"results"` Results []Album `json:"results"`
} }
// SearchArtistsResult represents artist search results // SearchArtistsResult represents artist search results.
type SearchArtistsResult struct { type SearchArtistsResult struct {
Total int `json:"total"` Total int `json:"total"`
Results []Artist `json:"results"` Results []Artist `json:"results"`
} }
// SearchPlaylistsResult represents playlist search results // SearchPlaylistsResult represents playlist search results.
type SearchPlaylistsResult struct { type SearchPlaylistsResult struct {
Total int `json:"total"` Total int `json:"total"`
Results []Playlist `json:"results"` Results []Playlist `json:"results"`
} }
// SearchVideosResult represents video search results // SearchVideosResult represents video search results.
type SearchVideosResult struct { type SearchVideosResult struct {
Total int `json:"total"` Total int `json:"total"`
Results []Video `json:"results"` Results []Video `json:"results"`
} }
// SearchUsersResult represents user search results // SearchUsersResult represents user search results.
type SearchUsersResult struct { type SearchUsersResult struct {
Total int `json:"total"` Total int `json:"total"`
Results []User `json:"results"` Results []User `json:"results"`
} }
// SearchBanner represents a search banner // SearchBanner represents a search banner.
type SearchBanner struct { type SearchBanner struct {
ID string `json:"id"` ID string `json:"id"`
Title string `json:"title"` Title string `json:"title"`
@@ -57,7 +58,7 @@ type SearchBanner struct {
Type string `json:"type"` Type string `json:"type"`
} }
// Tag represents a search tag // Tag represents a search tag.
type Tag struct { type Tag struct {
ID string `json:"id"` ID string `json:"id"`
Title string `json:"title"` Title string `json:"title"`
@@ -66,7 +67,7 @@ type Tag struct {
Type string `json:"type"` Type string `json:"type"`
} }
// Video represents a video (minimal) // Video represents a video (minimal).
type Video struct { type Video struct {
BaseModel BaseModel
ID string `json:"id"` ID string `json:"id"`
+18 -17
View File
@@ -1,17 +1,18 @@
// Package models provides data models for the Yandex Music API.
package models package models
import ( import (
"encoding/json" "encoding/json"
) )
// Experiments represents experiments // Experiments represents experiments from the Yandex Music API.
type Experiments struct { type Experiments struct {
BaseModel BaseModel
Experiments []ExperimentDetail `json:"experiments"` Experiments []ExperimentDetail `json:"experiments"`
Total int `json:"total"` Total int `json:"total"`
} }
// DeJSON deserializes Experiments from JSON // DeJSON deserializes Experiments from JSON data.
func (e *Experiments) DeJSON(data []byte, client ClientInterface) (Model, error) { func (e *Experiments) DeJSON(data []byte, client ClientInterface) (Model, error) {
var raw map[string]json.RawMessage var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil { if err := json.Unmarshal(data, &raw); err != nil {
@@ -32,7 +33,7 @@ func (e *Experiments) DeJSON(data []byte, client ClientInterface) (Model, error)
return experiments, nil return experiments, nil
} }
// DeList deserializes a list of Experiments // DeList deserializes a list of Experiments from JSON data.
func (e *Experiments) DeList(data []byte, client ClientInterface) ([]Model, error) { func (e *Experiments) DeList(data []byte, client ClientInterface) ([]Model, error) {
var rawList []json.RawMessage var rawList []json.RawMessage
if err := json.Unmarshal(data, &rawList); err != nil { if err := json.Unmarshal(data, &rawList); err != nil {
@@ -50,7 +51,7 @@ func (e *Experiments) DeList(data []byte, client ClientInterface) ([]Model, erro
return result, nil return result, nil
} }
// ExperimentDetail represents experiment details // ExperimentDetail represents experiment details.
type ExperimentDetail struct { type ExperimentDetail struct {
BaseModel BaseModel
ID string `json:"id"` ID string `json:"id"`
@@ -62,7 +63,7 @@ type ExperimentDetail struct {
EndDate string `json:"end_date"` EndDate string `json:"end_date"`
} }
// DeJSON deserializes ExperimentDetail from JSON // DeJSON deserializes ExperimentDetail from JSON data.
func (e *ExperimentDetail) DeJSON(data []byte, client ClientInterface) (Model, error) { func (e *ExperimentDetail) DeJSON(data []byte, client ClientInterface) (Model, error) {
var raw map[string]json.RawMessage var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil { if err := json.Unmarshal(data, &raw); err != nil {
@@ -96,7 +97,7 @@ func (e *ExperimentDetail) DeJSON(data []byte, client ClientInterface) (Model, e
return detail, nil return detail, nil
} }
// DeList deserializes a list of ExperimentDetails // DeList deserializes a list of ExperimentDetails from JSON data.
func (e *ExperimentDetail) DeList(data []byte, client ClientInterface) ([]Model, error) { func (e *ExperimentDetail) DeList(data []byte, client ClientInterface) ([]Model, error) {
var rawList []json.RawMessage var rawList []json.RawMessage
if err := json.Unmarshal(data, &rawList); err != nil { if err := json.Unmarshal(data, &rawList); err != nil {
@@ -114,7 +115,7 @@ func (e *ExperimentDetail) DeList(data []byte, client ClientInterface) ([]Model,
return result, nil return result, nil
} }
// Permissions represents user permissions // Permissions represents user permissions.
type Permissions struct { type Permissions struct {
BaseModel BaseModel
CanPlay bool `json:"can_play"` CanPlay bool `json:"can_play"`
@@ -129,7 +130,7 @@ type Permissions struct {
CanUseLossless bool `json:"can_use_lossless"` CanUseLossless bool `json:"can_use_lossless"`
} }
// DeJSON deserializes Permissions from JSON // DeJSON deserializes Permissions from JSON data.
func (p *Permissions) DeJSON(data []byte, client ClientInterface) (Model, error) { func (p *Permissions) DeJSON(data []byte, client ClientInterface) (Model, error) {
var raw map[string]json.RawMessage var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil { if err := json.Unmarshal(data, &raw); err != nil {
@@ -172,7 +173,7 @@ func (p *Permissions) DeJSON(data []byte, client ClientInterface) (Model, error)
return perms, nil return perms, nil
} }
// DeList deserializes a list of Permissions // DeList deserializes a list of Permissions from JSON data.
func (p *Permissions) DeList(data []byte, client ClientInterface) ([]Model, error) { func (p *Permissions) DeList(data []byte, client ClientInterface) ([]Model, error) {
var rawList []json.RawMessage var rawList []json.RawMessage
if err := json.Unmarshal(data, &rawList); err != nil { if err := json.Unmarshal(data, &rawList); err != nil {
@@ -190,14 +191,14 @@ func (p *Permissions) DeList(data []byte, client ClientInterface) ([]Model, erro
return result, nil return result, nil
} }
// PermissionAlerts represents permission alerts // PermissionAlerts represents permission alerts.
type PermissionAlerts struct { type PermissionAlerts struct {
BaseModel BaseModel
Alerts []PermissionAlert `json:"alerts"` Alerts []PermissionAlert `json:"alerts"`
Total int `json:"total"` Total int `json:"total"`
} }
// DeJSON deserializes PermissionAlerts from JSON // DeJSON deserializes PermissionAlerts from JSON data.
func (p *PermissionAlerts) DeJSON(data []byte, client ClientInterface) (Model, error) { func (p *PermissionAlerts) DeJSON(data []byte, client ClientInterface) (Model, error) {
var raw map[string]json.RawMessage var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil { if err := json.Unmarshal(data, &raw); err != nil {
@@ -218,7 +219,7 @@ func (p *PermissionAlerts) DeJSON(data []byte, client ClientInterface) (Model, e
return alerts, nil return alerts, nil
} }
// DeList deserializes a list of PermissionAlerts // DeList deserializes a list of PermissionAlerts from JSON data. from JSON data.
func (p *PermissionAlerts) DeList(data []byte, client ClientInterface) ([]Model, error) { func (p *PermissionAlerts) DeList(data []byte, client ClientInterface) ([]Model, error) {
var rawList []json.RawMessage var rawList []json.RawMessage
if err := json.Unmarshal(data, &rawList); err != nil { if err := json.Unmarshal(data, &rawList); err != nil {
@@ -236,7 +237,7 @@ func (p *PermissionAlerts) DeList(data []byte, client ClientInterface) ([]Model,
return result, nil return result, nil
} }
// PermissionAlert represents a permission alert // PermissionAlert represents a permission alert.
type PermissionAlert struct { type PermissionAlert struct {
BaseModel BaseModel
ID string `json:"id"` ID string `json:"id"`
@@ -248,7 +249,7 @@ type PermissionAlert struct {
CreatedAt string `json:"created_at"` CreatedAt string `json:"created_at"`
} }
// DeJSON deserializes PermissionAlert from JSON // DeJSON deserializes PermissionAlert from JSON data.
func (p *PermissionAlert) DeJSON(data []byte, client ClientInterface) (Model, error) { func (p *PermissionAlert) DeJSON(data []byte, client ClientInterface) (Model, error) {
var raw map[string]json.RawMessage var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil { if err := json.Unmarshal(data, &raw); err != nil {
@@ -300,7 +301,7 @@ func (p *PermissionAlert) DeList(data []byte, client ClientInterface) ([]Model,
return result, nil return result, nil
} }
// ContentRestrictions represents content restrictions // ContentRestrictions represents content restrictions.
type ContentRestrictions struct { type ContentRestrictions struct {
BaseModel BaseModel
HasExplicitContent bool `json:"has_explicit_content"` HasExplicitContent bool `json:"has_explicit_content"`
@@ -311,7 +312,7 @@ type ContentRestrictions struct {
BlockedArtists []string `json:"blocked_artists"` BlockedArtists []string `json:"blocked_artists"`
} }
// DeJSON deserializes ContentRestrictions from JSON // DeJSON deserializes ContentRestrictions from JSON data.
func (c *ContentRestrictions) DeJSON(data []byte, client ClientInterface) (Model, error) { func (c *ContentRestrictions) DeJSON(data []byte, client ClientInterface) (Model, error) {
var raw map[string]json.RawMessage var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil { if err := json.Unmarshal(data, &raw); err != nil {
@@ -342,7 +343,7 @@ func (c *ContentRestrictions) DeJSON(data []byte, client ClientInterface) (Model
return restrictions, nil return restrictions, nil
} }
// DeList deserializes a list of ContentRestrictions // DeList deserializes a list of ContentRestrictions from JSON data.
func (c *ContentRestrictions) DeList(data []byte, client ClientInterface) ([]Model, error) { func (c *ContentRestrictions) DeList(data []byte, client ClientInterface) ([]Model, error) {
var rawList []json.RawMessage var rawList []json.RawMessage
if err := json.Unmarshal(data, &rawList); err != nil { if err := json.Unmarshal(data, &rawList); err != nil {
+19 -18
View File
@@ -1,10 +1,11 @@
// Package models provides data models for the Yandex Music API.
package models package models
import ( import (
"encoding/json" "encoding/json"
) )
// LyricsMajor represents a lyrics provider (e.g., Genius, Musixmatch) // LyricsMajor represents a lyrics provider (e.g., Genius, Musixmatch).
type LyricsMajor struct { type LyricsMajor struct {
BaseModel BaseModel
ID int `json:"id"` ID int `json:"id"`
@@ -12,7 +13,7 @@ type LyricsMajor struct {
PrettyName string `json:"pretty_name"` PrettyName string `json:"pretty_name"`
} }
// DeJSON deserializes LyricsMajor from JSON // DeJSON deserializes LyricsMajor from JSON data.
func (lm *LyricsMajor) DeJSON(data []byte, c ClientInterface) (Model, error) { func (lm *LyricsMajor) DeJSON(data []byte, c ClientInterface) (Model, error) {
var raw map[string]json.RawMessage var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil { if err := json.Unmarshal(data, &raw); err != nil {
@@ -34,7 +35,7 @@ func (lm *LyricsMajor) DeJSON(data []byte, c ClientInterface) (Model, error) {
return major, nil return major, nil
} }
// DeList deserializes a list of LyricsMajor // DeList deserializes a list of LyricsMajor from JSON data.
func (lm *LyricsMajor) DeList(data []byte, c ClientInterface) ([]Model, error) { func (lm *LyricsMajor) DeList(data []byte, c ClientInterface) ([]Model, error) {
var rawList []json.RawMessage var rawList []json.RawMessage
if err := json.Unmarshal(data, &rawList); err != nil { if err := json.Unmarshal(data, &rawList); err != nil {
@@ -52,7 +53,7 @@ func (lm *LyricsMajor) DeList(data []byte, c ClientInterface) ([]Model, error) {
return result, nil return result, nil
} }
// TrackLyrics represents lyrics information from /tracks/{id}/lyrics endpoint // TrackLyrics represents lyrics information from /tracks/{id}/lyrics endpoint.
type TrackLyrics struct { type TrackLyrics struct {
BaseModel BaseModel
DownloadURL string `json:"download_url"` DownloadURL string `json:"download_url"`
@@ -62,7 +63,7 @@ type TrackLyrics struct {
Major *LyricsMajor `json:"major"` Major *LyricsMajor `json:"major"`
} }
// DeJSON deserializes TrackLyrics from JSON // DeJSON deserializes TrackLyrics from JSON data.
func (tl *TrackLyrics) DeJSON(data []byte, c ClientInterface) (Model, error) { func (tl *TrackLyrics) DeJSON(data []byte, c ClientInterface) (Model, error) {
var raw map[string]json.RawMessage var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil { if err := json.Unmarshal(data, &raw); err != nil {
@@ -92,7 +93,7 @@ func (tl *TrackLyrics) DeJSON(data []byte, c ClientInterface) (Model, error) {
return lyrics, nil return lyrics, nil
} }
// DeList deserializes a list of TrackLyrics // DeList deserializes a list of TrackLyrics from JSON data.
func (tl *TrackLyrics) DeList(data []byte, c ClientInterface) ([]Model, error) { func (tl *TrackLyrics) DeList(data []byte, c ClientInterface) ([]Model, error) {
var rawList []json.RawMessage var rawList []json.RawMessage
if err := json.Unmarshal(data, &rawList); err != nil { if err := json.Unmarshal(data, &rawList); err != nil {
@@ -110,7 +111,7 @@ func (tl *TrackLyrics) DeList(data []byte, c ClientInterface) ([]Model, error) {
return result, nil return result, nil
} }
// SupplementLyrics represents the actual lyrics content (from supplement) // SupplementLyrics represents the actual lyrics content from supplement.
type SupplementLyrics struct { type SupplementLyrics struct {
BaseModel BaseModel
ID int `json:"id"` ID int `json:"id"`
@@ -123,7 +124,7 @@ type SupplementLyrics struct {
Major *LyricsMajor `json:"major"` Major *LyricsMajor `json:"major"`
} }
// DeJSON deserializes SupplementLyrics from JSON // DeJSON deserializes SupplementLyrics from JSON data.
func (l *SupplementLyrics) DeJSON(data []byte, c ClientInterface) (Model, error) { func (l *SupplementLyrics) DeJSON(data []byte, c ClientInterface) (Model, error) {
var raw map[string]json.RawMessage var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil { if err := json.Unmarshal(data, &raw); err != nil {
@@ -162,7 +163,7 @@ func (l *SupplementLyrics) DeJSON(data []byte, c ClientInterface) (Model, error)
return lyrics, nil return lyrics, nil
} }
// DeList deserializes a list of SupplementLyrics // DeList deserializes a list of SupplementLyrics from JSON data.
func (l *SupplementLyrics) DeList(data []byte, c ClientInterface) ([]Model, error) { func (l *SupplementLyrics) DeList(data []byte, c ClientInterface) ([]Model, error) {
var rawList []json.RawMessage var rawList []json.RawMessage
if err := json.Unmarshal(data, &rawList); err != nil { if err := json.Unmarshal(data, &rawList); err != nil {
@@ -180,7 +181,7 @@ func (l *SupplementLyrics) DeList(data []byte, c ClientInterface) ([]Model, erro
return result, nil return result, nil
} }
// LyricsInfo represents lyrics availability information // LyricsInfo represents lyrics availability information.
type LyricsInfo struct { type LyricsInfo struct {
BaseModel BaseModel
TrackID string `json:"track_id"` TrackID string `json:"track_id"`
@@ -196,7 +197,7 @@ type LyricsInfo struct {
HasAvailableTextLyrics bool `json:"has_available_text_lyrics"` HasAvailableTextLyrics bool `json:"has_available_text_lyrics"`
} }
// DeJSON deserializes LyricsInfo from JSON // DeJSON deserializes LyricsInfo from JSON data.
func (li *LyricsInfo) DeJSON(data []byte, c ClientInterface) (Model, error) { func (li *LyricsInfo) DeJSON(data []byte, c ClientInterface) (Model, error) {
var raw map[string]json.RawMessage var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil { if err := json.Unmarshal(data, &raw); err != nil {
@@ -247,7 +248,7 @@ func (li *LyricsInfo) DeJSON(data []byte, c ClientInterface) (Model, error) {
return info, nil return info, nil
} }
// DeList deserializes a list of LyricsInfo // DeList deserializes a list of LyricsInfo from JSON data.
func (li *LyricsInfo) DeList(data []byte, c ClientInterface) ([]Model, error) { func (li *LyricsInfo) DeList(data []byte, c ClientInterface) ([]Model, error) {
var rawList []json.RawMessage var rawList []json.RawMessage
if err := json.Unmarshal(data, &rawList); err != nil { if err := json.Unmarshal(data, &rawList); err != nil {
@@ -265,7 +266,7 @@ func (li *LyricsInfo) DeList(data []byte, c ClientInterface) ([]Model, error) {
return result, nil return result, nil
} }
// VideoSupplement represents a video supplement (from supplement endpoint) // VideoSupplement represents a video supplement from supplement endpoint.
type VideoSupplement struct { type VideoSupplement struct {
BaseModel BaseModel
Cover string `json:"cover"` Cover string `json:"cover"`
@@ -277,7 +278,7 @@ type VideoSupplement struct {
Embed string `json:"embed"` Embed string `json:"embed"`
} }
// DeJSON deserializes VideoSupplement from JSON // DeJSON deserializes VideoSupplement from JSON data.
func (vs *VideoSupplement) DeJSON(data []byte, c ClientInterface) (Model, error) { func (vs *VideoSupplement) DeJSON(data []byte, c ClientInterface) (Model, error) {
var raw map[string]json.RawMessage var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil { if err := json.Unmarshal(data, &raw); err != nil {
@@ -311,7 +312,7 @@ func (vs *VideoSupplement) DeJSON(data []byte, c ClientInterface) (Model, error)
return supp, nil return supp, nil
} }
// DeList deserializes a list of VideoSupplements // DeList deserializes a list of VideoSupplements from JSON data.
func (vs *VideoSupplement) DeList(data []byte, c ClientInterface) ([]Model, error) { func (vs *VideoSupplement) DeList(data []byte, c ClientInterface) ([]Model, error) {
var rawList []json.RawMessage var rawList []json.RawMessage
if err := json.Unmarshal(data, &rawList); err != nil { if err := json.Unmarshal(data, &rawList); err != nil {
@@ -329,7 +330,7 @@ func (vs *VideoSupplement) DeList(data []byte, c ClientInterface) ([]Model, erro
return result, nil return result, nil
} }
// Supplement represents a track supplement // Supplement represents a track supplement.
type Supplement struct { type Supplement struct {
BaseModel BaseModel
ID string `json:"id"` ID string `json:"id"`
@@ -340,7 +341,7 @@ type Supplement struct {
Available bool `json:"available"` Available bool `json:"available"`
} }
// DeJSON deserializes Supplement from JSON // DeJSON deserializes Supplement from JSON data.
func (s *Supplement) DeJSON(data []byte, c ClientInterface) (Model, error) { func (s *Supplement) DeJSON(data []byte, c ClientInterface) (Model, error) {
var raw map[string]json.RawMessage var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil { if err := json.Unmarshal(data, &raw); err != nil {
@@ -376,7 +377,7 @@ func (s *Supplement) DeJSON(data []byte, c ClientInterface) (Model, error) {
return supp, nil return supp, nil
} }
// DeList deserializes a list of Supplements // DeList deserializes a list of Supplements from JSON data.
func (s *Supplement) DeList(data []byte, c ClientInterface) ([]Model, error) { func (s *Supplement) DeList(data []byte, c ClientInterface) ([]Model, error) {
var rawList []json.RawMessage var rawList []json.RawMessage
if err := json.Unmarshal(data, &rawList); err != nil { if err := json.Unmarshal(data, &rawList); err != nil {
+8 -7
View File
@@ -1,10 +1,11 @@
// Package models provides data models for the Yandex Music API.
package models package models
import ( import (
"encoding/json" "encoding/json"
) )
// Track represents a full track // Track represents a full track from the Yandex Music API.
type Track struct { type Track struct {
BaseModel BaseModel
ID string `json:"id"` ID string `json:"id"`
@@ -27,7 +28,7 @@ type Track struct {
DownloadInfo []DownloadInfo `json:"download_info"` DownloadInfo []DownloadInfo `json:"download_info"`
} }
// DeJSON deserializes a Track from JSON // DeJSON deserializes a Track from JSON data.
func (t *Track) DeJSON(data []byte, c ClientInterface) (Model, error) { func (t *Track) DeJSON(data []byte, c ClientInterface) (Model, error) {
var raw map[string]json.RawMessage var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil { if err := json.Unmarshal(data, &raw); err != nil {
@@ -115,7 +116,7 @@ func (t *Track) DeJSON(data []byte, c ClientInterface) (Model, error) {
return track, nil return track, nil
} }
// DeList deserializes a list of Tracks // DeList deserializes a list of Tracks from JSON data.
func (t *Track) DeList(data []byte, c ClientInterface) ([]Model, error) { func (t *Track) DeList(data []byte, c ClientInterface) ([]Model, error) {
var rawList []json.RawMessage var rawList []json.RawMessage
if err := json.Unmarshal(data, &rawList); err != nil { if err := json.Unmarshal(data, &rawList); err != nil {
@@ -133,7 +134,7 @@ func (t *Track) DeList(data []byte, c ClientInterface) ([]Model, error) {
return result, nil return result, nil
} }
// GetDownloadInfo returns download info for a specific quality // GetDownloadInfo returns download info for a specific quality, or nil if not found.
func (t *Track) GetDownloadInfo(quality string) *DownloadInfo { func (t *Track) GetDownloadInfo(quality string) *DownloadInfo {
for _, info := range t.DownloadInfo { for _, info := range t.DownloadInfo {
if info.Quality == quality { if info.Quality == quality {
@@ -146,14 +147,14 @@ func (t *Track) GetDownloadInfo(quality string) *DownloadInfo {
// Note: Artist and Album types are defined in their respective files // Note: Artist and Album types are defined in their respective files
// These are imported automatically since they're in the same package // These are imported automatically since they're in the same package
// Major represents major info // Major represents major label info for a track.
type Major struct { type Major struct {
ID string `json:"id"` ID string `json:"id"`
Name string `json:"name"` Name string `json:"name"`
Description string `json:"description"` Description string `json:"description"`
} }
// TrackLyricsInfo represents minimal lyrics info for a track // TrackLyricsInfo represents minimal lyrics info for a track.
type TrackLyricsInfo struct { type TrackLyricsInfo struct {
ID string `json:"id"` ID string `json:"id"`
Text string `json:"text"` Text string `json:"text"`
@@ -162,7 +163,7 @@ type TrackLyricsInfo struct {
HasText bool `json:"has_text"` HasText bool `json:"has_text"`
} }
// DownloadInfo represents file download info // DownloadInfo represents file download info for a track.
type DownloadInfo struct { type DownloadInfo struct {
Quality string `json:"quality"` Quality string `json:"quality"`
Codec string `json:"codec"` Codec string `json:"codec"`
+7 -6
View File
@@ -1,10 +1,11 @@
// Package models provides data models for the Yandex Music API.
package models package models
import ( import (
"encoding/json" "encoding/json"
) )
// TrackShort represents a lightweight track (used in lists) // TrackShort represents a lightweight track used in lists.
type TrackShort struct { type TrackShort struct {
BaseModel BaseModel
ID string `json:"id"` ID string `json:"id"`
@@ -31,7 +32,7 @@ type TrackShort struct {
RingtoneID string `json:"ringtone_id"` RingtoneID string `json:"ringtone_id"`
} }
// DeJSON deserializes a TrackShort from JSON // DeJSON deserializes a TrackShort from JSON data.
func (t *TrackShort) DeJSON(data []byte, c ClientInterface) (Model, error) { func (t *TrackShort) DeJSON(data []byte, c ClientInterface) (Model, error) {
var raw map[string]json.RawMessage var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil { if err := json.Unmarshal(data, &raw); err != nil {
@@ -131,7 +132,7 @@ func (t *TrackShort) DeJSON(data []byte, c ClientInterface) (Model, error) {
return track, nil return track, nil
} }
// DeList deserializes a list of TrackShort // DeList deserializes a list of TrackShort from JSON data.
func (t *TrackShort) DeList(data []byte, c ClientInterface) ([]Model, error) { func (t *TrackShort) DeList(data []byte, c ClientInterface) ([]Model, error) {
var rawList []json.RawMessage var rawList []json.RawMessage
if err := json.Unmarshal(data, &rawList); err != nil { if err := json.Unmarshal(data, &rawList); err != nil {
@@ -149,7 +150,7 @@ func (t *TrackShort) DeList(data []byte, c ClientInterface) ([]Model, error) {
return result, nil return result, nil
} }
// TracksList represents a list of tracks with metadata // TracksList represents a list of tracks with metadata.
type TracksList struct { type TracksList struct {
BaseModel BaseModel
Tracks []TrackShort `json:"tracks"` Tracks []TrackShort `json:"tracks"`
@@ -159,7 +160,7 @@ type TracksList struct {
Pager *Pager `json:"pager"` Pager *Pager `json:"pager"`
} }
// DeJSON deserializes a TracksList from JSON // DeJSON deserializes a TracksList from JSON data.
func (t *TracksList) DeJSON(data []byte, c ClientInterface) (Model, error) { func (t *TracksList) DeJSON(data []byte, c ClientInterface) (Model, error) {
var raw map[string]json.RawMessage var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil { if err := json.Unmarshal(data, &raw); err != nil {
@@ -193,7 +194,7 @@ func (t *TracksList) DeJSON(data []byte, c ClientInterface) (Model, error) {
return list, nil return list, nil
} }
// DeList deserializes a list of TracksList // DeList deserializes a list of TracksList from JSON data.
func (t *TracksList) DeList(data []byte, c ClientInterface) ([]Model, error) { func (t *TracksList) DeList(data []byte, c ClientInterface) ([]Model, error) {
var rawList []json.RawMessage var rawList []json.RawMessage
if err := json.Unmarshal(data, &rawList); err != nil { if err := json.Unmarshal(data, &rawList); err != nil {
+23 -12
View File
@@ -1,3 +1,4 @@
// Package utils provides utility functions for the Yandex Music API client.
package utils package utils
import ( import (
@@ -6,42 +7,49 @@ import (
"strings" "strings"
) )
// JSONBackend defines the interface for JSON encoding/decoding // JSONBackend defines the interface for JSON encoding/decoding.
// Implementations can use encoding/json, json-iterator, or other backends.
type JSONBackend interface { type JSONBackend interface {
// Marshal encodes a Go value to JSON.
Marshal(v any) ([]byte, error) Marshal(v any) ([]byte, error)
// Unmarshal decodes JSON data into a Go value.
Unmarshal(data []byte, v any) error Unmarshal(data []byte, v any) error
} }
// DefaultJSONBackend uses the standard library encoding/json // DefaultJSONBackend uses the standard library encoding/json.
type DefaultJSONBackend struct{} type DefaultJSONBackend struct{}
// Marshal encodes a Go value to JSON using encoding/json.
func (DefaultJSONBackend) Marshal(v any) ([]byte, error) { func (DefaultJSONBackend) Marshal(v any) ([]byte, error) {
return json.Marshal(v) return json.Marshal(v)
} }
// Unmarshal decodes JSON data into a Go value using encoding/json.
func (DefaultJSONBackend) Unmarshal(data []byte, v any) error { func (DefaultJSONBackend) Unmarshal(data []byte, v any) error {
return json.Unmarshal(data, v) return json.Unmarshal(data, v)
} }
// GetDefaultJSONBackend returns the default JSON backend // GetDefaultJSONBackend returns the default JSON backend (encoding/json).
func GetDefaultJSONBackend() JSONBackend { func GetDefaultJSONBackend() JSONBackend {
return DefaultJSONBackend{} return DefaultJSONBackend{}
} }
// RawMessage is a raw encoded JSON value // RawMessage is a raw encoded JSON value.
// It is an alias for encoding/json.RawMessage.
type RawMessage = json.RawMessage type RawMessage = json.RawMessage
// Marshal is a convenience function // Marshal is a convenience function that marshals a value using the default JSON backend.
func Marshal(v any) ([]byte, error) { func Marshal(v any) ([]byte, error) {
return GetDefaultJSONBackend().Marshal(v) return GetDefaultJSONBackend().Marshal(v)
} }
// Unmarshal is a convenience function // Unmarshal is a convenience function that unmarshals data using the default JSON backend.
func Unmarshal(data []byte, v any) error { func Unmarshal(data []byte, v any) error {
return GetDefaultJSONBackend().Unmarshal(data, v) return GetDefaultJSONBackend().Unmarshal(data, v)
} }
// ToSnakeCase converts camelCase to snake_case // ToSnakeCase converts camelCase to snake_case.
// For example, "camelCase" becomes "camel_case".
func ToSnakeCase(s string) string { func ToSnakeCase(s string) string {
if s == "" { if s == "" {
return s return s
@@ -60,7 +68,8 @@ func ToSnakeCase(s string) string {
return result.String() return result.String()
} }
// ToCamelCase converts snake_case to camelCase // ToCamelCase converts snake_case to camelCase.
// For example, "snake_case" becomes "snakeCase".
func ToCamelCase(s string) string { func ToCamelCase(s string) string {
if s == "" { if s == "" {
return s return s
@@ -79,7 +88,7 @@ func ToCamelCase(s string) string {
return result.String() return result.String()
} }
// MapKeysToSnakeCase converts all keys in a map to snake_case // MapKeysToSnakeCase converts all keys in a map to snake_case.
func MapKeysToSnakeCase(m map[string]any) map[string]any { func MapKeysToSnakeCase(m map[string]any) map[string]any {
result := make(map[string]any, len(m)) result := make(map[string]any, len(m))
for k, v := range m { for k, v := range m {
@@ -88,7 +97,7 @@ func MapKeysToSnakeCase(m map[string]any) map[string]any {
return result return result
} }
// MapKeysToCamelCase converts all keys in a map to camelCase // MapKeysToCamelCase converts all keys in a map to camelCase.
func MapKeysToCamelCase(m map[string]any) map[string]any { func MapKeysToCamelCase(m map[string]any) map[string]any {
result := make(map[string]any, len(m)) result := make(map[string]any, len(m))
for k, v := range m { for k, v := range m {
@@ -97,7 +106,8 @@ func MapKeysToCamelCase(m map[string]any) map[string]any {
return result return result
} }
// StructToMap converts a struct to a map using json tags // StructToMap converts a struct to a map using json tags.
// The forRequest parameter is currently unused but reserved for future use.
func StructToMap(v any, forRequest bool) (map[string]any, error) { func StructToMap(v any, forRequest bool) (map[string]any, error) {
data, err := Marshal(v) data, err := Marshal(v)
if err != nil { if err != nil {
@@ -110,7 +120,8 @@ func StructToMap(v any, forRequest bool) (map[string]any, error) {
return result, nil return result, nil
} }
// GetJSONTag returns the json tag for a struct field // GetJSONTag returns the json tag name for a struct field at the given index.
// It returns an empty string if the field has no json tag or the tag is "-".
func GetJSONTag(t reflect.Type, fieldIndex int) string { func GetJSONTag(t reflect.Type, fieldIndex int) string {
if fieldIndex >= t.NumField() { if fieldIndex >= t.NumField() {
return "" return ""
+26 -14
View File
@@ -1,3 +1,4 @@
// Package utils provides utility functions for the Yandex Music API client.
package utils package utils
import ( import (
@@ -5,19 +6,20 @@ import (
"errors" "errors"
) )
// Response represents an API response // Response represents an API response from the Yandex Music API.
type Response struct { type Response struct {
Result json.RawMessage `json:"result"` Result json.RawMessage `json:"result"`
Error string `json:"error,omitempty"` Error string `json:"error,omitempty"`
ErrorDescription string `json:"errorDescription,omitempty"` ErrorDescription string `json:"errorDescription,omitempty"`
} }
// GetResult returns the result as raw JSON // GetResult returns the result as raw JSON.
func (r *Response) GetResult() json.RawMessage { func (r *Response) GetResult() json.RawMessage {
return r.Result return r.Result
} }
// GetError returns the error message // 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 { func (r *Response) GetError() string {
if r.Error != "" { if r.Error != "" {
return r.Error return r.Error
@@ -28,12 +30,13 @@ func (r *Response) GetError() string {
return "Unknown error" return "Unknown error"
} }
// HasError returns true if the response contains an error // HasError returns true if the response contains an error.
func (r *Response) HasError() bool { func (r *Response) HasError() bool {
return r.Error != "" || r.ErrorDescription != "" return r.Error != "" || r.ErrorDescription != ""
} }
// UnmarshalJSON implements custom unmarshaling // UnmarshalJSON implements custom unmarshaling for Response.
// If result is missing, the whole response is wrapped in result.
func (r *Response) UnmarshalJSON(data []byte) error { func (r *Response) UnmarshalJSON(data []byte) error {
// First try to unmarshal as a standard response // First try to unmarshal as a standard response
type Alias Response type Alias Response
@@ -53,7 +56,7 @@ func (r *Response) UnmarshalJSON(data []byte) error {
return nil return nil
} }
// DeJSON creates a Response from JSON data // DeJSON creates a Response from JSON data.
func DeJSON(data []byte) (*Response, error) { func DeJSON(data []byte) (*Response, error) {
var resp Response var resp Response
if err := json.Unmarshal(data, &resp); err != nil { if err := json.Unmarshal(data, &resp); err != nil {
@@ -62,22 +65,30 @@ func DeJSON(data []byte) (*Response, error) {
return &resp, nil return &resp, nil
} }
// Error types // Error types for the Yandex Music API client.
var ( var (
// ErrUnauthorized is returned when authentication fails (HTTP 401/403).
ErrUnauthorized = errors.New("unauthorized") ErrUnauthorized = errors.New("unauthorized")
// ErrBadRequest is returned when the request is malformed (HTTP 400).
ErrBadRequest = errors.New("bad request") ErrBadRequest = errors.New("bad request")
// ErrNotFound is returned when the requested resource is not found (HTTP 404).
ErrNotFound = errors.New("not found") ErrNotFound = errors.New("not found")
// ErrNetwork is returned for network-related errors.
ErrNetwork = errors.New("network error") ErrNetwork = errors.New("network error")
// ErrTimeout is returned when a request times out.
ErrTimeout = errors.New("timeout") ErrTimeout = errors.New("timeout")
// ErrSchemaMismatch is returned when the API response schema doesn't match expectations.
ErrSchemaMismatch = errors.New("schema mismatch") ErrSchemaMismatch = errors.New("schema mismatch")
) )
// YandexMusicError is the base error type // YandexMusicError is the base error type for Yandex Music API errors.
// It wraps an underlying error with a descriptive message.
type YandexMusicError struct { type YandexMusicError struct {
Message string Message string
Err error Err error
} }
// Error returns the error message, including the wrapped error if present.
func (e *YandexMusicError) Error() string { func (e *YandexMusicError) Error() string {
if e.Err != nil { if e.Err != nil {
return e.Message + ": " + e.Err.Error() return e.Message + ": " + e.Err.Error()
@@ -85,16 +96,17 @@ func (e *YandexMusicError) Error() string {
return e.Message return e.Message
} }
// Unwrap returns the underlying error for compatibility with errors.Is and errors.As.
func (e *YandexMusicError) Unwrap() error { func (e *YandexMusicError) Unwrap() error {
return e.Err return e.Err
} }
// NewYandexMusicError creates a new YandexMusicError // NewYandexMusicError creates a new YandexMusicError with the given message and underlying error.
func NewYandexMusicError(message string, err error) *YandexMusicError { func NewYandexMusicError(message string, err error) *YandexMusicError {
return &YandexMusicError{Message: message, Err: err} return &YandexMusicError{Message: message, Err: err}
} }
// IsUnauthorizedError checks if error is unauthorized // IsUnauthorizedError checks if an error is an unauthorized error.
func IsUnauthorizedError(err error) bool { func IsUnauthorizedError(err error) bool {
var yme *YandexMusicError var yme *YandexMusicError
if errors.As(err, &yme) { if errors.As(err, &yme) {
@@ -103,7 +115,7 @@ func IsUnauthorizedError(err error) bool {
return errors.Is(err, ErrUnauthorized) return errors.Is(err, ErrUnauthorized)
} }
// IsBadRequestError checks if error is bad request // IsBadRequestError checks if an error is a bad request error.
func IsBadRequestError(err error) bool { func IsBadRequestError(err error) bool {
var yme *YandexMusicError var yme *YandexMusicError
if errors.As(err, &yme) { if errors.As(err, &yme) {
@@ -112,7 +124,7 @@ func IsBadRequestError(err error) bool {
return errors.Is(err, ErrBadRequest) return errors.Is(err, ErrBadRequest)
} }
// IsNotFoundError checks if error is not found // IsNotFoundError checks if an error is a not found error.
func IsNotFoundError(err error) bool { func IsNotFoundError(err error) bool {
var yme *YandexMusicError var yme *YandexMusicError
if errors.As(err, &yme) { if errors.As(err, &yme) {
@@ -121,7 +133,7 @@ func IsNotFoundError(err error) bool {
return errors.Is(err, ErrNotFound) return errors.Is(err, ErrNotFound)
} }
// IsNetworkError checks if error is network error // IsNetworkError checks if an error is a network error.
func IsNetworkError(err error) bool { func IsNetworkError(err error) bool {
var yme *YandexMusicError var yme *YandexMusicError
if errors.As(err, &yme) { if errors.As(err, &yme) {
@@ -130,7 +142,7 @@ func IsNetworkError(err error) bool {
return errors.Is(err, ErrNetwork) return errors.Is(err, ErrNetwork)
} }
// IsTimeoutError checks if error is timeout // IsTimeoutError checks if an error is a timeout error.
func IsTimeoutError(err error) bool { func IsTimeoutError(err error) bool {
var yme *YandexMusicError var yme *YandexMusicError
if errors.As(err, &yme) { if errors.As(err, &yme) {
+25 -6
View File
@@ -9,16 +9,24 @@ import (
"sync" "sync"
) )
// SchemaMismatch represents a mismatch between expected and actual API response // SchemaMismatch represents a mismatch between expected and actual API response.
// It captures details about missing fields, unknown fields, and unknown values.
type SchemaMismatch struct { type SchemaMismatch struct {
// ModelName is the name of the model that had the mismatch.
ModelName string ModelName string
// MissingFields lists fields that were expected but not found in the response.
MissingFields []string MissingFields []string
// UnknownFields lists fields that were not expected but found in the response.
UnknownFields []string UnknownFields []string
// UnknownValues maps unknown field names to their values.
UnknownValues map[string]any UnknownValues map[string]any
// Endpoint is the API endpoint where the mismatch occurred.
Endpoint string Endpoint string
// LibraryVersion is the version of the library when the mismatch occurred.
LibraryVersion string LibraryVersion string
} }
// Describe returns a human-readable description of the schema mismatch.
func (sm *SchemaMismatch) Describe() string { func (sm *SchemaMismatch) Describe() string {
var parts []string var parts []string
parts = append(parts, fmt.Sprintf("Model: %s", sm.ModelName)) parts = append(parts, fmt.Sprintf("Model: %s", sm.ModelName))
@@ -36,17 +44,22 @@ func (sm *SchemaMismatch) Describe() string {
return strings.Join(parts, "\n") return strings.Join(parts, "\n")
} }
// SchemaMismatchHandler is a callback for handling schema mismatches // SchemaMismatchHandler is a callback for handling schema mismatches.
// It is invoked when a schema mismatch is detected, if configured.
type SchemaMismatchHandler func(*SchemaMismatch) type SchemaMismatchHandler func(*SchemaMismatch)
// SchemaMismatchConfig holds configuration for schema mismatch handling // SchemaMismatchConfig holds configuration for schema mismatch handling.
type SchemaMismatchConfig struct { type SchemaMismatchConfig struct {
// ReportUnknownFields indicates whether unknown fields should be reported.
ReportUnknownFields bool ReportUnknownFields bool
// Strict indicates whether schema mismatches should be treated as errors.
Strict bool Strict bool
// OnSchemaMismatch is an optional callback for custom mismatch handling.
OnSchemaMismatch SchemaMismatchHandler OnSchemaMismatch SchemaMismatchHandler
} }
// DefaultSchemaMismatchConfig returns the default configuration // DefaultSchemaMismatchConfig returns the default configuration for schema mismatch handling.
// The default config does not report unknown fields, is not strict, and has no callback.
func DefaultSchemaMismatchConfig() SchemaMismatchConfig { func DefaultSchemaMismatchConfig() SchemaMismatchConfig {
return SchemaMismatchConfig{ return SchemaMismatchConfig{
ReportUnknownFields: false, ReportUnknownFields: false,
@@ -55,7 +68,9 @@ func DefaultSchemaMismatchConfig() SchemaMismatchConfig {
} }
} }
// ReportSchemaMismatch reports a schema mismatch according to config // ReportSchemaMismatch reports a schema mismatch according to the provided config.
// If a callback is configured, it is invoked with the mismatch details.
// If strict mode is enabled, an error is returned. Otherwise, a warning is logged.
func ReportSchemaMismatch(config SchemaMismatchConfig, modelName, endpoint string, missingFields, unknownFields []string, unknownValues map[string]any) error { func ReportSchemaMismatch(config SchemaMismatchConfig, modelName, endpoint string, missingFields, unknownFields []string, unknownValues map[string]any) error {
mismatch := &SchemaMismatch{ mismatch := &SchemaMismatch{
ModelName: modelName, ModelName: modelName,
@@ -80,18 +95,22 @@ func ReportSchemaMismatch(config SchemaMismatchConfig, modelName, endpoint strin
return nil return nil
} }
// SchemaMismatchTracker tracks reported mismatches to avoid duplicates // SchemaMismatchTracker tracks reported mismatches to avoid duplicate reports.
// It is safe for concurrent use.
type SchemaMismatchTracker struct { type SchemaMismatchTracker struct {
mu sync.Mutex mu sync.Mutex
reported map[string]bool reported map[string]bool
} }
// NewSchemaMismatchTracker creates a new SchemaMismatchTracker.
func NewSchemaMismatchTracker() *SchemaMismatchTracker { func NewSchemaMismatchTracker() *SchemaMismatchTracker {
return &SchemaMismatchTracker{ return &SchemaMismatchTracker{
reported: make(map[string]bool), reported: make(map[string]bool),
} }
} }
// ShouldReport returns true if the given model and fields have not been reported before.
// It marks them as reported so subsequent calls return false for the same key.
func (t *SchemaMismatchTracker) ShouldReport(modelName string, fields []string) bool { func (t *SchemaMismatchTracker) ShouldReport(modelName string, fields []string) bool {
t.mu.Lock() t.mu.Lock()
defer t.mu.Unlock() defer t.mu.Unlock()
+12 -6
View File
@@ -1,3 +1,4 @@
// Package utils provides utility functions for the Yandex Music API client.
package utils package utils
import ( import (
@@ -10,21 +11,23 @@ import (
) )
const ( const (
// DefaultSignKey is the signing key from the Android app // DefaultSignKey is the signing key from the Android app.
DefaultSignKey = "p93jhgh689SBReK6ghtw62" DefaultSignKey = "p93jhgh689SBReK6ghtw62"
// DesktopSignKey is the signing key from the desktop app // DesktopSignKey is the signing key from the desktop app.
DesktopSignKey = "kzqU4XhfCaY6B6JTHODeq5" DesktopSignKey = "kzqU4XhfCaY6B6JTHODeq5"
// DesktopClient is the X-Yandex-Music-Client header value for desktop // DesktopClient is the X-Yandex-Music-Client header value for desktop.
DesktopClient = "YandexMusicDesktopAppWindows/5.95.0" DesktopClient = "YandexMusicDesktopAppWindows/5.95.0"
) )
// Sign represents a request signature // Sign represents a request signature for signed API requests.
type Sign struct { type Sign struct {
Timestamp int64 Timestamp int64
Value string Value string
} }
// GetSignRequest creates a signature for a track request // GetSignRequest creates a signature for a track request using HMAC-SHA256.
// It returns a Sign with the timestamp and base64-encoded signature value.
// If key is empty, DefaultSignKey is used.
func GetSignRequest(trackID string, key string) Sign { func GetSignRequest(trackID string, key string) Sign {
if key == "" { if key == "" {
key = DefaultSignKey key = DefaultSignKey
@@ -43,7 +46,9 @@ func GetSignRequest(trackID string, key string) Sign {
} }
} }
// GetFileInfoSign creates a signature for file info requests // GetFileInfoSign creates a signature for file info requests using HMAC-SHA256.
// It returns a Sign with the timestamp and base64-encoded signature value (last character removed as in Python).
// If key is empty, DesktopSignKey is used.
func GetFileInfoSign(trackID, quality string, codecs []string, transport, key string) Sign { func GetFileInfoSign(trackID, quality string, codecs []string, transport, key string) Sign {
if key == "" { if key == "" {
key = DesktopSignKey key = DesktopSignKey
@@ -66,6 +71,7 @@ func GetFileInfoSign(trackID, quality string, codecs []string, transport, key st
} }
} }
// joinCodecs joins a list of codec strings into a single string.
func joinCodecs(codecs []string) string { func joinCodecs(codecs []string) string {
result := "" result := ""
for _, c := range codecs { for _, c := range codecs {
+23 -21
View File
@@ -1,5 +1,4 @@
// Package ynison provides a WebSocket client for the Yandex Music Ynison protocol, // Package ynison provides a Ynison WebSocket client for player synchronization across devices.
// enabling real-time player synchronization across devices.
package ynison package ynison
import ( import (
@@ -14,7 +13,7 @@ import (
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
) )
// YnisonClient represents a Ynison WebSocket client // YnisonClient represents a Ynison WebSocket client for player synchronization across devices.
type YnisonClient struct { type YnisonClient struct {
client *client.Client client *client.Client
conn *websocket.Conn conn *websocket.Conn
@@ -30,7 +29,7 @@ type YnisonClient struct {
closeOnce sync.Once // Ensures doneCh is closed only once closeOnce sync.Once // Ensures doneCh is closed only once
} }
// DeviceConfig holds device configuration for Ynison // DeviceConfig holds device configuration for Ynison WebSocket connections.
type DeviceConfig struct { type DeviceConfig struct {
DeviceID string DeviceID string
Title string Title string
@@ -42,7 +41,8 @@ type DeviceConfig struct {
VolumeGran int VolumeGran int
} }
// NewYnisonClient creates a new Ynison client // NewYnisonClient creates a new Ynison client with the given client and device config.
// Default values are applied for empty fields.
func NewYnisonClient(c *client.Client, config DeviceConfig) *YnisonClient { func NewYnisonClient(c *client.Client, config DeviceConfig) *YnisonClient {
if config.DeviceID == "" { if config.DeviceID == "" {
config.DeviceID = fmt.Sprintf("go-ynison-%d", time.Now().UnixNano()) config.DeviceID = fmt.Sprintf("go-ynison-%d", time.Now().UnixNano())
@@ -69,7 +69,8 @@ func NewYnisonClient(c *client.Client, config DeviceConfig) *YnisonClient {
} }
} }
// Connect establishes a WebSocket connection to Ynison // Connect establishes a WebSocket connection to the Ynison service.
// It sends an initial full state update after connecting.
func (y *YnisonClient) Connect(ctx context.Context) error { func (y *YnisonClient) Connect(ctx context.Context) error {
token := y.client.GetToken() token := y.client.GetToken()
if token == "" { if token == "" {
@@ -97,12 +98,12 @@ func (y *YnisonClient) Connect(ctx context.Context) error {
return y.sendUpdateFullState(ctx) return y.sendUpdateFullState(ctx)
} }
// overrideWSURL sets a custom WebSocket URL for testing // overrideWSURL sets a custom WebSocket URL for testing purposes.
func (y *YnisonClient) overrideWSURL(url string) { func (y *YnisonClient) overrideWSURL(url string) {
y.wsURL = url y.wsURL = url
} }
// Disconnect closes the WebSocket connection // Disconnect closes the WebSocket connection and cleans up resources.
func (y *YnisonClient) Disconnect() error { func (y *YnisonClient) Disconnect() error {
y.mu.Lock() y.mu.Lock()
defer y.mu.Unlock() defer y.mu.Unlock()
@@ -119,7 +120,7 @@ func (y *YnisonClient) Disconnect() error {
return nil return nil
} }
// IsConnected returns true if the client is connected // IsConnected returns true if the client is currently connected to the Ynison service.
func (y *YnisonClient) IsConnected() bool { func (y *YnisonClient) IsConnected() bool {
y.mu.Lock() y.mu.Lock()
defer y.mu.Unlock() defer y.mu.Unlock()
@@ -278,21 +279,22 @@ func (y *YnisonClient) sendRequest(ctx context.Context, req *proto.PutYnisonStat
return y.conn.WriteMessage(websocket.TextMessage, data) return y.conn.WriteMessage(websocket.TextMessage, data)
} }
// RegisterHandler registers a response handler // RegisterHandler registers a response handler for the given name.
// Handlers are invoked when a PutYnisonStateResponse is received from the server.
func (y *YnisonClient) RegisterHandler(name string, handler func(*proto.PutYnisonStateResponse)) { func (y *YnisonClient) RegisterHandler(name string, handler func(*proto.PutYnisonStateResponse)) {
y.mu.Lock() y.mu.Lock()
defer y.mu.Unlock() defer y.mu.Unlock()
y.handlers[name] = handler y.handlers[name] = handler
} }
// UnregisterHandler removes a response handler // UnregisterHandler removes a previously registered response handler by name.
func (y *YnisonClient) UnregisterHandler(name string) { func (y *YnisonClient) UnregisterHandler(name string) {
y.mu.Lock() y.mu.Lock()
defer y.mu.Unlock() defer y.mu.Unlock()
delete(y.handlers, name) delete(y.handlers, name)
} }
// UpdatePlayingStatus updates the playing status // UpdatePlayingStatus updates the playing status on the Ynison server.
func (y *YnisonClient) UpdatePlayingStatus(ctx context.Context, status *proto.PlayingStatus) error { func (y *YnisonClient) UpdatePlayingStatus(ctx context.Context, status *proto.PlayingStatus) error {
req := &proto.PutYnisonStateRequest{ req := &proto.PutYnisonStateRequest{
UpdatePlayingStatus: &proto.UpdatePlayingStatus{ UpdatePlayingStatus: &proto.UpdatePlayingStatus{
@@ -304,7 +306,7 @@ func (y *YnisonClient) UpdatePlayingStatus(ctx context.Context, status *proto.Pl
return y.sendRequest(ctx, req) return y.sendRequest(ctx, req)
} }
// UpdateVolume updates the volume // UpdateVolume updates the volume for a device on the Ynison server.
func (y *YnisonClient) UpdateVolume(ctx context.Context, deviceID string, volume float64, version *proto.UpdateVersion) error { func (y *YnisonClient) UpdateVolume(ctx context.Context, deviceID string, volume float64, version *proto.UpdateVersion) error {
req := &proto.PutYnisonStateRequest{ req := &proto.PutYnisonStateRequest{
UpdateVolumeInfo: &proto.UpdateVolumeInfo{ UpdateVolumeInfo: &proto.UpdateVolumeInfo{
@@ -320,7 +322,7 @@ func (y *YnisonClient) UpdateVolume(ctx context.Context, deviceID string, volume
return y.sendRequest(ctx, req) return y.sendRequest(ctx, req)
} }
// UpdateActiveDevice updates the active device // UpdateActiveDevice updates the active device on the Ynison server.
func (y *YnisonClient) UpdateActiveDevice(ctx context.Context, deviceID string) error { func (y *YnisonClient) UpdateActiveDevice(ctx context.Context, deviceID string) error {
req := &proto.PutYnisonStateRequest{ req := &proto.PutYnisonStateRequest{
UpdateActiveDevice: &proto.UpdateActiveDevice{ UpdateActiveDevice: &proto.UpdateActiveDevice{
@@ -332,7 +334,7 @@ func (y *YnisonClient) UpdateActiveDevice(ctx context.Context, deviceID string)
return y.sendRequest(ctx, req) return y.sendRequest(ctx, req)
} }
// UpdatePlayerState updates the player state (queue, repeat, shuffle) // UpdatePlayerState updates the player state (queue, repeat, shuffle) on the Ynison server.
func (y *YnisonClient) UpdatePlayerState(ctx context.Context, state *proto.PlayerState) error { func (y *YnisonClient) UpdatePlayerState(ctx context.Context, state *proto.PlayerState) error {
req := &proto.PutYnisonStateRequest{ req := &proto.PutYnisonStateRequest{
UpdatePlayerState: &proto.UpdatePlayerState{ UpdatePlayerState: &proto.UpdatePlayerState{
@@ -344,7 +346,7 @@ func (y *YnisonClient) UpdatePlayerState(ctx context.Context, state *proto.Playe
return y.sendRequest(ctx, req) return y.sendRequest(ctx, req)
} }
// UpdatePlayerQueueInject updates the injected queue entity // UpdatePlayerQueueInject updates the injected queue entity on the Ynison server.
func (y *YnisonClient) UpdatePlayerQueueInject(ctx context.Context, inject *proto.PlayerQueueInject) error { func (y *YnisonClient) UpdatePlayerQueueInject(ctx context.Context, inject *proto.PlayerQueueInject) error {
req := &proto.PutYnisonStateRequest{ req := &proto.PutYnisonStateRequest{
UpdatePlayerQueueInject: &proto.UpdatePlayerQueueInject{ UpdatePlayerQueueInject: &proto.UpdatePlayerQueueInject{
@@ -356,7 +358,7 @@ func (y *YnisonClient) UpdatePlayerQueueInject(ctx context.Context, inject *prot
return y.sendRequest(ctx, req) return y.sendRequest(ctx, req)
} }
// SyncStateFromEOV requests synchronization from EOV // SyncStateFromEOV requests synchronization from EOV (End of Verification).
func (y *YnisonClient) SyncStateFromEOV(ctx context.Context, actualQueueID string) error { func (y *YnisonClient) SyncStateFromEOV(ctx context.Context, actualQueueID string) error {
req := &proto.PutYnisonStateRequest{ req := &proto.PutYnisonStateRequest{
SyncStateFromEov: &proto.SyncStateFromEOV{ SyncStateFromEov: &proto.SyncStateFromEOV{
@@ -368,25 +370,25 @@ func (y *YnisonClient) SyncStateFromEOV(ctx context.Context, actualQueueID strin
return y.sendRequest(ctx, req) return y.sendRequest(ctx, req)
} }
// GetDevices returns the list of connected devices from the last response // GetDevices returns the list of connected devices from the last response.
func (y *YnisonClient) GetDevices() []*proto.Device { func (y *YnisonClient) GetDevices() []*proto.Device {
// This would need to be implemented with proper state tracking // This would need to be implemented with proper state tracking
return nil return nil
} }
// GetActiveDeviceID returns the active device ID from the last response // GetActiveDeviceID returns the active device ID from the last response.
func (y *YnisonClient) GetActiveDeviceID() string { func (y *YnisonClient) GetActiveDeviceID() string {
// This would need to be implemented with proper state tracking // This would need to be implemented with proper state tracking
return "" return ""
} }
// GetPlayerState returns the current player state from the last response // GetPlayerState returns the current player state from the last response.
func (y *YnisonClient) GetPlayerState() *proto.PlayerState { func (y *YnisonClient) GetPlayerState() *proto.PlayerState {
// This would need to be implemented with proper state tracking // This would need to be implemented with proper state tracking
return nil return nil
} }
// WaitForConnection waits for the connection to be established or context to be done // WaitForConnection waits for the connection to be established or the context to be done.
func (y *YnisonClient) WaitForConnection(ctx context.Context) error { func (y *YnisonClient) WaitForConnection(ctx context.Context) error {
select { select {
case <-ctx.Done(): case <-ctx.Done():
+9 -7
View File
@@ -1,3 +1,4 @@
// Package ynison provides a Ynison WebSocket client for player synchronization.
package ynison package ynison
import ( import (
@@ -6,7 +7,8 @@ import (
"gitea.mrixs.me/Mrixs/yandex-music-api-go/internal/ynison/proto" "gitea.mrixs.me/Mrixs/yandex-music-api-go/internal/ynison/proto"
) )
// CreatePlayingStatus creates a playing status // CreatePlayingStatus creates a playing status with the given parameters.
// The version timestamp is set to the current time.
func CreatePlayingStatus(progressMs, durationMs int64, paused bool, playbackSpeed float64, deviceID string) *proto.PlayingStatus { func CreatePlayingStatus(progressMs, durationMs int64, paused bool, playbackSpeed float64, deviceID string) *proto.PlayingStatus {
return &proto.PlayingStatus{ return &proto.PlayingStatus{
ProgressMs: progressMs, ProgressMs: progressMs,
@@ -21,7 +23,7 @@ func CreatePlayingStatus(progressMs, durationMs int64, paused bool, playbackSpee
} }
} }
// CreatePlayable creates a playable entity // CreatePlayable creates a playable entity with the given parameters.
func CreatePlayable(playableID, albumID, from, title, coverURL string, playableType proto.PlayablePlayableType) *proto.Playable { func CreatePlayable(playableID, albumID, from, title, coverURL string, playableType proto.PlayablePlayableType) *proto.Playable {
return &proto.Playable{ return &proto.Playable{
PlayableId: playableID, PlayableId: playableID,
@@ -33,7 +35,7 @@ func CreatePlayable(playableID, albumID, from, title, coverURL string, playableT
} }
} }
// CreateTrackPlayable creates a track playable // CreateTrackPlayable creates a track playable with the given parameters.
func CreateTrackPlayable(playableID, albumID, from, title, coverURL string, trackSourceKey uint32, batchID string) *proto.Playable { func CreateTrackPlayable(playableID, albumID, from, title, coverURL string, trackSourceKey uint32, batchID string) *proto.Playable {
return &proto.Playable{ return &proto.Playable{
PlayableId: playableID, PlayableId: playableID,
@@ -49,7 +51,7 @@ func CreateTrackPlayable(playableID, albumID, from, title, coverURL string, trac
} }
} }
// CreateVideoClipPlayable creates a video clip playable // CreateVideoClipPlayable creates a video clip playable with the given parameters.
func CreateVideoClipPlayable(playableID, from, title, coverURL string, recommendationType proto.VideoClipInfoRecommendationType) *proto.Playable { func CreateVideoClipPlayable(playableID, from, title, coverURL string, recommendationType proto.VideoClipInfoRecommendationType) *proto.Playable {
return &proto.Playable{ return &proto.Playable{
PlayableId: playableID, PlayableId: playableID,
@@ -63,7 +65,7 @@ func CreateVideoClipPlayable(playableID, from, title, coverURL string, recommend
} }
} }
// CreatePlayerQueue creates a player queue // CreatePlayerQueue creates a player queue with the given parameters.
func CreatePlayerQueue(entityID string, entityType proto.PlayerQueueEntityType, playables []*proto.Playable, currentIndex int32, deviceID string) *proto.PlayerQueue { func CreatePlayerQueue(entityID string, entityType proto.PlayerQueueEntityType, playables []*proto.Playable, currentIndex int32, deviceID string) *proto.PlayerQueue {
return &proto.PlayerQueue{ return &proto.PlayerQueue{
EntityId: entityID, EntityId: entityID,
@@ -82,7 +84,7 @@ func CreatePlayerQueue(entityID string, entityType proto.PlayerQueueEntityType,
} }
} }
// CreateWaveQueue creates a wave queue // CreateWaveQueue creates a wave queue with the given parameters.
func CreateWaveQueue(recommended []*proto.Playable, liveIndex int32, sessionID string, deviceID string) *proto.PlayerQueueQueue { func CreateWaveQueue(recommended []*proto.Playable, liveIndex int32, sessionID string, deviceID string) *proto.PlayerQueueQueue {
// Build track sources from playables // Build track sources from playables
var trackSources []*proto.PlayerQueueQueueWaveQueueEntityOptionsTrackSourceWithKey var trackSources []*proto.PlayerQueueQueueWaveQueueEntityOptionsTrackSourceWithKey
@@ -111,7 +113,7 @@ func CreateWaveQueue(recommended []*proto.Playable, liveIndex int32, sessionID s
} }
} }
// CreateGenerativeQueue creates a generative queue // CreateGenerativeQueue creates a generative queue with the given ID.
func CreateGenerativeQueue(id string) *proto.PlayerQueueQueue { func CreateGenerativeQueue(id string) *proto.PlayerQueueQueue {
return &proto.PlayerQueueQueue{ return &proto.PlayerQueueQueue{
GenerativeQueue: &proto.PlayerQueueQueueGenerativeQueue{ GenerativeQueue: &proto.PlayerQueueQueueGenerativeQueue{
+103 -101
View File
@@ -1,3 +1,5 @@
// Package yandexmusic provides the public API for the Yandex Music Go client.
// It re-exports types and functions from the internal packages for convenient use.
package yandexmusic package yandexmusic
import ( import (
@@ -7,313 +9,313 @@ import (
"gitea.mrixs.me/Mrixs/yandex-music-api-go/internal/ynison" "gitea.mrixs.me/Mrixs/yandex-music-api-go/internal/ynison"
) )
// ClientConfig holds configuration for the Client // ClientConfig holds configuration for the Client.
type ClientConfig = client.ClientConfig type ClientConfig = client.ClientConfig
// Client is the main Yandex Music API client // Client is the main Yandex Music API client.
type Client = client.Client type Client = client.Client
// NewClient creates a new Yandex Music client // NewClient creates a new Yandex Music client with the given configuration.
func NewClient(config ClientConfig) *Client { func NewClient(config ClientConfig) *Client {
return client.NewClient(config) return client.NewClient(config)
} }
// Request is the HTTP request handler // Request is the HTTP request handler.
type Request = client.Request type Request = client.Request
// DeviceCode represents the device authorization response // DeviceCode represents the device authorization response.
type DeviceCode = client.DeviceCode type DeviceCode = client.DeviceCode
// OAuthToken represents an OAuth token response // OAuthToken represents an OAuth token response.
type OAuthToken = client.OAuthToken type OAuthToken = client.OAuthToken
// Status represents account status // Status represents account status.
type Status = client.Status type Status = client.Status
// Account represents a user account // Account represents a user account.
type Account = client.Account type Account = client.Account
// Track represents a music track // Track represents a music track.
type Track = models.Track type Track = models.Track
// Artist represents an artist // Artist represents an artist.
type Artist = models.Artist type Artist = models.Artist
// Album represents an album // Album represents an album.
type Album = models.Album type Album = models.Album
// Playlist represents a playlist // Playlist represents a playlist.
type Playlist = models.Playlist type Playlist = models.Playlist
// User represents a user // User represents a user.
type User = models.User type User = models.User
// DownloadInfo represents file download info // DownloadInfo represents file download info.
type DownloadInfo = models.DownloadInfo type DownloadInfo = models.DownloadInfo
// SupplementLyrics represents lyrics content from supplement // SupplementLyrics represents lyrics content from supplement.
type SupplementLyrics = models.SupplementLyrics type SupplementLyrics = models.SupplementLyrics
// Major represents major label info // Major represents major label info.
type Major = models.Major type Major = models.Major
// Label represents a label // Label represents a label.
type Label = models.Label type Label = models.Label
// Availability represents availability info // Availability represents availability info.
type Availability = models.Availability type Availability = models.Availability
// Upsell represents upsell info // Upsell represents upsell info.
type Upsell = models.Upsell type Upsell = models.Upsell
// AlbumMeta represents album metadata // AlbumMeta represents album metadata.
type AlbumMeta = models.AlbumMeta type AlbumMeta = models.AlbumMeta
// Best represents best tracks info // Best represents best tracks info.
type Best = models.Best type Best = models.Best
// Ratings represents artist ratings // Ratings represents artist ratings.
type Ratings = models.Ratings type Ratings = models.Ratings
// Counts represents artist counts // Counts represents artist counts.
type Counts = models.Counts type Counts = models.Counts
// TrackShort represents a lightweight track // TrackShort represents a lightweight track.
type TrackShort = models.TrackShort type TrackShort = models.TrackShort
// TracksList represents a list of tracks with metadata // TracksList represents a list of tracks with metadata.
type TracksList = models.TracksList type TracksList = models.TracksList
// Pager represents pagination info // Pager represents pagination info.
type Pager = models.Pager type Pager = models.Pager
// TrackPosition represents track position // TrackPosition represents track position.
type TrackPosition = models.TrackPosition type TrackPosition = models.TrackPosition
// TrailerInfo represents trailer info // TrailerInfo represents trailer info.
type TrailerInfo = models.TrailerInfo type TrailerInfo = models.TrailerInfo
// Cover represents cover image info // Cover represents cover image info.
type Cover = models.Cover type Cover = models.Cover
// ArtistBriefInfo represents brief artist info // ArtistBriefInfo represents brief artist info.
type ArtistBriefInfo = models.ArtistBriefInfo type ArtistBriefInfo = models.ArtistBriefInfo
// ArtistDonations represents artist donations info // ArtistDonations represents artist donations info.
type ArtistDonations = models.ArtistDonations type ArtistDonations = models.ArtistDonations
// DonationItem represents a donation item // DonationItem represents a donation item.
type DonationItem = models.DonationItem type DonationItem = models.DonationItem
// Concert represents a concert (minimal) // Concert represents a concert (minimal).
type Concert = models.Concert type Concert = models.Concert
// Clip represents a clip (short video) // Clip represents a clip (short video).
type Clip = models.Clip type Clip = models.Clip
// SearchResult represents search results // SearchResult represents search results.
type SearchResult = models.SearchResult type SearchResult = models.SearchResult
// SearchTracksResult represents track search results // SearchTracksResult represents track search results.
type SearchTracksResult = models.SearchTracksResult type SearchTracksResult = models.SearchTracksResult
// SearchAlbumsResult represents album search results // SearchAlbumsResult represents album search results.
type SearchAlbumsResult = models.SearchAlbumsResult type SearchAlbumsResult = models.SearchAlbumsResult
// SearchArtistsResult represents artist search results // SearchArtistsResult represents artist search results.
type SearchArtistsResult = models.SearchArtistsResult type SearchArtistsResult = models.SearchArtistsResult
// SearchPlaylistsResult represents playlist search results // SearchPlaylistsResult represents playlist search results.
type SearchPlaylistsResult = models.SearchPlaylistsResult type SearchPlaylistsResult = models.SearchPlaylistsResult
// SearchVideosResult represents video search results // SearchVideosResult represents video search results.
type SearchVideosResult = models.SearchVideosResult type SearchVideosResult = models.SearchVideosResult
// SearchUsersResult represents user search results // SearchUsersResult represents user search results.
type SearchUsersResult = models.SearchUsersResult type SearchUsersResult = models.SearchUsersResult
// SearchBanner represents a search banner // SearchBanner represents a search banner.
type SearchBanner = models.SearchBanner type SearchBanner = models.SearchBanner
// Tag represents a search tag // Tag represents a search tag.
type Tag = models.Tag type Tag = models.Tag
// Video represents a video // Video represents a video.
type Video = models.Video type Video = models.Video
// ChartInfoMenu represents a chart info menu // ChartInfoMenu represents a chart info menu.
type ChartInfoMenu = models.ChartInfoMenu type ChartInfoMenu = models.ChartInfoMenu
// ChartInfoMenuItem represents a chart info menu item // ChartInfoMenuItem represents a chart info menu item.
type ChartInfoMenuItem = models.ChartInfoMenuItem type ChartInfoMenuItem = models.ChartInfoMenuItem
// ChartItems represents chart items response // ChartItems represents chart items response.
type ChartItems = models.ChartItems type ChartItems = models.ChartItems
// AccountSettings represents account settings // AccountSettings represents account settings.
type AccountSettings = models.AccountSettings type AccountSettings = models.AccountSettings
// Subscription represents subscription info // Subscription represents subscription info.
type Subscription = models.Subscription type Subscription = models.Subscription
// PlusInfo represents Plus subscription info // PlusInfo represents Plus subscription info.
type PlusInfo = models.PlusInfo type PlusInfo = models.PlusInfo
// PromoCodeStatus represents promo code status // PromoCodeStatus represents promo code status.
type PromoCodeStatus = models.PromoCodeStatus type PromoCodeStatus = models.PromoCodeStatus
// Queue represents a playback queue // Queue represents a playback queue.
type Queue = models.Queue type Queue = models.Queue
// QueueItem represents a queue item // QueueItem represents a queue item.
type QueueItem = models.QueueItem type QueueItem = models.QueueItem
// PlayContext represents a play context // PlayContext represents a play context.
type PlayContext = models.PlayContext type PlayContext = models.PlayContext
// PlayContextsData represents play contexts data // PlayContextsData represents play contexts data.
type PlayContextsData = models.PlayContextsData type PlayContextsData = models.PlayContextsData
// Feed represents the main feed // Feed represents the main feed.
type Feed = models.Feed type Feed = models.Feed
// Day represents a day in the feed // Day represents a day in the feed.
type Day = models.Day type Day = models.Day
// DayBlock represents a block in a day // DayBlock represents a block in a day.
type DayBlock = models.DayBlock type DayBlock = models.DayBlock
// DayBlockData represents data in a day block // DayBlockData represents data in a day block.
type DayBlockData = models.DayBlockData type DayBlockData = models.DayBlockData
// GeneratedPlaylist represents a generated playlist // GeneratedPlaylist represents a generated playlist.
type GeneratedPlaylist = models.GeneratedPlaylist type GeneratedPlaylist = models.GeneratedPlaylist
// Event represents a feed event // Event represents a feed event.
type Event = models.Event type Event = models.Event
// AlbumEvent represents an album event // AlbumEvent represents an album event.
type AlbumEvent = models.AlbumEvent type AlbumEvent = models.AlbumEvent
// ArtistEvent represents an artist event // ArtistEvent represents an artist event.
type ArtistEvent = models.ArtistEvent type ArtistEvent = models.ArtistEvent
// TrackWithAds represents a track with ads // TrackWithAds represents a track with ads.
type TrackWithAds = models.TrackWithAds type TrackWithAds = models.TrackWithAds
// Ad represents an ad // Ad represents an ad.
type Ad = models.Ad type Ad = models.Ad
// AdParams represents ad parameters // AdParams represents ad parameters.
type AdParams = models.AdParams type AdParams = models.AdParams
// Landing represents a landing page // Landing represents a landing page.
type Landing = models.Landing type Landing = models.Landing
// LandingBlock represents a block in a landing // LandingBlock represents a block in a landing.
type LandingBlock = models.LandingBlock type LandingBlock = models.LandingBlock
// LandingBlockData represents data in a landing block // LandingBlockData represents data in a landing block.
type LandingBlockData = models.LandingBlockData type LandingBlockData = models.LandingBlockData
// LandingList represents a list of landings // LandingList represents a list of landings.
type LandingList = models.LandingList type LandingList = models.LandingList
// LyricsInfo represents lyrics information // LyricsInfo represents lyrics information.
type LyricsInfo = models.LyricsInfo type LyricsInfo = models.LyricsInfo
// VideoSupplement represents video supplement // VideoSupplement represents video supplement.
type VideoSupplement = models.VideoSupplement type VideoSupplement = models.VideoSupplement
// Supplement represents track supplement // Supplement represents track supplement.
type Supplement = models.Supplement type Supplement = models.Supplement
// LyricsMajor represents a lyrics provider (e.g., Genius, Musixmatch) // LyricsMajor represents a lyrics provider (e.g., Genius, Musixmatch).
type LyricsMajor = models.LyricsMajor type LyricsMajor = models.LyricsMajor
// TrackLyrics represents lyrics information from /tracks/{id}/lyrics endpoint // TrackLyrics represents lyrics information from /tracks/{id}/lyrics endpoint.
type TrackLyrics = models.TrackLyrics type TrackLyrics = models.TrackLyrics
// Credits represents track credits // Credits represents track credits.
type Credits = models.Credits type Credits = models.Credits
// Credit represents a credit item // Credit represents a credit item.
type Credit = models.Credit type Credit = models.Credit
// ArtistTracks represents a page of tracks by an artist // ArtistTracks represents a page of tracks by an artist.
type ArtistTracks = models.ArtistTracks type ArtistTracks = models.ArtistTracks
// ArtistAlbums represents a page of albums by an artist // ArtistAlbums represents a page of albums by an artist.
type ArtistAlbums = models.ArtistAlbums type ArtistAlbums = models.ArtistAlbums
// RadioStation represents a radio station // RadioStation represents a radio station.
type RadioStation = models.RadioStation type RadioStation = models.RadioStation
// StationTracksResult represents station tracks result // StationTracksResult represents station tracks result.
type StationTracksResult = models.StationTracksResult type StationTracksResult = models.StationTracksResult
// RotorStation represents a rotor (generative) station // RotorStation represents a rotor (generative) station.
type RotorStation = models.RotorStation type RotorStation = models.RotorStation
// RotorSettings represents rotor station settings // RotorSettings represents rotor station settings.
type RotorSettings = models.RotorSettings type RotorSettings = models.RotorSettings
// RotorStationTracksResult represents rotor station tracks result // RotorStationTracksResult represents rotor station tracks result.
type RotorStationTracksResult = models.RotorStationTracksResult type RotorStationTracksResult = models.RotorStationTracksResult
// RotorSession represents a rotor session // RotorSession represents a rotor session.
type RotorSession = models.RotorSession type RotorSession = models.RotorSession
// SessionFeedback represents session feedback // SessionFeedback represents session feedback.
type SessionFeedback = models.SessionFeedback type SessionFeedback = models.SessionFeedback
// SessionFeedbacks represents multiple session feedbacks // SessionFeedbacks represents multiple session feedbacks.
type SessionFeedbacks = models.SessionFeedbacks type SessionFeedbacks = models.SessionFeedbacks
// Experiments represents experiments // Experiments represents experiments.
type Experiments = models.Experiments type Experiments = models.Experiments
// ExperimentDetail represents experiment details // ExperimentDetail represents experiment details.
type ExperimentDetail = models.ExperimentDetail type ExperimentDetail = models.ExperimentDetail
// Permissions represents user permissions // Permissions represents user permissions.
type Permissions = models.Permissions type Permissions = models.Permissions
// PermissionAlerts represents permission alerts // PermissionAlerts represents permission alerts.
type PermissionAlerts = models.PermissionAlerts type PermissionAlerts = models.PermissionAlerts
// PermissionAlert represents a permission alert // PermissionAlert represents a permission alert.
type PermissionAlert = models.PermissionAlert type PermissionAlert = models.PermissionAlert
// ContentRestrictions represents content restrictions // ContentRestrictions represents content restrictions.
type ContentRestrictions = models.ContentRestrictions type ContentRestrictions = models.ContentRestrictions
// JSONBackend defines the interface for JSON encoding/decoding // JSONBackend defines the interface for JSON encoding/decoding.
type JSONBackend = utils.JSONBackend type JSONBackend = utils.JSONBackend
// GetDefaultJSONBackend returns the default JSON backend // GetDefaultJSONBackend returns the default JSON backend.
func GetDefaultJSONBackend() JSONBackend { func GetDefaultJSONBackend() JSONBackend {
return utils.GetDefaultJSONBackend() return utils.GetDefaultJSONBackend()
} }
// SchemaMismatchConfig holds configuration for schema mismatch handling // SchemaMismatchConfig holds configuration for schema mismatch handling.
type SchemaMismatchConfig = utils.SchemaMismatchConfig type SchemaMismatchConfig = utils.SchemaMismatchConfig
// DefaultSchemaMismatchConfig returns the default configuration // DefaultSchemaMismatchConfig returns the default configuration.
func DefaultSchemaMismatchConfig() SchemaMismatchConfig { func DefaultSchemaMismatchConfig() SchemaMismatchConfig {
return utils.DefaultSchemaMismatchConfig() return utils.DefaultSchemaMismatchConfig()
} }
// SchemaMismatchHandler is a callback for handling schema mismatches // SchemaMismatchHandler is a callback for handling schema mismatches.
type SchemaMismatchHandler = utils.SchemaMismatchHandler type SchemaMismatchHandler = utils.SchemaMismatchHandler
// SchemaMismatch represents a mismatch between expected and actual API response // SchemaMismatch represents a mismatch between expected and actual API response.
type SchemaMismatch = utils.SchemaMismatch type SchemaMismatch = utils.SchemaMismatch
// YnisonClient represents a Ynison WebSocket client // YnisonClient represents a Ynison WebSocket client.
type YnisonClient = ynison.YnisonClient type YnisonClient = ynison.YnisonClient
// DeviceConfig holds device configuration for Ynison // DeviceConfig holds device configuration for Ynison.
type DeviceConfig = ynison.DeviceConfig type DeviceConfig = ynison.DeviceConfig
// Example usage: // Example usage: