From 463e0bcd1a21ace00efd182429e7b75b2d4206f6 Mon Sep 17 00:00:00 2001 From: Vladimir Zagainov Date: Sun, 18 Oct 2026 13:14:15 +0300 Subject: [PATCH] Add missing model fields from Python reference Feed: Added can_get_more_events, pumpkin, is_wizard_passed, headlines, today, next_revision Label: Added description_formatted, image, links ([]Link), type Landing: Added pumpkin, content_id Pin: Added content_restrictions Search: Added search_request_id, text, best, podcasts, podcast_episodes, clips, banner, page, per_page, misspell fields Clip: Rewrote with all missing fields (version, player_id, uuid, thumbnail, track_ids, disclaimers, explicit, cover, content_restrictions) Concert: Added datetime, afisha_url, city, place, address, content_rating, data_session_id, event_info --- internal/models/clip.go | 130 ++++++++++++++++++++----------------- internal/models/concert.go | 70 ++++++++++++++------ internal/models/feed.go | 30 ++++++++- internal/models/label.go | 20 ++++-- internal/models/landing.go | 10 ++- internal/models/pin.go | 8 ++- internal/models/search.go | 25 +++++-- 7 files changed, 198 insertions(+), 95 deletions(-) diff --git a/internal/models/clip.go b/internal/models/clip.go index 6d364d1..5d29c4e 100644 --- a/internal/models/clip.go +++ b/internal/models/clip.go @@ -8,21 +8,24 @@ import ( // Clip represents a clip (short video) from the Yandex Music API. type Clip 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"` - Artist *Artist `json:"artist"` - Track *Track `json:"track"` - Playlist *Playlist `json:"playlist"` - ClipType string `json:"clip_type"` - IsVertical bool `json:"is_vertical"` - AspectRatio string `json:"aspect_ratio"` + ID JSONID `json:"id"` + Title string `json:"title"` + Version string `json:"version"` + PlayerID string `json:"player_id"` + UUID string `json:"uuid"` + Thumbnail string `json:"thumbnail"` + PreviewURL string `json:"preview_url"` + Duration int `json:"duration"` + TrackIDs []int `json:"track_ids"` + Artists []Artist `json:"artists"` + Disclaimers []string `json:"disclaimers"` + Explicit bool `json:"explicit"` + Cover *Cover `json:"cover"` + ContentRestrictions *ContentRestrictions `json:"content_restrictions"` + Client *ClientInterface `json:"-"` + ClipType string `json:"clip_type"` + IsVertical bool `json:"is_vertical"` + AspectRatio string `json:"aspect_ratio"` } // DeJSON deserializes a Clip from JSON data. @@ -40,26 +43,47 @@ func (c *Clip) DeJSON(data []byte, client ClientInterface) (Model, error) { if v, ok := raw["title"]; ok { json.Unmarshal(v, &clip.Title) } + if v, ok := raw["version"]; ok { + json.Unmarshal(v, &clip.Version) + } + if v, ok := raw["player_id"]; ok { + json.Unmarshal(v, &clip.PlayerID) + } + if v, ok := raw["uuid"]; ok { + json.Unmarshal(v, &clip.UUID) + } + if v, ok := raw["thumbnail"]; ok { + json.Unmarshal(v, &clip.Thumbnail) + } + if v, ok := raw["preview_url"]; ok { + json.Unmarshal(v, &clip.PreviewURL) + } 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["track_ids"]; ok { + json.Unmarshal(v, &clip.TrackIDs) } - if v, ok := raw["preview_uri"]; ok { - json.Unmarshal(v, &clip.PreviewURI) + if v, ok := raw["artists"]; ok { + var artists []Artist + json.Unmarshal(v, &artists) + clip.Artists = artists } - if v, ok := raw["available"]; ok { - json.Unmarshal(v, &clip.Available) + if v, ok := raw["disclaimers"]; ok { + json.Unmarshal(v, &clip.Disclaimers) } - if v, ok := raw["views"]; ok { - json.Unmarshal(v, &clip.Views) + if v, ok := raw["explicit"]; ok { + json.Unmarshal(v, &clip.Explicit) } - if v, ok := raw["likes"]; ok { - json.Unmarshal(v, &clip.Likes) + if v, ok := raw["cover"]; ok { + var cover Cover + json.Unmarshal(v, &cover) + clip.Cover = &cover } - if v, ok := raw["created_at"]; ok { - json.Unmarshal(v, &clip.CreatedAt) + if v, ok := raw["content_restrictions"]; ok { + var cr ContentRestrictions + json.Unmarshal(v, &cr) + clip.ContentRestrictions = &cr } if v, ok := raw["clip_type"]; ok { json.Unmarshal(v, &clip.ClipType) @@ -71,22 +95,6 @@ func (c *Clip) DeJSON(data []byte, client ClientInterface) (Model, error) { json.Unmarshal(v, &clip.AspectRatio) } - if v, ok := raw["artist"]; ok { - var artist Artist - json.Unmarshal(v, &artist) - clip.Artist = &artist - } - if v, ok := raw["track"]; ok { - var track Track - json.Unmarshal(v, &track) - clip.Track = &track - } - if v, ok := raw["playlist"]; ok { - var playlist Playlist - json.Unmarshal(v, &playlist) - clip.Playlist = &playlist - } - return clip, nil } @@ -132,23 +140,23 @@ type ArtistClipItem struct { // Shot represents a shot (short video). type Shot struct { BaseModel - ID JSONID `json:"id"` - Title string `json:"title"` - Description string `json:"description"` - 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"` - Comments int `json:"comments"` - CreatedAt string `json:"created_at"` - Author *User `json:"author"` - Track *Track `json:"track"` - ShotType string `json:"shot_type"` - Tags []string `json:"tags"` - IsVertical bool `json:"is_vertical"` - AspectRatio string `json:"aspect_ratio"` + ID JSONID `json:"id"` + Title string `json:"title"` + Description string `json:"description"` + 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"` + Comments int `json:"comments"` + CreatedAt string `json:"created_at"` + Author *User `json:"author"` + Track *Track `json:"track"` + ShotType string `json:"shot_type"` + Tags []string `json:"tags"` + IsVertical bool `json:"is_vertical"` + AspectRatio string `json:"aspect_ratio"` } // DeJSON deserializes a Shot from JSON data. @@ -258,7 +266,7 @@ type ShotEvent struct { // ShotType represents a shot type. type ShotType struct { BaseModel - ID JSONID `json:"id"` + ID JSONID `json:"id"` Name string `json:"name"` Description string `json:"description"` Icon string `json:"icon"` diff --git a/internal/models/concert.go b/internal/models/concert.go index b5c22fc..23b5bf5 100644 --- a/internal/models/concert.go +++ b/internal/models/concert.go @@ -8,25 +8,33 @@ import ( // Concert represents a concert from the Yandex Music API. type Concert struct { BaseModel - ID JSONID `json:"id"` - Title string `json:"title"` - Description string `json:"description"` - Date string `json:"date"` - Time string `json:"time"` - Venue *ConcertVenue `json:"venue"` - Location *ConcertLocation `json:"location"` - MinPrice int `json:"min_price"` - MaxPrice int `json:"max_price"` - Currency string `json:"currency"` - TicketURI string `json:"ticket_uri"` - ImageURI string `json:"image_uri"` - Available bool `json:"available"` - SoldOut bool `json:"sold_out"` - Artists []Artist `json:"artists"` - Genres []string `json:"genres"` - Cashback *ConcertCashback `json:"cashback"` - Tabs []ConcertTabConfig `json:"tabs"` - Skeleton *ConcertSkeleton `json:"skeleton"` + ID JSONID `json:"id"` + Title string `json:"title"` + Description string `json:"description"` + Date string `json:"date"` + Time string `json:"time"` + Datetime string `json:"datetime"` + Venue *ConcertVenue `json:"venue"` + Location *ConcertLocation `json:"location"` + MinPrice int `json:"min_price"` + MaxPrice int `json:"max_price"` + Currency string `json:"currency"` + TicketURI string `json:"ticket_uri"` + ImageURI string `json:"image_uri"` + Available bool `json:"available"` + SoldOut bool `json:"sold_out"` + Artists []Artist `json:"artists"` + Genres []string `json:"genres"` + Cashback *ConcertCashback `json:"cashback"` + Tabs []ConcertTabConfig `json:"tabs"` + Skeleton *ConcertSkeleton `json:"skeleton"` + AfishaURL string `json:"afisha_url"` + City string `json:"city"` + Place string `json:"place"` + Address string `json:"address"` + ContentRating string `json:"content_rating"` + DataSessionID string `json:"data_session_id"` + EventInfo *ConcertEventInfo `json:"event_info"` } // DeJSON deserializes a Concert from JSON data. @@ -77,6 +85,30 @@ func (c *Concert) DeJSON(data []byte, client ClientInterface) (Model, error) { if v, ok := raw["genres"]; ok { json.Unmarshal(v, &concert.Genres) } + if v, ok := raw["datetime"]; ok { + json.Unmarshal(v, &concert.Datetime) + } + if v, ok := raw["afisha_url"]; ok { + json.Unmarshal(v, &concert.AfishaURL) + } + if v, ok := raw["city"]; ok { + json.Unmarshal(v, &concert.City) + } + if v, ok := raw["place"]; ok { + json.Unmarshal(v, &concert.Place) + } + if v, ok := raw["address"]; ok { + json.Unmarshal(v, &concert.Address) + } + if v, ok := raw["content_rating"]; ok { + json.Unmarshal(v, &concert.ContentRating) + } + if v, ok := raw["data_session_id"]; ok { + json.Unmarshal(v, &concert.DataSessionID) + } + if v, ok := raw["event_info"]; ok { + json.Unmarshal(v, &concert.EventInfo) + } if v, ok := raw["venue"]; ok { var venue ConcertVenue diff --git a/internal/models/feed.go b/internal/models/feed.go index 12d12d6..5268153 100644 --- a/internal/models/feed.go +++ b/internal/models/feed.go @@ -8,9 +8,15 @@ import ( // Feed represents the main feed from the Yandex Music API. type Feed struct { BaseModel - Days []Day `json:"days"` - GeneratedPlaylists []GeneratedPlaylist `json:"generated_playlists"` - PlayContexts []PlayContext `json:"play_contexts"` + CanGetMoreEvents bool `json:"can_get_more_events"` + Pumpkin bool `json:"pumpkin"` + IsWizardPassed bool `json:"is_wizard_passed"` + Headlines []string `json:"headlines"` + Today string `json:"today"` + Days []Day `json:"days"` + GeneratedPlaylists []GeneratedPlaylist `json:"generated_playlists"` + PlayContexts []PlayContext `json:"play_contexts"` + NextRevision string `json:"next_revision"` } // DeJSON deserializes a Feed from JSON data. @@ -22,6 +28,21 @@ func (f *Feed) DeJSON(data []byte, c ClientInterface) (Model, error) { feed := &Feed{BaseModel: *NewBaseModel(c)} + if v, ok := raw["can_get_more_events"]; ok { + json.Unmarshal(v, &feed.CanGetMoreEvents) + } + if v, ok := raw["pumpkin"]; ok { + json.Unmarshal(v, &feed.Pumpkin) + } + if v, ok := raw["is_wizard_passed"]; ok { + json.Unmarshal(v, &feed.IsWizardPassed) + } + if v, ok := raw["headlines"]; ok { + json.Unmarshal(v, &feed.Headlines) + } + if v, ok := raw["today"]; ok { + json.Unmarshal(v, &feed.Today) + } if v, ok := raw["days"]; ok { var days []Day json.Unmarshal(v, &days) @@ -37,6 +58,9 @@ func (f *Feed) DeJSON(data []byte, c ClientInterface) (Model, error) { json.Unmarshal(v, &contexts) feed.PlayContexts = contexts } + if v, ok := raw["next_revision"]; ok { + json.Unmarshal(v, &feed.NextRevision) + } return feed, nil } diff --git a/internal/models/label.go b/internal/models/label.go index 44a5ead..2dbbf2c 100644 --- a/internal/models/label.go +++ b/internal/models/label.go @@ -12,8 +12,11 @@ type Label struct { Name string `json:"name"` CoverURI string `json:"cover_uri"` Description string `json:"description"` + DescriptionFormatted string `json:"description_formatted"` + Image string `json:"image"` Website string `json:"website"` - SocialLinks []SocialLink `json:"social_links"` + Links []Link `json:"links"` + Type string `json:"type"` Available bool `json:"available"` Owner *User `json:"owner"` } @@ -45,10 +48,19 @@ func (l *Label) DeJSON(data []byte, client ClientInterface) (Model, error) { if v, ok := raw["available"]; ok { json.Unmarshal(v, &label.Available) } - if v, ok := raw["social_links"]; ok { - var links []SocialLink + if v, ok := raw["description_formatted"]; ok { + json.Unmarshal(v, &label.DescriptionFormatted) + } + if v, ok := raw["image"]; ok { + json.Unmarshal(v, &label.Image) + } + if v, ok := raw["links"]; ok { + var links []Link json.Unmarshal(v, &links) - label.SocialLinks = links + label.Links = links + } + if v, ok := raw["type"]; ok { + json.Unmarshal(v, &label.Type) } if v, ok := raw["owner"]; ok { var user User diff --git a/internal/models/landing.go b/internal/models/landing.go index 23a7a6a..f043599 100644 --- a/internal/models/landing.go +++ b/internal/models/landing.go @@ -8,13 +8,15 @@ import ( // Landing represents a landing page from the Yandex Music API. type Landing struct { BaseModel - ID JSONID `json:"id"` + ID JSONID `json:"id"` Title string `json:"title"` Description string `json:"description"` CoverURI string `json:"cover_uri"` Type string `json:"type"` Blocks []LandingBlock `json:"blocks"` Available bool `json:"available"` + Pumpkin bool `json:"pumpkin"` + ContentID string `json:"content_id"` } // DeJSON deserializes a Landing from JSON data. @@ -44,6 +46,12 @@ func (l *Landing) DeJSON(data []byte, c ClientInterface) (Model, error) { if v, ok := raw["available"]; ok { json.Unmarshal(v, &landing.Available) } + if v, ok := raw["pumpkin"]; ok { + json.Unmarshal(v, &landing.Pumpkin) + } + if v, ok := raw["content_id"]; ok { + json.Unmarshal(v, &landing.ContentID) + } if v, ok := raw["blocks"]; ok { var blocks []LandingBlock diff --git a/internal/models/pin.go b/internal/models/pin.go index 826ae6f..a33327c 100644 --- a/internal/models/pin.go +++ b/internal/models/pin.go @@ -8,7 +8,7 @@ import ( // Pin represents a pin from the Yandex Music API. type Pin struct { BaseModel - ID JSONID `json:"id"` + ID JSONID `json:"id"` Title string `json:"title"` Description string `json:"description"` Image string `json:"image"` @@ -21,6 +21,7 @@ type Pin struct { CreatedAt string `json:"created_at"` ExpiresAt string `json:"expires_at"` Active bool `json:"active"` + ContentRestrictions *ContentRestrictions `json:"content_restrictions"` } // DeJSON deserializes a Pin from JSON data. @@ -59,6 +60,11 @@ func (p *Pin) DeJSON(data []byte, client ClientInterface) (Model, error) { if v, ok := raw["active"]; ok { json.Unmarshal(v, &pin.Active) } + if v, ok := raw["content_restrictions"]; ok { + var cr ContentRestrictions + json.Unmarshal(v, &cr) + pin.ContentRestrictions = &cr + } if v, ok := raw["track"]; ok { var track Track diff --git a/internal/models/search.go b/internal/models/search.go index 906b369..af30b9f 100644 --- a/internal/models/search.go +++ b/internal/models/search.go @@ -3,12 +3,25 @@ package models // SearchResult represents search results from the Yandex Music API. type SearchResult struct { - Tracks *SearchTracksResult `json:"tracks"` - Albums *SearchAlbumsResult `json:"albums"` - Artists *SearchArtistsResult `json:"artists"` - Playlists *SearchPlaylistsResult `json:"playlists"` - Videos *SearchVideosResult `json:"videos"` - Users *SearchUsersResult `json:"users"` + SearchRequestID string `json:"search_request_id"` + Text string `json:"text"` + Best *Best `json:"best"` + Tracks *SearchTracksResult `json:"tracks"` + Albums *SearchAlbumsResult `json:"albums"` + Artists *SearchArtistsResult `json:"artists"` + Playlists *SearchPlaylistsResult `json:"playlists"` + Videos *SearchVideosResult `json:"videos"` + Users *SearchUsersResult `json:"users"` + Podcasts *SearchAlbumsResult `json:"podcasts"` + PodcastEpisodes *SearchTracksResult `json:"podcast_episodes"` + Clips *SearchVideosResult `json:"clips"` + Banner *SearchBanner `json:"banner"` + Page int `json:"page"` + PerPage int `json:"per_page"` + MisspellResult bool `json:"misspell_result"` + MisspellOriginal string `json:"misspell_original"` + MisspellCorrected bool `json:"misspell_corrected"` + Nocorrect bool `json:"nocorrect"` } // SearchTracksResult represents track search results.