Files
yandex-music-api-go/internal/models/album.go
T
Mrixs bc026d82b4 Add missing Track and Album model fields from Python reference
Track: Added 50+ missing fields (storage_dir, file_size, real_id, og_image, type,
normalization, error, can_publish, state, filename, user_info, meta_data, regions,
content_warning, preview_duration_ms, remember_position, background_video_uri,
short_description, is_suitable_for_children, track_source, available_for_options,
derived_colors, fade, smart_preview_params, special_audio_resources, disclaimers,
background_video_id, player_id, mix_fade, chart, clip_ids, isrc, ugc_artist_name,
podcast_episode_type, pub_date, and more)

New types: Normalization, MetaData, Fade, SmartPreviewParams, CoverDerivedColors,
CustomWave, TrackId, TrackFullInfo, SimilarTracks, TrackTrailer

Album: Added 40+ missing fields (error, version, original_release_year, text_color,
short_description, is_premiere, is_banner, meta_type, storage_dir, og_image, buy,
recent, very_important, bests, duplicates, prerolls, regions, available_as_rbt,
lyrics_available, remember_position, duration_ms, explicit, start_date, likes_count,
deprecation, available_regions, available_for_options, disclaimers, action_button,
cover, derived_colors, meta_tag_id, child_content, background_image_url, duration_sec,
has_trailer, pager, sort_order)

New types: Deprecation, AlbumActionButton
2026-10-18 13:12:13 +03:00

425 lines
13 KiB
Go

