From 48028bd51b5abe64de1c8e2e156bedece0b8387d Mon Sep 17 00:00:00 2001 From: ZxwyWebSite Date: Mon, 25 Dec 2023 03:13:06 +0800 Subject: [PATCH] 2023-12-24 v1.0.2-b0.6 --- src/env/env.go | 6 +- src/middleware/loadpublic/loadpublic.go | 10 ++- .../loadpublic/public/lx-custom-source.js | 22 +++-- src/router/router.go | 25 ++++-- src/sources/builtin/driver.go | 43 ++++++++-- src/sources/builtin/types.go | 86 ++++++++++++++++++- update.md | 11 +++ 7 files changed, 166 insertions(+), 37 deletions(-) diff --git a/src/env/env.go b/src/env/env.go index 8918a3f..86d0011 100644 --- a/src/env/env.go +++ b/src/env/env.go @@ -9,7 +9,7 @@ import ( ) const ( - Version = `1.0.2-b0.5` + Version = `1.0.2-b0.6` ) var ( @@ -120,9 +120,9 @@ var ( Script: Conf_Script{ Log: `发布更新 (请删除旧源后重新导入):进行了部分优化,修复了部分Bug`, // 更新日志 - Ver: `1.0.1`, // 自定义脚本版本 + Ver: `1.0.3`, // 自定义脚本版本 Url: `lx-custom-source.js`, // 脚本下载地址 - Force: false, // 强制推送更新 + Force: true, // 强制推送更新 }, Cache: Conf_Cache{ Mode: `local`, // 缓存模式 diff --git a/src/middleware/loadpublic/loadpublic.go b/src/middleware/loadpublic/loadpublic.go index 4a298fa..200b309 100644 --- a/src/middleware/loadpublic/loadpublic.go +++ b/src/middleware/loadpublic/loadpublic.go @@ -22,12 +22,12 @@ func LoadPublic(r *gin.Engine) { pf := env.Loger.NewGroup(`PublicFS`) var httpFS http.FileSystem dir := ztool.Str_FastConcat(env.RunPath, `/data/public`) + publicFS, err := fs.Sub(publicEM, `public`) + if err != nil { + pf.Fatal(`内置Public目录载入错误: %s, 请尝试重新编译`, err) + } if !ztool.Fbj_IsExists(dir) { pf.Info(`不存在Public目录, 释放默认静态文件`) - publicFS, err := fs.Sub(publicEM, `public`) - if err != nil { - pf.Fatal(`内置Public目录载入错误: %s, 请尝试重新编译`, err) - } walk := func(relPath string, d fs.DirEntry, err error) error { if err != nil { return fmt.Errorf(`无法获取[%q]的信息: %s`, relPath, err) @@ -63,6 +63,8 @@ func LoadPublic(r *gin.Engine) { switch file { case `favicon.ico`: c.FileFromFS(`icon.ico`, httpFS) + case `lx-custom-source.js`: + c.FileFromFS(`lx-custom-source.js`, http.FS(publicFS)) default: c.FileFromFS(file, httpFS) } diff --git a/src/middleware/loadpublic/public/lx-custom-source.js b/src/middleware/loadpublic/public/lx-custom-source.js index eaf1826..7d745c8 100644 --- a/src/middleware/loadpublic/public/lx-custom-source.js +++ b/src/middleware/loadpublic/public/lx-custom-source.js @@ -7,18 +7,19 @@ */ // 脚本配置 -const version = '1.0.2' // 脚本版本 +const version = '1.0.3' // 脚本版本 const apiaddr = 'http://127.0.0.1:1011/' // 服务端地址,末尾加斜杠 const apipass = '' // 验证密钥,由服务端自动生成 '${apipass}' const devmode = true // 调试模式 // 常量 & 默认值 const { EVENT_NAMES, request, on, send } = window.lx ?? globalThis.lx -const defaults = { - type: 'music', // 目前固定为 music - actions: ['musicUrl'], // 目前固定为 ['musicUrl'] - qualitys: ['128k', '320k', 'flac', 'flac24bit'], // 当前脚本的该源所支持获取的Url音质,有效的值有:['128k', '320k', 'flac', 'flac24bit'] -} +const defs = { type: 'music', actions: ['musicUrl'] } +// const defaults = { +// type: 'music', // 目前固定为 music +// actions: ['musicUrl'], // 目前固定为 ['musicUrl'] +// qualitys: ['128k', '320k', 'flac', 'flac24bit'], // 当前脚本的该源所支持获取的Url音质,有效的值有:['128k', '320k', 'flac', 'flac24bit'] +// } const defheaders = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.84 Safari/537.36 HBPC/12.1.2.300', 'Accept': 'application/json, text/plain, */*', @@ -99,17 +100,14 @@ const init = () => { } // 激活可用源 const source = body.source // 定位到Source部分 - // const defs = { type: 'music', actions: ['musicUrl'] } Object.keys(source).forEach(v => { - if (source[v] == true) { + if (source[v] != null /*== true*/) { sourcess[v] = { name: v, - ...defaults, - // ...defs, qualitys: source[v].qualitys, // 支持返回音质时启用 使用后端音质表 + ...defs, // ...defaults, + qualitys: source[v], // 支持返回音质时启用 使用后端音质表 } } - sourcess['kg'] = { name: '酷狗试听', ...defaults } - sourcess['kg'].qualitys = ['128k'] }) // 完成初始化 stat = true diff --git a/src/router/router.go b/src/router/router.go index 3e22be2..a6d714f 100644 --- a/src/router/router.go +++ b/src/router/router.go @@ -16,6 +16,13 @@ import ( "github.com/gin-gonic/gin" ) +var ( + // 默认音质 + defQuality = []string{`128k`, `320k`, `flac`, `flac24bit`} + // 试听音质 + tstQuality = []string{`128k`} +) + // 载入路由 func InitRouter() *gin.Engine { r := gin.Default() @@ -34,14 +41,14 @@ func InitRouter() *gin.Engine { `github`: `https://github.com/ZxwyWebSite/lx-source`, // 可用平台 `source`: gin.H{ - `mg`: true, - `wy`: true, - `kg`: []string{`128k`, `320k`}, // 测试结构2, 启用时返回音质列表, 禁用为false - `tx`: gin.H{ // "测试结构 不代表最终方式" - `enable`: false, - `qualitys`: []string{`128k`, `320k`, `flac`, `flac24bit`}, - }, - `kw`: true, + `mg`: defQuality, //true, + `wy`: defQuality, //true, + `kg`: tstQuality, //[]string{`128k`, `320k`}, // 测试结构2, 启用时返回音质列表, 禁用为false + `tx`: tstQuality, //gin.H{ // "测试结构 不代表最终方式" + // `enable`: false, + // `qualitys`: []string{`128k`, `320k`, `flac`, `flac24bit`}, + // }, + `kw`: []string{`128k`, `320k`, `flac`}, //true, }, // 自定义源脚本更新 `script`: env.Config.Script, @@ -142,7 +149,7 @@ func linkHandler(c *gin.Context) { return &resp.Resp{Code: 2, Msg: emsg} } // 缓存并获取直链 - if outlink != `` && cstat && cquery.Source != `kg` { + if outlink != `` && cstat && !ztool.Chk_IsMatch(cquery.Source, `kg`, `tx`) { sc.Debug(`Method: Set, Link: %v`, outlink) if link := caches.UseCache.Set(cquery, outlink); link != `` { env.Cache.Set(cquery.Query(), link, 3600) diff --git a/src/sources/builtin/driver.go b/src/sources/builtin/driver.go index 4bf8d7b..d0e9927 100644 --- a/src/sources/builtin/driver.go +++ b/src/sources/builtin/driver.go @@ -28,9 +28,13 @@ var ( mg_pool = &sync.Pool{New: func() any { return new(MgApi_Song) }} kw_pool = &sync.Pool{New: func() any { return new(KwApi_Song) }} kg_pool = &sync.Pool{New: func() any { return new(KgApi_Song) }} + tx_pool = &sync.Pool{New: func() any { return new(res_tx) }} ) -const errHttpReq = `无法连接解析接口` +const ( + errHttpReq = `无法连接解析接口` + errNoLink = `无法获取试听链接` +) // 查询 func (s *Source) GetLink(c *caches.Query) (outlink string, msg string) { @@ -129,7 +133,7 @@ func (s *Source) GetLink(c *caches.Query) (outlink string, msg string) { return `` }() url := ztool.Str_FastConcat(api_kg, `&hash=`, sep[0], `&album_id=`, alb, `&_=`, strconv.FormatInt(time.Now().UnixMilli(), 10)) - jx.Debug(`Kg, Url: %s`, url) + // jx.Debug(`Kg, Url: %s`, url) _, err := ztool.Net_HttpReq(http.MethodGet, url, nil, nil, &resp) if err != nil { jx.Error(`Kg, HttpReq: %s`, err) @@ -147,14 +151,39 @@ func (s *Source) GetLink(c *caches.Query) (outlink string, msg string) { msg = err.Error() return } - if data.PlayURL == `` { - if data.PlayBackupURL == `` { - msg = `无法获取试听链接` + if data.PlayBackupURL == `` { + if data.PlayURL == `` { + msg = errNoLink return } - outlink = data.PlayBackupURL + outlink = data.PlayURL } - outlink = data.PlayURL + outlink = data.PlayBackupURL + case s_tx: + resp := tx_pool.Get().(*res_tx) + defer tx_pool.Put(resp) + + url := ztool.Str_FastConcat(api_tx, + `{"comm":{"ct":24,"cv":0,"format":"json","uin":"10086"},"req":{"method":"GetCdnDispatch","module":"CDN.SrfCdnDispatchServer","param":{"calltype":0,"guid":"1535153710","userip":""}},"req_0":{"method":"CgiGetVkey","module":"vkey.GetVkeyServer","param":{"guid":"1535153710","loginflag":1,"platform":"20","songmid":["`, + c.MusicID, `"],"songtype":[0],"uin":"10086"}}}`, + ) + // jx.Debug(`Tx, Url: %s`, url) + out, err := ztool.Net_HttpReq(http.MethodGet, url, nil, header_tx, &resp) + if err != nil { + jx.Error(`Tx, HttpReq: %s`, err) + msg = errHttpReq + return + } + jx.Debug(`Tx, Resp: %s`, out) + if resp.Code != 0 { + msg = ztool.Str_FastConcat(`Error: `, strconv.Itoa(resp.Code)) + return + } + if resp.Req0.Data.Midurlinfo[0].Purl == `` { + msg = errNoLink + return + } + outlink = ztool.Str_FastConcat(`https://dl.stream.qqmusic.qq.com/`, resp.Req0.Data.Midurlinfo[0].Purl) default: msg = `不支持的平台` return diff --git a/src/sources/builtin/types.go b/src/sources/builtin/types.go index f6ca457..a3d2e31 100644 --- a/src/sources/builtin/types.go +++ b/src/sources/builtin/types.go @@ -123,6 +123,85 @@ type ( // EncodeAlbumAudioID string `json:"encode_album_audio_id"` // EVideoID string `json:"e_video_id"` } + // 腾讯试听接口 + res_tx struct { + Code int `json:"code"` + // Ts int64 `json:"ts"` + // StartTs int64 `json:"start_ts"` + // Traceid string `json:"traceid"` + // Req struct { + // Code int `json:"code"` + // Data struct { + // Expiration int `json:"expiration"` + // Freeflowsip []string `json:"freeflowsip"` + // Keepalivefile string `json:"keepalivefile"` + // Msg string `json:"msg"` + // Retcode int `json:"retcode"` + // Servercheck string `json:"servercheck"` + // Sip []string `json:"sip"` + // Testfile2G string `json:"testfile2g"` + // Testfilewifi string `json:"testfilewifi"` + // Uin string `json:"uin"` + // Userip string `json:"userip"` + // Vkey string `json:"vkey"` + // } `json:"data"` + // } `json:"req"` + Req0 struct { + Code int `json:"code"` + Data struct { + // Uin string `json:"uin"` + // Retcode int `json:"retcode"` + // VerifyType int `json:"verify_type"` + // LoginKey string `json:"login_key"` + // Msg string `json:"msg"` + // Sip []string `json:"sip"` + // Thirdip []string `json:"thirdip"` + // Testfile2G string `json:"testfile2g"` + // Testfilewifi string `json:"testfilewifi"` + Midurlinfo []struct { + // Songmid string `json:"songmid"` + // Filename string `json:"filename"` + Purl string `json:"purl"` + // Errtype string `json:"errtype"` + // P2Pfromtag int `json:"p2pfromtag"` + // Qmdlfromtag int `json:"qmdlfromtag"` + // CommonDownfromtag int `json:"common_downfromtag"` + // VipDownfromtag int `json:"vip_downfromtag"` + // Pdl int `json:"pdl"` + // Premain int `json:"premain"` + // Hisdown int `json:"hisdown"` + // Hisbuy int `json:"hisbuy"` + // UIAlert int `json:"uiAlert"` + // Isbuy int `json:"isbuy"` + // Pneedbuy int `json:"pneedbuy"` + // Pneed int `json:"pneed"` + // Isonly int `json:"isonly"` + // Onecan int `json:"onecan"` + // Result int `json:"result"` + // Tips string `json:"tips"` + // Opi48Kurl string `json:"opi48kurl"` + // Opi96Kurl string `json:"opi96kurl"` + // Opi192Kurl string `json:"opi192kurl"` + // Opiflackurl string `json:"opiflackurl"` + // Opi128Kurl string `json:"opi128kurl"` + // Opi192Koggurl string `json:"opi192koggurl"` + // Wififromtag string `json:"wififromtag"` + // Flowfromtag string `json:"flowfromtag"` + // Wifiurl string `json:"wifiurl"` + // Flowurl string `json:"flowurl"` + // Vkey string `json:"vkey"` + // Opi30Surl string `json:"opi30surl"` + // Ekey string `json:"ekey"` + // AuthSwitch int `json:"auth_switch"` + // Subcode int `json:"subcode"` + // Opi96Koggurl string `json:"opi96koggurl"` + // AuthSwitch2 int `json:"auth_switch2"` + } `json:"midurlinfo"` + // Servercheck string `json:"servercheck"` + // Expiration int `json:"expiration"` + } `json:"data"` + } `json:"req_0"` + } ) const ( @@ -131,7 +210,7 @@ const ( s_mg = `mg` s_kw = `kw` s_kg = `kg` - // s_tx = `tx` + s_tx = `tx` // s_lx = `lx` ) @@ -142,7 +221,8 @@ var ( s_wy: `standard`, s_mg: `1`, s_kw: `128k`, - s_kg: `128k`, + s_kg: ``, + s_tx: ``, }, `320k`: { s_wy: `exhigh`, @@ -168,10 +248,12 @@ var ( 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=` // Headers 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() { diff --git a/update.md b/update.md index ac848e8..59122c1 100644 --- a/update.md +++ b/update.md @@ -1,5 +1,16 @@ ## Lx-Source/更新日志 +### 2023-12-24 v1.0.2-b0.6 (beta) +#### 功能: + ++ 添加tx试听源(同样不计入缓存) ++ [不兼容] 支持使用服务端返回音质列表 +#### 注: ++ **请再次更新客户端脚本!** ++ 支持从服务端获取内置脚本: http://127.0.0.1:1011/lx-custom-source.js +#### 已知问题: ++ kg试听源返回1分钟试听文件会错误识别成完整版,导致播放器卡死 + #### **2023-12-23 v1.0.2-b0.5 (beta)**