From f60f0b3d07add95612e4f9abecdc87ba2cf0c073 Mon Sep 17 00:00:00 2001 From: Unlock Music Dev Date: Fri, 25 Nov 2022 03:58:50 +0800 Subject: [PATCH] feat(qmc): add search interface --- algo/qmc/client/base.go | 23 +++++++---------- algo/qmc/client/search.go | 52 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 14 deletions(-) create mode 100644 algo/qmc/client/search.go diff --git a/algo/qmc/client/base.go b/algo/qmc/client/base.go index 62f0b53..7c3ea96 100644 --- a/algo/qmc/client/base.go +++ b/algo/qmc/client/base.go @@ -10,28 +10,23 @@ import ( "time" ) -const endpointURL = "https://u.y.qq.com/cgi-bin/musicu.fcg" - type QQMusic struct { http *http.Client } -func (c *QQMusic) doRequest(ctx context.Context, reqBody any) ([]byte, error) { - reqBodyBuf, ok := reqBody.([]byte) - if !ok { - var err error - reqBodyBuf, err = json.Marshal(reqBody) - if err != nil { - return nil, fmt.Errorf("qqMusicClient[doRequest] marshal request: %w", err) - } +func (c *QQMusic) rpcDoRequest(ctx context.Context, reqBody any) ([]byte, error) { + reqBodyBuf, err := json.Marshal(reqBody) + if err != nil { + return nil, fmt.Errorf("qqMusicClient[rpcDoRequest] marshal request: %w", err) } + const endpointURL = "https://u.y.qq.com/cgi-bin/musicu.fcg" req, err := http.NewRequestWithContext(ctx, http.MethodPost, endpointURL+fmt.Sprintf("?pcachetime=%d", time.Now().Unix()), bytes.NewReader(reqBodyBuf), ) if err != nil { - return nil, fmt.Errorf("qqMusicClient[doRequest] create request: %w", err) + return nil, fmt.Errorf("qqMusicClient[rpcDoRequest] create request: %w", err) } req.Header.Set("Accept", "*/*") @@ -42,13 +37,13 @@ func (c *QQMusic) doRequest(ctx context.Context, reqBody any) ([]byte, error) { reqp, err := c.http.Do(req) if err != nil { - return nil, fmt.Errorf("qqMusicClient[doRequest] send request: %w", err) + return nil, fmt.Errorf("qqMusicClient[rpcDoRequest] send request: %w", err) } defer reqp.Body.Close() respBodyBuf, err := io.ReadAll(reqp.Body) if err != nil { - return nil, fmt.Errorf("qqMusicClient[doRequest] read response: %w", err) + return nil, fmt.Errorf("qqMusicClient[rpcDoRequest] read response: %w", err) } return respBodyBuf, nil @@ -82,7 +77,7 @@ func (c *QQMusic) rpcCall(ctx context.Context, Param: param, }} - respBodyBuf, err := c.doRequest(ctx, reqBody) + respBodyBuf, err := c.rpcDoRequest(ctx, reqBody) if err != nil { return nil, fmt.Errorf("qqMusicClient[rpcCall] do request: %w", err) } diff --git a/algo/qmc/client/search.go b/algo/qmc/client/search.go new file mode 100644 index 0000000..d619574 --- /dev/null +++ b/algo/qmc/client/search.go @@ -0,0 +1,52 @@ +package client + +import ( + "context" + "encoding/json" + "fmt" +) + +type searchParams struct { + Grp int `json:"grp"` + NumPerPage int `json:"num_per_page"` + PageNum int `json:"page_num"` + Query string `json:"query"` + RemotePlace string `json:"remoteplace"` + SearchType int `json:"search_type"` + //SearchID string `json:"searchid"` // todo: it seems generated randomly +} + +type searchResponse struct { + Body struct { + Song struct { + List []*TrackInfo `json:"list"` + } `json:"song"` + } `json:"body"` + Code int `json:"code"` +} + +func (c *QQMusic) Search(ctx context.Context, keyword string) ([]*TrackInfo, error) { + + resp, err := c.rpcCall(ctx, + "music.search.SearchCgiService", + "DoSearchForQQMusicDesktop", + "music.search.SearchCgiService", + &searchParams{ + SearchType: 0, Query: keyword, + PageNum: 1, NumPerPage: 40, + + // static values + Grp: 1, RemotePlace: "sizer.newclient.song", + }) + if err != nil { + return nil, fmt.Errorf("qqMusicClient[Search] rpc call: %w", err) + } + + respData := searchResponse{} + if err := json.Unmarshal(resp, &respData); err != nil { + return nil, fmt.Errorf("qqMusicClient[Search] unmarshal response: %w", err) + } + + return respData.Body.Song.List, nil + +}