Fix Track model to match Python reference
- R128: changed from JSONR128 float64 to R128 struct with i, tp, important_secs fields (Python R128 is an object, not a number) - StorageID -> StorageDir with json tag storage_dir (Python API uses storage_dir) - Lyrics: replaced TrackLyricsInfo with Lyrics (from supplement/lyrics.py) and TrackLyricsInfo (from track/lyrics_info.py with has_available_sync_lyrics, has_available_text_lyrics fields) - Track.Lyrics field now maps to lyrics_info JSON key with TrackLyricsInfo type
This commit is contained in:
1 parent
ad83d84531
commit
6312c24b0f
5 files changed
+192
-52
No files matched your search
+53
-17
@@ -111,33 +111,69 @@ func (id JSONID) String() string {
|
||||
return string(id)
|
||||
}
|
||||
|
||||
// JSONR128 is a flexible R128 loudness normalization value that accepts both JSON numbers and objects.
|
||||
// The Yandex Music API sometimes returns r128 as a number (e.g., -23.5) and sometimes
|
||||
// as an object (e.g., {"value": -23.5}). JSONR128 accepts both and stores as float64.
|
||||
type JSONR128 float64
|
||||
// R128 represents EBU R 128 loudness normalization parameters.
|
||||
// The Yandex Music API returns this either as a number (e.g., -23.5) or as an object
|
||||
// with fields i, tp, important_secs.
|
||||
type R128 struct {
|
||||
BaseModel
|
||||
I float64 `json:"i"`
|
||||
Tp float64 `json:"tp"`
|
||||
ImportantSecs int `json:"important_secs"`
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements json.Unmarshaler, accepting both JSON numbers and objects.
|
||||
func (r *JSONR128) UnmarshalJSON(data []byte) error {
|
||||
// Try float64 first
|
||||
func (r *R128) UnmarshalJSON(data []byte) error {
|
||||
// Try float64 first (API sometimes returns just a number)
|
||||
var f float64
|
||||
if err := json.Unmarshal(data, &f); err == nil {
|
||||
*r = JSONR128(f)
|
||||
r.I = f
|
||||
r.Tp = 0
|
||||
r.ImportantSecs = 0
|
||||
return nil
|
||||
}
|
||||
// Try object with "value" key
|
||||
// Try object with fields i, tp, important_secs
|
||||
var obj struct {
|
||||
Value float64 `json:"value"`
|
||||
I float64 `json:"i"`
|
||||
Tp float64 `json:"tp"`
|
||||
ImportantSecs int `json:"important_secs"`
|
||||
}
|
||||
if err := json.Unmarshal(data, &obj); err == nil {
|
||||
*r = JSONR128(obj.Value)
|
||||
return nil
|
||||
if err := json.Unmarshal(data, &obj); err != nil {
|
||||
return err
|
||||
}
|
||||
// Default to 0 if neither format works
|
||||
*r = 0
|
||||
r.I = obj.I
|
||||
r.Tp = obj.Tp
|
||||
r.ImportantSecs = obj.ImportantSecs
|
||||
return nil
|
||||
}
|
||||
|
||||
// Float64 returns the R128 value as a float64.
|
||||
func (r JSONR128) Float64() float64 {
|
||||
return float64(r)
|
||||
// Float64 returns the integrated loudness (i) value as a float64.
|
||||
func (r R128) Float64() float64 {
|
||||
return r.I
|
||||
}
|
||||
|
||||
// DeJSON deserializes an R128 from JSON data.
|
||||
func (r *R128) DeJSON(data []byte, c ClientInterface) (Model, error) {
|
||||
r128 := &R128{BaseModel: *NewBaseModel(c)}
|
||||
if err := r128.UnmarshalJSON(data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return r128, nil
|
||||
}
|
||||
|
||||
// DeList deserializes a list of R128 from JSON data.
|
||||
func (r *R128) 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 {
|
||||
r128 := &R128{BaseModel: *NewBaseModel(c)}
|
||||
if err := r128.UnmarshalJSON(item); err != nil {
|
||||
continue
|
||||
}
|
||||
result = append(result, r128)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
Reference in new issue
Block a user