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
425 lines
13 KiB
Go
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"`
|
|
}
|
|
|