mirror of
https://github.com/ZxwyWebSite/lx-source.git
synced 2025-05-23 21:37:42 +08:00
2023-12-18
This commit is contained in:
parent
ba8c0faf0e
commit
8e9359e6df
@ -14,6 +14,7 @@
|
||||
+ 使用Golang编写,运行效率较高
|
||||
+ 测试阶段,不代表最终品质
|
||||
+ 验证部分暂未完善,建议仅本地使用,不要公开发布
|
||||
+ 视频教程:[使用教程.mp4](https://r2eu.zxwy.link/gh/lx-source/v1.0.2-b0.1/%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B.mp4)
|
||||
<!-- + **锟斤拷** -->
|
||||
|
||||
### 使用
|
||||
@ -74,12 +75,7 @@
|
||||
+ 部分功能参考 [Python版](https://github.com/lxmusics/lx-music-api-server-python) 实现
|
||||
|
||||
### 更新
|
||||
#### ~2023-12-16
|
||||
+ 参考Python版移植部分功能
|
||||
+ 完善、优化逻辑
|
||||
+ 发布源码
|
||||
#### 2023-10-21
|
||||
+ 立项制作
|
||||
+ 见 `update.md`
|
||||
|
||||
### 项目协议
|
||||
|
||||
|
@ -3,7 +3,6 @@ package localcache
|
||||
import (
|
||||
"errors"
|
||||
"lx-source/src/caches"
|
||||
"lx-source/src/env"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
@ -24,13 +23,13 @@ func (c *Cache) getLink(q string) string {
|
||||
}
|
||||
|
||||
func (c *Cache) Get(q *caches.Query) string {
|
||||
// 加一层缓存,减少重复检测文件造成的性能损耗
|
||||
if _, ok := env.Cache.Get(q.Query()); !ok {
|
||||
if _, e := os.Stat(ztool.Str_FastConcat(c.Path, `/`, q.Query())); e != nil {
|
||||
return ``
|
||||
}
|
||||
env.Cache.Set(q.Query(), struct{}{}, 3600)
|
||||
// 加一层缓存,减少重复检测文件造成的性能损耗 (缓存已移至Router)
|
||||
// if _, ok := env.Cache.Get(q.Query()); !ok {
|
||||
if _, e := os.Stat(ztool.Str_FastConcat(c.Path, `/`, q.Query())); e != nil {
|
||||
return ``
|
||||
}
|
||||
// env.Cache.Set(q.Query(), struct{}{}, 3600)
|
||||
// }
|
||||
return c.getLink(q.Query())
|
||||
// fpath := filepath.Join(c.Path, q.Source, q.MusicID, q.Quality)
|
||||
// if _, e := os.Stat(fpath); e != nil {
|
||||
@ -45,7 +44,7 @@ func (c *Cache) Set(q *caches.Query, l string) string {
|
||||
loger.Error(`DownloadFile: %v`, err)
|
||||
return ``
|
||||
}
|
||||
env.Cache.Set(q.Query(), struct{}{}, 3600)
|
||||
// env.Cache.Set(q.Query(), struct{}{}, 3600)
|
||||
return c.getLink(q.Query())
|
||||
// fpath := filepath.Join(c.Path, q.String)
|
||||
// os.MkdirAll(filepath.Dir(fpath), fs.ModePerm)
|
||||
|
4
src/env/env.go
vendored
4
src/env/env.go
vendored
@ -9,7 +9,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
Version = `1.0.2-β0.1`
|
||||
Version = `1.0.2-β0.2`
|
||||
)
|
||||
|
||||
var (
|
||||
@ -142,7 +142,7 @@ var (
|
||||
Loger: Loger.NewGroup(`Config`),
|
||||
})
|
||||
Defer = new(ztool.Err_DeferList)
|
||||
Cache = memo.NewMemoStoreConf(Loger, 300) //memo.NewMemoStore()
|
||||
Cache = memo.NewMemoStoreConf(Loger, 300) // 内存缓存 默认每5分钟进行一次GC //memo.NewMemoStore()
|
||||
)
|
||||
|
||||
// func init() {
|
||||
|
@ -45,9 +45,11 @@ const httpRequest = (url, options) => new Promise((resolve, reject) => {
|
||||
})
|
||||
|
||||
const musicUrl = async (source, info, quality) => {
|
||||
const start = new Date().getTime();
|
||||
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 body = await httpRequest(`${apiaddr}link/${query}`, { method: 'get' }); console.log('返回数据: %O', body)
|
||||
const body = await httpRequest(`${apiaddr}link/${query}`, { method: 'get' });
|
||||
console.log('返回数据: %O', body, `, 耗时 ${new Date().getTime() - start} ms`)
|
||||
return body.data != '' ? body.data : Promise.reject(body.msg) // 没有获取到链接则将msg作为错误抛出
|
||||
}
|
||||
|
||||
|
1
src/middleware/resp/error.base64
Normal file
1
src/middleware/resp/error.base64
Normal file
File diff suppressed because one or more lines are too long
@ -2,6 +2,7 @@
|
||||
package resp
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
@ -10,13 +11,13 @@ import (
|
||||
// 统一输出
|
||||
/*
|
||||
返回码对应表:
|
||||
0: http.StatusOK, // 成功
|
||||
1: http.StatusForbidden, // IP被封禁
|
||||
2: http.StatusServiceUnavailable, // 获取失败
|
||||
3: http.StatusUnauthorized, // 验证失败
|
||||
4: http.StatusInternalServerError, // 服务器内部错误
|
||||
5: http.StatusTooManyRequests, // 请求过于频繁
|
||||
6: http.StatusBadRequest, // 参数错误
|
||||
0: http.StatusOK, // [200] 成功
|
||||
1: http.StatusForbidden, // [403] IP被封禁
|
||||
2: http.StatusServiceUnavailable, // [503] 获取失败
|
||||
3: http.StatusUnauthorized, // [401] 验证失败
|
||||
4: http.StatusInternalServerError, // [500] 服务器内部错误
|
||||
5: http.StatusTooManyRequests, // [429] 请求过于频繁
|
||||
6: http.StatusBadRequest, // [400] 参数错误
|
||||
*/
|
||||
type Resp struct {
|
||||
Code int `json:"code"` // 状态码 为兼容内置源设置 暂无实际作用 (1.0.2后已兼容Python版定义)
|
||||
@ -36,6 +37,9 @@ var statusMap = map[int]int{
|
||||
6: http.StatusBadRequest, // 参数错误
|
||||
}
|
||||
|
||||
//go:embed error.base64
|
||||
var errormp3 string
|
||||
|
||||
// 返回请求
|
||||
/*
|
||||
注:Code不为0时调用c.Abort()终止Handler
|
||||
@ -46,6 +50,9 @@ func (o *Resp) Execute(c *gin.Context) {
|
||||
status = http.StatusOK
|
||||
}
|
||||
if o.Code != 0 {
|
||||
if o.Code == 2 /*&& o.Data == ``*/ {
|
||||
o.Data = errormp3
|
||||
}
|
||||
c.Abort()
|
||||
}
|
||||
c.JSON(status, o)
|
||||
|
@ -101,6 +101,17 @@ func linkHandler(c *gin.Context) {
|
||||
// if !ok {
|
||||
// return &resp.Resp{Code: 6, Msg: `不支持的平台或音质`}
|
||||
// }
|
||||
|
||||
// 查询内存
|
||||
clink, ok := env.Cache.Get(cquery.Query())
|
||||
if ok {
|
||||
if str, ok := clink.(string); ok {
|
||||
if str == `` {
|
||||
return &resp.Resp{Code: 2, Msg: `MemCache Reject`} // 拒绝请求,当前一段时间内解析出错
|
||||
}
|
||||
return &resp.Resp{Msg: `MemCache HIT`, Data: str}
|
||||
}
|
||||
}
|
||||
// 查询缓存
|
||||
var cstat bool
|
||||
if caches.UseCache != nil {
|
||||
@ -110,6 +121,7 @@ func linkHandler(c *gin.Context) {
|
||||
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 {
|
||||
@ -121,12 +133,14 @@ func linkHandler(c *gin.Context) {
|
||||
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 {
|
||||
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}
|
||||
}
|
||||
}
|
||||
|
@ -98,7 +98,7 @@ func (s *Source) GetLink(c *caches.Query) (outlink string, msg string) {
|
||||
}
|
||||
if resp.Code != 200 || resp.Data.AudioInfo.Bitrate == `1` {
|
||||
jx.Debug(`Kw, Err: %#v`, resp)
|
||||
msg = `failed`
|
||||
msg = ztool.Str_FastConcat(`failed: `, resp.Msg)
|
||||
return
|
||||
}
|
||||
outlink = strings.Split(resp.Data.URL, `?`)[0]
|
||||
|
28
update.md
Normal file
28
update.md
Normal file
@ -0,0 +1,28 @@
|
||||
## Lx-Source/更新日志
|
||||
|
||||
#### 2023-12-(17-18) (beta)
|
||||
+ 脚本增加请求耗时输出
|
||||
+ 优化zTool文件下载逻辑
|
||||
+ 链接缓存由Source上移至Router级 (为临时链实现基础)
|
||||
+ 完善缓存规则
|
||||
- 查询成功将链接写入内存,保留一小时 (MemCache HIT)
|
||||
- 解析错误将空字符串写入内存,阻止请求10分钟 (MemCache Reject)
|
||||
+ 防止自动换源机制瞎查,解析失败返回一段提示语音
|
||||
```
|
||||
非常抱歉,
|
||||
本音频可能由以下原因导致无法正常播放,
|
||||
|
||||
不支持的平台或音质,
|
||||
触发风控或专辑单独收费,
|
||||
缓存文件已被删除,
|
||||
实际音质不匹配,
|
||||
|
||||
--洛雪自定义源
|
||||
(Lx-Source)
|
||||
```
|
||||
#### ~2023-12-16
|
||||
+ 参考Python版移植部分功能
|
||||
+ 完善、优化逻辑
|
||||
+ 发布源码
|
||||
#### 2023-10-21
|
||||
+ 立项制作
|
Loading…
x
Reference in New Issue
Block a user