lx-source/src/router/router.go
2023-12-25 03:13:06 +08:00

164 lines
5.5 KiB
Go

package router
import (
"lx-source/src/caches"
"lx-source/src/env"
"lx-source/src/middleware/auth"
"lx-source/src/middleware/dynlink"
"lx-source/src/middleware/loadpublic"
"lx-source/src/middleware/resp"
"lx-source/src/middleware/util"
"lx-source/src/sources"
"net/http"
"github.com/ZxwyWebSite/ztool"
"github.com/gin-contrib/gzip"
"github.com/gin-gonic/gin"
)
var (
// 默认音质
defQuality = []string{`128k`, `320k`, `flac`, `flac24bit`}
// 试听音质
tstQuality = []string{`128k`}
)
// 载入路由
func InitRouter() *gin.Engine {
r := gin.Default()
// Gzip压缩
if env.Config.Main.Gzip {
r.Use(gzip.Gzip(gzip.DefaultCompression, gzip.WithExcludedPaths([]string{"/file/"})))
}
// 源信息
r.GET(`/`, func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
`version`: env.Version, // 服务端程序版本
`name`: `lx-music-source`, // 名称
`msg`: `Hello~::^-^::~v1~`, // Api大版本
`developer`: []string{`Zxwy`}, // 开发者列表, 可在保留原作者的基础上添加你自己的名字?
// 仓库地址
`github`: `https://github.com/ZxwyWebSite/lx-source`,
// 可用平台
`source`: gin.H{
`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,
})
})
// 静态文件
loadpublic.LoadPublic(r)
// 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)...)
dynlink.LoadHandler(r)
// r.GET(`/file/:t/:x/:f`, dynlink.FileHandler())
// if cache, ok := caches.UseCache.(*localcache.Cache); ok {
// r.Static(`/file`, cache.Path)
// }
// if env.Config.Cache.Mode == `local` {
// r.Static(`/file`, env.Config.Cache.Local_Path)
// }
// 数据接口
// r.GET(`/file/:t/:hq/:n`, func(c *gin.Context) {
// c.String(http.StatusOK, time.Now().Format(`20060102150405`))
// })
// 暂不对文件接口进行验证 脚本返回链接无法附加请求头 只可在Get添加Query
// g := r.Group(``)
// {
// g.Use(authHandler)
// g.GET(`/link/:s/:id/:q`, linkHandler)
// g.Static(`/file`, LocalCachePath)
// }
return r
}
// 数据返回格式
const (
cacheHIT = `Cache HIT` // 缓存已命中
cacheMISS = `Cache MISS` // 缓存未命中
cacheSet = `Cache Seted` // 缓存已设置
memHIT = `Memory HIT` // 内存已命中
memRej = `Memory Reject` // 内存已拒绝
)
// 外链解析
func linkHandler(c *gin.Context) {
resp.Wrap(c, func() *resp.Resp {
// 获取传入参数 检查合法性
parms := util.ParaMap(c)
// getParam := func(p string) string { return strings.TrimSuffix(strings.TrimPrefix(c.Param(p), `/`), `/`) } //strings.Trim(c.Param(p), `/`)
s := parms[`s`] //c.Param(`s`) //getParam(`s`) // source 平台 wy, mg, kw
id := parms[`id`] //c.Param(`id`) //getParam(`id`) // sid 音乐ID wy: songmid, mg: copyrightId
q := parms[`q`] //c.Param(`q`) //getParam(`q`) // quality 音质 128k / 320k / flac / flac24bit
env.Loger.NewGroup(`LinkQuery`).Debug(`s: %v, id: %v, q: %v`, s, id, q)
if ztool.Chk_IsNilStr(s, q, id) {
return &resp.Resp{Code: 6, Msg: `参数不全`} // http.StatusBadRequest
}
cquery := caches.NewQuery(s, id, q)
// fmt.Printf("%+v\n", cquery)
defer cquery.Free()
// _, ok := sources.UseSource.Verify(cquery) // 获取请求音质 同时检测是否支持(如kw源没有flac24bit) qualitys[q][s]rquery
// if !ok {
// return &resp.Resp{Code: 6, Msg: `不支持的平台或音质`}
// }
// 查询内存
clink, ok := env.Cache.Get(cquery.Query())
if ok {
if str, ok := clink.(string); ok {
env.Loger.NewGroup(`MemCache`).Debug(`MemHIT [%q]=>[%q]`, cquery.Query(), str)
if str == `` {
return &resp.Resp{Code: 2, Msg: memRej} // 拒绝请求,当前一段时间内解析出错 `MemCache Reject`
}
return &resp.Resp{Msg: memHIT, Data: str} // `MemCache HIT`
}
}
// 查询缓存
var cstat bool
if caches.UseCache != nil {
cstat = caches.UseCache.Stat()
}
sc := env.Loger.NewGroup(`StatCache`)
if cstat {
sc.Debug(`Method: Get, Query: %v`, cquery.Query())
if link := caches.UseCache.Get(cquery); link != `` {
env.Cache.Set(cquery.Query(), link, 3600)
return &resp.Resp{Msg: cacheHIT, Data: link}
}
} else {
sc.Debug(`Disabled`)
}
// 解析歌曲外链
outlink, emsg := sources.UseSource.GetLink(cquery)
if emsg != `` {
if emsg == sources.Err_Verify { // Verify Failed: 不支持的平台或音质
return &resp.Resp{Code: 6, Msg: ztool.Str_FastConcat(emsg, `: 不支持的平台或音质`)}
}
env.Cache.Set(cquery.Query(), ``, 600) // 发生错误的10分钟内禁止再次查询
return &resp.Resp{Code: 2, Msg: emsg}
}
// 缓存并获取直链
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)
return &resp.Resp{Msg: cacheSet, Data: link}
}
}
// 无法获取直链 直接返回原链接
env.Cache.Set(cquery.Query(), outlink, 1200)
return &resp.Resp{Msg: cacheMISS, Data: outlink}
})
}