mirror of
https://github.com/ZxwyWebSite/lx-source.git
synced 2025-05-23 21:37:42 +08:00
2023-12-31 v1.0.2-b0.8.2
This commit is contained in:
parent
b26d69a162
commit
0b7e1a9425
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,7 +1,7 @@
|
|||||||
bin/
|
bin/
|
||||||
# cache/
|
# cache/
|
||||||
data/
|
data/
|
||||||
outdated/
|
.outdated/
|
||||||
# conf.ini
|
# conf.ini
|
||||||
test.go
|
test.go
|
||||||
test_test.go
|
test_test.go
|
||||||
|
@ -11,9 +11,9 @@
|
|||||||
## ZxwyWebSite/LX-Source
|
## ZxwyWebSite/LX-Source
|
||||||
### 简介
|
### 简介
|
||||||
+ LX-Music 解析源 (洛雪音乐自定义源)
|
+ LX-Music 解析源 (洛雪音乐自定义源)
|
||||||
+ 使用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)
|
+ 视频教程:[使用教程.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)
|
||||||
<!-- + **锟斤拷** -->
|
<!-- + **锟斤拷** -->
|
||||||
|
|
||||||
|
14
src/env/env.go
vendored
14
src/env/env.go
vendored
@ -63,6 +63,19 @@ type (
|
|||||||
// 平台账号
|
// 平台账号
|
||||||
// ...(待实现)
|
// ...(待实现)
|
||||||
} // `comment:""`
|
} // `comment:""`
|
||||||
|
Conf_Custom struct {
|
||||||
|
// kg (暂未实现)
|
||||||
|
// Kg_Enable bool `comment:"是否开启小枸源"`
|
||||||
|
// tx
|
||||||
|
Tx_Enable bool `comment:"是否开启小秋源"`
|
||||||
|
Tx_Ukey string `comment:"Cookie中/客户端的请求体中的(comm.authst)"`
|
||||||
|
Tx_Uuin string `comment:"key对应的QQ号"`
|
||||||
|
// wy (暂未实现)
|
||||||
|
// Wy_Enable bool `comment:"是否开启小芸源"`
|
||||||
|
// Wy_Cookie string `comment:"账号cookie数据"`
|
||||||
|
// mg (暂未实现)
|
||||||
|
// Mg_Enable bool `comment:"是否开启小蜜源"`
|
||||||
|
}
|
||||||
Conf_Script struct {
|
Conf_Script struct {
|
||||||
Ver string `comment:"自定义脚本版本" json:"ver"`
|
Ver string `comment:"自定义脚本版本" json:"ver"`
|
||||||
Log string `comment:"更新日志" json:"log"`
|
Log string `comment:"更新日志" json:"log"`
|
||||||
@ -87,6 +100,7 @@ type (
|
|||||||
Apis Conf_Apis `comment:"接口设置"`
|
Apis Conf_Apis `comment:"接口设置"`
|
||||||
Auth Conf_Auth `comment:"访问控制"`
|
Auth Conf_Auth `comment:"访问控制"`
|
||||||
Source Conf_Source `comment:"解析源配置"`
|
Source Conf_Source `comment:"解析源配置"`
|
||||||
|
Custom Conf_Custom `comment:"解析账号配置"`
|
||||||
Script Conf_Script `comment:"自定义脚本更新"` // ini:",omitempty"
|
Script Conf_Script `comment:"自定义脚本更新"` // ini:",omitempty"
|
||||||
Cache Conf_Cache `comment:"音乐缓存设置"`
|
Cache Conf_Cache `comment:"音乐缓存设置"`
|
||||||
}
|
}
|
||||||
|
@ -46,6 +46,8 @@ func InitHandler(h gin.HandlerFunc) (out []gin.HandlerFunc) {
|
|||||||
loger.Debug(`RateLimit Enabled`)
|
loger.Debug(`RateLimit Enabled`)
|
||||||
loger.Info(`已启用速率限制,当前配置 %v/%v`, env.Config.Auth.RateLimit_Single, env.Config.Auth.RateLimit_Block)
|
loger.Info(`已启用速率限制,当前配置 %v/%v`, env.Config.Auth.RateLimit_Single, env.Config.Auth.RateLimit_Block)
|
||||||
newRateLimit := func() *RateLimit { return &RateLimit{Tim: time.Now().Unix(), Num: 1} }
|
newRateLimit := func() *RateLimit { return &RateLimit{Tim: time.Now().Unix(), Num: 1} }
|
||||||
|
block_int64 := int64(env.Config.Auth.RateLimit_Block)
|
||||||
|
block_int := int(env.Config.Auth.RateLimit_Block)
|
||||||
out = append(out, func(c *gin.Context) {
|
out = append(out, func(c *gin.Context) {
|
||||||
resp.Wrap(c, func() *resp.Resp {
|
resp.Wrap(c, func() *resp.Resp {
|
||||||
rip := c.RemoteIP()
|
rip := c.RemoteIP()
|
||||||
@ -57,7 +59,7 @@ func InitHandler(h gin.HandlerFunc) (out []gin.HandlerFunc) {
|
|||||||
if ok {
|
if ok {
|
||||||
if oip, ok := cip.(*RateLimit); ok {
|
if oip, ok := cip.(*RateLimit); ok {
|
||||||
loger.Debug(`GetMemOut: %+v`, oip)
|
loger.Debug(`GetMemOut: %+v`, oip)
|
||||||
if oip.Tim+int64(env.Config.Auth.RateLimit_Block) > time.Now().Unix() {
|
if oip.Tim+block_int64 > time.Now().Unix() {
|
||||||
oi := atomic.AddUint32(&oip.Num, 1)
|
oi := atomic.AddUint32(&oip.Num, 1)
|
||||||
if oi > env.Config.Auth.RateLimit_Single {
|
if oi > env.Config.Auth.RateLimit_Single {
|
||||||
return &resp.Resp{Code: 5, Msg: `请求过快,请稍后重试`}
|
return &resp.Resp{Code: 5, Msg: `请求过快,请稍后重试`}
|
||||||
@ -67,7 +69,7 @@ func InitHandler(h gin.HandlerFunc) (out []gin.HandlerFunc) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
val := newRateLimit()
|
val := newRateLimit()
|
||||||
if err := env.Cache.Set(rip, val, int(env.Config.Auth.RateLimit_Block)); err != nil {
|
if err := env.Cache.Set(rip, val, block_int); err != nil {
|
||||||
loger.Error(`写入内存: %s`, err)
|
loger.Error(`写入内存: %s`, err)
|
||||||
return &resp.Resp{Code: 4, Msg: `速率限制内部异常,请联系网站管理员`}
|
return &resp.Resp{Code: 4, Msg: `速率限制内部异常,请联系网站管理员`}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"lx-source/src/caches"
|
"lx-source/src/caches"
|
||||||
"lx-source/src/env"
|
"lx-source/src/env"
|
||||||
"lx-source/src/sources"
|
"lx-source/src/sources"
|
||||||
|
"lx-source/src/sources/custom/tx"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@ -28,7 +29,7 @@ var (
|
|||||||
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) }}
|
kg_pool = &sync.Pool{New: func() any { return new(KgApi_Song) }}
|
||||||
tx_pool = &sync.Pool{New: func() any { return new(res_tx) }}
|
// tx_pool = &sync.Pool{New: func() any { return new(res_tx) }}
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -161,37 +162,45 @@ func (s *Source) GetLink(c *caches.Query) (outlink string, msg string) {
|
|||||||
}
|
}
|
||||||
outlink = data.PlayBackupURL
|
outlink = data.PlayBackupURL
|
||||||
case s_tx:
|
case s_tx:
|
||||||
resp := tx_pool.Get().(*res_tx)
|
|
||||||
defer tx_pool.Put(resp)
|
|
||||||
|
|
||||||
sep := c.Split()
|
sep := c.Split()
|
||||||
url := ztool.Str_FastConcat(api_tx,
|
ourl, emsg := tx.Url(sep[0], c.Quality)
|
||||||
`{"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":{`,
|
if emsg != `` {
|
||||||
func(s string) string {
|
msg = emsg
|
||||||
if s == `` {
|
|
||||||
return ``
|
|
||||||
}
|
|
||||||
return ztool.Str_FastConcat(`"filename":["`, rquery, s, `.`, c.Extname, `"],`)
|
|
||||||
}(sep[1]),
|
|
||||||
`"guid":"1535153710","loginflag":1,"platform":"20","songmid":["`, sep[0], `"],"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
|
return
|
||||||
}
|
}
|
||||||
jx.Debug(`Tx, Resp: %s`, out)
|
outlink = ourl
|
||||||
if resp.Code != 0 {
|
// case `otx`:
|
||||||
msg = ztool.Str_FastConcat(`Error: `, strconv.Itoa(resp.Code))
|
// resp := tx_pool.Get().(*res_tx)
|
||||||
return
|
// defer tx_pool.Put(resp)
|
||||||
}
|
|
||||||
if resp.Req0.Data.Midurlinfo[0].Purl == `` {
|
// sep := c.Split()
|
||||||
msg = errNoLink
|
// url := ztool.Str_FastConcat(api_tx,
|
||||||
return
|
// `{"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":{`,
|
||||||
}
|
// func(s string) string {
|
||||||
outlink = ztool.Str_FastConcat(`https://dl.stream.qqmusic.qq.com/`, resp.Req0.Data.Midurlinfo[0].Purl)
|
// if s == `` {
|
||||||
|
// return ``
|
||||||
|
// }
|
||||||
|
// return ztool.Str_FastConcat(`"filename":["`, rquery, s, `.`, c.Extname, `"],`)
|
||||||
|
// }(sep[1]),
|
||||||
|
// `"guid":"1535153710","loginflag":1,"platform":"20","songmid":["`, sep[0], `"],"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:
|
default:
|
||||||
msg = `不支持的平台`
|
msg = `不支持的平台`
|
||||||
return
|
return
|
||||||
|
@ -124,84 +124,84 @@ type (
|
|||||||
// EVideoID string `json:"e_video_id"`
|
// EVideoID string `json:"e_video_id"`
|
||||||
}
|
}
|
||||||
// 腾讯试听接口
|
// 腾讯试听接口
|
||||||
res_tx struct {
|
// res_tx struct {
|
||||||
Code int `json:"code"`
|
// Code int `json:"code"`
|
||||||
// Ts int64 `json:"ts"`
|
// // Ts int64 `json:"ts"`
|
||||||
// StartTs int64 `json:"start_ts"`
|
// // StartTs int64 `json:"start_ts"`
|
||||||
// Traceid string `json:"traceid"`
|
// // Traceid string `json:"traceid"`
|
||||||
// Req struct {
|
// // Req struct {
|
||||||
// Code int `json:"code"`
|
// // Code int `json:"code"`
|
||||||
// Data struct {
|
// // Data struct {
|
||||||
// Expiration int `json:"expiration"`
|
// // Expiration int `json:"expiration"`
|
||||||
// Freeflowsip []string `json:"freeflowsip"`
|
// // Freeflowsip []string `json:"freeflowsip"`
|
||||||
// Keepalivefile string `json:"keepalivefile"`
|
// // Keepalivefile string `json:"keepalivefile"`
|
||||||
// Msg string `json:"msg"`
|
// // Msg string `json:"msg"`
|
||||||
// Retcode int `json:"retcode"`
|
// // Retcode int `json:"retcode"`
|
||||||
// Servercheck string `json:"servercheck"`
|
// // Servercheck string `json:"servercheck"`
|
||||||
// Sip []string `json:"sip"`
|
// // Sip []string `json:"sip"`
|
||||||
// Testfile2G string `json:"testfile2g"`
|
// // Testfile2G string `json:"testfile2g"`
|
||||||
// Testfilewifi string `json:"testfilewifi"`
|
// // Testfilewifi string `json:"testfilewifi"`
|
||||||
// Uin string `json:"uin"`
|
// // Uin string `json:"uin"`
|
||||||
// Userip string `json:"userip"`
|
// // Userip string `json:"userip"`
|
||||||
// Vkey string `json:"vkey"`
|
// // Vkey string `json:"vkey"`
|
||||||
// } `json:"data"`
|
// // } `json:"data"`
|
||||||
// } `json:"req"`
|
// // } `json:"req"`
|
||||||
Req0 struct {
|
// Req0 struct {
|
||||||
Code int `json:"code"`
|
// Code int `json:"code"`
|
||||||
Data struct {
|
// Data struct {
|
||||||
// Uin string `json:"uin"`
|
// // Uin string `json:"uin"`
|
||||||
// Retcode int `json:"retcode"`
|
// // Retcode int `json:"retcode"`
|
||||||
// VerifyType int `json:"verify_type"`
|
// // VerifyType int `json:"verify_type"`
|
||||||
// LoginKey string `json:"login_key"`
|
// // LoginKey string `json:"login_key"`
|
||||||
// Msg string `json:"msg"`
|
// // Msg string `json:"msg"`
|
||||||
// Sip []string `json:"sip"`
|
// // Sip []string `json:"sip"`
|
||||||
// Thirdip []string `json:"thirdip"`
|
// // Thirdip []string `json:"thirdip"`
|
||||||
// Testfile2G string `json:"testfile2g"`
|
// // Testfile2G string `json:"testfile2g"`
|
||||||
// Testfilewifi string `json:"testfilewifi"`
|
// // Testfilewifi string `json:"testfilewifi"`
|
||||||
Midurlinfo []struct {
|
// Midurlinfo []struct {
|
||||||
// Songmid string `json:"songmid"`
|
// // Songmid string `json:"songmid"`
|
||||||
// Filename string `json:"filename"`
|
// // Filename string `json:"filename"`
|
||||||
Purl string `json:"purl"`
|
// Purl string `json:"purl"`
|
||||||
// Errtype string `json:"errtype"`
|
// // Errtype string `json:"errtype"`
|
||||||
// P2Pfromtag int `json:"p2pfromtag"`
|
// // P2Pfromtag int `json:"p2pfromtag"`
|
||||||
// Qmdlfromtag int `json:"qmdlfromtag"`
|
// // Qmdlfromtag int `json:"qmdlfromtag"`
|
||||||
// CommonDownfromtag int `json:"common_downfromtag"`
|
// // CommonDownfromtag int `json:"common_downfromtag"`
|
||||||
// VipDownfromtag int `json:"vip_downfromtag"`
|
// // VipDownfromtag int `json:"vip_downfromtag"`
|
||||||
// Pdl int `json:"pdl"`
|
// // Pdl int `json:"pdl"`
|
||||||
// Premain int `json:"premain"`
|
// // Premain int `json:"premain"`
|
||||||
// Hisdown int `json:"hisdown"`
|
// // Hisdown int `json:"hisdown"`
|
||||||
// Hisbuy int `json:"hisbuy"`
|
// // Hisbuy int `json:"hisbuy"`
|
||||||
// UIAlert int `json:"uiAlert"`
|
// // UIAlert int `json:"uiAlert"`
|
||||||
// Isbuy int `json:"isbuy"`
|
// // Isbuy int `json:"isbuy"`
|
||||||
// Pneedbuy int `json:"pneedbuy"`
|
// // Pneedbuy int `json:"pneedbuy"`
|
||||||
// Pneed int `json:"pneed"`
|
// // Pneed int `json:"pneed"`
|
||||||
// Isonly int `json:"isonly"`
|
// // Isonly int `json:"isonly"`
|
||||||
// Onecan int `json:"onecan"`
|
// // Onecan int `json:"onecan"`
|
||||||
// Result int `json:"result"`
|
// // Result int `json:"result"`
|
||||||
// Tips string `json:"tips"`
|
// // Tips string `json:"tips"`
|
||||||
// Opi48Kurl string `json:"opi48kurl"`
|
// // Opi48Kurl string `json:"opi48kurl"`
|
||||||
// Opi96Kurl string `json:"opi96kurl"`
|
// // Opi96Kurl string `json:"opi96kurl"`
|
||||||
// Opi192Kurl string `json:"opi192kurl"`
|
// // Opi192Kurl string `json:"opi192kurl"`
|
||||||
// Opiflackurl string `json:"opiflackurl"`
|
// // Opiflackurl string `json:"opiflackurl"`
|
||||||
// Opi128Kurl string `json:"opi128kurl"`
|
// // Opi128Kurl string `json:"opi128kurl"`
|
||||||
// Opi192Koggurl string `json:"opi192koggurl"`
|
// // Opi192Koggurl string `json:"opi192koggurl"`
|
||||||
// Wififromtag string `json:"wififromtag"`
|
// // Wififromtag string `json:"wififromtag"`
|
||||||
// Flowfromtag string `json:"flowfromtag"`
|
// // Flowfromtag string `json:"flowfromtag"`
|
||||||
// Wifiurl string `json:"wifiurl"`
|
// // Wifiurl string `json:"wifiurl"`
|
||||||
// Flowurl string `json:"flowurl"`
|
// // Flowurl string `json:"flowurl"`
|
||||||
// Vkey string `json:"vkey"`
|
// // Vkey string `json:"vkey"`
|
||||||
// Opi30Surl string `json:"opi30surl"`
|
// // Opi30Surl string `json:"opi30surl"`
|
||||||
// Ekey string `json:"ekey"`
|
// // Ekey string `json:"ekey"`
|
||||||
// AuthSwitch int `json:"auth_switch"`
|
// // AuthSwitch int `json:"auth_switch"`
|
||||||
// Subcode int `json:"subcode"`
|
// // Subcode int `json:"subcode"`
|
||||||
// Opi96Koggurl string `json:"opi96koggurl"`
|
// // Opi96Koggurl string `json:"opi96koggurl"`
|
||||||
// AuthSwitch2 int `json:"auth_switch2"`
|
// // AuthSwitch2 int `json:"auth_switch2"`
|
||||||
} `json:"midurlinfo"`
|
// } `json:"midurlinfo"`
|
||||||
// Servercheck string `json:"servercheck"`
|
// // Servercheck string `json:"servercheck"`
|
||||||
// Expiration int `json:"expiration"`
|
// // Expiration int `json:"expiration"`
|
||||||
} `json:"data"`
|
// } `json:"data"`
|
||||||
} `json:"req_0"`
|
// } `json:"req_0"`
|
||||||
}
|
// }
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -255,12 +255,12 @@ var (
|
|||||||
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`
|
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=`
|
// api_tx string = `https://u.y.qq.com/cgi-bin/musicu.fcg?data=`
|
||||||
// Headers
|
// Headers
|
||||||
header_wy map[string]string
|
header_wy map[string]string
|
||||||
header_mg map[string]string
|
header_mg map[string]string
|
||||||
header_kw map[string]string
|
header_kw map[string]string
|
||||||
header_tx = map[string]string{`Referer`: `https://y.qq.com/`}
|
// header_tx = map[string]string{`Referer`: `https://y.qq.com/`}
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
126
src/sources/custom/tx/QMWSign.go
Normal file
126
src/sources/custom/tx/QMWSign.go
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
package tx
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/md5"
|
||||||
|
"encoding/hex"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/ZxwyWebSite/ztool"
|
||||||
|
"github.com/ZxwyWebSite/ztool/x/bytesconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
func v(b string) string {
|
||||||
|
res := []byte{}
|
||||||
|
p := [...]int{21, 4, 9, 26, 16, 20, 27, 30}
|
||||||
|
for _, x := range p {
|
||||||
|
res = append(res, b[x])
|
||||||
|
}
|
||||||
|
return bytesconv.BytesToString(res) //string(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
func c(b string) string {
|
||||||
|
res := []byte{}
|
||||||
|
p := [...]int{18, 11, 3, 2, 1, 7, 6, 25}
|
||||||
|
for _, x := range p {
|
||||||
|
res = append(res, b[x])
|
||||||
|
}
|
||||||
|
return bytesconv.BytesToString(res) //string(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
func y(a, b, c int) (e []int) {
|
||||||
|
// e := []int{}
|
||||||
|
r25 := a >> 2
|
||||||
|
if b != 0 && c != 0 {
|
||||||
|
r26 := a & 3
|
||||||
|
r26_2 := r26 << 4
|
||||||
|
r26_3 := b >> 4
|
||||||
|
r26_4 := r26_2 | r26_3
|
||||||
|
r27 := b & 15
|
||||||
|
r27_2 := r27 << 2
|
||||||
|
r27_3 := r27_2 | (c >> 6)
|
||||||
|
r28 := c & 63
|
||||||
|
e = append(e, r25)
|
||||||
|
e = append(e, r26_4)
|
||||||
|
e = append(e, r27_3)
|
||||||
|
e = append(e, r28)
|
||||||
|
} else {
|
||||||
|
r10 := a >> 2
|
||||||
|
r11 := a & 3
|
||||||
|
r11_2 := r11 << 4
|
||||||
|
e = append(e, r10)
|
||||||
|
e = append(e, r11_2)
|
||||||
|
}
|
||||||
|
return //e
|
||||||
|
}
|
||||||
|
|
||||||
|
func n(ls []int) string {
|
||||||
|
e := []int{}
|
||||||
|
for i, r := 0, len(ls); i < r; i += 3 {
|
||||||
|
if i < r-2 {
|
||||||
|
e = append(e, y(ls[i], ls[i+1], ls[i+2])...)
|
||||||
|
} else {
|
||||||
|
e = append(e, y(ls[i], 0, 0)...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
res := []byte{}
|
||||||
|
b64all := `ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=`
|
||||||
|
for _, i := range e {
|
||||||
|
res = append(res, b64all[i])
|
||||||
|
}
|
||||||
|
return bytesconv.BytesToString(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
func t(b string) (res []int) {
|
||||||
|
zd := map[string]int{
|
||||||
|
`0`: 0,
|
||||||
|
`1`: 1,
|
||||||
|
`2`: 2,
|
||||||
|
`3`: 3,
|
||||||
|
`4`: 4,
|
||||||
|
`5`: 5,
|
||||||
|
`6`: 6,
|
||||||
|
`7`: 7,
|
||||||
|
`8`: 8,
|
||||||
|
`9`: 9,
|
||||||
|
`A`: 10,
|
||||||
|
`B`: 11,
|
||||||
|
`C`: 12,
|
||||||
|
`D`: 13,
|
||||||
|
`E`: 14,
|
||||||
|
`F`: 15,
|
||||||
|
}
|
||||||
|
ol := [...]int{212, 45, 80, 68, 195, 163, 163, 203, 157, 220, 254, 91, 204, 79, 104, 6}
|
||||||
|
// res := []int{}
|
||||||
|
j := 0
|
||||||
|
for i, r := 0, len(b); i < r; i += 2 {
|
||||||
|
one := zd[string(b[i])]
|
||||||
|
two := zd[string(b[i+1])]
|
||||||
|
r := one*16 ^ two
|
||||||
|
// if j >= 16 {
|
||||||
|
// break
|
||||||
|
// }
|
||||||
|
res = append(res, r^ol[j])
|
||||||
|
j++
|
||||||
|
}
|
||||||
|
return //res
|
||||||
|
}
|
||||||
|
|
||||||
|
func createMD5(s []byte) string {
|
||||||
|
hash := md5.New()
|
||||||
|
hash.Write(s)
|
||||||
|
return hex.EncodeToString(hash.Sum(nil))
|
||||||
|
}
|
||||||
|
|
||||||
|
func sign(params []byte) string {
|
||||||
|
md5Str := strings.ToUpper(createMD5(params))
|
||||||
|
h := v(md5Str)
|
||||||
|
e := c(md5Str)
|
||||||
|
ls := t(md5Str)
|
||||||
|
m := n(ls)
|
||||||
|
res := ztool.Str_FastConcat(`zzb`, h, m, e) //`zzb` + h + m + e
|
||||||
|
res = strings.ToLower(res)
|
||||||
|
r := regexp.MustCompile(`[\/+]`)
|
||||||
|
res = r.ReplaceAllString(res, ``)
|
||||||
|
return res
|
||||||
|
}
|
25
src/sources/custom/tx/info.go
Normal file
25
src/sources/custom/tx/info.go
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
package tx
|
||||||
|
|
||||||
|
// func Info(songMid string) (info any, msg string) {
|
||||||
|
// req, emsg := getMusicInfo(songMid)
|
||||||
|
// if emsg != `` {
|
||||||
|
// msg = emsg
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
// var singerList []any
|
||||||
|
// for _, s := range req.TrackInfo.Singer {
|
||||||
|
// // item := new(struct{
|
||||||
|
// // ID int `json:"id"`
|
||||||
|
// // Str string
|
||||||
|
// // })
|
||||||
|
// // item.ID = s.ID
|
||||||
|
// singerList = append(singerList, s)
|
||||||
|
// }
|
||||||
|
// var file_info map[string]struct{
|
||||||
|
// Size interface{}
|
||||||
|
// }
|
||||||
|
// if req.TrackInfo.File.Size128Mp3 != 0 {
|
||||||
|
// file_info[`128k`].Size =
|
||||||
|
// }
|
||||||
|
// return
|
||||||
|
// }
|
247
src/sources/custom/tx/musicinfo.go
Normal file
247
src/sources/custom/tx/musicinfo.go
Normal file
@ -0,0 +1,247 @@
|
|||||||
|
package tx
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/ZxwyWebSite/ztool"
|
||||||
|
"github.com/ZxwyWebSite/ztool/x/bytesconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
type musicInfo struct {
|
||||||
|
// Info struct {
|
||||||
|
// Company struct {
|
||||||
|
// Title string `json:"title"`
|
||||||
|
// Type string `json:"type"`
|
||||||
|
// Content []struct {
|
||||||
|
// ID int `json:"id"`
|
||||||
|
// Value string `json:"value"`
|
||||||
|
// Mid string `json:"mid"`
|
||||||
|
// Type int `json:"type"`
|
||||||
|
// ShowType int `json:"show_type"`
|
||||||
|
// IsParent int `json:"is_parent"`
|
||||||
|
// Picurl string `json:"picurl"`
|
||||||
|
// ReadCnt int `json:"read_cnt"`
|
||||||
|
// Author string `json:"author"`
|
||||||
|
// Jumpurl string `json:"jumpurl"`
|
||||||
|
// OriPicurl string `json:"ori_picurl"`
|
||||||
|
// } `json:"content"`
|
||||||
|
// Pos int `json:"pos"`
|
||||||
|
// More int `json:"more"`
|
||||||
|
// Selected string `json:"selected"`
|
||||||
|
// UsePlatform int `json:"use_platform"`
|
||||||
|
// } `json:"company"`
|
||||||
|
// Genre struct {
|
||||||
|
// Title string `json:"title"`
|
||||||
|
// Type string `json:"type"`
|
||||||
|
// Content []struct {
|
||||||
|
// ID int `json:"id"`
|
||||||
|
// Value string `json:"value"`
|
||||||
|
// Mid string `json:"mid"`
|
||||||
|
// Type int `json:"type"`
|
||||||
|
// ShowType int `json:"show_type"`
|
||||||
|
// IsParent int `json:"is_parent"`
|
||||||
|
// Picurl string `json:"picurl"`
|
||||||
|
// ReadCnt int `json:"read_cnt"`
|
||||||
|
// Author string `json:"author"`
|
||||||
|
// Jumpurl string `json:"jumpurl"`
|
||||||
|
// OriPicurl string `json:"ori_picurl"`
|
||||||
|
// } `json:"content"`
|
||||||
|
// Pos int `json:"pos"`
|
||||||
|
// More int `json:"more"`
|
||||||
|
// Selected string `json:"selected"`
|
||||||
|
// UsePlatform int `json:"use_platform"`
|
||||||
|
// } `json:"genre"`
|
||||||
|
// Lan struct {
|
||||||
|
// Title string `json:"title"`
|
||||||
|
// Type string `json:"type"`
|
||||||
|
// Content []struct {
|
||||||
|
// ID int `json:"id"`
|
||||||
|
// Value string `json:"value"`
|
||||||
|
// Mid string `json:"mid"`
|
||||||
|
// Type int `json:"type"`
|
||||||
|
// ShowType int `json:"show_type"`
|
||||||
|
// IsParent int `json:"is_parent"`
|
||||||
|
// Picurl string `json:"picurl"`
|
||||||
|
// ReadCnt int `json:"read_cnt"`
|
||||||
|
// Author string `json:"author"`
|
||||||
|
// Jumpurl string `json:"jumpurl"`
|
||||||
|
// OriPicurl string `json:"ori_picurl"`
|
||||||
|
// } `json:"content"`
|
||||||
|
// Pos int `json:"pos"`
|
||||||
|
// More int `json:"more"`
|
||||||
|
// Selected string `json:"selected"`
|
||||||
|
// UsePlatform int `json:"use_platform"`
|
||||||
|
// } `json:"lan"`
|
||||||
|
// } `json:"info"`
|
||||||
|
// Extras struct {
|
||||||
|
// Name string `json:"name"`
|
||||||
|
// Transname string `json:"transname"`
|
||||||
|
// Subtitle string `json:"subtitle"`
|
||||||
|
// From string `json:"from"`
|
||||||
|
// Wikiurl string `json:"wikiurl"`
|
||||||
|
// } `json:"extras"`
|
||||||
|
TrackInfo struct {
|
||||||
|
ID int `json:"id"`
|
||||||
|
Type int `json:"type"`
|
||||||
|
Mid string `json:"mid"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Title string `json:"title"`
|
||||||
|
Subtitle string `json:"subtitle"`
|
||||||
|
Singer []struct {
|
||||||
|
ID int `json:"id"`
|
||||||
|
Mid string `json:"mid"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Title string `json:"title"`
|
||||||
|
Type int `json:"type"`
|
||||||
|
Uin int `json:"uin"`
|
||||||
|
} `json:"singer"`
|
||||||
|
Album struct {
|
||||||
|
ID int `json:"id"`
|
||||||
|
Mid string `json:"mid"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Title string `json:"title"`
|
||||||
|
Subtitle string `json:"subtitle"`
|
||||||
|
TimePublic string `json:"time_public"`
|
||||||
|
Pmid string `json:"pmid"`
|
||||||
|
} `json:"album"`
|
||||||
|
Mv struct {
|
||||||
|
ID int `json:"id"`
|
||||||
|
Vid string `json:"vid"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Title string `json:"title"`
|
||||||
|
Vt int `json:"vt"`
|
||||||
|
} `json:"mv"`
|
||||||
|
Interval int `json:"interval"`
|
||||||
|
Isonly int `json:"isonly"`
|
||||||
|
Language int `json:"language"`
|
||||||
|
Genre int `json:"genre"`
|
||||||
|
IndexCd int `json:"index_cd"`
|
||||||
|
IndexAlbum int `json:"index_album"`
|
||||||
|
TimePublic string `json:"time_public"`
|
||||||
|
Status int `json:"status"`
|
||||||
|
Fnote int `json:"fnote"`
|
||||||
|
File struct {
|
||||||
|
MediaMid string `json:"media_mid"`
|
||||||
|
Size24Aac int `json:"size_24aac"`
|
||||||
|
Size48Aac int `json:"size_48aac"`
|
||||||
|
Size96Aac int `json:"size_96aac"`
|
||||||
|
Size192Ogg int `json:"size_192ogg"`
|
||||||
|
Size192Aac int `json:"size_192aac"`
|
||||||
|
Size128Mp3 int `json:"size_128mp3"`
|
||||||
|
Size320Mp3 int `json:"size_320mp3"`
|
||||||
|
SizeApe int `json:"size_ape"`
|
||||||
|
SizeFlac int `json:"size_flac"`
|
||||||
|
SizeDts int `json:"size_dts"`
|
||||||
|
SizeTry int `json:"size_try"`
|
||||||
|
TryBegin int `json:"try_begin"`
|
||||||
|
TryEnd int `json:"try_end"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
SizeHires int `json:"size_hires"`
|
||||||
|
HiresSample int `json:"hires_sample"`
|
||||||
|
HiresBitdepth int `json:"hires_bitdepth"`
|
||||||
|
B30S int `json:"b_30s"`
|
||||||
|
E30S int `json:"e_30s"`
|
||||||
|
Size96Ogg int `json:"size_96ogg"`
|
||||||
|
Size360Ra []interface{} `json:"size_360ra"`
|
||||||
|
SizeDolby int `json:"size_dolby"`
|
||||||
|
SizeNew []int `json:"size_new"`
|
||||||
|
} `json:"file"`
|
||||||
|
Pay struct {
|
||||||
|
PayMonth int `json:"pay_month"`
|
||||||
|
PriceTrack int `json:"price_track"`
|
||||||
|
PriceAlbum int `json:"price_album"`
|
||||||
|
PayPlay int `json:"pay_play"`
|
||||||
|
PayDown int `json:"pay_down"`
|
||||||
|
PayStatus int `json:"pay_status"`
|
||||||
|
TimeFree int `json:"time_free"`
|
||||||
|
} `json:"pay"`
|
||||||
|
Action struct {
|
||||||
|
Switch int `json:"switch"`
|
||||||
|
Msgid int `json:"msgid"`
|
||||||
|
Alert int `json:"alert"`
|
||||||
|
Icons int `json:"icons"`
|
||||||
|
Msgshare int `json:"msgshare"`
|
||||||
|
Msgfav int `json:"msgfav"`
|
||||||
|
Msgdown int `json:"msgdown"`
|
||||||
|
Msgpay int `json:"msgpay"`
|
||||||
|
Switch2 int `json:"switch2"`
|
||||||
|
Icon2 int `json:"icon2"`
|
||||||
|
} `json:"action"`
|
||||||
|
Ksong struct {
|
||||||
|
ID int `json:"id"`
|
||||||
|
Mid string `json:"mid"`
|
||||||
|
} `json:"ksong"`
|
||||||
|
Volume struct {
|
||||||
|
Gain float64 `json:"gain"`
|
||||||
|
Peak float64 `json:"peak"`
|
||||||
|
Lra float64 `json:"lra"`
|
||||||
|
} `json:"volume"`
|
||||||
|
Label string `json:"label"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
Bpm int `json:"bpm"`
|
||||||
|
Version int `json:"version"`
|
||||||
|
Trace string `json:"trace"`
|
||||||
|
DataType int `json:"data_type"`
|
||||||
|
ModifyStamp int `json:"modify_stamp"`
|
||||||
|
Pingpong string `json:"pingpong"`
|
||||||
|
Ppurl string `json:"ppurl"`
|
||||||
|
Tid int `json:"tid"`
|
||||||
|
Ov int `json:"ov"`
|
||||||
|
Sa int `json:"sa"`
|
||||||
|
Es string `json:"es"`
|
||||||
|
Vs []string `json:"vs"`
|
||||||
|
Vi []int `json:"vi"`
|
||||||
|
Ktag string `json:"ktag"`
|
||||||
|
Vf []float64 `json:"vf"`
|
||||||
|
} `json:"track_info"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func getMusicInfo(songMid string) (infoBody musicInfo, emsg string) {
|
||||||
|
infoReqBody := ztool.Str_FastConcat(`{"comm":{"ct":"19","cv":"1859","uin":"0"},"req":{"method":"get_song_detail_yqq","module":"music.pf_song_detail_svr","param":{"song_mid":"`, songMid, `","song_type":0}}}`)
|
||||||
|
var infoResp 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 musicInfo `json:"data"`
|
||||||
|
} `json:"req"`
|
||||||
|
}
|
||||||
|
err := signRequest(bytesconv.StringToBytes(infoReqBody), &infoResp)
|
||||||
|
if err != nil {
|
||||||
|
emsg = err.Error()
|
||||||
|
return //nil, err.Error()
|
||||||
|
}
|
||||||
|
if infoResp.Code != 0 || infoResp.Req.Code != 0 {
|
||||||
|
emsg = `获取音乐信息失败`
|
||||||
|
return //nil, `获取音乐信息失败`
|
||||||
|
}
|
||||||
|
infoBody = infoResp.Req.Data
|
||||||
|
return //infoBody.Req.Data, ``
|
||||||
|
}
|
||||||
|
|
||||||
|
// func (infoBody *musicInfo) GetLink(songMid, strFileName string) (ourl, msg string) {
|
||||||
|
// var uauthst, uuin string = env.Config.Custom.Tx_Ukey, env.Config.Custom.Tx_Uuin
|
||||||
|
// if uuin == `` {
|
||||||
|
// uuin = `1535153710`
|
||||||
|
// }
|
||||||
|
// requestBody := ztool.Str_FastConcat(`{"comm":{"authst":"`, uauthst, `","ct":"26","cv":"2010101","qq":"`, uuin, `","v":"2010101"},"req_0":{"method":"CgiGetVkey","module":"vkey.GetVkeyServer","param":{"filename":["`, strFileName, `"],"guid":"114514","loginflag":1,"platform":"20","songmid":["`, songMid, `"],"songtype":[0],"uin":"10086"}}}`)
|
||||||
|
// var infoResp struct {
|
||||||
|
// Code int `json:"code"`
|
||||||
|
// // Ts int64 `json:"ts"`
|
||||||
|
// // StartTs int64 `json:"start_ts"`
|
||||||
|
// // Traceid string `json:"traceid"`
|
||||||
|
// Req0 playInfo `json:"req_0"`
|
||||||
|
// }
|
||||||
|
// err := signRequest(bytesconv.StringToBytes(requestBody), &infoResp)
|
||||||
|
// if err != nil {
|
||||||
|
// msg = err.Error()
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
// infoData := infoResp.Req0.Data.Midurlinfo[0]
|
||||||
|
// if infoData.Purl == `` {
|
||||||
|
// msg = `无法获取音乐链接`
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
// ourl = infoData.Purl
|
||||||
|
// return
|
||||||
|
// }
|
137
src/sources/custom/tx/player.go
Normal file
137
src/sources/custom/tx/player.go
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
package tx
|
||||||
|
|
||||||
|
import (
|
||||||
|
"lx-source/src/env"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/ZxwyWebSite/ztool"
|
||||||
|
"github.com/ZxwyWebSite/ztool/x/bytesconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
type playInfo 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"`
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
音乐URL获取逻辑:
|
||||||
|
if需要付费播放and无账号信息:
|
||||||
|
试听获取
|
||||||
|
el有账号信息or无需付费:
|
||||||
|
正常获取
|
||||||
|
if没有链接:
|
||||||
|
尝试获取试听
|
||||||
|
if还没有链接:
|
||||||
|
报错
|
||||||
|
返回结果
|
||||||
|
注:
|
||||||
|
以上逻辑暂时没想好怎么改,
|
||||||
|
当前根据配置文件 [Custom].Tx_Enable 是否开启判断,
|
||||||
|
if需要付费播放and未开启账号解析:
|
||||||
|
试听获取
|
||||||
|
el无需付费or有账号信息:
|
||||||
|
正常获取
|
||||||
|
if没有链接:
|
||||||
|
报错
|
||||||
|
返回结果
|
||||||
|
*/
|
||||||
|
|
||||||
|
func Url(songMid, quality string) (ourl, msg string) {
|
||||||
|
infoFile, ok := fileInfo[quality]
|
||||||
|
if !ok {
|
||||||
|
msg = `不支持的音质`
|
||||||
|
return
|
||||||
|
}
|
||||||
|
infoBody, emsg := getMusicInfo(songMid)
|
||||||
|
if emsg != `` {
|
||||||
|
msg = emsg
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var uauthst, uuin string = env.Config.Custom.Tx_Ukey, env.Config.Custom.Tx_Uuin
|
||||||
|
if uuin == `` {
|
||||||
|
uuin = `1535153710`
|
||||||
|
}
|
||||||
|
var strFileName string
|
||||||
|
tryLink := infoBody.TrackInfo.Pay.PayPlay == 1 && /*uauthst == ``&&*/ !env.Config.Custom.Tx_Enable
|
||||||
|
if tryLink {
|
||||||
|
strFileName = ztool.Str_FastConcat(`RS02`, infoBody.TrackInfo.Vs[0], `.mp3`)
|
||||||
|
} else {
|
||||||
|
strFileName = ztool.Str_FastConcat(infoFile.H, infoBody.TrackInfo.File.MediaMid, infoFile.E)
|
||||||
|
}
|
||||||
|
requestBody := ztool.Str_FastConcat(`{"comm":{"authst":"`, uauthst, `","ct":"26","cv":"2010101","qq":"`, uuin, `","v":"2010101"},"req_0":{"method":"CgiGetVkey","module":"vkey.GetVkeyServer","param":{"filename":["`, strFileName, `"],"guid":"114514","loginflag":1,"platform":"20","songmid":["`, songMid, `"],"songtype":[0],"uin":"10086"}}}`)
|
||||||
|
var infoResp struct {
|
||||||
|
Code int `json:"code"`
|
||||||
|
// Ts int64 `json:"ts"`
|
||||||
|
// StartTs int64 `json:"start_ts"`
|
||||||
|
// Traceid string `json:"traceid"`
|
||||||
|
Req0 playInfo `json:"req_0"`
|
||||||
|
}
|
||||||
|
err := signRequest(bytesconv.StringToBytes(requestBody), &infoResp)
|
||||||
|
if err != nil {
|
||||||
|
msg = err.Error()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
infoData := infoResp.Req0.Data.Midurlinfo[0]
|
||||||
|
if infoData.Purl == `` {
|
||||||
|
msg = `无法获取音乐链接`
|
||||||
|
return
|
||||||
|
}
|
||||||
|
realQuality := strings.Split(infoData.Filename, `.`)[0][:4]
|
||||||
|
if qualityMapReverse[realQuality] != quality && /*infoBody.TrackInfo.Pay.PayPlay == 0*/ !tryLink {
|
||||||
|
msg = `实际音质不匹配`
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ourl = ztool.Str_FastConcat(`https://ws.stream.qqmusic.qq.com/`, infoData.Purl)
|
||||||
|
return
|
||||||
|
}
|
65
src/sources/custom/tx/utils.go
Normal file
65
src/sources/custom/tx/utils.go
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
package tx
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"lx-source/src/sources"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/ZxwyWebSite/ztool"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
fileInfo = map[string]struct {
|
||||||
|
E string
|
||||||
|
H string
|
||||||
|
}{
|
||||||
|
sources.Q_128k: {
|
||||||
|
E: `.mp3`,
|
||||||
|
H: `M500`,
|
||||||
|
},
|
||||||
|
sources.Q_320k: {
|
||||||
|
E: `.mp3`,
|
||||||
|
H: `M800`,
|
||||||
|
},
|
||||||
|
sources.Q_flac: {
|
||||||
|
E: `.flac`,
|
||||||
|
H: `F000`,
|
||||||
|
},
|
||||||
|
sources.Q_fl24: {
|
||||||
|
E: `.flac`,
|
||||||
|
H: `RS01`,
|
||||||
|
},
|
||||||
|
`dolby`: {
|
||||||
|
E: `.flac`,
|
||||||
|
H: `Q000`,
|
||||||
|
},
|
||||||
|
`master`: {
|
||||||
|
E: `.flac`,
|
||||||
|
H: `AI00`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
qualityMapReverse = map[string]string{
|
||||||
|
`M500`: sources.Q_128k,
|
||||||
|
`M800`: sources.Q_320k,
|
||||||
|
`F000`: sources.Q_flac,
|
||||||
|
`RS01`: sources.Q_fl24,
|
||||||
|
`Q000`: `dolby`,
|
||||||
|
`AI00`: `master`,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func signRequest(data []byte, out any) error {
|
||||||
|
s := sign(data)
|
||||||
|
return ztool.Net_Request(http.MethodPost,
|
||||||
|
ztool.Str_FastConcat(`https://u.y.qq.com/cgi-bin/musics.fcg?format=json&sign=`, s),
|
||||||
|
bytes.NewReader(data),
|
||||||
|
[]ztool.Net_ReqHandlerFunc{
|
||||||
|
ztool.Net_ReqAddHeaders(map[string]string{
|
||||||
|
`Referer`: `https://y.qq.com/`,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
[]ztool.Net_ResHandlerFunc{
|
||||||
|
ztool.Net_ResToStruct(out),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
12
src/sources/custom/utils/utils.go
Normal file
12
src/sources/custom/utils/utils.go
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
// func SizeFormat(size int) string {
|
||||||
|
// if size < 1024 {
|
||||||
|
// return ztool.Str_FastConcat(strconv.Itoa(size), `B`)
|
||||||
|
// }
|
||||||
|
// size64 := float64(size)
|
||||||
|
// if size64 < math.Pow(size64, 2) {
|
||||||
|
|
||||||
|
// }
|
||||||
|
// return ``
|
||||||
|
// }
|
@ -5,8 +5,21 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// var Loger = env.Loger.NewGroup(`Sources`) // JieXiApis
|
// var Loger = env.Loger.NewGroup(`Sources`) // JieXiApis
|
||||||
|
|
||||||
const (
|
const (
|
||||||
Err_Verify = `Verify Failed`
|
Err_Verify = `Verify Failed`
|
||||||
|
// 通用音质
|
||||||
|
Q_128k = `128k`
|
||||||
|
Q_320k = `320k`
|
||||||
|
Q_flac = `flac`
|
||||||
|
Q_fl24 = `flac24bit`
|
||||||
|
// 通用平台
|
||||||
|
S_wy = `wy` // 小芸
|
||||||
|
S_mg = `mg` // 小蜜
|
||||||
|
S_kw = `kw` // 小蜗
|
||||||
|
S_kg = `kg` // 小枸
|
||||||
|
S_tx = `tx` // 小秋
|
||||||
|
S_lx = `lx` // 小洛 (预留)
|
||||||
)
|
)
|
||||||
|
|
||||||
// 源查询接口
|
// 源查询接口
|
||||||
|
@ -1,5 +1,11 @@
|
|||||||
## Lx-Source/更新日志
|
## Lx-Source/更新日志
|
||||||
|
|
||||||
|
#### 2023-12-31 v1.0.2-b0.8.2 (dev)
|
||||||
|
- 注:本次还是累积更新,不单独发布Release
|
||||||
|
+ 从Python版移植部分代码
|
||||||
|
+ (兼容tx源一分钟试听链接获取)
|
||||||
|
+ 优化速率限制相关逻辑
|
||||||
|
|
||||||
#### 2023-12-30 v1.0.2-b0.8.1 (dev)
|
#### 2023-12-30 v1.0.2-b0.8.1 (dev)
|
||||||
+ 注:本次累积更新,不单独发布Release
|
+ 注:本次累积更新,不单独发布Release
|
||||||
+ 实现单ip速率限制,配置方法:
|
+ 实现单ip速率限制,配置方法:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user