Yonah ea54772c03
song: struct for /api/song/%d
This also includes tests against a sample response from the
https://monster-siren.hypergryph.com/api/song/048794 endpoint.

Signed-off-by: Yonah <contrib@gensokyo.uk>
2025-09-17 07:49:06 +09:00

56 lines
1.6 KiB
Go

package monstersirenfetch
import (
"bytes"
"encoding/json"
)
// SongResponse is the response of /api/song/%d.
type SongResponse Response[Song]
// Song holds the metadata of a song.
type Song struct {
CID StringInt `json:"cid"`
Name string `json:"name"`
AlbumCID StringInt `json:"albumCid"`
SourceURL string `json:"sourceUrl,omitempty"`
LyricURL string `json:"lyricUrl,omitempty"`
MvURL string `json:"mvUrl,omitempty"`
MvCoverURL string `json:"mvCoverUrl,omitempty"`
Artists []string `json:"artists"`
}
// IsFull returns whether the metadata held by [Song] is considered full (originating from a [SongResponse]).
func (s *Song) IsFull() bool { return s.SourceURL != "" }
// songDirect is [Song] without its MarshalJSON method.
type songDirect Song
// songNullable is [Song] with corresponding nullable string fields.
type songNullable struct {
CID StringInt `json:"cid"`
Name string `json:"name"`
AlbumCID StringInt `json:"albumCid"`
SourceURL string `json:"sourceUrl"`
LyricURL NullableString `json:"lyricUrl"`
MvURL NullableString `json:"mvUrl"`
MvCoverURL NullableString `json:"mvCoverUrl"`
Artists []string `json:"artists"`
}
func (s *Song) MarshalJSON() (data []byte, err error) {
buf := new(bytes.Buffer)
e := json.NewEncoder(buf)
e.SetEscapeHTML(false)
if !s.IsFull() {
err = e.Encode((*songDirect)(s))
data = buf.Bytes()
return
}
return json.Marshal(&songNullable{s.CID, s.Name, s.AlbumCID, s.SourceURL,
NullableString(s.LyricURL), NullableString(s.MvURL), NullableString(s.MvCoverURL),
s.Artists})
}