// Package models provides data models for the Yandex Music API.
package models
import (
"encoding/json"
)
// Album represents a full album from the Yandex Music API.
type Album struct {
BaseModel
ID JSONID `json:"id"`
Error string `json:"error"`
Title string `json:"title"`
TrackCount int `json:"track_count"`
Artists []Artist `json:"artists"`
Labels []LabelOrString `json:"labels"`
Available bool `json:"available"`
AvailableForPremiumUsers bool `json:"available_for_premium_users"`
Version string `json:"version"`
CoverURI string `json:"cover_uri"`
ContentWarning string `json:"content_warning"`
OriginalReleaseYear int `json:"original_release_year"`
Genre string `json:"genre"`
TextColor string `json:"text_color"`
ShortDescription string `json:"short_description"`
Description string `json:"description"`
IsPremiere bool `json:"is_premiere"`
IsBanner bool `json:"is_banner"`
MetaType string `json:"meta_type"`
StorageDir string `json:"storage_dir"`
OgImage string `json:"og_image"`
Buy []json.RawMessage `json:"buy"`
Recent bool `json:"recent"`
VeryImportant bool `json:"very_important"`
AvailableForMobile bool `json:"available_for_mobile"`
AvailablePartially bool `json:"available_partially"`
Bests []int `json:"bests"`
Duplicates []Album `json:"duplicates"`
Prerolls []json.RawMessage `json:"prerolls"`
Volumes [][]Track `json:"volumes"`
Year int `json:"year"`
ReleaseDate string `json:"release_date"`
Type string `json:"type"`
TrackPosition *TrackPosition `json:"track_position"`
Regions []string `json:"regions"`
AvailableAsRbt bool `json:"available_as_rbt"`
LyricsAvailable bool `json:"lyrics_available"`
RememberPosition bool `json:"remember_position"`
Albums []Album `json:"albums"`
DurationMs int `json:"duration_ms"`
Explicit bool `json:"explicit"`
StartDate string `json:"start_date"`
LikesCount int `json:"likes_count"`
Deprecation *Deprecation `json:"deprecation"`
AvailableRegions []string `json:"available_regions"`
AvailableForOptions []string `json:"available_for_options"`
ListeningFinished bool `json:"listening_finished"`
Disclaimers []string `json:"disclaimers"`
ActionButton *AlbumActionButton `json:"action_button"`
Cover *Cover `json:"cover"`
DerivedColors *CoverDerivedColors `json:"derived_colors"`
MetaTagID string `json:"meta_tag_id"`
ChildContent bool `json:"child_content"`
BackgroundImageURL string `json:"background_image_url"`
CustomWave *CustomWave `json:"custom_wave"`
DurationSec int `json:"duration_sec"`
HasTrailer bool `json:"has_trailer"`
Trailer *AlbumTrailerStatus `json:"trailer"`
Pager *Pager `json:"pager"`
SortOrder string `json:"sort_order"`
Meta *AlbumMeta `json:"meta"`
Best *Best `json:"best"`
Region string `json:"region"`
AvailableForPremiumUsersOnly bool `json:"available_for_premium_users_only"`
Label string `json:"label"`
CatalogNumber string `json:"catalog_number"`
Options []string `json:"options"`
TrackPositions []TrackPosition `json:"track_positions"`
SimilarAlbums []Album `json:"similar_albums"`
}
// LabelOrString represents a label that can be either a Label object or a string.
type LabelOrString struct {
Label *Label `json:"-"`
Str string `json:"-"`
IsStr bool `json:"-"`
}
// UnmarshalJSON implements json.Unmarshaler, accepting both Label objects and strings.
func (l *LabelOrString) UnmarshalJSON(data []byte) error {
var s string
if err := json.Unmarshal(data, &s); err == nil {
l.Str = s
l.IsStr = true
return nil
}
var label Label
if err := json.Unmarshal(data, &label); err != nil {
return err
}
l.Label = &label
l.IsStr = false
return nil
}
// MarshalJSON implements json.Marshaler.
func (l LabelOrString) MarshalJSON() ([]byte, error) {
if l.IsStr {
return json.Marshal(l.Str)
}
return json.Marshal(l.Label)
}
// String returns the label as a string.
func (l LabelOrString) String() string {
if l.IsStr {
return l.Str
}
if l.Label != nil {
return l.Label.Name
}
return ""
}
// DeJSON deserializes an Album from JSON data.
func (a *Album) DeJSON(data []byte, c ClientInterface) (Model, error) {
var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil {
return nil, err
}
album := &Album{BaseModel: *NewBaseModel(c)}
// Simple fields
if v, ok := raw["id"]; ok {
json.Unmarshal(v, &album.ID)
}
if v, ok := raw["error"]; ok {
json.Unmarshal(v, &album.Error)
}
if v, ok := raw["title"]; ok {
json.Unmarshal(v, &album.Title)
}
if v, ok := raw["cover_uri"]; ok {
json.Unmarshal(v, &album.CoverURI)
}
if v, ok := raw["genre"]; ok {
json.Unmarshal(v, &album.Genre)
}
if v, ok := raw["year"]; ok {
json.Unmarshal(v, &album.Year)
}
if v, ok := raw["track_count"]; ok {
json.Unmarshal(v, &album.TrackCount)
}
if v, ok := raw["available"]; ok {
json.Unmarshal(v, &album.Available)
}
if v, ok := raw["release_date"]; ok {
json.Unmarshal(v, &album.ReleaseDate)
}
if v, ok := raw["description"]; ok {
json.Unmarshal(v, &album.Description)
}
if v, ok := raw["region"]; ok {
json.Unmarshal(v, &album.Region)
}
if v, ok := raw["available_for_premium_users"]; ok {
json.Unmarshal(v, &album.AvailableForPremiumUsers)
}
if v, ok := raw["available_for_premium_users_only"]; ok {
json.Unmarshal(v, &album.AvailableForPremiumUsersOnly)
}
if v, ok := raw["content_warning"]; ok {
json.Unmarshal(v, &album.ContentWarning)
}
if v, ok := raw["label"]; ok {
json.Unmarshal(v, &album.Label)
}
if v, ok := raw["catalog_number"]; ok {
json.Unmarshal(v, &album.CatalogNumber)
}
if v, ok := raw["options"]; ok {
json.Unmarshal(v, &album.Options)
}
// Nested objects
if v, ok := raw["artists"]; ok {
var artists []Artist
json.Unmarshal(v, &artists)
album.Artists = artists
}
if v, ok := raw["labels"]; ok {
var labels []LabelOrString
if err := json.Unmarshal(v, &labels); err == nil {
album.Labels = labels
}
}
if v, ok := raw["volumes"]; ok {
var volumes [][]Track
json.Unmarshal(v, &volumes)
album.Volumes = volumes
}
if v, ok := raw["meta"]; ok {
var meta AlbumMeta
json.Unmarshal(v, &meta)
album.Meta = &meta
}
if v, ok := raw["best"]; ok {
var best Best
json.Unmarshal(v, &best)
album.Best = &best
}
if v, ok := raw["track_positions"]; ok {
var positions []TrackPosition
json.Unmarshal(v, &positions)
album.TrackPositions = positions
}
if v, ok := raw["similar_albums"]; ok {
var similar []Album
json.Unmarshal(v, &similar)
album.SimilarAlbums = similar
}
if v, ok := raw["trailer"]; ok {
var trailer AlbumTrailerStatus
json.Unmarshal(v, &trailer)
album.Trailer = &trailer
}
return album, nil
}
// DeList deserializes a list of Albums from JSON data.
func (a *Album) DeList(data []byte, c ClientInterface) ([]Model, error) {
var rawList []json.RawMessage
if err := json.Unmarshal(data, &rawList); err != nil {
return nil, err
}
result := make([]Model, 0, len(rawList))
for _, item := range rawList {
album := &Album{BaseModel: *NewBaseModel(c)}
if err := json.Unmarshal(item, album); err != nil {
continue
}
result = append(result, album)
}
return result, nil
}
// AlbumMeta represents album metadata.
type AlbumMeta struct {
BaseModel
Availability *Availability `json:"availability"`
Upsell *Upsell `json:"upsell"`
}
// DeJSON deserializes an AlbumMeta from JSON data.
func (am *AlbumMeta) DeJSON(data []byte, c ClientInterface) (Model, error) {
var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil {
return nil, err
}
meta := &AlbumMeta{BaseModel: *NewBaseModel(c)}
if v, ok := raw["availability"]; ok {
var avail Availability
json.Unmarshal(v, &avail)
meta.Availability = &avail
}
if v, ok := raw["upsell"]; ok {
var upsell Upsell
json.Unmarshal(v, &upsell)
meta.Upsell = &upsell
}
return meta, nil
}
// DeList deserializes a list of AlbumMeta from JSON data.
func (am *AlbumMeta) DeList(data []byte, c ClientInterface) ([]Model, error) {
var rawList []json.RawMessage
if err := json.Unmarshal(data, &rawList); err != nil {
return nil, err
}
result := make([]Model, 0, len(rawList))
for _, item := range rawList {
meta := &AlbumMeta{BaseModel: *NewBaseModel(c)}
if err := json.Unmarshal(item, meta); err != nil {
continue
}
result = append(result, meta)
}
return result, nil
}
// Availability represents availability info for an album.
type Availability struct {
AvailableForPremiumUsers bool `json:"available_for_premium_users"`
Territories []string `json:"territories"`
}
// Upsell represents upsell info for an album.
type Upsell struct {
Type string `json:"type"`
Description string `json:"description"`
}
// Best represents best tracks info for an album.
type Best struct {
Tracks []Track `json:"tracks"`
}
// TrailerInfo represents album/track trailer info.
type TrailerInfo struct {
BaseModel
PreviewURI string `json:"preview_uri"`
TrackID JSONID `json:"track_id"`
AlbumID JSONID `json:"album_id"`
Duration int `json:"duration"`
}
// DeJSON deserializes a TrailerInfo from JSON data.
func (ti *TrailerInfo) DeJSON(data []byte, c ClientInterface) (Model, error) {
var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil {
return nil, err
}
trailer := &TrailerInfo{BaseModel: *NewBaseModel(c)}
if v, ok := raw["preview_uri"]; ok {
json.Unmarshal(v, &trailer.PreviewURI)
}
if v, ok := raw["track_id"]; ok {
json.Unmarshal(v, &trailer.TrackID)
}
if v, ok := raw["album_id"]; ok {
json.Unmarshal(v, &trailer.AlbumID)
}
if v, ok := raw["duration"]; ok {
json.Unmarshal(v, &trailer.Duration)
}
return trailer, nil
}
// DeList deserializes a list of TrailerInfo from JSON data.
func (ti *TrailerInfo) DeList(data []byte, c ClientInterface) ([]Model, error) {
var rawList []json.RawMessage
if err := json.Unmarshal(data, &rawList); err != nil {
return nil, err
}
result := make([]Model, 0, len(rawList))
for _, item := range rawList {
trailer := &TrailerInfo{BaseModel: *NewBaseModel(c)}
if err := json.Unmarshal(item, trailer); err != nil {
continue
}
result = append(result, trailer)
}
return result, nil
}
// AlbumTrailerStatus represents trailer availability status for an album.
type AlbumTrailerStatus struct {
BaseModel
Available bool `json:"available"`
}
// DeJSON deserializes AlbumTrailerStatus from JSON data.
func (ats *AlbumTrailerStatus) DeJSON(data []byte, c ClientInterface) (Model, error) {
var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil {
return nil, err
}
status := &AlbumTrailerStatus{BaseModel: *NewBaseModel(c)}
if v, ok := raw["available"]; ok {
json.Unmarshal(v, &status.Available)
}
return status, nil
}
// DeList deserializes a list of AlbumTrailerStatus from JSON data.
func (ats *AlbumTrailerStatus) DeList(data []byte, c ClientInterface) ([]Model, error) {
var rawList []json.RawMessage
if err := json.Unmarshal(data, &rawList); err != nil {
return nil, err
}
result := make([]Model, 0, len(rawList))
for _, item := range rawList {
status := &AlbumTrailerStatus{BaseModel: *NewBaseModel(c)}
if err := json.Unmarshal(item, status); err != nil {
continue
}
result = append(result, status)
}
return result, nil
}
// Deprecation represents album deprecation info.
type Deprecation struct {
BaseModel
TargetAlbumID JSONID `json:"target_album_id"`
Status string `json:"status"`
Done bool `json:"done"`
}
// AlbumActionButton represents an action button for an album.
type AlbumActionButton struct {
BaseModel
Text string `json:"text"`
URL string `json:"url"`
Color string `json:"color"`
ViewBrowser bool `json:"view_browser"`
}