mirror of
https://git.um-react.app/um/cli.git
synced 2025-11-28 03:33:02 +00:00
feat(qmc): support audio meta getter
This commit is contained in:
178
algo/qmc/client/track.go
Normal file
178
algo/qmc/client/track.go
Normal file
@@ -0,0 +1,178 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user