// Package models provides data models for the Yandex Music API. package models import ( "encoding/json" ) // Artist represents a full artist from the Yandex Music API. type Artist struct { BaseModel ID JSONID `json:"id"` Name string `json:"name"` CoverURI string `json:"cover_uri"` Genres []string `json:"genres"` Tracks int `json:"tracks"` Albums int `json:"albums"` Available bool `json:"available"` Composer bool `json:"composer"` Various bool `json:"various"` Decomposed []Decomposed `json:"decomposed"` Ratings *Ratings `json:"ratings"` Counts *Counts `json:"counts"` Links []Link `json:"social_links"` Description *Description `json:"description"` // Additional fields IDForFrom string `json:"id_for_from"` Cover *Cover `json:"cover"` BriefInfo *ArtistBriefInfo `json:"brief_info"` DonationInfo *ArtistDonationInfo `json:"donation_info"` Concerts []Concert `json:"concerts"` Clips []Clip `json:"clips"` Similar []Artist `json:"similar"` AlbumsData []Album `json:"albums_data"` TracksData []Track `json:"tracks_data"` } // DeJSON deserializes an Artist from JSON data. func (a *Artist) DeJSON(data []byte, c ClientInterface) (Model, error) { var raw map[string]json.RawMessage if err := json.Unmarshal(data, &raw); err != nil { return nil, err } artist := &Artist{BaseModel: *NewBaseModel(c)} // Simple fields if v, ok := raw["id"]; ok { json.Unmarshal(v, &artist.ID) } if v, ok := raw["name"]; ok { json.Unmarshal(v, &artist.Name) } if v, ok := raw["cover_uri"]; ok { json.Unmarshal(v, &artist.CoverURI) } if v, ok := raw["genres"]; ok { json.Unmarshal(v, &artist.Genres) } if v, ok := raw["tracks"]; ok { json.Unmarshal(v, &artist.Tracks) } if v, ok := raw["albums"]; ok { json.Unmarshal(v, &artist.Albums) } if v, ok := raw["available"]; ok { json.Unmarshal(v, &artist.Available) } if v, ok := raw["composer"]; ok { json.Unmarshal(v, &artist.Composer) } if v, ok := raw["various"]; ok { json.Unmarshal(v, &artist.Various) } if v, ok := raw["id_for_from"]; ok { json.Unmarshal(v, &artist.IDForFrom) } // Nested objects if v, ok := raw["decomposed"]; ok { var decomposed []Decomposed if err := json.Unmarshal(v, &decomposed); err == nil { artist.Decomposed = decomposed } } if v, ok := raw["ratings"]; ok { var ratings Ratings json.Unmarshal(v, &ratings) artist.Ratings = &ratings } if v, ok := raw["counts"]; ok { var counts Counts json.Unmarshal(v, &counts) artist.Counts = &counts } if v, ok := raw["social_links"]; ok { var links []Link if err := json.Unmarshal(v, &links); err == nil { artist.Links = links } } if v, ok := raw["cover"]; ok { var cover Cover json.Unmarshal(v, &cover) artist.Cover = &cover } if v, ok := raw["brief_info"]; ok { var brief ArtistBriefInfo json.Unmarshal(v, &brief) artist.BriefInfo = &brief } if v, ok := raw["donation_info"]; ok { var donation ArtistDonationInfo json.Unmarshal(v, &donation) artist.DonationInfo = &donation } if v, ok := raw["concerts"]; ok { var concerts []Concert json.Unmarshal(v, &concerts) artist.Concerts = concerts } if v, ok := raw["clips"]; ok { var clips []Clip json.Unmarshal(v, &clips) artist.Clips = clips } if v, ok := raw["similar"]; ok { var similar []Artist json.Unmarshal(v, &similar) artist.Similar = similar } if v, ok := raw["albums"]; ok { var albums []Album json.Unmarshal(v, &albums) artist.AlbumsData = albums } if v, ok := raw["tracks"]; ok { var tracks []Track json.Unmarshal(v, &tracks) artist.TracksData = tracks } return artist, nil } // DeList deserializes a list of Artists from JSON data. func (a *Artist) 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 { artist := &Artist{BaseModel: *NewBaseModel(c)} if err := json.Unmarshal(item, artist); err != nil { continue } result = append(result, artist) } return result, nil } // Ratings represents artist ratings. type Ratings struct { Rating int `json:"rating"` Votes int `json:"votes"` Week int `json:"week"` Day int `json:"day"` } // Counts represents artist counts. type Counts struct { Tracks int `json:"tracks"` Albums int `json:"albums"` Folders int `json:"folders"` } // SocialLink represents a social media link. type SocialLink struct { URL string `json:"url"` Title string `json:"title"` Type string `json:"type"` } // Cover represents cover image info. type Cover struct { URI string `json:"uri"` Type string `json:"type"` Prefix string `json:"prefix"` Pattern string `json:"pattern"` Background string `json:"background"` } // ArtistBriefInfo represents brief artist info. type ArtistBriefInfo struct { BaseModel Description string `json:"description"` Available bool `json:"available"` } // ArtistDonations represents artist donations info. type ArtistDonations struct { BaseModel Items []DonationItem `json:"items"` Total int `json:"total"` Goal int `json:"goal"` Raised int `json:"raised"` } // DonationItem represents a donation item. type DonationItem struct { ID JSONID `json:"id"` Title string `json:"title"` Description string `json:"description"` Amount int `json:"amount"` Goal int `json:"goal"` Raised int `json:"raised"` Currency string `json:"currency"` } // Decomposed represents a decomposed artist that can be either a string or an Artist object. type Decomposed struct { Artist *Artist `json:"-"` Str string `json:"-"` IsStr bool `json:"-"` } // UnmarshalJSON implements json.Unmarshaler, accepting both string and Artist object. func (d *Decomposed) UnmarshalJSON(data []byte) error { var s string if err := json.Unmarshal(data, &s); err == nil { d.Str = s d.IsStr = true return nil } var artist Artist if err := json.Unmarshal(data, &artist); err != nil { return err } d.Artist = &artist d.IsStr = false return nil } // MarshalJSON implements json.Marshaler. func (d Decomposed) MarshalJSON() ([]byte, error) { if d.IsStr { return json.Marshal(d.Str) } return json.Marshal(d.Artist) } // Link represents a link to an artist's official page or social network. type Link struct { BaseModel Title string `json:"title"` Href string `json:"href"` Type string `json:"type"` SocialNetwork string `json:"social_network"` } // DeJSON deserializes Link from JSON data. func (l *Link) DeJSON(data []byte, c ClientInterface) (Model, error) { var raw map[string]json.RawMessage if err := json.Unmarshal(data, &raw); err != nil { return nil, err } link := &Link{BaseModel: *NewBaseModel(c)} if v, ok := raw["title"]; ok { json.Unmarshal(v, &link.Title) } if v, ok := raw["href"]; ok { json.Unmarshal(v, &link.Href) } if v, ok := raw["type"]; ok { json.Unmarshal(v, &link.Type) } if v, ok := raw["social_network"]; ok { json.Unmarshal(v, &link.SocialNetwork) } return link, nil } // DeList deserializes a list of Links from JSON data. func (l *Link) 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 { link := &Link{BaseModel: *NewBaseModel(c)} if err := json.Unmarshal(item, link); err != nil { continue } result = append(result, link) } return result, nil } // Description represents artist description. type Description struct { BaseModel Text string `json:"text"` URI string `json:"uri"` } // DeJSON deserializes Description from JSON data. func (d *Description) DeJSON(data []byte, c ClientInterface) (Model, error) { var raw map[string]json.RawMessage if err := json.Unmarshal(data, &raw); err != nil { return nil, err } desc := &Description{BaseModel: *NewBaseModel(c)} if v, ok := raw["text"]; ok { json.Unmarshal(v, &desc.Text) } if v, ok := raw["uri"]; ok { json.Unmarshal(v, &desc.URI) } return desc, nil } // DeList deserializes a list of Descriptions from JSON data. func (d *Description) 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 { desc := &Description{BaseModel: *NewBaseModel(c)} if err := json.Unmarshal(item, desc); err != nil { continue } result = append(result, desc) } return result, nil } // ArtistDonationInfo represents artist donation info. type ArtistDonationInfo struct { BaseModel Title string `json:"title"` URL string `json:"url"` } // DeJSON deserializes ArtistDonationInfo from JSON data. func (adi *ArtistDonationInfo) 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 := &ArtistDonationInfo{BaseModel: *NewBaseModel(c)} if v, ok := raw["title"]; ok { json.Unmarshal(v, &info.Title) } if v, ok := raw["url"]; ok { json.Unmarshal(v, &info.URL) } return info, nil } // DeList deserializes a list of ArtistDonationInfo from JSON data. func (adi *ArtistDonationInfo) 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 := &ArtistDonationInfo{BaseModel: *NewBaseModel(c)} if err := json.Unmarshal(item, info); err != nil { continue } result = append(result, info) } return result, nil } // ConcertShort represents a concert (minimal for artist). type ConcertShort struct { BaseModel ID JSONID `json:"id"` Title string `json:"title"` Date string `json:"date"` Venue string `json:"venue"` Location string `json:"location"` TicketURI string `json:"ticket_uri"` ImageURI string `json:"image_uri"` MinPrice int `json:"min_price"` MaxPrice int `json:"max_price"` Available bool `json:"available"` } // DeJSON deserializes a ConcertShort from JSON data. func (c *ConcertShort) DeJSON(data []byte, client ClientInterface) (Model, error) { var raw map[string]json.RawMessage if err := json.Unmarshal(data, &raw); err != nil { return nil, err } concert := &ConcertShort{BaseModel: *NewBaseModel(client)} if v, ok := raw["id"]; ok { json.Unmarshal(v, &concert.ID) } if v, ok := raw["title"]; ok { json.Unmarshal(v, &concert.Title) } if v, ok := raw["date"]; ok { json.Unmarshal(v, &concert.Date) } if v, ok := raw["venue"]; ok { json.Unmarshal(v, &concert.Venue) } if v, ok := raw["location"]; ok { json.Unmarshal(v, &concert.Location) } if v, ok := raw["ticket_uri"]; ok { json.Unmarshal(v, &concert.TicketURI) } if v, ok := raw["image_uri"]; ok { json.Unmarshal(v, &concert.ImageURI) } if v, ok := raw["min_price"]; ok { json.Unmarshal(v, &concert.MinPrice) } if v, ok := raw["max_price"]; ok { json.Unmarshal(v, &concert.MaxPrice) } if v, ok := raw["available"]; ok { json.Unmarshal(v, &concert.Available) } return concert, nil } // DeList deserializes a list of ConcertShort from JSON data. func (c *ConcertShort) DeList(data []byte, client 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 { concert := &ConcertShort{BaseModel: *NewBaseModel(client)} if err := json.Unmarshal(item, concert); err != nil { continue } result = append(result, concert) } return result, nil } // ClipShort represents a clip (minimal for artist). type ClipShort struct { BaseModel ID JSONID `json:"id"` Title string `json:"title"` Duration int `json:"duration"` CoverURI string `json:"cover_uri"` PreviewURI string `json:"preview_uri"` Available bool `json:"available"` Views int `json:"views"` Likes int `json:"likes"` CreatedAt string `json:"created_at"` } // DeJSON deserializes a ClipShort from JSON data. func (c *ClipShort) DeJSON(data []byte, client ClientInterface) (Model, error) { var raw map[string]json.RawMessage if err := json.Unmarshal(data, &raw); err != nil { return nil, err } clip := &ClipShort{BaseModel: *NewBaseModel(client)} if v, ok := raw["id"]; ok { json.Unmarshal(v, &clip.ID) } if v, ok := raw["title"]; ok { json.Unmarshal(v, &clip.Title) } if v, ok := raw["duration"]; ok { json.Unmarshal(v, &clip.Duration) } if v, ok := raw["cover_uri"]; ok { json.Unmarshal(v, &clip.CoverURI) } if v, ok := raw["preview_uri"]; ok { json.Unmarshal(v, &clip.PreviewURI) } if v, ok := raw["available"]; ok { json.Unmarshal(v, &clip.Available) } if v, ok := raw["views"]; ok { json.Unmarshal(v, &clip.Views) } if v, ok := raw["likes"]; ok { json.Unmarshal(v, &clip.Likes) } if v, ok := raw["created_at"]; ok { json.Unmarshal(v, &clip.CreatedAt) } return clip, nil } // DeList deserializes a list of ClipShort from JSON data. func (c *ClipShort) DeList(data []byte, client 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 { clip := &ClipShort{BaseModel: *NewBaseModel(client)} if err := json.Unmarshal(item, clip); err != nil { continue } result = append(result, clip) } return result, nil } // ArtistSimilar represents similar artists. type ArtistSimilar struct { BaseModel Artist *Artist `json:"artist"` SimilarArtists []Artist `json:"similar_artists"` } // DeJSON deserializes ArtistSimilar from JSON data. func (as *ArtistSimilar) 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 := &ArtistSimilar{BaseModel: *NewBaseModel(c)} if v, ok := raw["artist"]; ok { var artist Artist json.Unmarshal(v, &artist) similar.Artist = &artist } if v, ok := raw["similar_artists"]; ok { var artists []Artist json.Unmarshal(v, &artists) similar.SimilarArtists = artists } return similar, nil } // DeList deserializes a list of ArtistSimilar from JSON data. func (as *ArtistSimilar) 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 := &ArtistSimilar{BaseModel: *NewBaseModel(c)} if err := json.Unmarshal(item, similar); err != nil { continue } result = append(result, similar) } return result, nil } // ArtistLinks represents links to artist's official pages or social networks. type ArtistLinks struct { BaseModel Links []Link `json:"links"` } // DeJSON deserializes ArtistLinks from JSON data. func (al *ArtistLinks) DeJSON(data []byte, c ClientInterface) (Model, error) { var raw map[string]json.RawMessage if err := json.Unmarshal(data, &raw); err != nil { return nil, err } links := &ArtistLinks{BaseModel: *NewBaseModel(c)} if v, ok := raw["links"]; ok { var linkList []Link json.Unmarshal(v, &linkList) links.Links = linkList } return links, nil } // DeList deserializes a list of ArtistLinks from JSON data. func (al *ArtistLinks) 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 { links := &ArtistLinks{BaseModel: *NewBaseModel(c)} if err := json.Unmarshal(item, links); err != nil { continue } result = append(result, links) } return result, nil } // ArtistAbout represents information "About artist". type ArtistAbout struct { BaseModel Artist *Artist `json:"artist"` Stats *Stats `json:"stats"` Description string `json:"description"` Links []ArtistLink `json:"links"` Covers []Cover `json:"covers"` ArtistType string `json:"artist_type"` } // DeJSON deserializes ArtistAbout from JSON data. func (aa *ArtistAbout) DeJSON(data []byte, c ClientInterface) (Model, error) { var raw map[string]json.RawMessage if err := json.Unmarshal(data, &raw); err != nil { return nil, err } about := &ArtistAbout{BaseModel: *NewBaseModel(c)} if v, ok := raw["artist"]; ok { var artist Artist json.Unmarshal(v, &artist) about.Artist = &artist } if v, ok := raw["stats"]; ok { var stats Stats json.Unmarshal(v, &stats) about.Stats = &stats } if v, ok := raw["description"]; ok { json.Unmarshal(v, &about.Description) } if v, ok := raw["links"]; ok { var linkList []ArtistLink json.Unmarshal(v, &linkList) about.Links = linkList } if v, ok := raw["covers"]; ok { var covers []Cover json.Unmarshal(v, &covers) about.Covers = covers } if v, ok := raw["artist_type"]; ok { json.Unmarshal(v, &about.ArtistType) } return about, nil } // DeList deserializes a list of ArtistAbout from JSON data. func (aa *ArtistAbout) 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 { about := &ArtistAbout{BaseModel: *NewBaseModel(c)} if err := json.Unmarshal(item, about); err != nil { continue } result = append(result, about) } return result, nil } // ArtistInfo represents detailed artist info. type ArtistInfo struct { BaseModel Artist *Artist `json:"artist"` LikesCount int `json:"likes_count"` Stats *Stats `json:"stats"` Trailer *ArtistTrailerStatus `json:"trailer"` Covers []Cover `json:"covers"` Description string `json:"description"` ArtistType string `json:"artist_type"` } // DeJSON deserializes ArtistInfo from JSON data. func (ai *ArtistInfo) 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 := &ArtistInfo{BaseModel: *NewBaseModel(c)} if v, ok := raw["artist"]; ok { var artist Artist json.Unmarshal(v, &artist) info.Artist = &artist } if v, ok := raw["likes_count"]; ok { json.Unmarshal(v, &info.LikesCount) } if v, ok := raw["stats"]; ok { var stats Stats json.Unmarshal(v, &stats) info.Stats = &stats } if v, ok := raw["trailer"]; ok { var trailer ArtistTrailerStatus json.Unmarshal(v, &trailer) info.Trailer = &trailer } if v, ok := raw["covers"]; ok { var covers []Cover json.Unmarshal(v, &covers) info.Covers = covers } if v, ok := raw["description"]; ok { json.Unmarshal(v, &info.Description) } if v, ok := raw["artist_type"]; ok { json.Unmarshal(v, &info.ArtistType) } return info, nil } // DeList deserializes a list of ArtistInfo from JSON data. func (ai *ArtistInfo) 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 := &ArtistInfo{BaseModel: *NewBaseModel(c)} if err := json.Unmarshal(item, info); err != nil { continue } result = append(result, info) } return result, nil } // ArtistSkeleton represents artist page skeleton. type ArtistSkeleton struct { BaseModel ID string `json:"id"` Title string `json:"title"` Blocks []SkeletonBlock `json:"blocks"` } // DeJSON deserializes ArtistSkeleton from JSON data. func (as *ArtistSkeleton) DeJSON(data []byte, c ClientInterface) (Model, error) { var raw map[string]json.RawMessage if err := json.Unmarshal(data, &raw); err != nil { return nil, err } skeleton := &ArtistSkeleton{BaseModel: *NewBaseModel(c)} if v, ok := raw["id"]; ok { json.Unmarshal(v, &skeleton.ID) } if v, ok := raw["title"]; ok { json.Unmarshal(v, &skeleton.Title) } if v, ok := raw["blocks"]; ok { var blocks []SkeletonBlock json.Unmarshal(v, &blocks) skeleton.Blocks = blocks } return skeleton, nil } // DeList deserializes a list of ArtistSkeleton from JSON data. func (as *ArtistSkeleton) 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 { skeleton := &ArtistSkeleton{BaseModel: *NewBaseModel(c)} if err := json.Unmarshal(item, skeleton); err != nil { continue } result = append(result, skeleton) } return result, nil } // ArtistTrailerStatus represents trailer availability for artist. type ArtistTrailerStatus struct { BaseModel Available bool `json:"available"` } // DeJSON deserializes ArtistTrailerStatus from JSON data. func (ats *ArtistTrailerStatus) 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 := &ArtistTrailerStatus{BaseModel: *NewBaseModel(c)} if v, ok := raw["available"]; ok { json.Unmarshal(v, &status.Available) } return status, nil } // DeList deserializes a list of ArtistTrailerStatus from JSON data. func (ats *ArtistTrailerStatus) 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 := &ArtistTrailerStatus{BaseModel: *NewBaseModel(c)} if err := json.Unmarshal(item, status); err != nil { continue } result = append(result, status) } return result, nil } // ArtistLink represents a link for artist about page. type ArtistLink struct { BaseModel Title string `json:"title"` Subtitle string `json:"subtitle,omitempty"` URL string `json:"url,omitempty"` ImgURL string `json:"img_url,omitempty"` } // Stats represents artist stats. type Stats struct { BaseModel Rating int `json:"rating"` Votes int `json:"votes"` Month int `json:"month"` Week int `json:"week"` Day int `json:"day"` } // SkeletonBlock represents a skeleton block. type SkeletonBlock struct { BaseModel ID string `json:"id"` Type string `json:"type"` Data json.RawMessage `json:"data"` }