2023-12-18

This commit is contained in:
ZxwyWebSite 2023-12-19 02:42:26 +08:00
parent ba8c0faf0e
commit 8e9359e6df
9 changed files with 72 additions and 25 deletions

View File

@ -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`
### 项目协议

View File

@ -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
View File

@ -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() {

View File

@ -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作为错误抛出
}

File diff suppressed because one or more lines are too long

View File

@ -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)

View File

@ -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}
}
}

View File

@ -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
View 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
+ 立项制作