mirror of
https://github.com/ZxwyWebSite/lx-source.git
synced 2025-05-23 21:37:42 +08:00
2023-12-23 v1.0.2-b0.5
This commit is contained in:
parent
2535319005
commit
83cf0eee8f
1
main.go
1
main.go
@ -87,6 +87,7 @@ func init() {
|
|||||||
// logs.DefLogger(`LX-SOURCE`, logs.LevelDebu)
|
// logs.DefLogger(`LX-SOURCE`, logs.LevelDebu)
|
||||||
// logs.Main = `LX-SOURCE`
|
// logs.Main = `LX-SOURCE`
|
||||||
env.Cfg.MustInit(confPath) //conf.InitConfig(confPath)
|
env.Cfg.MustInit(confPath) //conf.InitConfig(confPath)
|
||||||
|
// fmt.Printf("%+v\n", env.Config)
|
||||||
env.Loger.NewGroup(`ServHello`).Info(`欢迎使用 LX-SOURCE 洛雪音乐自定义源`)
|
env.Loger.NewGroup(`ServHello`).Info(`欢迎使用 LX-SOURCE 洛雪音乐自定义源`)
|
||||||
if !env.Config.Main.Debug {
|
if !env.Config.Main.Debug {
|
||||||
gin.SetMode(gin.ReleaseMode)
|
gin.SetMode(gin.ReleaseMode)
|
||||||
|
26
src/env/env.go
vendored
26
src/env/env.go
vendored
@ -9,7 +9,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
Version = `1.0.2-β0.4`
|
Version = `1.0.2-b0.5`
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -79,19 +79,19 @@ type (
|
|||||||
Cloud_Path string `comment:"Cloudreve存储路径"`
|
Cloud_Path string `comment:"Cloudreve存储路径"`
|
||||||
}
|
}
|
||||||
Conf struct {
|
Conf struct {
|
||||||
Main *Conf_Main `comment:"程序主配置"`
|
Main Conf_Main `comment:"程序主配置"`
|
||||||
Apis *Conf_Apis `comment:"接口设置"`
|
Apis Conf_Apis `comment:"接口设置"`
|
||||||
Auth *Conf_Auth `comment:"访问控制"`
|
Auth Conf_Auth `comment:"访问控制"`
|
||||||
Source *Conf_Source `comment:"解析源配置"`
|
Source Conf_Source `comment:"解析源配置"`
|
||||||
Script *Conf_Script `comment:"自定义脚本更新"` // ini:",omitempty"
|
Script Conf_Script `comment:"自定义脚本更新"` // ini:",omitempty"
|
||||||
Cache *Conf_Cache `comment:"音乐缓存设置"`
|
Cache Conf_Cache `comment:"音乐缓存设置"`
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// 默认配置
|
// 默认配置
|
||||||
defCfg = Conf{
|
defCfg = Conf{
|
||||||
Main: &Conf_Main{
|
Main: Conf_Main{
|
||||||
Debug: false,
|
Debug: false,
|
||||||
Listen: `0.0.0.0:1011`,
|
Listen: `0.0.0.0:1011`,
|
||||||
Gzip: false,
|
Gzip: false,
|
||||||
@ -99,10 +99,10 @@ var (
|
|||||||
Print: true,
|
Print: true,
|
||||||
SysLev: false,
|
SysLev: false,
|
||||||
},
|
},
|
||||||
Apis: &Conf_Apis{
|
Apis: Conf_Apis{
|
||||||
// BindAddr: `http://192.168.10.22:1011/`,
|
// BindAddr: `http://192.168.10.22:1011/`,
|
||||||
},
|
},
|
||||||
Auth: &Conf_Auth{
|
Auth: Conf_Auth{
|
||||||
ApiKey_Enable: true,
|
ApiKey_Enable: true,
|
||||||
RateLimit_Enable: false,
|
RateLimit_Enable: false,
|
||||||
RateLimit_Global: 1,
|
RateLimit_Global: 1,
|
||||||
@ -110,21 +110,21 @@ var (
|
|||||||
BanList_Mode: `off`,
|
BanList_Mode: `off`,
|
||||||
BanList_White: []string{`127.0.0.1`},
|
BanList_White: []string{`127.0.0.1`},
|
||||||
},
|
},
|
||||||
Source: &Conf_Source{
|
Source: Conf_Source{
|
||||||
Mode: `builtin`,
|
Mode: `builtin`,
|
||||||
FakeIP_Mode: `0`,
|
FakeIP_Mode: `0`,
|
||||||
FakeIP_Value: `192.168.10.2`,
|
FakeIP_Value: `192.168.10.2`,
|
||||||
Proxy_Enable: false,
|
Proxy_Enable: false,
|
||||||
Proxy_Address: `{protocol}://({user}:{password})@{address}:{port}`,
|
Proxy_Address: `{protocol}://({user}:{password})@{address}:{port}`,
|
||||||
},
|
},
|
||||||
Script: &Conf_Script{
|
Script: Conf_Script{
|
||||||
Log: `发布更新 (请删除旧源后重新导入):进行了部分优化,修复了部分Bug`, // 更新日志
|
Log: `发布更新 (请删除旧源后重新导入):进行了部分优化,修复了部分Bug`, // 更新日志
|
||||||
|
|
||||||
Ver: `1.0.1`, // 自定义脚本版本
|
Ver: `1.0.1`, // 自定义脚本版本
|
||||||
Url: `lx-custom-source.js`, // 脚本下载地址
|
Url: `lx-custom-source.js`, // 脚本下载地址
|
||||||
Force: false, // 强制推送更新
|
Force: false, // 强制推送更新
|
||||||
},
|
},
|
||||||
Cache: &Conf_Cache{
|
Cache: Conf_Cache{
|
||||||
Mode: `local`, // 缓存模式
|
Mode: `local`, // 缓存模式
|
||||||
LinkMode: `1`,
|
LinkMode: `1`,
|
||||||
Local_Path: `data/cache`,
|
Local_Path: `data/cache`,
|
||||||
|
@ -4,11 +4,10 @@ import (
|
|||||||
"lx-source/src/caches"
|
"lx-source/src/caches"
|
||||||
"lx-source/src/caches/localcache"
|
"lx-source/src/caches/localcache"
|
||||||
"lx-source/src/env"
|
"lx-source/src/env"
|
||||||
|
"lx-source/src/middleware/util"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
// "lx-source/src/middleware/util"
|
"github.com/ZxwyWebSite/ztool"
|
||||||
// "net/http"
|
|
||||||
|
|
||||||
// "github.com/ZxwyWebSite/ztool"
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -17,14 +16,13 @@ type DynLink struct {
|
|||||||
Link string
|
Link string
|
||||||
}
|
}
|
||||||
|
|
||||||
func LoadHandler(r *gin.Engine) {
|
// var ExLink func(string) string = func(s string) string { return s }
|
||||||
loger := env.Loger.NewGroup(`DynLink`)
|
|
||||||
if cache, ok := caches.UseCache.(*localcache.Cache); ok {
|
// func localInit(c string) func(string) string {
|
||||||
loger.Debug(`UseStatic`)
|
// return func(l string) string {
|
||||||
r.Static(`/file`, cache.Path)
|
// return ztool.Str_FastConcat(c, `/`, l)
|
||||||
}
|
// }
|
||||||
// 动态链暂未完成...
|
// }
|
||||||
}
|
|
||||||
|
|
||||||
// Doc 动态链
|
// Doc 动态链
|
||||||
/*
|
/*
|
||||||
@ -38,6 +36,7 @@ func LoadHandler(r *gin.Engine) {
|
|||||||
+ Data2 直链缓存
|
+ Data2 直链缓存
|
||||||
- key: "20231221/1703176257/6c782f303030303030303030312f3332306b.mp3"
|
- key: "20231221/1703176257/6c782f303030303030303030312f3332306b.mp3"
|
||||||
- val: "&DynLink{Mode: 0, Link: 'cache/lx/0000000001/320k'}"
|
- val: "&DynLink{Mode: 0, Link: 'cache/lx/0000000001/320k'}"
|
||||||
|
+ 返回链接: "http://127.0.0.1/file/lx/0000000001/320k.mp3"
|
||||||
2. 查询缓存
|
2. 查询缓存
|
||||||
- key: "20231221/1703176257/6c782f303030303030303030312f3332306b.mp3"
|
- key: "20231221/1703176257/6c782f303030303030303030312f3332306b.mp3"
|
||||||
- val: "&DynLink{Mode: 0, Link: 'cache/lx/0000000001/320k'}"
|
- val: "&DynLink{Mode: 0, Link: 'cache/lx/0000000001/320k'}"
|
||||||
@ -52,6 +51,36 @@ func LoadHandler(r *gin.Engine) {
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
func LoadHandler(r *gin.Engine) {
|
||||||
|
loger := env.Loger.NewGroup(`DynLink`)
|
||||||
|
cache, cok := caches.UseCache.(*localcache.Cache)
|
||||||
|
// env.Cache.Set(`date/second/fname.mp3`, DynLink{Mode: 0, Link: `wy/3203127/320k.mp3`}, 0)
|
||||||
|
// env.Cache.Set(`date/second/lname.mp3`, DynLink{Mode: 1, Link: `https://r2eu.zxwy.link/gh/lx-source/static/error.mp3`}, 0)
|
||||||
|
// 动态链已完成(beta)...
|
||||||
|
if env.Config.Cache.LinkMode == `dynamic` || env.Config.Cache.LinkMode == `2` /*|| true*/ {
|
||||||
|
loger.Debug(`UseDynamic`)
|
||||||
|
r.GET(`/file/:t/:x/:f`, func(c *gin.Context) {
|
||||||
|
parms := util.ParaMap(c)
|
||||||
|
t, x, f := parms[`t`], parms[`x`], parms[`f`]
|
||||||
|
if clink, ok := env.Cache.Get(ztool.Str_FastConcat(t, `/`, x, `/`, f)); ok {
|
||||||
|
if dyn, ok := clink.(DynLink); ok {
|
||||||
|
if dyn.Mode == 0 && cok {
|
||||||
|
c.File(ztool.Str_FastConcat(cache.Path, `/`, dyn.Link))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.Redirect(http.StatusFound, dyn.Link)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c.AbortWithStatus(http.StatusNotFound)
|
||||||
|
})
|
||||||
|
} else if cok {
|
||||||
|
loger.Debug(`UseStatic`)
|
||||||
|
// ExLink = localInit(cache.Path)
|
||||||
|
r.Static(`/file`, cache.Path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// func FileHandler() gin.HandlerFunc {
|
// func FileHandler() gin.HandlerFunc {
|
||||||
// loger := env.Loger.NewGroup(`DynLink`)
|
// loger := env.Loger.NewGroup(`DynLink`)
|
||||||
// // 为了兼容原静态链,必须设置3个参数
|
// // 为了兼容原静态链,必须设置3个参数
|
||||||
|
@ -47,7 +47,9 @@ const httpRequest = (url, options) => new Promise((resolve, reject) => {
|
|||||||
const musicUrl = async (source, info, quality) => {
|
const musicUrl = async (source, info, quality) => {
|
||||||
const start = new Date().getTime();
|
const start = new Date().getTime();
|
||||||
const id = info.hash ?? info.copyrightId ?? info.songmid // 音乐id kg源为hash, mg源为copyrightId
|
const id = info.hash ?? info.copyrightId ?? info.songmid // 音乐id kg源为hash, mg源为copyrightId
|
||||||
const query = `${source}/${id}/${quality}`; console.log('创建任务: %s, 音乐信息: %O', query, info)
|
const album = source == 'kg' && info.albumId != void 0 ? '-' + info.albumId : ''
|
||||||
|
const query = `${source}/${id}${album}/${quality}`
|
||||||
|
console.log('创建任务: %s, 音乐信息: %O', query, info)
|
||||||
const body = await httpRequest(`${apiaddr}link/${query}`, { method: 'get' });
|
const body = await httpRequest(`${apiaddr}link/${query}`, { method: 'get' });
|
||||||
console.log('返回数据: %O', body, `, 耗时 ${new Date().getTime() - start} ms`)
|
console.log('返回数据: %O', body, `, 耗时 ${new Date().getTime() - start} ms`)
|
||||||
return body.data != '' ? body.data : Promise.reject(body.msg) // 没有获取到链接则将msg作为错误抛出
|
return body.data != '' ? body.data : Promise.reject(body.msg) // 没有获取到链接则将msg作为错误抛出
|
||||||
@ -106,6 +108,8 @@ const init = () => {
|
|||||||
// ...defs, qualitys: source[v].qualitys, // 支持返回音质时启用 使用后端音质表
|
// ...defs, qualitys: source[v].qualitys, // 支持返回音质时启用 使用后端音质表
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
sourcess['kg'] = { name: '酷狗试听', ...defaults }
|
||||||
|
sourcess['kg'].qualitys = ['128k']
|
||||||
})
|
})
|
||||||
// 完成初始化
|
// 完成初始化
|
||||||
stat = true
|
stat = true
|
||||||
|
@ -36,6 +36,8 @@ var statusMap = map[int]int{
|
|||||||
6: http.StatusBadRequest, // 参数错误
|
6: http.StatusBadRequest, // 参数错误
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var ErrMp3 = `https://r2eu.zw-cdn.tk/gh/lx-source/static/error.mp3`
|
||||||
|
|
||||||
// 返回请求
|
// 返回请求
|
||||||
/*
|
/*
|
||||||
注:Code不为0时调用c.Abort()终止Handler
|
注:Code不为0时调用c.Abort()终止Handler
|
||||||
@ -47,7 +49,7 @@ func (o *Resp) Execute(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
if o.Code != 0 {
|
if o.Code != 0 {
|
||||||
if o.Code == 2 /*&& o.Data == ``*/ {
|
if o.Code == 2 /*&& o.Data == ``*/ {
|
||||||
o.Data = `https://r2eu.zw-cdn.tk/gh/lx-source/static/error.mp3`
|
o.Data = ErrMp3
|
||||||
}
|
}
|
||||||
c.Abort()
|
c.Abort()
|
||||||
}
|
}
|
||||||
|
@ -77,9 +77,12 @@ func InitRouter() *gin.Engine {
|
|||||||
|
|
||||||
// 数据返回格式
|
// 数据返回格式
|
||||||
const (
|
const (
|
||||||
CacheHIT = `Cache HIT` // 缓存已命中
|
cacheHIT = `Cache HIT` // 缓存已命中
|
||||||
CacheMISS = `Cache MISS` // 缓存未命中
|
cacheMISS = `Cache MISS` // 缓存未命中
|
||||||
CacheSet = `Cache Seted` // 缓存已设置
|
cacheSet = `Cache Seted` // 缓存已设置
|
||||||
|
|
||||||
|
memHIT = `Memory HIT` // 内存已命中
|
||||||
|
memRej = `Memory Reject` // 内存已拒绝
|
||||||
)
|
)
|
||||||
|
|
||||||
// 外链解析
|
// 外链解析
|
||||||
@ -109,9 +112,9 @@ func linkHandler(c *gin.Context) {
|
|||||||
if str, ok := clink.(string); ok {
|
if str, ok := clink.(string); ok {
|
||||||
env.Loger.NewGroup(`MemCache`).Debug(`MemHIT [%q]=>[%q]`, cquery.Query(), str)
|
env.Loger.NewGroup(`MemCache`).Debug(`MemHIT [%q]=>[%q]`, cquery.Query(), str)
|
||||||
if str == `` {
|
if str == `` {
|
||||||
return &resp.Resp{Code: 2, Msg: `MemCache Reject`} // 拒绝请求,当前一段时间内解析出错
|
return &resp.Resp{Code: 2, Msg: memRej} // 拒绝请求,当前一段时间内解析出错 `MemCache Reject`
|
||||||
}
|
}
|
||||||
return &resp.Resp{Msg: `MemCache HIT`, Data: str}
|
return &resp.Resp{Msg: memHIT, Data: str} // `MemCache HIT`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 查询缓存
|
// 查询缓存
|
||||||
@ -124,7 +127,7 @@ func linkHandler(c *gin.Context) {
|
|||||||
sc.Debug(`Method: Get, Query: %v`, cquery.Query())
|
sc.Debug(`Method: Get, Query: %v`, cquery.Query())
|
||||||
if link := caches.UseCache.Get(cquery); link != `` {
|
if link := caches.UseCache.Get(cquery); link != `` {
|
||||||
env.Cache.Set(cquery.Query(), link, 3600)
|
env.Cache.Set(cquery.Query(), link, 3600)
|
||||||
return &resp.Resp{Msg: CacheHIT, Data: link}
|
return &resp.Resp{Msg: cacheHIT, Data: link}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sc.Debug(`Disabled`)
|
sc.Debug(`Disabled`)
|
||||||
@ -139,15 +142,15 @@ func linkHandler(c *gin.Context) {
|
|||||||
return &resp.Resp{Code: 2, Msg: emsg}
|
return &resp.Resp{Code: 2, Msg: emsg}
|
||||||
}
|
}
|
||||||
// 缓存并获取直链
|
// 缓存并获取直链
|
||||||
if outlink != `` && cstat {
|
if outlink != `` && cstat && cquery.Source != `kg` {
|
||||||
sc.Debug(`Method: Set, Link: %v`, outlink)
|
sc.Debug(`Method: Set, Link: %v`, outlink)
|
||||||
if link := caches.UseCache.Set(cquery, outlink); link != `` {
|
if link := caches.UseCache.Set(cquery, outlink); link != `` {
|
||||||
env.Cache.Set(cquery.Query(), link, 3600)
|
env.Cache.Set(cquery.Query(), link, 3600)
|
||||||
return &resp.Resp{Msg: CacheSet, Data: link}
|
return &resp.Resp{Msg: cacheSet, Data: link}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 无法获取直链 直接返回原链接
|
// 无法获取直链 直接返回原链接
|
||||||
env.Cache.Set(cquery.Query(), outlink, 1200)
|
env.Cache.Set(cquery.Query(), outlink, 1200)
|
||||||
return &resp.Resp{Msg: CacheMISS, Data: outlink}
|
return &resp.Resp{Msg: cacheMISS, Data: outlink}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"lx-source/src/env"
|
"lx-source/src/env"
|
||||||
"lx-source/src/sources"
|
"lx-source/src/sources"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@ -26,8 +27,11 @@ var (
|
|||||||
wy_pool = &sync.Pool{New: func() any { return new(FyApi_Song) }}
|
wy_pool = &sync.Pool{New: func() any { return new(FyApi_Song) }}
|
||||||
mg_pool = &sync.Pool{New: func() any { return new(MgApi_Song) }}
|
mg_pool = &sync.Pool{New: func() any { return new(MgApi_Song) }}
|
||||||
kw_pool = &sync.Pool{New: func() any { return new(KwApi_Song) }}
|
kw_pool = &sync.Pool{New: func() any { return new(KwApi_Song) }}
|
||||||
|
kg_pool = &sync.Pool{New: func() any { return new(KgApi_Song) }}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const errHttpReq = `无法连接解析接口`
|
||||||
|
|
||||||
// 查询
|
// 查询
|
||||||
func (s *Source) GetLink(c *caches.Query) (outlink string, msg string) {
|
func (s *Source) GetLink(c *caches.Query) (outlink string, msg string) {
|
||||||
rquery, ok := s.Verify(c)
|
rquery, ok := s.Verify(c)
|
||||||
@ -50,7 +54,8 @@ func (s *Source) GetLink(c *caches.Query) (outlink string, msg string) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
jx.Error(`HttpReq, Err: %s, ReTry: %v`, err, i)
|
jx.Error(`HttpReq, Err: %s, ReTry: %v`, err, i)
|
||||||
if i > 3 {
|
if i > 3 {
|
||||||
msg = err.Error()
|
jx.Error(`Wy, HttpReq: %s`, err)
|
||||||
|
msg = errHttpReq //err.Error()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
time.Sleep(time.Second)
|
time.Sleep(time.Second)
|
||||||
@ -64,13 +69,13 @@ func (s *Source) GetLink(c *caches.Query) (outlink string, msg string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
var data = resp.Data[0]
|
var data = resp.Data[0]
|
||||||
if data.FreeTrialInfo != nil {
|
if data.Code != 200 || data.FreeTrialInfo != nil {
|
||||||
// jx.Error("发生错误, 返回数据:\n%#v", resp)
|
// jx.Error("发生错误, 返回数据:\n%#v", resp)
|
||||||
msg = `触发风控或专辑单独收费`
|
msg = `触发风控或专辑单独收费`
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if data.Level != rquery {
|
if data.Level != rquery {
|
||||||
msg = `实际音质不匹配`
|
msg = ztool.Str_FastConcat(`实际音质不匹配: `, rquery, ` <= `, data.Level) // 实际音质不匹配: exhigh <= standard
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// jx.Info(`WyLink, RealQuality: %v`, data.Level)
|
// jx.Info(`WyLink, RealQuality: %v`, data.Level)
|
||||||
@ -83,7 +88,8 @@ func (s *Source) GetLink(c *caches.Query) (outlink string, msg string) {
|
|||||||
// jx.Debug(`Mg, Url: %v`, url)
|
// 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, header_mg, &resp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
msg = err.Error()
|
jx.Error(`Mg, HttpReq: %s`, err)
|
||||||
|
msg = errHttpReq //err.Error()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
jx.Debug(`Mg, Resp: %+v`, resp)
|
jx.Debug(`Mg, Resp: %+v`, resp)
|
||||||
@ -100,7 +106,8 @@ func (s *Source) GetLink(c *caches.Query) (outlink string, msg string) {
|
|||||||
// jx.Debug(`Kw, Url: %s`, url)
|
// jx.Debug(`Kw, Url: %s`, url)
|
||||||
_, err := ztool.Net_HttpReq(http.MethodGet, url, nil, header_kw, &resp)
|
_, err := ztool.Net_HttpReq(http.MethodGet, url, nil, header_kw, &resp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
msg = err.Error()
|
jx.Error(`Kw, HttpReq: %s`, err)
|
||||||
|
msg = errHttpReq //err.Error()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
jx.Debug(`Kw, Resp: %+v`, resp)
|
jx.Debug(`Kw, Resp: %+v`, resp)
|
||||||
@ -110,6 +117,44 @@ func (s *Source) GetLink(c *caches.Query) (outlink string, msg string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
outlink = strings.Split(resp.Data.URL, `?`)[0]
|
outlink = strings.Split(resp.Data.URL, `?`)[0]
|
||||||
|
case s_kg:
|
||||||
|
resp := kg_pool.Get().(*KgApi_Song)
|
||||||
|
defer kg_pool.Put(resp)
|
||||||
|
|
||||||
|
sep := strings.Split(c.MusicID, `-`) // 分割 Hash-Album 如 6DC276334F56E22BE2A0E8254D332B45-13097991
|
||||||
|
alb := func() string {
|
||||||
|
if len(sep) >= 2 {
|
||||||
|
return sep[1]
|
||||||
|
}
|
||||||
|
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)
|
||||||
|
_, err := ztool.Net_HttpReq(http.MethodGet, url, nil, nil, &resp)
|
||||||
|
if err != nil {
|
||||||
|
jx.Error(`Kg, HttpReq: %s`, err)
|
||||||
|
msg = errHttpReq //err.Error()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
jx.Debug(`Kw, Resp: %+v`, resp)
|
||||||
|
if resp.ErrCode != 0 {
|
||||||
|
msg = ztool.Str_FastConcat(`Error: `, strconv.Itoa(resp.ErrCode))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var data KgApi_Data
|
||||||
|
err = ztool.Val_MapToStruct(resp.Data, &data)
|
||||||
|
if err != nil {
|
||||||
|
msg = err.Error()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if data.PlayURL == `` {
|
||||||
|
if data.PlayBackupURL == `` {
|
||||||
|
msg = `无法获取试听链接`
|
||||||
|
return
|
||||||
|
}
|
||||||
|
outlink = data.PlayBackupURL
|
||||||
|
}
|
||||||
|
outlink = data.PlayURL
|
||||||
default:
|
default:
|
||||||
msg = `不支持的平台`
|
msg = `不支持的平台`
|
||||||
return
|
return
|
||||||
|
@ -76,6 +76,53 @@ type (
|
|||||||
ProfileID string `json:"profileId"`
|
ProfileID string `json:"profileId"`
|
||||||
CurTime int64 `json:"curTime"`
|
CurTime int64 `json:"curTime"`
|
||||||
}
|
}
|
||||||
|
// 酷狗试听接口
|
||||||
|
KgApi_Song struct {
|
||||||
|
Status int `json:"status"`
|
||||||
|
ErrCode int `json:"err_code"`
|
||||||
|
Data any `json:"data"`
|
||||||
|
}
|
||||||
|
KgApi_Data struct {
|
||||||
|
// Hash string `json:"hash"`
|
||||||
|
// Timelength int `json:"timelength"`
|
||||||
|
// Filesize int `json:"filesize"`
|
||||||
|
// AudioName string `json:"audio_name"`
|
||||||
|
// HaveAlbum int `json:"have_album"`
|
||||||
|
// AlbumName string `json:"album_name"`
|
||||||
|
// AlbumID any `json:"album_id"`
|
||||||
|
// Img string `json:"img"`
|
||||||
|
// HaveMv int `json:"have_mv"`
|
||||||
|
// VideoID any `json:"video_id"`
|
||||||
|
// AuthorName string `json:"author_name"`
|
||||||
|
// SongName string `json:"song_name"`
|
||||||
|
// Lyrics string `json:"lyrics"`
|
||||||
|
// AuthorID any `json:"author_id"`
|
||||||
|
// Privilege int `json:"privilege"`
|
||||||
|
// Privilege2 string `json:"privilege2"`
|
||||||
|
PlayURL string `json:"play_url"`
|
||||||
|
// Authors []struct {
|
||||||
|
// AuthorID any `json:"author_id"`
|
||||||
|
// AuthorName string `json:"author_name"`
|
||||||
|
// IsPublish string `json:"is_publish"`
|
||||||
|
// SizableAvatar string `json:"sizable_avatar"`
|
||||||
|
// EAuthorID string `json:"e_author_id"`
|
||||||
|
// Avatar string `json:"avatar"`
|
||||||
|
// } `json:"authors"`
|
||||||
|
// IsFreePart int `json:"is_free_part"`
|
||||||
|
// Bitrate int `json:"bitrate"`
|
||||||
|
// RecommendAlbumID string `json:"recommend_album_id"`
|
||||||
|
// StoreType string `json:"store_type"`
|
||||||
|
// AlbumAudioID int `json:"album_audio_id"`
|
||||||
|
// IsPublish int `json:"is_publish"`
|
||||||
|
// EAuthorID string `json:"e_author_id"`
|
||||||
|
// AudioID any `json:"audio_id"`
|
||||||
|
// HasPrivilege bool `json:"has_privilege"`
|
||||||
|
PlayBackupURL string `json:"play_backup_url"`
|
||||||
|
// SmallLibrarySong int `json:"small_library_song"`
|
||||||
|
// EncodeAlbumID string `json:"encode_album_id"`
|
||||||
|
// EncodeAlbumAudioID string `json:"encode_album_audio_id"`
|
||||||
|
// EVideoID string `json:"e_video_id"`
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -83,7 +130,7 @@ const (
|
|||||||
s_wy = `wy`
|
s_wy = `wy`
|
||||||
s_mg = `mg`
|
s_mg = `mg`
|
||||||
s_kw = `kw`
|
s_kw = `kw`
|
||||||
// s_kg = `kg`
|
s_kg = `kg`
|
||||||
// s_tx = `tx`
|
// s_tx = `tx`
|
||||||
// s_lx = `lx`
|
// s_lx = `lx`
|
||||||
)
|
)
|
||||||
@ -95,6 +142,7 @@ var (
|
|||||||
s_wy: `standard`,
|
s_wy: `standard`,
|
||||||
s_mg: `1`,
|
s_mg: `1`,
|
||||||
s_kw: `128k`,
|
s_kw: `128k`,
|
||||||
|
s_kg: `128k`,
|
||||||
},
|
},
|
||||||
`320k`: {
|
`320k`: {
|
||||||
s_wy: `exhigh`,
|
s_wy: `exhigh`,
|
||||||
@ -119,6 +167,7 @@ var (
|
|||||||
api_wy string
|
api_wy string
|
||||||
api_mg string
|
api_mg string
|
||||||
api_kw string
|
api_kw string
|
||||||
|
api_kg string = `https://wwwapi.kugou.com/yy/index.php?r=play/getdata&platid=4&mid=1`
|
||||||
// Headers
|
// Headers
|
||||||
header_wy map[string]string
|
header_wy map[string]string
|
||||||
header_mg map[string]string
|
header_mg map[string]string
|
||||||
|
15
update.md
15
update.md
@ -1,5 +1,20 @@
|
|||||||
## Lx-Source/更新日志
|
## Lx-Source/更新日志
|
||||||
|
|
||||||
|
#### **2023-12-23 v1.0.2-b0.5 (beta)**
|
||||||
|
<!-- + zTool:
|
||||||
|
- 修复直接传入make([]byte, n)时潜在内存泄露问题 -->
|
||||||
|
### update:
|
||||||
|
- 请求解析接口时遇到的错误输出到log,不返回msg
|
||||||
|
<!-- - 服务端返回音质列表(需更新脚本) -->
|
||||||
|
### feature:
|
||||||
|
- 添加kg试听源(不计入缓存) **\*(需更新脚本)**
|
||||||
|
- 注:部分歌曲只能试听前1分钟内容,无法试听的无法播放
|
||||||
|
- (请手动删除 `data/public` 目录后启动程序重新释放静态资源)
|
||||||
|
- 脚本还是 `data/public/lx-coustom-source.js`,开了Key验证的记得将原apipass复制过去
|
||||||
|
### bugfix:
|
||||||
|
- 修复wy源返回错误判断逻辑
|
||||||
|
<!-- + [msg] 当前api结构与动态链实现方式不兼容,需要大改,故推迟更新 -->
|
||||||
|
|
||||||
#### 2023-12-22 v1.0.2-b0.4 (beta)
|
#### 2023-12-22 v1.0.2-b0.4 (beta)
|
||||||
<!-- + 没有功能更新,几个未来的想法
|
<!-- + 没有功能更新,几个未来的想法
|
||||||
- 利用缓存信息制作数据库,可通过api搜索音乐
|
- 利用缓存信息制作数据库,可通过api搜索音乐
|
||||||
|
Loading…
x
Reference in New Issue
Block a user