package client import ( "context" "encoding/json" "fmt" "github.com/samber/lo" ) type getTrackInfoParams struct { Ctx int `json:"ctx"` Ids []int `json:"ids"` Types []int `json:"types"` } type getTrackInfoResponse struct { Tracks []*TrackInfo `json:"tracks"` } func (c *QQMusic) GetTracksInfo(ctx context.Context, songIDs []int) ([]*TrackInfo, error) { resp, err := c.rpcCall(ctx, "Protocol_UpdateSongInfo", "CgiGetTrackInfo", "music.trackInfo.UniformRuleCtrl", &getTrackInfoParams{Ctx: 0, Ids: songIDs, Types: []int{0}}, ) if err != nil { return nil, fmt.Errorf("qqMusicClient[GetTrackInfo] rpc call: %w", err) } respData := getTrackInfoResponse{} if err := json.Unmarshal(resp, &respData); err != nil { return nil, fmt.Errorf("qqMusicClient[GetTrackInfo] unmarshal response: %w", err) } return respData.Tracks, nil } func (c *QQMusic) GetTrackInfo(ctx context.Context, songID int) (*TrackInfo, error) { tracks, err := c.GetTracksInfo(ctx, []int{songID}) if err != nil { return nil, fmt.Errorf("qqMusicClient[GetTrackInfo] get tracks info: %w", err) } if len(tracks) == 0 { return nil, fmt.Errorf("qqMusicClient[GetTrackInfo] track not found") } return tracks[0], nil } type TrackSinger struct { Id int `json:"id"` Mid string `json:"mid"` Name string `json:"name"` Title string `json:"title"` Type int `json:"type"` Uin int `json:"uin"` Pmid string `json:"pmid"` } type TrackAlbum struct { Id int `json:"id"` Mid string `json:"mid"` Name string `json:"name"` Title string `json:"title"` Subtitle string `json:"subtitle"` Pmid string `json:"pmid"` } type TrackInfo struct { Id int `json:"id"` Type int `json:"type"` Mid string `json:"mid"` Name string `json:"name"` Title string `json:"title"` Subtitle string `json:"subtitle"` Singer []TrackSinger `json:"singer"` Album TrackAlbum `json:"album"` Mv struct { Id int `json:"id"` Vid string `json:"vid"` Name string `json:"name"` Title string `json:"title"` Vt int `json:"vt"` } `json:"mv"` Interval int `json:"interval"` Isonly int `json:"isonly"` Language int `json:"language"` Genre int `json:"genre"` IndexCd int `json:"index_cd"` IndexAlbum int `json:"index_album"` TimePublic string `json:"time_public"` Status int `json:"status"` Fnote int `json:"fnote"` File struct { MediaMid string `json:"media_mid"` Size24Aac int `json:"size_24aac"` Size48Aac int `json:"size_48aac"` Size96Aac int `json:"size_96aac"` Size192Ogg int `json:"size_192ogg"` Size192Aac int `json:"size_192aac"` Size128Mp3 int `json:"size_128mp3"` Size320Mp3 int `json:"size_320mp3"` SizeApe int `json:"size_ape"` SizeFlac int `json:"size_flac"` SizeDts int `json:"size_dts"` SizeTry int `json:"size_try"` TryBegin int `json:"try_begin"` TryEnd int `json:"try_end"` Url string `json:"url"` SizeHires int `json:"size_hires"` HiresSample int `json:"hires_sample"` HiresBitdepth int `json:"hires_bitdepth"` B30S int `json:"b_30s"` E30S int `json:"e_30s"` Size96Ogg int `json:"size_96ogg"` Size360Ra []interface{} `json:"size_360ra"` SizeDolby int `json:"size_dolby"` SizeNew []interface{} `json:"size_new"` } `json:"file"` Pay struct { PayMonth int `json:"pay_month"` PriceTrack int `json:"price_track"` PriceAlbum int `json:"price_album"` PayPlay int `json:"pay_play"` PayDown int `json:"pay_down"` PayStatus int `json:"pay_status"` TimeFree int `json:"time_free"` } `json:"pay"` Action struct { Switch int `json:"switch"` Msgid int `json:"msgid"` Alert int `json:"alert"` Icons int `json:"icons"` Msgshare int `json:"msgshare"` Msgfav int `json:"msgfav"` Msgdown int `json:"msgdown"` Msgpay int `json:"msgpay"` Switch2 int `json:"switch2"` Icon2 int `json:"icon2"` } `json:"action"` Ksong struct { Id int `json:"id"` Mid string `json:"mid"` } `json:"ksong"` Volume struct { Gain float64 `json:"gain"` Peak float64 `json:"peak"` Lra float64 `json:"lra"` } `json:"volume"` Label string `json:"label"` Url string `json:"url"` Ppurl string `json:"ppurl"` Bpm int `json:"bpm"` Version int `json:"version"` Trace string `json:"trace"` DataType int `json:"data_type"` ModifyStamp int `json:"modify_stamp"` Aid int `json:"aid"` Tid int `json:"tid"` Ov int `json:"ov"` Sa int `json:"sa"` Es string `json:"es"` Vs []string `json:"vs"` } func (t *TrackInfo) GetArtists() []string { return lo.Map(t.Singer, func(v TrackSinger, i int) string { return v.Name }) } func (t *TrackInfo) GetTitle() string { return t.Title } func (t *TrackInfo) GetAlbum() string { return t.Album.Name }