package models import ( "encoding/json" ) // LyricsMajor represents a lyrics provider (e.g., Genius, Musixmatch) type LyricsMajor struct { BaseModel ID int `json:"id"` Name string `json:"name"` PrettyName string `json:"pretty_name"` } // DeJSON deserializes LyricsMajor from JSON func (lm *LyricsMajor) DeJSON(data []byte, c ClientInterface) (Model, error) { var raw map[string]json.RawMessage if err := json.Unmarshal(data, &raw); err != nil { return nil, err } major := &LyricsMajor{BaseModel: *NewBaseModel(c)} if v, ok := raw["id"]; ok { json.Unmarshal(v, &major.ID) } if v, ok := raw["name"]; ok { json.Unmarshal(v, &major.Name) } if v, ok := raw["pretty_name"]; ok { json.Unmarshal(v, &major.PrettyName) } return major, nil } // DeList deserializes a list of LyricsMajor func (lm *LyricsMajor) 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 { major := &LyricsMajor{BaseModel: *NewBaseModel(c)} if err := json.Unmarshal(item, major); err != nil { continue } result = append(result, major) } return result, nil } // TrackLyrics represents lyrics information from /tracks/{id}/lyrics endpoint type TrackLyrics struct { BaseModel DownloadURL string `json:"download_url"` LyricID int `json:"lyric_id"` ExternalLyricID string `json:"external_lyric_id"` Writers []string `json:"writers"` Major *LyricsMajor `json:"major"` } // DeJSON deserializes TrackLyrics from JSON func (tl *TrackLyrics) 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 := &TrackLyrics{BaseModel: *NewBaseModel(c)} if v, ok := raw["download_url"]; ok { json.Unmarshal(v, &lyrics.DownloadURL) } if v, ok := raw["lyric_id"]; ok { json.Unmarshal(v, &lyrics.LyricID) } if v, ok := raw["external_lyric_id"]; ok { json.Unmarshal(v, &lyrics.ExternalLyricID) } if v, ok := raw["writers"]; ok { json.Unmarshal(v, &lyrics.Writers) } if v, ok := raw["major"]; ok { var major LyricsMajor json.Unmarshal(v, &major) lyrics.Major = &major } return lyrics, nil } // DeList deserializes a list of TrackLyrics func (tl *TrackLyrics) 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 := &TrackLyrics{BaseModel: *NewBaseModel(c)} if err := json.Unmarshal(item, lyrics); err != nil { continue } result = append(result, lyrics) } return result, nil } // SupplementLyrics represents the actual lyrics content (from supplement) type SupplementLyrics struct { BaseModel ID int `json:"id"` Text string `json:"lyrics"` // First lines of lyrics FullLyrics string `json:"full_lyrics"` // Full lyrics text HasRights bool `json:"has_rights"` ShowTranslation bool `json:"show_translation"` TextLanguage string `json:"text_language"` URL string `json:"url"` Major *LyricsMajor `json:"major"` } // DeJSON deserializes SupplementLyrics from JSON func (l *SupplementLyrics) 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 := &SupplementLyrics{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 LyricsMajor json.Unmarshal(v, &major) lyrics.Major = &major } return lyrics, nil } // DeList deserializes a list of SupplementLyrics func (l *SupplementLyrics) 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 := &SupplementLyrics{BaseModel: *NewBaseModel(c)} if err := json.Unmarshal(item, lyrics); err != nil { continue } result = append(result, lyrics) } return result, nil } // LyricsInfo represents lyrics availability information type LyricsInfo struct { BaseModel TrackID string `json:"track_id"` Lyrics *SupplementLyrics `json:"lyrics"` Text string `json:"text"` Language string `json:"language"` HasText bool `json:"has_text"` HasSync bool `json:"has_sync"` SyncType string `json:"sync_type"` Major *LyricsMajor `json:"major"` Available bool `json:"available"` HasAvailableSyncLyrics bool `json:"has_available_sync_lyrics"` HasAvailableTextLyrics bool `json:"has_available_text_lyrics"` } // DeJSON deserializes LyricsInfo from JSON func (li *LyricsInfo) 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 := &LyricsInfo{BaseModel: *NewBaseModel(c)} if v, ok := raw["track_id"]; ok { json.Unmarshal(v, &info.TrackID) } if v, ok := raw["text"]; ok { json.Unmarshal(v, &info.Text) } if v, ok := raw["language"]; ok { json.Unmarshal(v, &info.Language) } if v, ok := raw["has_text"]; ok { json.Unmarshal(v, &info.HasText) } if v, ok := raw["has_sync"]; ok { json.Unmarshal(v, &info.HasSync) } if v, ok := raw["sync_type"]; ok { json.Unmarshal(v, &info.SyncType) } if v, ok := raw["available"]; ok { json.Unmarshal(v, &info.Available) } if v, ok := raw["has_available_sync_lyrics"]; ok { json.Unmarshal(v, &info.HasAvailableSyncLyrics) } if v, ok := raw["has_available_text_lyrics"]; ok { json.Unmarshal(v, &info.HasAvailableTextLyrics) } if v, ok := raw["lyrics"]; ok { var lyrics SupplementLyrics json.Unmarshal(v, &lyrics) info.Lyrics = &lyrics } if v, ok := raw["major"]; ok { var major LyricsMajor json.Unmarshal(v, &major) info.Major = &major } return info, nil } // DeList deserializes a list of LyricsInfo func (li *LyricsInfo) 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 := &LyricsInfo{BaseModel: *NewBaseModel(c)} if err := json.Unmarshal(item, info); err != nil { continue } result = append(result, info) } return result, nil } // VideoSupplement represents a video supplement (from supplement endpoint) type VideoSupplement struct { BaseModel Cover string `json:"cover"` Provider string `json:"provider"` Title string `json:"title"` ProviderVideoID string `json:"provider_video_id"` URL string `json:"url"` EmbedURL string `json:"embed_url"` Embed string `json:"embed"` } // DeJSON deserializes VideoSupplement from JSON func (vs *VideoSupplement) DeJSON(data []byte, c ClientInterface) (Model, error) { var raw map[string]json.RawMessage if err := json.Unmarshal(data, &raw); err != nil { return nil, err } supp := &VideoSupplement{BaseModel: *NewBaseModel(c)} if v, ok := raw["cover"]; ok { json.Unmarshal(v, &supp.Cover) } if v, ok := raw["provider"]; ok { json.Unmarshal(v, &supp.Provider) } if v, ok := raw["title"]; ok { json.Unmarshal(v, &supp.Title) } if v, ok := raw["provider_video_id"]; ok { json.Unmarshal(v, &supp.ProviderVideoID) } if v, ok := raw["url"]; ok { json.Unmarshal(v, &supp.URL) } if v, ok := raw["embed_url"]; ok { json.Unmarshal(v, &supp.EmbedURL) } if v, ok := raw["embed"]; ok { json.Unmarshal(v, &supp.Embed) } return supp, nil } // DeList deserializes a list of VideoSupplements func (vs *VideoSupplement) 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 { supp := &VideoSupplement{BaseModel: *NewBaseModel(c)} if err := json.Unmarshal(item, supp); err != nil { continue } result = append(result, supp) } return result, nil } // Supplement represents a track supplement type Supplement struct { BaseModel ID string `json:"id"` Lyrics *LyricsInfo `json:"lyrics"` Videos []VideoSupplement `json:"videos"` RadioIsAvailable bool `json:"radio_is_available"` Description string `json:"description"` Available bool `json:"available"` } // DeJSON deserializes Supplement from JSON func (s *Supplement) DeJSON(data []byte, c ClientInterface) (Model, error) { var raw map[string]json.RawMessage if err := json.Unmarshal(data, &raw); err != nil { return nil, err } supp := &Supplement{BaseModel: *NewBaseModel(c)} if v, ok := raw["id"]; ok { json.Unmarshal(v, &supp.ID) } if v, ok := raw["radio_is_available"]; ok { json.Unmarshal(v, &supp.RadioIsAvailable) } if v, ok := raw["description"]; ok { json.Unmarshal(v, &supp.Description) } if v, ok := raw["available"]; ok { json.Unmarshal(v, &supp.Available) } if v, ok := raw["lyrics"]; ok { var lyrics LyricsInfo json.Unmarshal(v, &lyrics) supp.Lyrics = &lyrics } if v, ok := raw["videos"]; ok { var videos []VideoSupplement json.Unmarshal(v, &videos) supp.Videos = videos } return supp, nil } // DeList deserializes a list of Supplements func (s *Supplement) 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 { supp := &Supplement{BaseModel: *NewBaseModel(c)} if err := json.Unmarshal(item, supp); err != nil { continue } result = append(result, supp) } return result, nil }