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
This commit is contained in:
Mrixs committed 2026-10-18 13:12:13 +03:00
1 parent a9be10b5e5
commit bc026d82b4
2 files changed
+455 -136

No files matched your search

+115 -53
View File
@@ -9,34 +9,77 @@ import (
type Album struct {
BaseModel
ID JSONID `json:"id"`
Error string `json:"error"`
Title string `json:"title"`
CoverURI string `json:"cover_uri"`
Genre string `json:"genre"`
Year int `json:"year"`
TrackCount int `json:"track_count"`
Available bool `json:"available"`
ReleaseDate string `json:"release_date"`
Artists []Artist `json:"artists"`
Labels []LabelOrString `json:"labels"`
Volumes [][]Track `json:"volumes"`
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"`
// Additional fields
Region string `json:"region"`
AvailableForPremiumUsers bool `json:"available_for_premium_users"`
AvailableForPremiumUsersOnly bool `json:"available_for_premium_users_only"`
ContentWarning string `json:"content_warning"`
Label string `json:"label"`
CatalogNumber string `json:"catalog_number"`
Options []string `json:"options"`
TrackPositions []TrackPosition `json:"track_positions"`
SimilarAlbums []Album `json:"similar_albums"`
Trailer *AlbumTrailerStatus `json:"trailer"`
}
// LabelOrString represents a label that can be either a Label object or a string.
// The Yandex Music API sometimes returns labels as objects and sometimes as strings.
type LabelOrString struct {
Label *Label `json:"-"`
Str string `json:"-"`
@@ -45,14 +88,12 @@ type LabelOrString struct {
// UnmarshalJSON implements json.Unmarshaler, accepting both Label objects and strings.
func (l *LabelOrString) UnmarshalJSON(data []byte) error {
// Try string first
var s string
if err := json.Unmarshal(data, &s); err == nil {
l.Str = s
l.IsStr = true
return nil
}
// Try Label object
var label Label
if err := json.Unmarshal(data, &label); err != nil {
return err
@@ -81,46 +122,6 @@ func (l LabelOrString) String() string {
return ""
}
// 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
}
// DeJSON deserializes an Album from JSON data.
func (a *Album) DeJSON(data []byte, c ClientInterface) (Model, error) {
var raw map[string]json.RawMessage
@@ -134,6 +135,9 @@ func (a *Album) DeJSON(data []byte, c ClientInterface) (Model, error) {
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)
}
@@ -360,3 +364,61 @@ func (ti *TrailerInfo) DeList(data []byte, c ClientInterface) ([]Model, error) {
}
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"`
}
+340 -83
View File
@@ -10,21 +10,65 @@ type Track struct {
BaseModel
ID JSONID `json:"id"`
Title string `json:"title"`
DurationMs int `json:"duration_ms"`
StorageDir string `json:"storage_dir"`
CoverURI string `json:"cover_uri"`
Available bool `json:"available"`
Artists []Artist `json:"artists"`
Albums []Album `json:"albums"`
Genre string `json:"genre"`
Version string `json:"version"`
Explicit bool `json:"explicit"`
Available bool `json:"available"`
AvailableForPremiumUsers bool `json:"available_for_premium_users"`
R128 *R128 `json:"r128"`
TrackSharingFlag string `json:"track_sharing_flag"`
LyricsAvailable bool `json:"lyrics_available"`
Best bool `json:"best"`
RealID JSONID `json:"real_id"`
OgImage string `json:"og_image"`
Type string `json:"type"`
CoverURI string `json:"cover_uri"`
Major *Major `json:"major"`
LyricsInfo *TrackLyricsInfo `json:"lyrics_info"`
DurationMs int `json:"duration_ms"`
StorageDir string `json:"storage_dir"`
FileSize int64 `json:"file_size"`
Genre string `json:"genre"`
AvailableAsRingtone bool `json:"available_as_ringtone"`
RingtoneID string `json:"ringtone_id"`
SimilarTracks []Track `json:"similar_tracks"`
Position *TrackPosition `json:"position"`
Substituted *Track `json:"substituted"`
MatchedTrack *Track `json:"matched_track"`
Normalization *Normalization `json:"normalization"`
Error string `json:"error"`
CanPublish bool `json:"can_publish"`
State string `json:"state"`
DesiredVisibility string `json:"desired_visibility"`
Filename string `json:"filename"`
UserInfo *User `json:"user_info"`
MetaData *MetaData `json:"meta_data"`
Regions []string `json:"regions"`
AvailableAsRbt bool `json:"available_as_rbt"`
ContentWarning string `json:"content_warning"`
Explicit bool `json:"explicit"`
PreviewDurationMs int `json:"preview_duration_ms"`
AvailableFullWithoutPermission bool `json:"available_full_without_permission"`
Version string `json:"version"`
RememberPosition bool `json:"remember_position"`
BackgroundVideoURI string `json:"background_video_uri"`
ShortDescription string `json:"short_description"`
IsSuitableForChildren bool `json:"is_suitable_for_children"`
TrackSource string `json:"track_source"`
AvailableForOptions []string `json:"available_for_options"`
R128 *R128 `json:"r128"`
LyricsInfo *TrackLyricsInfo `json:"lyrics_info"`
TrackSharingFlag string `json:"track_sharing_flag"`
DerivedColors *CoverDerivedColors `json:"derived_colors"`
Fade *Fade `json:"fade"`
SmartPreviewParams *SmartPreviewParams `json:"smart_preview_params"`
SpecialAudioResources []string `json:"special_audio_resources"`
Disclaimers []string `json:"disclaimers"`
BackgroundVideoID string `json:"background_video_id"`
PlayerID string `json:"player_id"`
MixFade *Fade `json:"mix_fade"`
Chart *Chart `json:"chart"`
ClipIDs []int `json:"clip_ids"`
Isrc string `json:"isrc"`
UgcArtistName string `json:"ugc_artist_name"`
PodcastEpisodeType string `json:"podcast_episode_type"`
PubDate string `json:"pub_date"`
DownloadInfo []DownloadInfo `json:"download_info"`
}
@@ -74,6 +118,12 @@ func (t *Track) DeJSON(data []byte, c ClientInterface) (Model, error) {
if v, ok := raw["track_sharing_flag"]; ok {
json.Unmarshal(v, &track.TrackSharingFlag)
}
if v, ok := raw["available_as_ringtone"]; ok {
json.Unmarshal(v, &track.AvailableAsRingtone)
}
if v, ok := raw["ringtone_id"]; ok {
json.Unmarshal(v, &track.RingtoneID)
}
// Nested objects
if v, ok := raw["artists"]; ok {
@@ -112,6 +162,12 @@ func (t *Track) DeJSON(data []byte, c ClientInterface) (Model, error) {
track.DownloadInfo = downloadInfo
}
}
if v, ok := raw["position"]; ok {
var pos TrackPosition
if err := json.Unmarshal(v, &pos); err == nil {
track.Position = &pos
}
}
return track, nil
}
@@ -144,9 +200,6 @@ func (t *Track) GetDownloadInfo(quality string) *DownloadInfo {
return nil
}
// Note: Artist and Album types are defined in their respective files
// These are imported automatically since they're in the same package
// Major represents major label info for a track.
type Major struct {
ID JSONID `json:"id"`
@@ -154,76 +207,6 @@ type Major struct {
Description string `json:"description"`
}
// Lyrics represents track lyrics from supplement endpoint.
type Lyrics struct {
BaseModel
ID JSONID `json:"id"`
Text string `json:"lyrics"`
FullLyrics string `json:"full_lyrics"`
HasRights bool `json:"has_rights"`
ShowTranslation bool `json:"show_translation"`
TextLanguage string `json:"text_language"`
URL string `json:"url"`
Major *Major `json:"major"`
}
// DeJSON deserializes Lyrics from JSON data.
func (l *Lyrics) DeJSON(data []byte, c ClientInterface) (Model, error) {
var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil {
return nil, err
}
lyrics := &Lyrics{BaseModel: *NewBaseModel(c)}
if v, ok := raw["id"]; ok {
json.Unmarshal(v, &lyrics.ID)
}
if v, ok := raw["lyrics"]; ok {
json.Unmarshal(v, &lyrics.Text)
}
if v, ok := raw["full_lyrics"]; ok {
json.Unmarshal(v, &lyrics.FullLyrics)
}
if v, ok := raw["has_rights"]; ok {
json.Unmarshal(v, &lyrics.HasRights)
}
if v, ok := raw["show_translation"]; ok {
json.Unmarshal(v, &lyrics.ShowTranslation)
}
if v, ok := raw["text_language"]; ok {
json.Unmarshal(v, &lyrics.TextLanguage)
}
if v, ok := raw["url"]; ok {
json.Unmarshal(v, &lyrics.URL)
}
if v, ok := raw["major"]; ok {
var major Major
json.Unmarshal(v, &major)
lyrics.Major = &major
}
return lyrics, nil
}
// DeList deserializes a list of Lyrics from JSON data.
func (l *Lyrics) 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 {
lyrics := &Lyrics{BaseModel: *NewBaseModel(c)}
if err := json.Unmarshal(item, lyrics); err != nil {
continue
}
result = append(result, lyrics)
}
return result, nil
}
// TrackLyricsInfo represents lyrics availability info for a track.
type TrackLyricsInfo struct {
BaseModel
@@ -267,6 +250,7 @@ func (tli *TrackLyricsInfo) DeList(data []byte, c ClientInterface) ([]Model, err
}
return result, nil
}
// DownloadInfo represents file download info for a track.
type DownloadInfo struct {
Quality string `json:"quality"`
@@ -278,3 +262,276 @@ type DownloadInfo struct {
DownloadInfoURL string `json:"download_info_url"`
DirectLinkURL string `json:"-"` // Computed signed download URL
}
// Normalization represents track normalization values.
type Normalization struct {
BaseModel
Gain float64 `json:"gain"`
Peak int `json:"peak"`
}
// MetaData represents track metadata.
type MetaData struct {
BaseModel
Album string `json:"album"`
Volume int `json:"volume"`
Year int `json:"year"`
Number int `json:"number"`
Genre string `json:"genre"`
Lyricist string `json:"lyricist"`
Version string `json:"version"`
Composer string `json:"composer"`
}
// Fade represents fade parameters for a track.
type Fade struct {
BaseModel
InStart float64 `json:"in_start"`
InStop float64 `json:"in_stop"`
OutStart float64 `json:"out_start"`
OutStop float64 `json:"out_stop"`
}
// SmartPreviewParams represents smart preview parameters.
type SmartPreviewParams struct {
BaseModel
DurationMs int `json:"duration_ms"`
Fade *Fade `json:"fade"`
}
// CoverDerivedColors represents derived colors from cover art.
type CoverDerivedColors struct {
BaseModel
Average string `json:"average"`
WaveText string `json:"wave_text"`
MiniPlayer string `json:"mini_player"`
Accent string `json:"accent"`
}
// CustomWave represents a custom wave for playlists.
type CustomWave struct {
BaseModel
Title string `json:"title"`
AnimationURL string `json:"animation_url"`
Position string `json:"position"`
Header string `json:"header"`
BackgroundImageURL string `json:"background_image_url"`
SquareAgentAnimation string `json:"square_agent_animation"`
}
// TrackId represents a track ID reference.
type TrackId struct {
BaseModel
ID JSONID `json:"id"`
TrackID JSONID `json:"track_id"`
AlbumID JSONID `json:"album_id"`
From string `json:"from"`
}
// DeJSON deserializes a TrackId from JSON data.
func (ti *TrackId) DeJSON(data []byte, c ClientInterface) (Model, error) {
var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil {
return nil, err
}
tid := &TrackId{BaseModel: *NewBaseModel(c)}
if v, ok := raw["id"]; ok {
json.Unmarshal(v, &tid.ID)
}
if v, ok := raw["track_id"]; ok {
json.Unmarshal(v, &tid.TrackID)
}
if v, ok := raw["album_id"]; ok {
json.Unmarshal(v, &tid.AlbumID)
}
if v, ok := raw["from"]; ok {
json.Unmarshal(v, &tid.From)
}
return tid, nil
}
// DeList deserializes a list of TrackId from JSON data.
func (ti *TrackId) 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 {
tid := &TrackId{BaseModel: *NewBaseModel(c)}
if err := json.Unmarshal(item, tid); err != nil {
continue
}
result = append(result, tid)
}
return result, nil
}
// TrackFullInfo represents full track info.
type TrackFullInfo struct {
BaseModel
Track *Track `json:"track"`
SimilarTracks []Track `json:"similar_tracks"`
AlsoInAlbums []Track `json:"also_in_albums"`
Aliases []string `json:"aliases"`
Artists []Artist `json:"artists"`
}
// DeJSON deserializes a TrackFullInfo from JSON data.
func (tfi *TrackFullInfo) DeJSON(data []byte, c ClientInterface) (Model, error) {
var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil {
return nil, err
}
info := &TrackFullInfo{BaseModel: *NewBaseModel(c)}
if v, ok := raw["track"]; ok {
var track Track
if err := json.Unmarshal(v, &track); err == nil {
info.Track = &track
}
}
if v, ok := raw["similar_tracks"]; ok {
var tracks []Track
if err := json.Unmarshal(v, &tracks); err == nil {
info.SimilarTracks = tracks
}
}
if v, ok := raw["also_in_albums"]; ok {
var tracks []Track
if err := json.Unmarshal(v, &tracks); err == nil {
info.AlsoInAlbums = tracks
}
}
if v, ok := raw["aliases"]; ok {
json.Unmarshal(v, &info.Aliases)
}
if v, ok := raw["artists"]; ok {
var artists []Artist
if err := json.Unmarshal(v, &artists); err == nil {
info.Artists = artists
}
}
return info, nil
}
// DeList deserializes a list of TrackFullInfo from JSON data.
func (tfi *TrackFullInfo) 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 {
info := &TrackFullInfo{BaseModel: *NewBaseModel(c)}
if err := json.Unmarshal(item, info); err != nil {
continue
}
result = append(result, info)
}
return result, nil
}
// SimilarTracks represents similar tracks.
type SimilarTracks struct {
BaseModel
Track *Track `json:"track"`
SimilarTracks []Track `json:"similar_tracks"`
}
// DeJSON deserializes SimilarTracks from JSON data.
func (st *SimilarTracks) DeJSON(data []byte, c ClientInterface) (Model, error) {
var raw map[string]json.RawMessage
if err := json.Unmarshal(data, &raw); err != nil {
return nil, err
}
similar := &SimilarTracks{BaseModel: *NewBaseModel(c)}
if v, ok := raw["track"]; ok {
var track Track
if err := json.Unmarshal(v, &track); err == nil {
similar.Track = &track
}
}
if v, ok := raw["similar_tracks"]; ok {
var tracks []Track
if err := json.Unmarshal(v, &tracks); err == nil {
similar.SimilarTracks = tracks
}
}
return similar, nil
}
// DeList deserializes a list of SimilarTracks from JSON data.
func (st *SimilarTracks) 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 {
similar := &SimilarTracks{BaseModel: *NewBaseModel(c)}
if err := json.Unmarshal(item, similar); err != nil {
continue
}
result = append(result, similar)
}
return result, nil
}
// TrackTrailer represents track trailer info.
type TrackTrailer struct {
BaseModel
Title string `json:"title"`
Track *Track `json:"track"`
}
// DeJSON deserializes a TrackTrailer from JSON data.
func (tt *TrackTrailer) 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 := &TrackTrailer{BaseModel: *NewBaseModel(c)}
if v, ok := raw["title"]; ok {
json.Unmarshal(v, &trailer.Title)
}
if v, ok := raw["track"]; ok {
var track Track
if err := json.Unmarshal(v, &track); err == nil {
trailer.Track = &track
}
}
return trailer, nil
}
// DeList deserializes a list of TrackTrailer from JSON data.
func (tt *TrackTrailer) 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 := &TrackTrailer{BaseModel: *NewBaseModel(c)}
if err := json.Unmarshal(item, trailer); err != nil {
continue
}
result = append(result, trailer)
}
return result, nil
}