From 07c32ab6d4db1e490f9304e8453373a752ae9147 Mon Sep 17 00:00:00 2001 From: ZxwyWebSite Date: Wed, 21 Feb 2024 03:49:01 +0800 Subject: [PATCH] 2024-02-20 v1.0.3-fix --- readme.md | 2 +- src/env/env.go | 23 ++- src/middleware/resp/resp.go | 12 +- src/server/api_music.go | 83 ++++++--- src/server/router.go | 6 +- src/sources/builtin/driver.go | 13 +- src/sources/builtin/types.go | 38 +--- src/sources/custom/driver.go | 76 ++++---- src/sources/custom/kg/player.go | 14 +- src/sources/custom/kg/refresh.go | 149 ++++++++++++++++ src/sources/custom/kg/types.go | 298 +++++++++++++++++++++++++++++++ src/sources/custom/kg/utils.go | 26 +-- src/sources/custom/mg/player.go | 41 ++++- src/sources/custom/mg/types.go | 13 ++ src/sources/custom/mg/utils.go | 6 + src/sources/custom/tx/refresh.go | 2 +- src/sources/custom/wy/player.go | 62 +++++-- src/sources/custom/wy/refresh.go | 25 ++- src/sources/example/data.go | 38 ++++ update.md | 11 +- 20 files changed, 784 insertions(+), 154 deletions(-) create mode 100644 src/sources/custom/kg/refresh.go create mode 100644 src/sources/example/data.go diff --git a/readme.md b/readme.md index e0f5945..df00bab 100644 --- a/readme.md +++ b/readme.md @@ -99,5 +99,5 @@ 音乐平台不易,请尊重版权,支持正版。 本项目仅用于对技术可行性的探索及研究,不接受任何商业(包括但不限于广告等)合作及捐赠。 -若对此有疑问请 mail to: admin+zxwy.tk (请将`+`替换为`@`) +若对此有疑问请 mail to: admin+zxwy.link (请将`+`替换为`@`) \ No newline at end of file diff --git a/src/env/env.go b/src/env/env.go index ddae468..665a716 100644 --- a/src/env/env.go +++ b/src/env/env.go @@ -12,7 +12,7 @@ import ( ) const ( - Version = `1.0.3-pre` + Version = `1.0.3-fix` ) var ( @@ -121,9 +121,19 @@ type ( Kw_Des_Header string `comment:"请求头 User-Agent"` // kg - Kg_Enable bool `comment:"是否启用小枸源"` + Kg_Enable bool `comment:"是否启用小枸源"` + // kg client + Kg_Client_AppId string `comment:"酷狗音乐的appid,官方安卓为1005,官方PC为1001(client.appid)"` + Kg_Client_SignKey string `comment:"客户端signature采用的key值,需要与appid对应(client.signatureKey)"` + Kg_Client_Version string `comment:"客户端versioncode,pidversionsecret可能随此值而变化(client.clientver)"` + Kg_Client_PidVerSec string `comment:"获取URL时所用的key值计算验证值(client.pidversionsecret)"` + Kg_Client_Pid string `comment:"field client.pid"` + // kg user Kg_token string `comment:"field user.token"` Kg_userId string `comment:"field user.userid"` + // kg lite_sign_in + Kg_Lite_Enable bool `comment:"是否启用概念版自动签到,仅在appid=3116时运行"` + Kg_Lite_Interval int64 `comment:"调用时间,自动刷新"` // tx Tx_Enable bool `comment:"是否启用小秋源"` @@ -227,8 +237,13 @@ var ( Kw_Des_Type: `json`, Kw_Des_Header: `okhttp/3.10.0`, - Kg_Enable: false, - Kg_userId: `0`, + Kg_Enable: false, + Kg_Client_AppId: `1005`, + Kg_Client_SignKey: `OIlwieks28dk2k092lksi2UIkp`, + Kg_Client_Version: `12029`, + Kg_Client_PidVerSec: `57ae12eb6890223e355ccfcb74edf70d`, + Kg_Client_Pid: `2`, + Kg_userId: `0`, Tx_Enable: false, Tx_Refresh_Enable: false, diff --git a/src/middleware/resp/resp.go b/src/middleware/resp/resp.go index cc1c49c..c64e223 100644 --- a/src/middleware/resp/resp.go +++ b/src/middleware/resp/resp.go @@ -56,12 +56,12 @@ func (o *Resp) Execute(c *gin.Context) { default: status = http.StatusOK } - // if o.Code != 0 { - // if o.Code == 2 /*&& o.Data == ``*/ { - // o.Data = ErrMp3 - // } - // c.Abort() - // } + if o.Code != 0 { + // if o.Code == 2 /*&& o.Data == ``*/ { + // o.Data = ErrMp3 + // } + c.Abort() + } c.JSON(status, o) } diff --git a/src/server/api_music.go b/src/server/api_music.go index 27659bc..4a17320 100644 --- a/src/server/api_music.go +++ b/src/server/api_music.go @@ -3,11 +3,13 @@ package server import ( "lx-source/src/caches" "lx-source/src/env" + "lx-source/src/middleware/auth" "lx-source/src/middleware/resp" "lx-source/src/middleware/util" "lx-source/src/sources" "lx-source/src/sources/custom" "strings" + "sync/atomic" "github.com/ZxwyWebSite/ztool" "github.com/gin-gonic/gin" @@ -23,10 +25,9 @@ import ( // } // ) -func loadMusic(api *gin.RouterGroup) { +func loadMusic(api gin.IRouter) { // /{method}/{source}/{musicId}/{?quality} - api.GET(`/:m/:s/:id/*q`, musicHandler) - + api.GET(`/:m/:s/:id/*q`, auth.InitHandler(musicHandler)...) } func musicHandler(c *gin.Context) { @@ -40,32 +41,36 @@ func musicHandler(c *gin.Context) { loger.Debug(`s:'%v', m:'%v', id:'%v', q:'%v'`, ps, pm, pid, pq) // 查询内存缓存 cquery := strings.Join([]string{pm, ps, pid, pq}, `/`) - loger.Debug(cquery) - if clink, ok := env.Cache.Get(cquery); ok { - if cstr, ok := clink.(string); ok { - loger.Debug(`MemHIT [%q]=>[%q]`, cquery, cstr) - if cstr == `` { - out.Code = 2 - out.Msg = `Memory Reject` - } else { - out.Msg = `Memory HIT` - out.Data = cstr - } - return out + loger.Debug(`MemoGet: %v`, cquery) + if cdata, ok := env.Cache.Get(cquery); ok { + loger.Debug(`MemoHIT: %q`, cdata) + if cdata == `` { + out.Code = 2 + out.Msg = memRej + } else { + out.Msg = memHIT + out.Data = cdata } + return out } // 定位音乐源 var source custom.Source + var active bool // 是否激活(自定义账号) switch ps { case sources.S_wy: + active = env.Config.Custom.Wy_Enable source = custom.WySource case sources.S_mg: + active = env.Config.Custom.Mg_Enable source = custom.MgSource case sources.S_kw: + active = env.Config.Custom.Kw_Enable source = custom.KwSource case sources.S_kg: + active = env.Config.Custom.Kg_Enable source = custom.KgSource case sources.S_tx: + active = env.Config.Custom.Tx_Enable source = custom.TxSource case sources.S_lx: source = custom.LxSource @@ -88,18 +93,45 @@ func musicHandler(c *gin.Context) { switch pm { case `url`, `link`: // 查询文件缓存 - if caches.UseCache.Stat() { - uquery := caches.NewQuery(ps, pid, pq) - defer uquery.Free() + var cstat bool + if caches.UseCache != nil { + cstat = caches.UseCache.Stat() + } + uquery := caches.NewQuery(ps, pid, pq) + defer uquery.Free() + if cstat { + loger.Debug(`FileGet: %v`, uquery.Query()) if olink := caches.UseCache.Get(uquery); olink != `` { - env.Cache.Set(cquery, olink, 3600) - out.Msg = `Cache HIT` + env.Cache.Set(cquery, olink, 7200) + out.Msg = cacheHIT out.Data = olink return out } } - out.Msg = `No Link` - // out.Data, out.Msg = source.Url(pid, pq) + // 解析歌曲外链 + atomic.AddInt64(&reqnum, 1) + out.Data, out.Msg = source.Url(pid, pq) + if out.Data != `` { + // 缓存并获取直链 + atomic.AddInt64(&secnum, 1) + if out.Msg == `` { + if cstat && active { + loger.Debug(`FileSet: %v`, out.Data) + if link := caches.UseCache.Set(uquery, out.Data.(string)); link != `` { + env.Cache.Set(cquery, link, 7200) + out.Msg = cacheSet + out.Data = link + return out + } + out.Msg = cacheFAIL + } else { + out.Msg = cacheMISS + } + } + // 无法获取直链 直接返回原链接 + env.Cache.Set(cquery, out.Data, 1200) + return out + } case `lrc`, `lyric`: out.Data, out.Msg = source.Lrc(pid) case `pic`, `cover`: @@ -107,10 +139,11 @@ func musicHandler(c *gin.Context) { default: out.Code = 6 out.Msg = ztool.Str_FastConcat(`无效源方法:'`, pm, `'`) - // return + return out } - // 缓存并获取直链 - if out.Data != `` { + if out.Msg != `` { + out.Code = 2 + env.Cache.Set(cquery, out.Data, 600) } return out }) diff --git a/src/server/router.go b/src/server/router.go index 03438f6..0081c70 100644 --- a/src/server/router.go +++ b/src/server/router.go @@ -3,7 +3,6 @@ package server import ( "lx-source/src/caches" "lx-source/src/env" - "lx-source/src/middleware/auth" "lx-source/src/middleware/dynlink" "lx-source/src/middleware/resp" "lx-source/src/middleware/util" @@ -64,7 +63,8 @@ func InitRouter() *gin.Engine { // r.StaticFile(`/favicon.ico`, `public/icon.ico`) // r.StaticFile(`/lx-custom-source.js`, `public/lx-custom-source.js`) // 解析接口 - r.GET(`/link/:s/:id/:q`, auth.InitHandler(linkHandler)...) + loadMusic(r) + // r.GET(`/link/:s/:id/:q`, auth.InitHandler(linkHandler)...) dynlink.LoadHandler(r) // 动态链? // r.GET(`/file/:t/:x/:f`, dynlink.FileHandler()) @@ -75,7 +75,6 @@ func InitRouter() *gin.Engine { // r.Static(`/file`, env.Config.Cache.Local_Path) // } // 功能接口 - // loadMusic(r.Group(`/api`)) // api := r.Group(`/api`) // { // api.GET(`/:s/:m/:q`) // {source}/{method}/{query} @@ -105,6 +104,7 @@ const ( cacheHIT = `Cache HIT` // 缓存已命中 cacheMISS = `Cache MISS` // 缓存未命中 cacheSet = `Cache Seted` // 缓存已设置 + cacheFAIL = `Cache FAIL` // 缓存未成功 memHIT = `Memory HIT` // 内存已命中 memRej = `Memory Reject` // 内存已拒绝 diff --git a/src/sources/builtin/driver.go b/src/sources/builtin/driver.go index 187d66c..4b1504f 100644 --- a/src/sources/builtin/driver.go +++ b/src/sources/builtin/driver.go @@ -11,6 +11,7 @@ import ( "lx-source/src/sources/custom/tx" "lx-source/src/sources/custom/wy" wm "lx-source/src/sources/custom/wy/modules" + "lx-source/src/sources/example" "net/http" "strconv" "sync" @@ -72,8 +73,8 @@ func (s *Source) GetLink(c *caches.Query) (outlink string, msg string) { if env.Config.Source.MusicIdVerify { vef := wv_pool.Get().(*wm.VerifyInfo) defer wv_pool.Put(vef) - vurl := ztool.Str_FastConcat(`https://`, vef_wy, `&id=`, c.MusicID) - _, err := ztool.Net_HttpReq(http.MethodGet, vurl, nil, header_wy, &vef) + vurl := ztool.Str_FastConcat(`https://`, example.Vef_wy, `&id=`, c.MusicID) + _, err := ztool.Net_HttpReq(http.MethodGet, vurl, nil, example.Header_wy, &vef) if err != nil { jx.Error(`Wy, VefReq: %s`, err) msg = sources.ErrHttpReq @@ -95,13 +96,13 @@ func (s *Source) GetLink(c *caches.Query) (outlink string, msg string) { // } // url := urls[rand.Intn(len(urls))] url := ztool.Str_FastConcat( - `https://`, api_wy, `&id=`, c.MusicID, `&level=`, rquery, + `https://`, example.Api_wy, `&id=`, c.MusicID, `&level=`, rquery, `×tamp=`, strconv.FormatInt(time.Now().UnixMilli(), 10), ) // jx.Debug(`Wy, Url: %v`, url) // wy源增加后端重试 默认3次 for i := 0; true; i++ { - _, err := ztool.Net_HttpReq(http.MethodGet, url, nil, header_wy, &resp) + _, err := ztool.Net_HttpReq(http.MethodGet, url, nil, example.Header_wy, &resp) if err != nil { jx.Error(`HttpReq, Err: %s, ReTry: %v`, err, i) if i > 3 { @@ -149,9 +150,9 @@ func (s *Source) GetLink(c *caches.Query) (outlink string, msg string) { resp := mg_pool.Get().(*MgApi_Song) defer mg_pool.Put(resp) - url := ztool.Str_FastConcat(`https://`, api_mg, `?copyrightId=`, c.MusicID, `&type=`, rquery) + url := ztool.Str_FastConcat(`https://`, example.Api_mg, `?copyrightId=`, c.MusicID, `&type=`, rquery) // jx.Debug(`Mg, Url: %v`, url) - _, err := ztool.Net_HttpReq(http.MethodGet, url, nil, header_mg, &resp) + _, err := ztool.Net_HttpReq(http.MethodGet, url, nil, example.Header_mg, &resp) if err != nil { jx.Error(`Mg, HttpReq: %s`, err) msg = sources.ErrHttpReq diff --git a/src/sources/builtin/types.go b/src/sources/builtin/types.go index a59e7f6..9aa8e62 100644 --- a/src/sources/builtin/types.go +++ b/src/sources/builtin/types.go @@ -1,11 +1,7 @@ package builtin import ( - "encoding/base64" "lx-source/src/sources" - - "github.com/ZxwyWebSite/ztool" - "github.com/ZxwyWebSite/ztool/zcypt" ) type ( @@ -242,18 +238,20 @@ var ( sources.S_wy: `exhigh`, sources.S_mg: `2`, sources.S_kw: sources.Q_320k, - // sources.S_kg: ``, + sources.S_kg: ``, sources.S_tx: `M800`, }, sources.Q_flac: { sources.S_wy: `lossless`, sources.S_mg: `3`, sources.S_kw: `2000k`, + sources.S_kg: ``, sources.S_tx: `F000`, }, sources.Q_fl24: { sources.S_wy: `hires`, sources.S_mg: `4`, + sources.S_kg: ``, // sources.S_tx: `RS01`, }, // `fl24`: { @@ -262,35 +260,15 @@ var ( // }, } // ApiAddr - api_wy string - api_mg string + // api_wy string + // api_mg string // api_kw string // api_kg string = `https://wwwapi.kugou.com/yy/index.php?r=play/getdata&platid=4&mid=1` // api_tx string = `https://u.y.qq.com/cgi-bin/musicu.fcg?data=` - vef_wy string + // vef_wy string // Headers - header_wy map[string]string - header_mg map[string]string + // header_wy map[string]string + // header_mg map[string]string // header_kw map[string]string // header_tx = map[string]string{`Referer`: `https://y.qq.com/`} ) - -func init() { - // InitBuiltInSource - var initdata = struct { - Api_Wy *string - Api_Mg *string - Vef_Wy *string - Header_Wy *map[string]string - Header_Mg *map[string]string - }{ - Api_Wy: &api_wy, - Api_Mg: &api_mg, - Vef_Wy: &vef_wy, - Header_Wy: &header_wy, - Header_Mg: &header_mg, - } - data := []byte{0x53, 0x6e, 0x38, 0x44, 0x41, 0x51, 0x4c, 0x2f, 0x67, 0x41, 0x41, 0x42, 0x42, 0x51, 0x45, 0x47, 0x51, 0x58, 0x42, 0x70, 0x58, 0x31, 0x64, 0x35, 0x41, 0x51, 0x77, 0x41, 0x41, 0x51, 0x5a, 0x42, 0x63, 0x47, 0x6c, 0x66, 0x54, 0x57, 0x63, 0x42, 0x44, 0x41, 0x41, 0x42, 0x42, 0x6c, 0x5a, 0x6c, 0x5a, 0x6c, 0x39, 0x58, 0x65, 0x51, 0x45, 0x4d, 0x41, 0x41, 0x45, 0x4a, 0x53, 0x47, 0x56, 0x68, 0x5a, 0x47, 0x56, 0x79, 0x58, 0x31, 0x64, 0x35, 0x41, 0x66, 0x2b, 0x43, 0x41, 0x41, 0x45, 0x4a, 0x53, 0x47, 0x56, 0x68, 0x5a, 0x47, 0x56, 0x79, 0x58, 0x30, 0x31, 0x6e, 0x41, 0x66, 0x2b, 0x43, 0x41, 0x41, 0x41, 0x41, 0x49, 0x66, 0x2b, 0x42, 0x42, 0x41, 0x45, 0x42, 0x45, 0x57, 0x31, 0x68, 0x63, 0x46, 0x74, 0x7a, 0x64, 0x48, 0x4a, 0x70, 0x62, 0x6d, 0x64, 0x64, 0x63, 0x33, 0x52, 0x79, 0x61, 0x57, 0x35, 0x6e, 0x41, 0x66, 0x2b, 0x43, 0x41, 0x41, 0x45, 0x4d, 0x41, 0x51, 0x77, 0x41, 0x41, 0x50, 0x34, 0x42, 0x72, 0x76, 0x2b, 0x41, 0x41, 0x53, 0x52, 0x6a, 0x63, 0x32, 0x30, 0x75, 0x63, 0x32, 0x46, 0x35, 0x63, 0x58, 0x6f, 0x75, 0x59, 0x32, 0x39, 0x74, 0x4c, 0x32, 0x46, 0x77, 0x61, 0x53, 0x38, 0x2f, 0x64, 0x48, 0x6c, 0x77, 0x5a, 0x54, 0x31, 0x68, 0x63, 0x47, 0x6c, 0x54, 0x62, 0x32, 0x35, 0x6e, 0x56, 0x58, 0x4a, 0x73, 0x56, 0x6a, 0x45, 0x42, 0x4e, 0x6d, 0x30, 0x75, 0x62, 0x58, 0x56, 0x7a, 0x61, 0x57, 0x4d, 0x75, 0x62, 0x57, 0x6c, 0x6e, 0x64, 0x53, 0x35, 0x6a, 0x62, 0x69, 0x39, 0x74, 0x61, 0x57, 0x64, 0x31, 0x62, 0x58, 0x56, 0x7a, 0x61, 0x57, 0x4d, 0x76, 0x61, 0x44, 0x55, 0x76, 0x63, 0x47, 0x78, 0x68, 0x65, 0x53, 0x39, 0x68, 0x64, 0x58, 0x52, 0x6f, 0x4c, 0x32, 0x64, 0x6c, 0x64, 0x46, 0x4e, 0x76, 0x62, 0x6d, 0x64, 0x51, 0x62, 0x47, 0x46, 0x35, 0x53, 0x57, 0x35, 0x6d, 0x62, 0x77, 0x45, 0x6c, 0x59, 0x33, 0x4e, 0x74, 0x4c, 0x6e, 0x4e, 0x68, 0x65, 0x58, 0x46, 0x36, 0x4c, 0x6d, 0x4e, 0x76, 0x62, 0x53, 0x39, 0x68, 0x63, 0x47, 0x6b, 0x76, 0x50, 0x33, 0x52, 0x35, 0x63, 0x47, 0x55, 0x39, 0x59, 0x33, 0x4e, 0x74, 0x51, 0x32, 0x68, 0x6c, 0x59, 0x57, 0x74, 0x4e, 0x64, 0x58, 0x4e, 0x70, 0x59, 0x77, 0x45, 0x43, 0x43, 0x6c, 0x56, 0x7a, 0x5a, 0x58, 0x49, 0x74, 0x51, 0x57, 0x64, 0x6c, 0x62, 0x6e, 0x52, 0x65, 0x54, 0x57, 0x39, 0x36, 0x61, 0x57, 0x78, 0x73, 0x59, 0x53, 0x38, 0x31, 0x4c, 0x6a, 0x41, 0x67, 0x4b, 0x46, 0x64, 0x70, 0x62, 0x6d, 0x52, 0x76, 0x64, 0x33, 0x4d, 0x67, 0x54, 0x6c, 0x51, 0x67, 0x4e, 0x69, 0x34, 0x78, 0x4f, 0x79, 0x42, 0x58, 0x54, 0x31, 0x63, 0x32, 0x4e, 0x43, 0x6b, 0x67, 0x51, 0x58, 0x42, 0x77, 0x62, 0x47, 0x56, 0x58, 0x5a, 0x57, 0x4a, 0x4c, 0x61, 0x58, 0x51, 0x76, 0x4e, 0x54, 0x4d, 0x33, 0x4c, 0x6a, 0x4d, 0x32, 0x49, 0x43, 0x68, 0x4c, 0x53, 0x46, 0x52, 0x4e, 0x54, 0x43, 0x77, 0x67, 0x62, 0x47, 0x6c, 0x72, 0x5a, 0x53, 0x42, 0x48, 0x5a, 0x57, 0x4e, 0x72, 0x62, 0x79, 0x6b, 0x67, 0x51, 0x32, 0x68, 0x79, 0x62, 0x32, 0x31, 0x6c, 0x4c, 0x7a, 0x55, 0x77, 0x4c, 0x6a, 0x41, 0x75, 0x4d, 0x6a, 0x59, 0x32, 0x4d, 0x53, 0x34, 0x34, 0x4e, 0x78, 0x42, 0x59, 0x4c, 0x56, 0x4a, 0x6c, 0x63, 0x58, 0x56, 0x6c, 0x63, 0x33, 0x52, 0x6c, 0x5a, 0x43, 0x31, 0x58, 0x61, 0x58, 0x52, 0x6f, 0x44, 0x6c, 0x68, 0x4e, 0x54, 0x45, 0x68, 0x30, 0x64, 0x48, 0x42, 0x53, 0x5a, 0x58, 0x46, 0x31, 0x5a, 0x58, 0x4e, 0x30, 0x41, 0x51, 0x51, 0x48, 0x55, 0x6d, 0x56, 0x6d, 0x5a, 0x58, 0x4a, 0x6c, 0x63, 0x68, 0x74, 0x6f, 0x64, 0x48, 0x52, 0x77, 0x63, 0x7a, 0x6f, 0x76, 0x4c, 0x32, 0x30, 0x75, 0x62, 0x58, 0x56, 0x7a, 0x61, 0x57, 0x4d, 0x75, 0x62, 0x57, 0x6c, 0x6e, 0x64, 0x53, 0x35, 0x6a, 0x62, 0x69, 0x39, 0x32, 0x4e, 0x43, 0x38, 0x43, 0x51, 0x6e, 0x6b, 0x67, 0x4d, 0x44, 0x52, 0x6d, 0x4f, 0x44, 0x45, 0x30, 0x4e, 0x6a, 0x46, 0x68, 0x4f, 0x54, 0x68, 0x6a, 0x4e, 0x32, 0x46, 0x6d, 0x4e, 0x54, 0x55, 0x33, 0x5a, 0x6d, 0x56, 0x68, 0x4d, 0x32, 0x4e, 0x6d, 0x4d, 0x6a, 0x68, 0x6a, 0x4e, 0x47, 0x56, 0x68, 0x4d, 0x54, 0x55, 0x48, 0x59, 0x32, 0x68, 0x68, 0x62, 0x6d, 0x35, 0x6c, 0x62, 0x41, 0x63, 0x77, 0x4d, 0x54, 0x51, 0x77, 0x4d, 0x44, 0x42, 0x45, 0x42, 0x6b, 0x4e, 0x76, 0x62, 0x32, 0x74, 0x70, 0x5a, 0x54, 0x68, 0x54, 0x52, 0x56, 0x4e, 0x54, 0x53, 0x55, 0x39, 0x4f, 0x50, 0x56, 0x70, 0x55, 0x53, 0x58, 0x64, 0x50, 0x52, 0x47, 0x74, 0x35, 0x54, 0x55, 0x52, 0x52, 0x64, 0x45, 0x39, 0x55, 0x52, 0x54, 0x46, 0x4f, 0x55, 0x7a, 0x41, 0x77, 0x54, 0x55, 0x52, 0x6f, 0x62, 0x45, 0x78, 0x55, 0x61, 0x47, 0x68, 0x4e, 0x56, 0x30, 0x56, 0x30, 0x54, 0x57, 0x70, 0x52, 0x4d, 0x45, 0x34, 0x79, 0x57, 0x54, 0x4a, 0x4e, 0x65, 0x6d, 0x73, 0x79, 0x54, 0x31, 0x52, 0x42, 0x65, 0x67, 0x41, 0x3d} - dec, _ := zcypt.Base64Decode(base64.StdEncoding, data) - ztool.Val_GobDecode(dec, &initdata) -} diff --git a/src/sources/custom/driver.go b/src/sources/custom/driver.go index b40b7d2..669f868 100644 --- a/src/sources/custom/driver.go +++ b/src/sources/custom/driver.go @@ -60,42 +60,54 @@ var ( func init() { env.Inits.Add(func() { - WySource = &WrapSource{ - UrlFunc: wy.Url, - LrcFunc: notSupport, - PicFunc: notSupport, - VefFunc: func(songMid string) bool { - _, err := strconv.ParseUint(songMid, 10, 0) - return err == nil - }, + if env.Config.Source.Enable_Wy { + WySource = &WrapSource{ + UrlFunc: wy.Url, + LrcFunc: notSupport, + PicFunc: notSupport, + VefFunc: func(songMid string) bool { + _, err := strconv.ParseUint(songMid, 10, 0) + return err == nil + }, + } } - MgSource = &WrapSource{ - UrlFunc: mg.Url, - LrcFunc: notSupport, - PicFunc: notSupport, - VefFunc: func(songMid string) bool { return len(songMid) == 11 }, + if env.Config.Source.Enable_Mg { + MgSource = &WrapSource{ + UrlFunc: mg.Url, + LrcFunc: notSupport, + PicFunc: notSupport, + VefFunc: func(songMid string) bool { return len(songMid) == 11 }, + } } - KwSource = &WrapSource{ - UrlFunc: kw.Url, - LrcFunc: notSupport, - PicFunc: notSupport, - VefFunc: func(songMid string) bool { - _, err := strconv.ParseUint(songMid, 10, 0) - return err == nil - }, + if env.Config.Source.Enable_Kw { + KwSource = &WrapSource{ + UrlFunc: kw.Url, + LrcFunc: notSupport, + PicFunc: notSupport, + VefFunc: func(songMid string) bool { + _, err := strconv.ParseUint(songMid, 10, 0) + return err == nil + }, + } } - KgSource = &WrapSource{ - UrlFunc: kg.Url, - LrcFunc: notSupport, - PicFunc: notSupport, - VefFunc: func(songMid string) bool { return len(songMid) == 32 }, + if env.Config.Source.Enable_Kg { + KgSource = &WrapSource{ + UrlFunc: kg.Url, + LrcFunc: notSupport, + PicFunc: notSupport, + VefFunc: func(songMid string) bool { return len(songMid) == 32 }, + } } - TxSource = &WrapSource{ - UrlFunc: tx.Url, - LrcFunc: notSupport, - PicFunc: notSupport, - VefFunc: func(songMid string) bool { return len(songMid) == 14 }, + if env.Config.Source.Enable_Tx { + TxSource = &WrapSource{ + UrlFunc: tx.Url, + LrcFunc: notSupport, + PicFunc: notSupport, + VefFunc: func(songMid string) bool { return len(songMid) == 14 }, + } + } + if env.Config.Source.Enable_Lx { + LxSource = nil } - LxSource = nil }) } diff --git a/src/sources/custom/kg/player.go b/src/sources/custom/kg/player.go index 1de0295..554a793 100644 --- a/src/sources/custom/kg/player.go +++ b/src/sources/custom/kg/player.go @@ -3,6 +3,7 @@ package kg import ( "lx-source/src/env" "lx-source/src/sources" + "net/http" "strconv" "strings" "time" @@ -47,9 +48,9 @@ func Url(songMid, quality string) (ourl, msg string) { `hash`: tHash, `module`: ``, `mid`: mid, - `appid`: appid, + `appid`: env.Config.Custom.Kg_Client_AppId, `ssa_flag`: `is_fromtrack`, - `clientver`: clientver, + `clientver`: env.Config.Custom.Kg_Client_Version, `open_time`: now.Format(`20060102`), `vipType`: `6`, `ptype`: `0`, @@ -64,8 +65,11 @@ func Url(songMid, quality string) (ourl, msg string) { `dfid`: `-`, `pidversion`: `3001`, - `quality`: rquality, - `IsFreePart`: `1`, + `quality`: rquality, + // `IsFreePart`: `1`, + } + if !env.Config.Custom.Kg_Enable { + params[`IsFreePart`] = `1` // 仅游客登录时允许获取试听 } headers := map[string]string{ `User-Agent`: `Android712-AndroidPhone-8983-18-0-NetMusic-wifi`, @@ -76,7 +80,7 @@ func Url(songMid, quality string) (ourl, msg string) { `x-router`: `tracker.kugou.com`, } var resp playInfo - err := signRequest(url, params, headers, &resp) + err := signRequest(http.MethodGet, url, nil, params, headers, &resp) if err != nil { loger.Error(`Request: %s`, err) msg = sources.ErrHttpReq diff --git a/src/sources/custom/kg/refresh.go b/src/sources/custom/kg/refresh.go new file mode 100644 index 0000000..58b2b81 --- /dev/null +++ b/src/sources/custom/kg/refresh.go @@ -0,0 +1,149 @@ +package kg + +import ( + "errors" + "fmt" + "lx-source/src/env" + "math/rand" + "net/http" + "strconv" + "strings" + "time" + + "github.com/ZxwyWebSite/ztool" + "github.com/ZxwyWebSite/ztool/logs" + "github.com/ZxwyWebSite/ztool/zcypt" +) + +// 通过TOP500榜单获取随机歌曲的mixsongmid +func randomMixSongMid() (mid string, err error) { + // 声明榜单url + const rankUrl = `http://mobilecdnbj.kugou.com/api/v3/rank/song?version=9108&ranktype=1&plat=0&pagesize=100&area_code=1&page=1&rankid=8888&with_res_tag=0&show_portrait_mv=1` + // 请求 + var res rankInfo + err = ztool.Net_Request( + http.MethodGet, + rankUrl, nil, + []ztool.Net_ReqHandlerFunc{ztool.Net_ReqAddHeaders()}, + []ztool.Net_ResHandlerFunc{ztool.Net_ResToStruct(&res)}, + ) + if err != nil { + return + } + // fmt.Printf("%#v\n", res) + if res.Status != 1 { + err = errors.New(res.Error) + return + } + + // 随机选择一首歌曲 + randomSong := res.Data.Info[rand.Intn(len(res.Data.Info))] + // fmt.Printf("%#v\n", randomSong) + + // 因为排行榜api不会返回mixsongmid + // 所以需要进行一次搜索接口来获取 + var body searchInfo + err = ztool.Net_Request( + http.MethodGet, + ztool.Str_FastConcat( + `https://songsearch.kugou.com/song_search_v2?`, + ztool.Net_Values(map[string]string{ + `keyword`: randomSong.Filename, + `area_code`: `1`, + `page`: `1`, + `pagesize`: `1`, + `userid`: `0`, + `clientver`: ``, + `platform`: `WebFilter`, + `filter`: `2`, + `iscorrection`: `1`, + `privilege_filter`: `0`, + }), + ), nil, + []ztool.Net_ReqHandlerFunc{ztool.Net_ReqAddHeaders(map[string]string{ + `Referer`: `https://www.kugou.com`, + })}, + []ztool.Net_ResHandlerFunc{ztool.Net_ResToStruct(&body)}, + ) + if err != nil { + return + } + // fmt.Printf("%#v\n", body) + if body.Status != 1 { + err = errors.New(body.ErrorMsg) + return + } + if body.Data.Total == 0 || len(body.Data.Lists) == 0 { + err = errors.New(`歌曲搜索失败`) + return + } + mid = body.Data.Lists[0].MixSongID + return +} + +// 签到主函数,传入userinfo,响应None就是成功,报错即为不成功 +func do_account_signin(loger *logs.Logger, now int64) (err error) { + // 检查用户配置文件,获取mixsongmid + mixid := `582534238` + if mixid == `auto` { + mixid, err = randomMixSongMid() + if err != nil { + return + } + } + + // 声明变量 + headers := map[string]string{ + `User-Agent`: ztool.Str_FastConcat( + `Android712-AndroidPhone-`, + env.Config.Custom.Kg_Client_Version, + `-18-0-NetMusic-wifi`, + ), + `KG-THash`: `3e5ec6b`, + `KG-Rec`: `1`, + `KG-RC`: `1`, + `x-router`: `youth.kugou.com`, + } + body := ztool.Str_FastConcat( + `{"mixsongid":"`, mixid, `"}`, + ) + params := map[string]string{ + `userid`: env.Config.Custom.Kg_userId, + `token`: env.Config.Custom.Kg_token, + `appid`: env.Config.Custom.Kg_Client_AppId, + `clientver`: env.Config.Custom.Kg_Client_Version, + `clienttime`: strconv.FormatInt(time.Now().Unix(), 10), + `mid`: mid, + `uuid`: zcypt.HexToString(zcypt.RandomBytes(16)), + `dfid`: `-`, + } + + // 发送请求 + var out refreshInfo + err = signRequest( + http.MethodPost, + `https://gateway.kugou.com/v2/report/listen_song`, + strings.NewReader(body), + params, headers, &out, + ) + if err != nil { + return err + } + if out.Status != 1 { + return errors.New(out.ErrorMsg) + } + fmt.Printf("%#v\n", out) + env.Config.Custom.Kg_Lite_Interval = now + 86000 + + return nil +} + +func init() { + env.Inits.Add(func() { + if env.Config.Custom.Kg_Lite_Enable && false { + if env.Config.Custom.Kg_Client_AppId == `3116` && env.Config.Custom.Kg_token != `` { + env.Tasker.Add(`kg_refresh`, do_account_signin, 86000, true) + } + } + }) +} diff --git a/src/sources/custom/kg/types.go b/src/sources/custom/kg/types.go index 9dec202..6529717 100644 --- a/src/sources/custom/kg/types.go +++ b/src/sources/custom/kg/types.go @@ -156,3 +156,301 @@ type ( FileSize int `json:"fileSize"` } ) + +type rankInfo struct { + Data struct { + Timestamp int `json:"timestamp"` + Total int `json:"total"` + Info []struct { + LastSort int `json:"last_sort"` + Authors []struct { + SizableAvatar string `json:"sizable_avatar"` + IsPublish int `json:"is_publish"` + AuthorName string `json:"author_name"` + AuthorID int `json:"author_id"` + } `json:"authors"` + RankCount int `json:"rank_count"` + RankIDPublishDate string `json:"rank_id_publish_date"` + Songname string `json:"songname"` + TopicURL320 string `json:"topic_url_320"` + Sqhash string `json:"sqhash"` + FailProcess int `json:"fail_process"` + PayType int `json:"pay_type"` + RecommendReason string `json:"recommend_reason"` + RpType string `json:"rp_type"` + AlbumID string `json:"album_id"` + PrivilegeHigh int `json:"privilege_high"` + TopicURLSq string `json:"topic_url_sq"` + RankCid int `json:"rank_cid"` + Inlist int `json:"inlist"` + Three20Filesize int `json:"320filesize"` + PkgPrice320 int `json:"pkg_price_320"` + Feetype int `json:"feetype"` + Price320 int `json:"price_320"` + DurationHigh int `json:"duration_high"` + FailProcess320 int `json:"fail_process_320"` + Zone string `json:"zone"` + TopicURL string `json:"topic_url"` + RpPublish int `json:"rp_publish"` + TransObj struct { + RankShowSort int `json:"rank_show_sort"` + } `json:"trans_obj"` + Hash string `json:"hash"` + Sqfilesize int `json:"sqfilesize"` + Sqprivilege int `json:"sqprivilege"` + PayTypeSq int `json:"pay_type_sq"` + Bitrate int `json:"bitrate"` + PkgPriceSq int `json:"pkg_price_sq"` + HasAccompany int `json:"has_accompany"` + Musical interface{} `json:"musical"` + PayType320 int `json:"pay_type_320"` + Issue int `json:"issue"` + ExtnameSuper string `json:"extname_super"` + DurationSuper int `json:"duration_super"` + BitrateSuper int `json:"bitrate_super"` + HashHigh string `json:"hash_high"` + Duration int `json:"duration"` + Three20Hash string `json:"320hash"` + PriceSq int `json:"price_sq"` + OldCpy int `json:"old_cpy"` + AlbumAudioID int `json:"album_audio_id"` + M4Afilesize int `json:"m4afilesize"` + PkgPrice int `json:"pkg_price"` + First int `json:"first"` + AudioID int `json:"audio_id"` + HashSuper string `json:"hash_super"` + Addtime string `json:"addtime"` + FilesizeHigh int `json:"filesize_high"` + Price int `json:"price"` + Privilege int `json:"privilege"` + AlbumSizableCover string `json:"album_sizable_cover"` + Mvdata []struct { + Typ int `json:"typ"` + Trk string `json:"trk"` + Hash string `json:"hash"` + ID string `json:"id"` + } `json:"mvdata,omitempty"` + Sort int `json:"sort"` + TransParam struct { + CpyLevel int `json:"cpy_level"` + Classmap struct { + Attr0 int `json:"attr0"` + } `json:"classmap"` + CpyGrade int `json:"cpy_grade"` + Qualitymap struct { + Attr0 int `json:"attr0"` + } `json:"qualitymap"` + PayBlockTpl int `json:"pay_block_tpl"` + Cid int `json:"cid"` + Language string `json:"language"` + HashMultitrack string `json:"hash_multitrack"` + CpyAttr0 int `json:"cpy_attr0"` + Ipmap struct { + Attr0 int `json:"attr0"` + } `json:"ipmap"` + AppidBlock string `json:"appid_block"` + MusicpackAdvance int `json:"musicpack_advance"` + Display int `json:"display"` + DisplayRate int `json:"display_rate"` + } `json:"trans_param"` + FilesizeSuper int `json:"filesize_super"` + Filename string `json:"filename"` + BitrateHigh int `json:"bitrate_high"` + Remark string `json:"remark"` + Extname string `json:"extname"` + Filesize int `json:"filesize"` + Isfirst int `json:"isfirst"` + Mvhash string `json:"mvhash"` + Three20Privilege int `json:"320privilege"` + PrivilegeSuper int `json:"privilege_super"` + FailProcessSq int `json:"fail_process_sq"` + } `json:"info"` + } `json:"data"` + Errcode int `json:"errcode"` + Status int `json:"status"` + Error string `json:"error"` +} + +type searchInfo struct { + Data struct { + AlgPath string `json:"AlgPath"` + Aggregation struct { + } `json:"aggregation"` + Allowerr int `json:"allowerr"` + Chinesecount int `json:"chinesecount"` + Correctionforce int `json:"correctionforce"` + Correctionrelate string `json:"correctionrelate"` + Correctionsubject string `json:"correctionsubject"` + Correctiontip string `json:"correctiontip"` + Correctiontype int `json:"correctiontype"` + From int `json:"from"` + Isshareresult int `json:"isshareresult"` + Istag int `json:"istag"` + Istagresult int `json:"istagresult"` + Lists []struct { + A320Privilege int `json:"A320Privilege"` + ASQPrivilege int `json:"ASQPrivilege"` + Accompany int `json:"Accompany"` + AlbumAux string `json:"AlbumAux"` + AlbumID string `json:"AlbumID"` + AlbumName string `json:"AlbumName"` + AlbumPrivilege int `json:"AlbumPrivilege"` + AudioCdn int `json:"AudioCdn"` + Audioid int `json:"Audioid"` + Auxiliary string `json:"Auxiliary"` + Bitrate int `json:"Bitrate"` + Category int `json:"Category"` + Duration int `json:"Duration"` + ExtName string `json:"ExtName"` + FailProcess int `json:"FailProcess"` + FileHash string `json:"FileHash"` + FileName string `json:"FileName"` + FileSize int `json:"FileSize"` + FoldType int `json:"FoldType"` + Grp []interface{} `json:"Grp"` + HQBitrate int `json:"HQBitrate"` + HQDuration int `json:"HQDuration"` + HQExtName string `json:"HQExtName"` + HQFailProcess int `json:"HQFailProcess"` + HQFileHash string `json:"HQFileHash"` + HQFileSize int `json:"HQFileSize"` + HQPayType int `json:"HQPayType"` + HQPkgPrice int `json:"HQPkgPrice"` + HQPrice int `json:"HQPrice"` + HQPrivilege int `json:"HQPrivilege"` + HasAlbum int `json:"HasAlbum"` + HeatLevel int `json:"HeatLevel"` + HiFiQuality int `json:"HiFiQuality"` + ID string `json:"ID"` + Image string `json:"Image"` + IsOriginal int `json:"IsOriginal"` + M4ASize int `json:"M4aSize"` + MatchFlag int `json:"MatchFlag"` + MixSongID string `json:"MixSongID"` + MvHash string `json:"MvHash"` + MvTrac int `json:"MvTrac"` + MvType int `json:"MvType"` + OldCpy int `json:"OldCpy"` + OriOtherName string `json:"OriOtherName"` + OriSongName string `json:"OriSongName"` + OtherName string `json:"OtherName"` + OwnerCount int `json:"OwnerCount"` + PayType int `json:"PayType"` + PkgPrice int `json:"PkgPrice"` + Price int `json:"Price"` + Privilege int `json:"Privilege"` + Publish int `json:"Publish"` + PublishAge int `json:"PublishAge"` + PublishTime string `json:"PublishTime"` + QualityLevel int `json:"QualityLevel"` + RankID int `json:"RankId"` + Res struct { + FailProcess int `json:"FailProcess"` + PayType int `json:"PayType"` + PkgPrice int `json:"PkgPrice"` + Price int `json:"Price"` + Privilege int `json:"Privilege"` + } `json:"Res"` + ResBitrate int `json:"ResBitrate"` + ResDuration int `json:"ResDuration"` + ResFileHash string `json:"ResFileHash"` + ResFileSize int `json:"ResFileSize"` + SQBitrate int `json:"SQBitrate"` + SQDuration int `json:"SQDuration"` + SQExtName string `json:"SQExtName"` + SQFailProcess int `json:"SQFailProcess"` + SQFileHash string `json:"SQFileHash"` + SQFileSize int `json:"SQFileSize"` + SQPayType int `json:"SQPayType"` + SQPkgPrice int `json:"SQPkgPrice"` + SQPrice int `json:"SQPrice"` + SQPrivilege int `json:"SQPrivilege"` + Scid int `json:"Scid"` + ShowingFlag int `json:"ShowingFlag"` + SingerID []int `json:"SingerId"` + SingerName string `json:"SingerName"` + Singers []struct { + ID int `json:"id"` + IPID int `json:"ip_id"` + Name string `json:"name"` + } `json:"Singers"` + SongLabel string `json:"SongLabel"` + SongName string `json:"SongName"` + Source string `json:"Source"` + SourceID int `json:"SourceID"` + Suffix string `json:"Suffix"` + SuperBitrate int `json:"SuperBitrate"` + SuperDuration int `json:"SuperDuration"` + SuperExtName string `json:"SuperExtName"` + SuperFileHash string `json:"SuperFileHash"` + SuperFileSize int `json:"SuperFileSize"` + TagContent string `json:"TagContent"` + TagDetails []struct { + Content string `json:"content"` + Rankid int `json:"rankid"` + Type int `json:"type"` + Version int `json:"version"` + } `json:"TagDetails"` + TopID int `json:"TopID"` + TopicRemark string `json:"TopicRemark"` + TopicURL string `json:"TopicUrl"` + Type string `json:"Type"` + Uploader string `json:"Uploader"` + UploaderContent string `json:"UploaderContent"` + MvTotal int `json:"mvTotal"` + Mvdata []struct { + Hash string `json:"hash"` + ID string `json:"id"` + Trk string `json:"trk"` + Typ int `json:"typ"` + } `json:"mvdata"` + RecommendType int `json:"recommend_type"` + TransParam struct { + AppidBlock string `json:"appid_block"` + Cid int `json:"cid"` + Classmap struct { + Attr0 int `json:"attr0"` + } `json:"classmap"` + CpyAttr0 int `json:"cpy_attr0"` + CpyGrade int `json:"cpy_grade"` + CpyLevel int `json:"cpy_level"` + Display int `json:"display"` + DisplayRate int `json:"display_rate"` + HashMultitrack string `json:"hash_multitrack"` + Ipmap struct { + Attr0 int `json:"attr0"` + } `json:"ipmap"` + Language string `json:"language"` + MusicpackAdvance int `json:"musicpack_advance"` + PayBlockTpl int `json:"pay_block_tpl"` + Qualitymap struct { + Attr0 int `json:"attr0"` + } `json:"qualitymap"` + SongnameSuffix string `json:"songname_suffix"` + } `json:"trans_param"` + Vvid string `json:"vvid"` + } `json:"lists"` + Page int `json:"page"` + Pagesize int `json:"pagesize"` + Searchfull int `json:"searchfull"` + SecAggre struct { + } `json:"sec_aggre"` + SecAggreV2 []interface{} `json:"sec_aggre_v2"` + SectagInfo struct { + IsSectag int `json:"is_sectag"` + } `json:"sectag_info"` + Size int `json:"size"` + Subjecttype int `json:"subjecttype"` + Total int `json:"total"` + } `json:"data"` + ErrorCode int `json:"error_code"` + ErrorMsg string `json:"error_msg"` + Status int `json:"status"` +} + +type refreshInfo struct { + Data string `json:"data"` + ErrorCode int `json:"error_code"` + ErrorMsg string `json:"error_msg"` + Status int `json:"status"` +} diff --git a/src/sources/custom/kg/utils.go b/src/sources/custom/kg/utils.go index fec57d7..a330d80 100644 --- a/src/sources/custom/kg/utils.go +++ b/src/sources/custom/kg/utils.go @@ -1,9 +1,9 @@ package kg import ( + "io" "lx-source/src/env" "lx-source/src/sources" - "net/http" "slices" "strings" @@ -28,12 +28,12 @@ var ( ) const ( - signkey = `OIlwieks28dk2k092lksi2UIkp` - pidversec = `57ae12eb6890223e355ccfcb74edf70d` - clientver = `12029` - url = `https://gateway.kugou.com/v5/url` - appid = `1005` - mid = `211008` + // signkey = `OIlwieks28dk2k092lksi2UIkp` + // pidversec = `57ae12eb6890223e355ccfcb74edf70d` + // clientver = `12029` + url = `https://gateway.kugou.com/v5/url` + // appid = `1005` + mid = `211008` ) func sortDict(dictionary map[string]string) ([]string, int) { @@ -58,7 +58,7 @@ func sortDict(dictionary map[string]string) ([]string, int) { // return zcypt.MD5EncStr(ztool.Str_FastConcat(signkey, b.String(), signkey)) // } -func signRequest(url string, params, headers map[string]string, out any) error { +func signRequest(method string, url string, body io.Reader, params, headers map[string]string, out any) error { // buildSignatureParams keys, lens := sortDict(params) var b strings.Builder @@ -77,12 +77,15 @@ func signRequest(url string, params, headers map[string]string, out any) error { } c.WriteString(`signature`) c.WriteByte('=') - c.WriteString(zcypt.MD5EncStr(ztool.Str_FastConcat(signkey, b.String(), signkey))) + c.WriteString(zcypt.MD5EncStr(ztool.Str_FastConcat( + env.Config.Custom.Kg_Client_SignKey, + b.String(), env.Config.Custom.Kg_Client_SignKey, + ))) url = ztool.Str_FastConcat(url, `?`, c.String()) // ztool.Cmd_FastPrintln(url) return ztool.Net_Request( - http.MethodGet, url, nil, + method, url, body, []ztool.Net_ReqHandlerFunc{ztool.Net_ReqAddHeader(headers)}, []ztool.Net_ResHandlerFunc{ //func(res *http.Response) error { // body, err := io.ReadAll(res.Body) @@ -96,7 +99,8 @@ func signRequest(url string, params, headers map[string]string, out any) error { func getKey(hash_ string) string { return zcypt.MD5EncStr(ztool.Str_FastConcat( - strings.ToLower(hash_), pidversec, appid, mid, env.Config.Custom.Kg_userId, + strings.ToLower(hash_), env.Config.Custom.Kg_Client_PidVerSec, + env.Config.Custom.Kg_Client_AppId, mid, env.Config.Custom.Kg_userId, )) } diff --git a/src/sources/custom/mg/player.go b/src/sources/custom/mg/player.go index 4d6d20c..3353930 100644 --- a/src/sources/custom/mg/player.go +++ b/src/sources/custom/mg/player.go @@ -4,6 +4,7 @@ import ( "lx-source/src/env" "lx-source/src/sources" "lx-source/src/sources/custom/utils" + "lx-source/src/sources/example" "net/http" "sync" @@ -18,14 +19,12 @@ var ( func init() { env.Inits.Add(func() { - if !env.Config.Source.Enable_Mg { - return - } loger := env.Loger.NewGroup(`MgInit`) switch env.Config.Custom.Mg_Mode { case `0`, `builtin`: loger.Debug(`use builtin`) - // Url = builtin + mg_pool = &sync.Pool{New: func() any { return new(mgApi_Song) }} + Url = builtin case `1`, `custom`: loger.Debug(`use custom`) if ztool.Chk_IsNilStr( @@ -45,11 +44,35 @@ func init() { }) } -// func builtin(songMid, quality string) (ourl, msg string) { -// loger := env.Loger.NewGroup(`Mg`) -// defer loger.Free() -// return -// } +func builtin(songMid, quality string) (ourl, msg string) { + loger := env.Loger.NewGroup(`Mg`) + rquality, ok := qualitys[quality] + if !ok { + msg = sources.E_QNotSupport + return + } + defer loger.Free() + resp := mg_pool.Get().(*mgApi_Song) + defer mg_pool.Put(resp) + url := ztool.Str_FastConcat(`https://`, example.Api_mg, `?copyrightId=`, songMid, `&type=`, rquality) + err := ztool.Net_Request( + http.MethodGet, url, nil, + []ztool.Net_ReqHandlerFunc{ztool.Net_ReqAddHeaders(example.Header_mg)}, + []ztool.Net_ResHandlerFunc{ztool.Net_ResToStruct(&resp)}, + ) + if err != nil { + loger.Error(`HttpReq: %s`, err) + msg = sources.ErrHttpReq + return + } + loger.Debug(`Resp: %+v`, resp) + if resp.Data.PlayURL != `` { + ourl = `https:` + utils.DelQuery(resp.Data.PlayURL) + } else { + msg = ztool.Str_FastConcat(resp.Code, `: `, resp.Msg) + } + return +} func mcustom(songMid, quality string) (ourl, msg string) { loger := env.Loger.NewGroup(`Mg`) diff --git a/src/sources/custom/mg/types.go b/src/sources/custom/mg/types.go index 617fa9b..cbd93c7 100644 --- a/src/sources/custom/mg/types.go +++ b/src/sources/custom/mg/types.go @@ -42,3 +42,16 @@ type playInfo struct { } `json:"data"` Info string `json:"info"` } + +type mgApi_Song struct { + Code string `json:"code"` + Msg string `json:"msg"` + Data struct { + PlayURL string `json:"playUrl"` + FormatID string `json:"formatId"` + SalePrice string `json:"salePrice"` + BizType string `json:"bizType"` + BizCode string `json:"bizCode"` + AuditionsLength int `json:"auditionsLength"` + } `json:"data"` +} diff --git a/src/sources/custom/mg/utils.go b/src/sources/custom/mg/utils.go index 166b9b7..8068db7 100644 --- a/src/sources/custom/mg/utils.go +++ b/src/sources/custom/mg/utils.go @@ -22,4 +22,10 @@ var ( // q_flac: sources.Q_flac, // q_fl24: sources.Q_fl24, // } + qualitys = map[string]string{ + sources.Q_128k: `1`, + sources.Q_320k: `2`, + sources.Q_flac: `3`, + sources.Q_fl24: `4`, + } ) diff --git a/src/sources/custom/tx/refresh.go b/src/sources/custom/tx/refresh.go index 0f00327..573e8a3 100644 --- a/src/sources/custom/tx/refresh.go +++ b/src/sources/custom/tx/refresh.go @@ -129,7 +129,7 @@ func refresh(loger *logs.Logger, now int64) error { loger.Info(`刷新登录成功`) env.Config.Custom.Tx_Uuin = resp.Req1.Data.StrMusicId env.Config.Custom.Tx_Ukey = resp.Req1.Data.MusicKey - env.Config.Custom.Tx_Refresh_Interval = now + 518400 //(每6天刷新一次) //1209600 - 86000 // 14天提前一天 + env.Config.Custom.Tx_Refresh_Interval = now + 432000 //(每5天刷新一次) //1209600 - 86000 // 14天提前一天 loger.Debug(`Resp: %+v`, resp) loger.Debug(`Uuin: %v, Ukey: %v`, resp.Req1.Data.StrMusicId, resp.Req1.Data.MusicKey) loger.Debug(`ExpiresAt: %v, Real: %v`, resp.Req1.Data.ExpiredAt, env.Config.Custom.Tx_Refresh_Interval) diff --git a/src/sources/custom/wy/player.go b/src/sources/custom/wy/player.go index fc0b0b1..5504651 100644 --- a/src/sources/custom/wy/player.go +++ b/src/sources/custom/wy/player.go @@ -4,17 +4,19 @@ import ( "lx-source/src/env" "lx-source/src/sources" "lx-source/src/sources/custom/utils" - wy "lx-source/src/sources/custom/wy/modules" + wm "lx-source/src/sources/custom/wy/modules" + "lx-source/src/sources/example" "net/http" "strconv" "sync" + "time" "github.com/ZxwyWebSite/ztool" "github.com/ZxwyWebSite/ztool/x/cookie" ) var ( - wy_pool = &sync.Pool{New: func() any { return new(wy.PlayInfo) }} + wy_pool = &sync.Pool{New: func() any { return new(wm.PlayInfo) }} // wv_pool *sync.Pool Url func(string, string) (string, string) @@ -29,7 +31,7 @@ func init() { // if env.Config.Source.MusicIdVerify { // wv_pool = &sync.Pool{New: func() any { return new(verifyInfo) }} // } - // Url = builtin + Url = builtin case `1`, `163api`: if env.Config.Custom.Wy_Api_Cookie == `` { loger.Fatal(`使用163api且Cookie参数为空`) @@ -58,11 +60,49 @@ func init() { }) } -// func builtin(songMid, quality string) (ourl, msg string) { -// loger := env.Loger.NewGroup(`Wy`) -// defer loger.Free() -// return -// } +func builtin(songMid, quality string) (ourl, msg string) { + loger := env.Loger.NewGroup(`Wy`) + defer loger.Free() + rquality, ok := qualityMap[quality] + if !ok { + msg = sources.E_QNotSupport + return + } + resp := wy_pool.Get().(*wm.PlayInfo) + defer wy_pool.Put(resp) + url := ztool.Str_FastConcat( + `https://`, example.Api_wy, `&id=`, songMid, `&level=`, rquality, + `×tamp=`, strconv.FormatInt(time.Now().UnixMilli(), 10), + ) + err := ztool.Net_Request( + http.MethodGet, url, nil, + []ztool.Net_ReqHandlerFunc{ztool.Net_ReqAddHeaders(example.Header_wy)}, + []ztool.Net_ResHandlerFunc{ztool.Net_ResToStruct(&resp)}, + ) + if err != nil { + loger.Error(`HttpReq: %s`, err) + msg = sources.ErrHttpReq + return + } + loger.Debug(`Resp: %+v`, resp) + if len(resp.Data) == 0 { + msg = `No Data:Api接口忙,请稍后重试` + return + } + var data = resp.Data[0] + if data.Code != 200 || data.FreeTrialInfo != nil { + msg = `触发风控或专辑单独收费: ` + strconv.Itoa(data.Code) + return + } + if data.Level != rquality { + msg = ztool.Str_FastConcat(`实际音质不匹配: `, rquality, ` <= `, data.Level) + if !env.Config.Source.ForceFallback { + return + } + } + ourl = data.URL + return +} func nmModule(songMid, quality string) (ourl, msg string) { loger := env.Loger.NewGroup(`Wy`) @@ -73,13 +113,13 @@ func nmModule(songMid, quality string) (ourl, msg string) { return } cookies := cookie.Parse(env.Config.Custom.Wy_Api_Cookie) - answer, err := wy.SongUrlV1(wy.ReqQuery{ + answer, err := wm.SongUrlV1(wm.ReqQuery{ Cookie: cookie.ToMap(cookies), Ids: songMid, // Br: rquality, Level: rquality, }) - body := wy_pool.Get().(*wy.PlayInfo) + body := wy_pool.Get().(*wm.PlayInfo) defer wy_pool.Put(body) if err == nil { err = ztool.Val_MapToStruct(answer.Body, &body) @@ -122,7 +162,7 @@ func nmCustom(songMid, quality string) (ourl, msg string) { msg = sources.E_QNotSupport return } - body := wy_pool.Get().(*wy.PlayInfo) + body := wy_pool.Get().(*wm.PlayInfo) defer wy_pool.Put(body) err := ztool.Net_Request( http.MethodGet, diff --git a/src/sources/custom/wy/refresh.go b/src/sources/custom/wy/refresh.go index 272c3e3..4e68643 100644 --- a/src/sources/custom/wy/refresh.go +++ b/src/sources/custom/wy/refresh.go @@ -22,6 +22,12 @@ import ( 2024-02-15: MUSIC_U 改变 则 6天 后 继续执行 MUSIC_U 不变 则 1天 后 继续执行 + 原理: + 听说隔壁某解析群的账号经常使用,Token快一年了也没过期, + 所以模拟正常使用,每天调用一次刷新接口, + 证明这个Token还在使用,类似于给它"续期", + 就像SPlayer客户端一样,Cookie变了就合并, + (这是我随便猜的,未经测试仅供参考) */ func refresh(loger *logs.Logger, now int64) error { @@ -44,15 +50,16 @@ func refresh(loger *logs.Logger, now int64) error { maps.Copy(cookies, cmap) env.Config.Custom.Wy_Api_Cookie = cookie.Marshal(cookies) loger.Debug(`Cookie: %#v`, cookies) - if _, ok := cmap[`MUSIC_U`]; ok { - // MUSIC_U 改变 则 6天 后 继续执行 - env.Config.Custom.Wy_Refresh_Interval = now + 518400 //2147483647 - 86000 - loger.Debug(`MUSIC_U 改变, 6天 后 继续执行`) - } else { - // MUSIC_U 不变 则 1天 后 继续执行 - env.Config.Custom.Wy_Refresh_Interval = now + 86000 - loger.Debug(`MUSIC_U 不变, 1天 后 继续执行`) //`未发现有效结果,将在下次检测时再次尝试` - } + // if _, ok := cmap[`MUSIC_U`]; ok { + // // MUSIC_U 改变 则 6天 后 继续执行 + // env.Config.Custom.Wy_Refresh_Interval = now + 518400 //2147483647 - 86000 + // loger.Debug(`MUSIC_U 改变, 6天 后 继续执行`) + // } else { + // // MUSIC_U 不变 则 1天 后 继续执行 + // env.Config.Custom.Wy_Refresh_Interval = now + 86000 + // loger.Debug(`MUSIC_U 不变, 1天 后 继续执行`) //`未发现有效结果,将在下次检测时再次尝试` + // } + env.Config.Custom.Wy_Refresh_Interval = now + 86000 err = env.Cfg.Save(``) if err == nil { loger.Info(`配置更新成功`) diff --git a/src/sources/example/data.go b/src/sources/example/data.go new file mode 100644 index 0000000..1912149 --- /dev/null +++ b/src/sources/example/data.go @@ -0,0 +1,38 @@ +package example + +import ( + "encoding/base64" + + "github.com/ZxwyWebSite/ztool" + "github.com/ZxwyWebSite/ztool/zcypt" +) + +var ( + Api_wy string + Api_mg string + + Vef_wy string + + Header_wy map[string]string + Header_mg map[string]string +) + +func init() { + // InitBuiltInData + var initdata = struct { + Api_Wy *string + Api_Mg *string + Vef_Wy *string + Header_Wy *map[string]string + Header_Mg *map[string]string + }{ + Api_Wy: &Api_wy, + Api_Mg: &Api_mg, + Vef_Wy: &Vef_wy, + Header_Wy: &Header_wy, + Header_Mg: &Header_mg, + } + data := []byte{0x53, 0x6e, 0x38, 0x44, 0x41, 0x51, 0x4c, 0x2f, 0x67, 0x41, 0x41, 0x42, 0x42, 0x51, 0x45, 0x47, 0x51, 0x58, 0x42, 0x70, 0x58, 0x31, 0x64, 0x35, 0x41, 0x51, 0x77, 0x41, 0x41, 0x51, 0x5a, 0x42, 0x63, 0x47, 0x6c, 0x66, 0x54, 0x57, 0x63, 0x42, 0x44, 0x41, 0x41, 0x42, 0x42, 0x6c, 0x5a, 0x6c, 0x5a, 0x6c, 0x39, 0x58, 0x65, 0x51, 0x45, 0x4d, 0x41, 0x41, 0x45, 0x4a, 0x53, 0x47, 0x56, 0x68, 0x5a, 0x47, 0x56, 0x79, 0x58, 0x31, 0x64, 0x35, 0x41, 0x66, 0x2b, 0x43, 0x41, 0x41, 0x45, 0x4a, 0x53, 0x47, 0x56, 0x68, 0x5a, 0x47, 0x56, 0x79, 0x58, 0x30, 0x31, 0x6e, 0x41, 0x66, 0x2b, 0x43, 0x41, 0x41, 0x41, 0x41, 0x49, 0x66, 0x2b, 0x42, 0x42, 0x41, 0x45, 0x42, 0x45, 0x57, 0x31, 0x68, 0x63, 0x46, 0x74, 0x7a, 0x64, 0x48, 0x4a, 0x70, 0x62, 0x6d, 0x64, 0x64, 0x63, 0x33, 0x52, 0x79, 0x61, 0x57, 0x35, 0x6e, 0x41, 0x66, 0x2b, 0x43, 0x41, 0x41, 0x45, 0x4d, 0x41, 0x51, 0x77, 0x41, 0x41, 0x50, 0x34, 0x42, 0x72, 0x76, 0x2b, 0x41, 0x41, 0x53, 0x52, 0x6a, 0x63, 0x32, 0x30, 0x75, 0x63, 0x32, 0x46, 0x35, 0x63, 0x58, 0x6f, 0x75, 0x59, 0x32, 0x39, 0x74, 0x4c, 0x32, 0x46, 0x77, 0x61, 0x53, 0x38, 0x2f, 0x64, 0x48, 0x6c, 0x77, 0x5a, 0x54, 0x31, 0x68, 0x63, 0x47, 0x6c, 0x54, 0x62, 0x32, 0x35, 0x6e, 0x56, 0x58, 0x4a, 0x73, 0x56, 0x6a, 0x45, 0x42, 0x4e, 0x6d, 0x30, 0x75, 0x62, 0x58, 0x56, 0x7a, 0x61, 0x57, 0x4d, 0x75, 0x62, 0x57, 0x6c, 0x6e, 0x64, 0x53, 0x35, 0x6a, 0x62, 0x69, 0x39, 0x74, 0x61, 0x57, 0x64, 0x31, 0x62, 0x58, 0x56, 0x7a, 0x61, 0x57, 0x4d, 0x76, 0x61, 0x44, 0x55, 0x76, 0x63, 0x47, 0x78, 0x68, 0x65, 0x53, 0x39, 0x68, 0x64, 0x58, 0x52, 0x6f, 0x4c, 0x32, 0x64, 0x6c, 0x64, 0x46, 0x4e, 0x76, 0x62, 0x6d, 0x64, 0x51, 0x62, 0x47, 0x46, 0x35, 0x53, 0x57, 0x35, 0x6d, 0x62, 0x77, 0x45, 0x6c, 0x59, 0x33, 0x4e, 0x74, 0x4c, 0x6e, 0x4e, 0x68, 0x65, 0x58, 0x46, 0x36, 0x4c, 0x6d, 0x4e, 0x76, 0x62, 0x53, 0x39, 0x68, 0x63, 0x47, 0x6b, 0x76, 0x50, 0x33, 0x52, 0x35, 0x63, 0x47, 0x55, 0x39, 0x59, 0x33, 0x4e, 0x74, 0x51, 0x32, 0x68, 0x6c, 0x59, 0x57, 0x74, 0x4e, 0x64, 0x58, 0x4e, 0x70, 0x59, 0x77, 0x45, 0x43, 0x43, 0x6c, 0x56, 0x7a, 0x5a, 0x58, 0x49, 0x74, 0x51, 0x57, 0x64, 0x6c, 0x62, 0x6e, 0x52, 0x65, 0x54, 0x57, 0x39, 0x36, 0x61, 0x57, 0x78, 0x73, 0x59, 0x53, 0x38, 0x31, 0x4c, 0x6a, 0x41, 0x67, 0x4b, 0x46, 0x64, 0x70, 0x62, 0x6d, 0x52, 0x76, 0x64, 0x33, 0x4d, 0x67, 0x54, 0x6c, 0x51, 0x67, 0x4e, 0x69, 0x34, 0x78, 0x4f, 0x79, 0x42, 0x58, 0x54, 0x31, 0x63, 0x32, 0x4e, 0x43, 0x6b, 0x67, 0x51, 0x58, 0x42, 0x77, 0x62, 0x47, 0x56, 0x58, 0x5a, 0x57, 0x4a, 0x4c, 0x61, 0x58, 0x51, 0x76, 0x4e, 0x54, 0x4d, 0x33, 0x4c, 0x6a, 0x4d, 0x32, 0x49, 0x43, 0x68, 0x4c, 0x53, 0x46, 0x52, 0x4e, 0x54, 0x43, 0x77, 0x67, 0x62, 0x47, 0x6c, 0x72, 0x5a, 0x53, 0x42, 0x48, 0x5a, 0x57, 0x4e, 0x72, 0x62, 0x79, 0x6b, 0x67, 0x51, 0x32, 0x68, 0x79, 0x62, 0x32, 0x31, 0x6c, 0x4c, 0x7a, 0x55, 0x77, 0x4c, 0x6a, 0x41, 0x75, 0x4d, 0x6a, 0x59, 0x32, 0x4d, 0x53, 0x34, 0x34, 0x4e, 0x78, 0x42, 0x59, 0x4c, 0x56, 0x4a, 0x6c, 0x63, 0x58, 0x56, 0x6c, 0x63, 0x33, 0x52, 0x6c, 0x5a, 0x43, 0x31, 0x58, 0x61, 0x58, 0x52, 0x6f, 0x44, 0x6c, 0x68, 0x4e, 0x54, 0x45, 0x68, 0x30, 0x64, 0x48, 0x42, 0x53, 0x5a, 0x58, 0x46, 0x31, 0x5a, 0x58, 0x4e, 0x30, 0x41, 0x51, 0x51, 0x48, 0x55, 0x6d, 0x56, 0x6d, 0x5a, 0x58, 0x4a, 0x6c, 0x63, 0x68, 0x74, 0x6f, 0x64, 0x48, 0x52, 0x77, 0x63, 0x7a, 0x6f, 0x76, 0x4c, 0x32, 0x30, 0x75, 0x62, 0x58, 0x56, 0x7a, 0x61, 0x57, 0x4d, 0x75, 0x62, 0x57, 0x6c, 0x6e, 0x64, 0x53, 0x35, 0x6a, 0x62, 0x69, 0x39, 0x32, 0x4e, 0x43, 0x38, 0x43, 0x51, 0x6e, 0x6b, 0x67, 0x4d, 0x44, 0x52, 0x6d, 0x4f, 0x44, 0x45, 0x30, 0x4e, 0x6a, 0x46, 0x68, 0x4f, 0x54, 0x68, 0x6a, 0x4e, 0x32, 0x46, 0x6d, 0x4e, 0x54, 0x55, 0x33, 0x5a, 0x6d, 0x56, 0x68, 0x4d, 0x32, 0x4e, 0x6d, 0x4d, 0x6a, 0x68, 0x6a, 0x4e, 0x47, 0x56, 0x68, 0x4d, 0x54, 0x55, 0x48, 0x59, 0x32, 0x68, 0x68, 0x62, 0x6d, 0x35, 0x6c, 0x62, 0x41, 0x63, 0x77, 0x4d, 0x54, 0x51, 0x77, 0x4d, 0x44, 0x42, 0x45, 0x42, 0x6b, 0x4e, 0x76, 0x62, 0x32, 0x74, 0x70, 0x5a, 0x54, 0x68, 0x54, 0x52, 0x56, 0x4e, 0x54, 0x53, 0x55, 0x39, 0x4f, 0x50, 0x56, 0x70, 0x55, 0x53, 0x58, 0x64, 0x50, 0x52, 0x47, 0x74, 0x35, 0x54, 0x55, 0x52, 0x52, 0x64, 0x45, 0x39, 0x55, 0x52, 0x54, 0x46, 0x4f, 0x55, 0x7a, 0x41, 0x77, 0x54, 0x55, 0x52, 0x6f, 0x62, 0x45, 0x78, 0x55, 0x61, 0x47, 0x68, 0x4e, 0x56, 0x30, 0x56, 0x30, 0x54, 0x57, 0x70, 0x52, 0x4d, 0x45, 0x34, 0x79, 0x57, 0x54, 0x4a, 0x4e, 0x65, 0x6d, 0x73, 0x79, 0x54, 0x31, 0x52, 0x42, 0x65, 0x67, 0x41, 0x3d} + dec, _ := zcypt.Base64Decode(base64.StdEncoding, data) + ztool.Val_GobDecode(dec, &initdata) +} diff --git a/update.md b/update.md index e302c00..42f1b34 100644 --- a/update.md +++ b/update.md @@ -3,11 +3,20 @@ +#### \# 2024-02-20 v1.0.3-fix (fix) ++ 修复新版Wraper在Code不为0时未能正常结束Handler的问题 ++ zTool: 修复计划任务模块一处计时bug "时间倒流" ++ Tx源刷新登录间隔时间降至5天 ++ Wy源刷新登录间隔时间固定为1天 ++ Kg源暴露更多配置项 ++ 使用新版MusicRouter处理器(beta),兼容Python版**调用**方式? + + #### \# 2024-02-15 v1.0.3-pre (pre) + Wy源刷新登录模式确定:每天执行一次合并Cookie + zTool: task: 增加传参 now(int64): 执行时间(Unix) + 优化Tx源刷新登录函数,兼容计划任务错误处理模式 -+ 对源脚本进行部分更改,建议重新下载导入(http://127.0.0.1:1011/lx-custom-source.js) ++ 对源脚本进行部分更改,建议重新下载导入() + 简单优化旧版LinkHandler + 支持Mg源自定义账号