mirror of
https://github.com/AynaLivePlayer/miaosic.git
synced 2026-03-15 05:23:18 +08:00
update kugou playlist
This commit is contained in:
@@ -213,7 +213,7 @@ func (k *Kugou) GetMediaUrl(meta miaosic.MetaData, quality miaosic.Quality) ([]m
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fmt.Println(urlResp.String())
|
||||
//fmt.Println(urlResp.String())
|
||||
urlJson := gjson.ParseBytes(urlResp.Body())
|
||||
if !urlJson.Get("url").Exists() {
|
||||
return nil, errors.New("kugou: failed to get media url, might be vip only")
|
||||
|
||||
@@ -1,11 +1,138 @@
|
||||
package kugou
|
||||
|
||||
import "github.com/AynaLivePlayer/miaosic"
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/AynaLivePlayer/miaosic"
|
||||
"github.com/aynakeya/deepcolor"
|
||||
"github.com/tidwall/gjson"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func (k *Kugou) MatchPlaylist(uri string) (miaosic.MetaData, bool) {
|
||||
return miaosic.MetaData{}, false
|
||||
}
|
||||
|
||||
func (k *Kugou) GetPlaylist(meta miaosic.MetaData) (*miaosic.Playlist, error) {
|
||||
return nil, miaosic.ErrNotImplemented
|
||||
func (k *Kugou) getCollectionId(gcid string) (string, error) {
|
||||
data := map[string]interface{}{
|
||||
"data": []map[string]interface{}{
|
||||
{
|
||||
"id": gcid, "id_type": "1",
|
||||
},
|
||||
},
|
||||
"ret_info": 1,
|
||||
}
|
||||
dataBytes, _ := json.Marshal(data)
|
||||
param := k.addAndroidParams(map[string]interface{}{}, string(dataBytes))
|
||||
urlReq, _ := deepcolor.NewGetRequestWithQuery(
|
||||
"https://t.kugou.com/v1/songlist/batch_decode",
|
||||
param, map[string]string{},
|
||||
)
|
||||
urlReq.Method = http.MethodPost
|
||||
urlReq.Data = dataBytes
|
||||
resp, err := miaosic.Requester.HTTP(urlReq)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
collId := gjson.Get(resp.String(), "data.list.0.global_collection_id").String()
|
||||
if collId == "" {
|
||||
return "", fmt.Errorf("kugou: failed to get collection id")
|
||||
}
|
||||
return collId, nil
|
||||
}
|
||||
|
||||
func (k *Kugou) getPlaylistTitle(collId string) (string, error) {
|
||||
data := map[string]interface{}{
|
||||
"data": []map[string]interface{}{
|
||||
{
|
||||
"global_collection_id": collId,
|
||||
},
|
||||
},
|
||||
"userid": "0",
|
||||
"token": "",
|
||||
}
|
||||
dataBytes, _ := json.Marshal(data)
|
||||
param := k.addAndroidParams(map[string]interface{}{}, string(dataBytes))
|
||||
urlReq, _ := deepcolor.NewGetRequestWithQuery(
|
||||
"https://gateway.kugou.com/v3/get_list_info",
|
||||
param, map[string]string{
|
||||
"x-router": "pubsongs.kugou.com",
|
||||
},
|
||||
)
|
||||
urlReq.Method = http.MethodPost
|
||||
urlReq.Data = dataBytes
|
||||
resp, err := miaosic.Requester.HTTP(urlReq)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
title := gjson.Get(resp.String(), "data.0.name").String()
|
||||
if title == "" {
|
||||
return "", fmt.Errorf("kugou: failed to get playlist title")
|
||||
}
|
||||
return title, nil
|
||||
}
|
||||
|
||||
func (k *Kugou) GetPlaylist(meta miaosic.MetaData) (*miaosic.Playlist, error) {
|
||||
collId := meta.Identifier
|
||||
if !strings.HasPrefix(collId, "collection_") {
|
||||
var err error
|
||||
collId, err = k.getCollectionId(collId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
params := map[string]interface{}{
|
||||
"global_collection_id": collId,
|
||||
"pagesize": 100,
|
||||
"plat": 1,
|
||||
"type": 1,
|
||||
"area_code": 1,
|
||||
"begin_idx": 0,
|
||||
}
|
||||
playlist := &miaosic.Playlist{
|
||||
Meta: meta,
|
||||
Title: "Kugou Collection " + collId,
|
||||
Medias: make([]miaosic.MediaInfo, 0),
|
||||
}
|
||||
title, err := k.getPlaylistTitle(collId)
|
||||
if err == nil {
|
||||
playlist.Title = title
|
||||
}
|
||||
for page := 0; page < 25; page++ {
|
||||
params["begin_idx"] = page * 100
|
||||
params = k.addAndroidParams(params, "")
|
||||
urlReq, _ := deepcolor.NewGetRequestWithQuery(
|
||||
"https://gateway.kugou.com/pubsongs/v2/get_other_list_file_nofilt",
|
||||
params, map[string]string{},
|
||||
)
|
||||
resp, err := miaosic.Requester.HTTP(urlReq)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result := gjson.ParseBytes(resp.Body())
|
||||
if result.Get("error_code").Int() != 0 {
|
||||
return nil, errors.New("kugou: get playlist error")
|
||||
}
|
||||
count := int(result.Get("data.count").Int())
|
||||
medias := result.Get("data.songs")
|
||||
medias.ForEach(func(key, value gjson.Result) bool {
|
||||
playlist.Medias = append(playlist.Medias, miaosic.MediaInfo{
|
||||
Title: value.Get("name").String(),
|
||||
Cover: miaosic.Picture{Url: strings.Replace(value.Get("cover").String(), "{size}", "128", 1)},
|
||||
Artist: value.Get("singerinfo.0.name").String(),
|
||||
Album: value.Get("albuminfo.name").String(),
|
||||
Meta: miaosic.MetaData{
|
||||
Provider: k.GetName(),
|
||||
Identifier: value.Get("hash").String(),
|
||||
},
|
||||
})
|
||||
return true
|
||||
})
|
||||
if page*100+100 >= count {
|
||||
break
|
||||
}
|
||||
}
|
||||
return playlist, nil
|
||||
}
|
||||
|
||||
26
providers/kugou/playlist_test.go
Normal file
26
providers/kugou/playlist_test.go
Normal file
@@ -0,0 +1,26 @@
|
||||
package kugou
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/AynaLivePlayer/miaosic"
|
||||
"github.com/stretchr/testify/require"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestKugou_GetPlaylist(t *testing.T) {
|
||||
playlist, err := testApi.GetPlaylist(miaosic.MetaData{Identifier: "gcid_3zfcfgjcz31z06d"})
|
||||
require.NoError(t, err)
|
||||
fmt.Println(playlist.Medias)
|
||||
}
|
||||
|
||||
func TestKugou_getCollectionId(t *testing.T) {
|
||||
val, err := testApi.getCollectionId("gcid_3zfcfgjcz31z06d")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "collection_3_806499027_106_0", val)
|
||||
}
|
||||
|
||||
func TestKugou_getPlaylistTitle(t *testing.T) {
|
||||
val, err := testApi.getPlaylistTitle("collection_3_806499027_106_0")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "emo伤感天花板|来自0.8×的孤独与失恋", val)
|
||||
}
|
||||
5
providers/kugou/readme.txt
Normal file
5
providers/kugou/readme.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
part of code is inspired by
|
||||
|
||||
https://github.com/MakcRe/KuGouMusicApi
|
||||
|
||||
under MIT License
|
||||
@@ -6,8 +6,8 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -26,12 +26,6 @@ func signKey(appid string, hash, mid, userid string) string {
|
||||
return getMD5Hash(data)
|
||||
}
|
||||
|
||||
// signParamsKey encrypts the given parameters and returns the encrypted signParams.
|
||||
func signParamsKey(data int64) string {
|
||||
dataStr := appid + signkeyLite + clientver + strconv.FormatInt(data, 10)
|
||||
return getMD5Hash(dataStr)
|
||||
}
|
||||
|
||||
func signatureAndroidParams(signkey string, params map[string]interface{}, data string) string {
|
||||
// Sort the keys of the params map
|
||||
keys := make([]string, 0, len(params))
|
||||
@@ -56,7 +50,7 @@ func signatureAndroidParams(signkey string, params map[string]interface{}, data
|
||||
}
|
||||
|
||||
// Generate the MD5 hash
|
||||
hash := md5.Sum([]byte(signkey + paramsString.String() + string(data) + signkey))
|
||||
hash := md5.Sum([]byte(signkey + paramsString.String() + data + signkey))
|
||||
return hex.EncodeToString(hash[:])
|
||||
}
|
||||
|
||||
@@ -81,3 +75,24 @@ func signatureWebParams(params map[string]string) string {
|
||||
hash := md5.Sum([]byte(str + paramsString.String() + str))
|
||||
return strings.ToUpper(hex.EncodeToString(hash[:]))
|
||||
}
|
||||
|
||||
func (k *Kugou) addAndroidParams(params map[string]interface{}, data string) map[string]interface{} {
|
||||
if token, ok := k.cookie["token"]; ok {
|
||||
params["token"] = token
|
||||
} else {
|
||||
params["token"] = ""
|
||||
}
|
||||
if userId, ok := k.cookie["userid"]; ok {
|
||||
params["userid"] = userId
|
||||
} else {
|
||||
params["userid"] = "0"
|
||||
}
|
||||
params["appid"] = k.appid
|
||||
params["clientver"] = k.clientver
|
||||
params["dfid"] = k.dfid
|
||||
params["mid"] = getMD5Hash(k.dfid)
|
||||
params["uuid"] = getMD5Hash(k.dfid)
|
||||
params["clienttime"] = fmt.Sprintf("%d", time.Now().Unix())
|
||||
params["signature"] = signatureAndroidParams(k.signkey, params, data)
|
||||
return params
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user