2024-06-14 v1.0.3.0614

This commit is contained in:
ZxwyWebSite 2024-06-15 01:03:38 +08:00
parent 76e7f5a1b6
commit 55e7c6227e
9 changed files with 431 additions and 89 deletions

269
action.go
View File

@ -12,6 +12,7 @@ import (
"path/filepath" "path/filepath"
"runtime" "runtime"
"strings" "strings"
"unicode"
) )
const ( const (
@ -23,7 +24,10 @@ const (
args_home = `/home/runner` // 用户目录 args_home = `/home/runner` // 用户目录
) )
var workDir string var (
workDir string
homeDir string
)
func init() { func init() {
if runtime.GOOS != `linux` { if runtime.GOOS != `linux` {
@ -32,21 +36,35 @@ func init() {
} }
workDir, _ = os.Getwd() workDir, _ = os.Getwd()
fmt.Println(`运行目录:`, workDir) fmt.Println(`运行目录:`, workDir)
homeDir = os.Getenv(`HOME`)
if homeDir == `` {
homeDir = args_home
}
fmt.Println(`用户目录:`, homeDir)
} }
type ( type (
// 架构参数 [v2]
list_vers map[string]struct { list_vers map[string]struct {
Tags string Tags string
} }
list_arch map[string]struct { // CGO参数 [nil]
AR string list_cgos struct {
CC string AR string
CXX string CC string
Vers list_vers CXX string
} }
// 架构列表 [amd64]
list_arch map[string]struct {
Cgos *list_cgos
Vers list_vers
Venv string // 覆盖架构参数名 'mipsle'->'GOMIPS'
}
// 目标系统 [linux]
list_goos map[string]struct { list_goos map[string]struct {
Arch list_arch Arch list_arch
} }
// 编译环境 [go1.20.14]
list_conf map[string]struct { list_conf map[string]struct {
Args []string Args []string
GoOS list_goos GoOS list_goos
@ -66,9 +84,24 @@ type param struct {
GoIns string // 指令 GOAMD64=v2 GoIns string // 指令 GOAMD64=v2
Args []string // 参数 ldflags Args []string // 参数 ldflags
Tag string // 标志 go_json Tag string // 标志 go_json
AR string Cgos *list_cgos
CC string Venv string
CXX string }
// 获取相对用户目录
func home(str string) string {
return homeDir + `/` + str
}
// 检测环境是否存在
func chkenv(s ...string) (err error) {
for _, f := range s {
if _, e := exec.LookPath(f); e != nil && !errors.Is(e, exec.ErrDot) {
err = fmt.Errorf(`未找到指定环境: %s`, e)
break
}
}
return
} }
func main() { func main() {
@ -79,9 +112,11 @@ func main() {
`linux`: { `linux`: {
Arch: list_arch{ Arch: list_arch{
`amd64`: { `amd64`: {
AR: `x86_64-linux-gnu-ar`, Cgos: &list_cgos{
CC: `x86_64-linux-gnu-gcc`, AR: `x86_64-linux-gnu-ar`,
CXX: `x86_64-linux-gnu-g++`, CC: `x86_64-linux-gnu-gcc`,
CXX: `x86_64-linux-gnu-g++`,
},
Vers: list_vers{ Vers: list_vers{
`v1`: { `v1`: {
Tags: `go_json`, Tags: `go_json`,
@ -98,9 +133,11 @@ func main() {
}, },
}, },
`arm`: { `arm`: {
AR: `arm-linux-gnueabihf-gcc-ar`, Cgos: &list_cgos{
CC: `arm-linux-gnueabihf-gcc`, AR: `arm-linux-gnueabihf-gcc-ar`,
CXX: `arm-linux-gnueabihf-cpp`, CC: `arm-linux-gnueabihf-gcc`,
CXX: `arm-linux-gnueabihf-cpp`,
},
Vers: list_vers{ Vers: list_vers{
`5`: { `5`: {
Tags: `go_json`, Tags: `go_json`,
@ -114,23 +151,70 @@ func main() {
}, },
}, },
`arm64`: { `arm64`: {
AR: `aarch64-linux-gnu-gcc-ar`, Cgos: &list_cgos{
CC: `aarch64-linux-gnu-gcc`, AR: `aarch64-linux-gnu-gcc-ar`,
CXX: `aarch64-linux-gnu-cpp`, CC: `aarch64-linux-gnu-gcc`,
CXX: `aarch64-linux-gnu-cpp`,
},
Vers: list_vers{ Vers: list_vers{
``: { ``: {
Tags: `go_json`, Tags: `go_json`,
}, },
}, },
}, },
// 针对部分OpenWrt路由器系统 暂不支持开启CGO
`mips`: {
Vers: list_vers{
`hardfloat`: {
Tags: `go_json`,
},
`softfloat`: {
Tags: `go_json`,
},
},
},
`mipsle`: {
Vers: list_vers{
`hardfloat`: {
Tags: `go_json`,
},
`softfloat`: {
Tags: `go_json`,
},
},
Venv: `MIPS`,
},
`mips64`: {
Vers: list_vers{
`hardfloat`: {
Tags: `go_json`,
},
`softfloat`: {
Tags: `go_json`,
},
},
},
`mips64le`: {
Vers: list_vers{
`hardfloat`: {
Tags: `go_json`,
},
`softfloat`: {
Tags: `go_json`,
},
},
Venv: `MIPS64`,
},
}, },
}, },
`windows`: { `windows`: {
Arch: list_arch{ Arch: list_arch{
`amd64`: { `amd64`: {
AR: `x86_64-w64-mingw32-ar`, Cgos: &list_cgos{
CC: `x86_64-w64-mingw32-gcc`, AR: `x86_64-w64-mingw32-ar`,
CXX: `x86_64-w64-mingw32-cpp`, CC: `x86_64-w64-mingw32-gcc`,
CXX: `x86_64-w64-mingw32-cpp`,
},
Vers: list_vers{ Vers: list_vers{
`v2`: { `v2`: {
Tags: `go_json`, Tags: `go_json`,
@ -148,9 +232,11 @@ func main() {
`android`: { `android`: {
Arch: list_arch{ Arch: list_arch{
`amd64`: { `amd64`: {
AR: args_home + `/android-ndk-r26b/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar`, Cgos: &list_cgos{
CC: args_home + `/android-ndk-r26b/toolchains/llvm/prebuilt/linux-x86_64/bin/x86_64-linux-android24-clang`, AR: home(`android-ndk-r26b/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar`),
CXX: args_home + `/android-ndk-r26b/toolchains/llvm/prebuilt/linux-x86_64/bin/x86_64-linux-android24-clang++`, CC: home(`android-ndk-r26b/toolchains/llvm/prebuilt/linux-x86_64/bin/x86_64-linux-android24-clang`),
CXX: home(`android-ndk-r26b/toolchains/llvm/prebuilt/linux-x86_64/bin/x86_64-linux-android24-clang++`),
},
Vers: list_vers{ Vers: list_vers{
``: { ``: {
Tags: `go_json`, Tags: `go_json`,
@ -158,9 +244,11 @@ func main() {
}, },
}, },
`arm64`: { `arm64`: {
AR: args_home + `/android-ndk-r26b/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar`, Cgos: &list_cgos{
CC: args_home + `/android-ndk-r26b/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android24-clang`, AR: home(`android-ndk-r26b/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar`),
CXX: args_home + `/android-ndk-r26b/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android24-clang++`, CC: home(`android-ndk-r26b/toolchains/llvm/prebuilt/linux-x86_64/bin/x86_64-linux-android24-clang`),
CXX: home(`android-ndk-r26b/toolchains/llvm/prebuilt/linux-x86_64/bin/x86_64-linux-android24-clang++`),
},
Vers: list_vers{ Vers: list_vers{
``: { ``: {
Tags: `go_json`, Tags: `go_json`,
@ -168,9 +256,11 @@ func main() {
}, },
}, },
`386`: { `386`: {
AR: args_home + `/android-ndk-r26b/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar`, Cgos: &list_cgos{
CC: args_home + `/android-ndk-r26b/toolchains/llvm/prebuilt/linux-x86_64/bin/i686-linux-android24-clang`, AR: home(`android-ndk-r26b/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar`),
CXX: args_home + `/android-ndk-r26b/toolchains/llvm/prebuilt/linux-x86_64/bin/i686-linux-android24-clang++`, CC: home(`android-ndk-r26b/toolchains/llvm/prebuilt/linux-x86_64/bin/x86_64-linux-android24-clang`),
CXX: home(`android-ndk-r26b/toolchains/llvm/prebuilt/linux-x86_64/bin/x86_64-linux-android24-clang++`),
},
Vers: list_vers{ Vers: list_vers{
``: { ``: {
Tags: `go_json`, Tags: `go_json`,
@ -178,9 +268,33 @@ func main() {
}, },
}, },
`arm`: { `arm`: {
AR: args_home + `/android-ndk-r26b/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar`, Cgos: &list_cgos{
CC: args_home + `/android-ndk-r26b/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi24-clang`, AR: home(`android-ndk-r26b/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar`),
CXX: args_home + `/android-ndk-r26b/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi24-clang++`, CC: home(`android-ndk-r26b/toolchains/llvm/prebuilt/linux-x86_64/bin/x86_64-linux-android24-clang`),
CXX: home(`android-ndk-r26b/toolchains/llvm/prebuilt/linux-x86_64/bin/x86_64-linux-android24-clang++`),
},
Vers: list_vers{
``: {
Tags: `go_json`,
},
},
},
},
},
// Mac OS
`darwin`: {
Arch: list_arch{
`amd64`: {
Vers: list_vers{
`v2`: {
Tags: `go_json`,
},
`v3`: {
Tags: `sonic avx`,
},
},
},
`arm64`: {
Vers: list_vers{ Vers: list_vers{
``: { ``: {
Tags: `go_json`, Tags: `go_json`,
@ -189,27 +303,22 @@ func main() {
}, },
}, },
}, },
// `darwin`: {
// Arch: list_arch{
// `amd64`: {
// CC: ``,
// },
// `arm64`: {
// CC: ``,
// },
// },
// },
}, },
}, },
args_home + `/go/bin/go1.20.14`: { home(`go/bin/go1.20.14`): {
Args: def_args, Args: []string{
`-trimpath`, `-buildvcs=false`,
`-ldflags`, `-s -w`,
},
GoOS: list_goos{ GoOS: list_goos{
`windows`: { `windows`: {
Arch: list_arch{ Arch: list_arch{
`amd64`: { `amd64`: {
AR: `x86_64-w64-mingw32-ar`, Cgos: &list_cgos{
CC: `x86_64-w64-mingw32-gcc`, AR: `x86_64-w64-mingw32-ar`,
CXX: `x86_64-w64-mingw32-cpp`, CC: `x86_64-w64-mingw32-gcc`,
CXX: `x86_64-w64-mingw32-cpp`,
},
Vers: list_vers{ Vers: list_vers{
`v1`: { `v1`: {
Tags: `go_json`, Tags: `go_json`,
@ -237,8 +346,24 @@ func main() {
`, args_name, args_path, args_zpak) `, args_name, args_path, args_zpak)
// 解析配置文件 // 解析配置文件
for goVer, conf_list := range def_list { for goVer, conf_list := range def_list {
// 环境检测
if err := chkenv(goVer); err != nil {
fmt.Println(err, `跳过该环境`)
continue
}
for goOS, goos_list := range conf_list.GoOS { for goOS, goos_list := range conf_list.GoOS {
for goArch, arch_list := range goos_list.Arch { for goArch, arch_list := range goos_list.Arch {
// 工具链检测
if arch_list.Cgos != nil {
if err := chkenv(
arch_list.Cgos.AR,
arch_list.Cgos.CC,
arch_list.Cgos.CXX,
); err != nil {
fmt.Println(err, `跳过该架构`)
continue
}
}
for goIns, vers_list := range arch_list.Vers { for goIns, vers_list := range arch_list.Vers {
// 构建程序二进制 // 构建程序二进制
if err := build(&param{ if err := build(&param{
@ -248,9 +373,8 @@ func main() {
GoIns: goIns, GoIns: goIns,
Args: conf_list.Args, Args: conf_list.Args,
Tag: vers_list.Tags, Tag: vers_list.Tags,
AR: arch_list.AR, Cgos: arch_list.Cgos,
CC: arch_list.CC, Venv: arch_list.Venv,
CXX: arch_list.CXX,
}); err != nil { }); err != nil {
fmt.Println(`err:`, err) fmt.Println(`err:`, err)
} }
@ -262,15 +386,6 @@ func main() {
} }
func build(p *param) (err error) { func build(p *param) (err error) {
// 检测必要环境
for _, f := range []string{
p.GoVer, p.AR, p.CC, p.CXX,
} {
if _, e := exec.LookPath(f); e != nil && !errors.Is(e, exec.ErrDot) {
err = fmt.Errorf(`未找到指定环境: %s`, e)
return
}
}
// 拼接程序名称 // 拼接程序名称
var b strings.Builder var b strings.Builder
b.WriteString(args_name) // lx-source b.WriteString(args_name) // lx-source
@ -278,7 +393,17 @@ func build(p *param) (err error) {
b.WriteString(p.GoOS) // lx-source-linux b.WriteString(p.GoOS) // lx-source-linux
b.WriteByte('-') // lx-source-linux- b.WriteByte('-') // lx-source-linux-
b.WriteString(p.GoArch) // lx-source-linux-amd64 b.WriteString(p.GoArch) // lx-source-linux-amd64
b.WriteString(p.GoIns) // lx-source-linux-amd64v2 var digit byte
if p.Venv != `` {
digit = p.Venv[len(p.Venv)-1]
} else {
digit = p.GoArch[len(p.GoArch)-1]
}
if !unicode.IsDigit(rune(digit)) {
// 架构名结尾不是数字的再加一个连字符
b.WriteByte('-') // lx-source-linux-mipsle-softfloat
}
b.WriteString(p.GoIns) // lx-source-linux-amd64v2
if biname := filepath.Base(p.GoVer); biname != `go` { if biname := filepath.Base(p.GoVer); biname != `go` {
b.WriteByte('-') // lx-source-linux-amd64v2- b.WriteByte('-') // lx-source-linux-amd64v2-
b.WriteString(biname) // lx-source-linux-amd64v2-go1.20.14 b.WriteString(biname) // lx-source-linux-amd64v2-go1.20.14
@ -309,12 +434,24 @@ func build(p *param) (err error) {
cmd.Env = append(os.Environ(), []string{ cmd.Env = append(os.Environ(), []string{
`GOOS=` + p.GoOS, `GOOS=` + p.GoOS,
`GOARCH=` + p.GoArch, `GOARCH=` + p.GoArch,
`AR=` + p.AR,
`CC=` + p.CC,
`CXX=` + p.CXX,
`CGO_ENABLED=1`,
`GO` + strings.ToUpper(p.GoArch) + `=` + p.GoIns,
}...) }...)
if p.Cgos != nil {
cmd.Env = append(cmd.Env, []string{
`AR=` + p.Cgos.AR,
`CC=` + p.Cgos.CC,
`CXX=` + p.Cgos.CXX,
`CGO_ENABLED=1`,
}...)
} else {
cmd.Env = append(cmd.Env, `CGO_ENABLED=0`)
}
if p.GoIns != `` {
if p.Venv != `` {
cmd.Env = append(cmd.Env, `GO`+p.Venv+`=`+p.GoIns)
} else {
cmd.Env = append(cmd.Env, `GO`+strings.ToUpper(p.GoArch)+`=`+p.GoIns)
}
}
if err = cmd.Start(); err == nil { if err = cmd.Start(); err == nil {
err = cmd.Wait() err = cmd.Wait()

3
src/env/env.go vendored
View File

@ -12,7 +12,7 @@ import (
) )
const ( const (
Version = `1.0.3.0518` Version = `1.0.3.0614`
) )
var ( var (
@ -124,6 +124,7 @@ type (
Kw_Bd_DevId string `comment:"field user.device_id"` Kw_Bd_DevId string `comment:"field user.device_id"`
// kw kwdes // kw kwdes
Kw_Des_Type string `comment:"返回格式 0: text, 1: json"` Kw_Des_Type string `comment:"返回格式 0: text, 1: json"`
Kw_Des_Source string `comment:"query source"`
Kw_Des_Header string `comment:"请求头 User-Agent"` Kw_Des_Header string `comment:"请求头 User-Agent"`
// kg // kg

View File

@ -1,15 +1,19 @@
package kw package kw
import ( import (
"errors"
"io" "io"
"lx-source/src/env" "lx-source/src/env"
"lx-source/src/sources" "lx-source/src/sources"
"lx-source/src/sources/custom/utils" "lx-source/src/sources/custom/utils"
"net/http" "net/http"
"strconv" "strconv"
"strings"
"sync" "sync"
"github.com/ZxwyWebSite/ztool" "github.com/ZxwyWebSite/ztool"
"github.com/ZxwyWebSite/ztool/x/bytesconv"
"github.com/ZxwyWebSite/ztool/zcypt"
) )
var ( var (
@ -19,6 +23,7 @@ var (
parsemod bool parsemod bool
convtype string convtype string
desource string
// desParse func([]byte, *playInfo) error // desParse func([]byte, *playInfo) error
// desParse func(any) ztool.Net_ResHandlerFunc // desParse func(any) ztool.Net_ResHandlerFunc
) )
@ -36,11 +41,13 @@ func init() {
) { ) {
loger.Fatal(`使用bdapi且验证参数为空`) loger.Fatal(`使用bdapi且验证参数为空`)
} }
// bdheader[`token`] = env.Config.Custom.Kw_Bd_Token
bdheader[`uid`] = env.Config.Custom.Kw_Bd_Uid bdheader[`uid`] = env.Config.Custom.Kw_Bd_Uid
bdheader[`devId`] = env.Config.Custom.Kw_Bd_DevId bdheader[`devId`] = env.Config.Custom.Kw_Bd_DevId
kw_pool = &sync.Pool{New: func() any { return new(kwApi_Song) }} kw_pool = &sync.Pool{New: func() any { return new(kwApi_Song) }}
Url = bdapi Url = bdapi
case `1`, `kwdes`: case `1`, `kwdes`:
Url = kwdes
switch env.Config.Custom.Kw_Des_Type { switch env.Config.Custom.Kw_Des_Type {
case `0`, `text`: case `0`, `text`:
loger.Debug(`use kwdes text`) loger.Debug(`use kwdes text`)
@ -51,12 +58,20 @@ func init() {
convtype = `convert_url_with_sign` convtype = `convert_url_with_sign`
// desParse = ztool.Net_ResToStruct // desParse = ztool.Net_ResToStruct
parsemod = true parsemod = true
case `2`, `anti`:
loger.Debug(`use kwdes anti`)
Url = manti
default: default:
loger.Fatal(`未定义的返回格式,请检查配置 [Custom].Kw_Des_Type`) loger.Fatal(`未定义的返回格式,请检查配置 [Custom].Kw_Des_Type`)
} }
desheader[`User-Agent`] = env.Config.Custom.Kw_Des_Header desheader[`User-Agent`] = env.Config.Custom.Kw_Des_Header
kw_pool = &sync.Pool{New: func() any { return new(playInfo) }} kw_pool = &sync.Pool{New: func() any { return new(playInfo) }}
Url = kwdes if env.Config.Custom.Kw_Des_Source != `` {
desource = env.Config.Custom.Kw_Des_Source
} else {
dec, _ := zcypt.HexDecode([]byte{0x36, 0x62, 0x37, 0x37, 0x37, 0x30, 0x36, 0x63, 0x36, 0x31, 0x37, 0x39, 0x36, 0x35, 0x37, 0x32, 0x36, 0x38, 0x36, 0x34, 0x35, 0x66, 0x36, 0x31, 0x37, 0x32, 0x35, 0x66, 0x33, 0x35, 0x32, 0x65, 0x33, 0x31, 0x32, 0x65, 0x33, 0x30, 0x32, 0x65, 0x33, 0x30, 0x35, 0x66, 0x34, 0x32, 0x35, 0x66, 0x36, 0x61, 0x36, 0x39, 0x36, 0x31, 0x36, 0x62, 0x36, 0x66, 0x36, 0x65, 0x36, 0x37, 0x35, 0x66, 0x37, 0x36, 0x36, 0x38, 0x32, 0x65, 0x36, 0x31, 0x37, 0x30, 0x36, 0x62})
desource = bytesconv.BytesToString(dec)
}
default: default:
loger.Fatal(`未定义的接口模式,请检查配置 [Custom].Kw_Mode`) loger.Fatal(`未定义的接口模式,请检查配置 [Custom].Kw_Mode`)
} }
@ -92,7 +107,7 @@ func bdapi(songMid, quality string) (ourl, msg string) {
loger.Debug(`Resp: %+v`, resp) loger.Debug(`Resp: %+v`, resp)
if resp.Code != 200 || resp.Data.AudioInfo.Bitrate == `1` { if resp.Code != 200 || resp.Data.AudioInfo.Bitrate == `1` {
// jx.Debug(`Kw, Err: %#v`, resp) // jx.Debug(`Kw, Err: %#v`, resp)
msg = ztool.Str_FastConcat(`failed: `, resp.Msg) msg = ztool.Str_FastConcat(strconv.Itoa(resp.Code), `: `, resp.Msg)
return return
} }
ourl = utils.DelQuery(resp.Data.URL) //strings.Split(resp.Data.URL, `?`)[0] ourl = utils.DelQuery(resp.Data.URL) //strings.Split(resp.Data.URL, `?`)[0]
@ -110,12 +125,12 @@ func kwdes(songMid, quality string) (ourl, msg string) {
target_url := ztool.Str_FastConcat( target_url := ztool.Str_FastConcat(
`https://mobi.kuwo.cn/mobi.s?f=kuwo&q=`, `https://mobi.kuwo.cn/mobi.s?f=kuwo&q=`,
base64_encrypt(ztool.Str_FastConcat( base64_encrypt(ztool.Str_FastConcat(
`corp=kuwo&source=kwplayer_ar_1.1.9_oppo_118980_320.apk&p2p=1&sig=0`, `corp=kuwo&p2p=1&sig=0&notrace=0&priority=bitrate&network=WIFI&mode=down`,
`&source=`, desource,
`&type=`, convtype, `&type=`, convtype,
`&br=`, infoFile.H, infoFile.E, `&br=`, infoFile.H, infoFile.E,
`&format=`, infoFile.E, `&format=`, infoFile.E,
`&rid=`, songMid, `&rid=`, songMid,
`&notrace=0&priority=bitrate&network=WIFI&mode=down`,
)), )),
) )
if parsemod { if parsemod {
@ -131,6 +146,7 @@ func kwdes(songMid, quality string) (ourl, msg string) {
msg = sources.ErrHttpReq msg = sources.ErrHttpReq
return return
} }
resp.Data.URL = utils.DelQuery(resp.Data.URL)
loger.Debug(`Resp: %+v`, resp) loger.Debug(`Resp: %+v`, resp)
if resp.Code != http.StatusOK { if resp.Code != http.StatusOK {
msg = ztool.Str_FastConcat(`failed: `, resp.Msg) msg = ztool.Str_FastConcat(`failed: `, resp.Msg)
@ -144,7 +160,7 @@ func kwdes(songMid, quality string) (ourl, msg string) {
return return
} }
} }
ourl = utils.DelQuery(resp.Data.URL) //resp.Data.URL[:strings.Index(resp.Data.URL, `?`)] ourl = resp.Data.URL //resp.Data.URL[:strings.Index(resp.Data.URL, `?`)]
return return
} }
ztool.Net_Request(http.MethodGet, target_url, nil, ztool.Net_Request(http.MethodGet, target_url, nil,
@ -179,3 +195,133 @@ func kwdes(songMid, quality string) (ourl, msg string) {
) )
return return
} }
// 一种替代方案仅在试听可用时获取cdn前缀缺点是无法获取不能试听的歌曲
func manti(songMid, quality string) (ourl, msg string) {
loger := env.Loger.NewGroup(`Kw`)
defer loger.Free()
infoFile, ok := fileInfo[quality]
if !ok {
msg = sources.E_QNotSupport
return
}
// 获取CDN地址
// var out_a string
/*var out_c struct {
// Timestamp int `json:"timestamp"`
Songs []struct {
ID int `json:"id"`
Duration int `json:"duration"`
URL string `json:"url"`
HTTPS string `json:"https"`
CarURL string `json:"car_url"`
CarURLHTTPS string `json:"car_url_https"`
Format string `json:"format"`
Br int `json:"br"`
OverseasCopyright string `json:"overseas_copyright"`
Start int `json:"start"`
End int `json:"end"`
Group string `json:"group"`
} `json:"songs"`
IP string `json:"ip"`
Country string `json:"country"`
Region string `json:"region"`
Locationid int `json:"locationid"`
Code int `json:"code"`
Result string `json:"result"`
}
err := ztool.Net_Request(
http.MethodGet,
`https://musicpay30.kuwo.cn/audi.tion?op=query&ids=`+songMid,
nil,
[]ztool.Net_ReqHandlerFunc{ztool.Net_ReqAddHeaders()},
[]ztool.Net_ResHandlerFunc{ztool.Net_ResToStruct(&out_c)},
)
if err != nil {
loger.Error(`Request: %s`, err)
msg = sources.ErrHttpReq
return
}*/
// 获取音频路径
if quality != sources.Q_128k {
ourl, msg = manti(songMid, sources.Q_128k)
if msg != `` {
return
}
if i := strings.LastIndexByte(ourl, '/'); i != -1 {
if ourl[i+1:] == `2272659253.mp3` {
msg = sources.ErrNoLink
return
}
}
target_url := ztool.Str_FastConcat(
`https://mobi.kuwo.cn/mobi.s?f=web&type=convert_url`,
`&br=`, infoFile.H, infoFile.E,
`&format=`, infoFile.E,
`&rid=`, songMid,
)
var out_u, realQuality string
err := ztool.Net_Request(
http.MethodGet, target_url, nil,
[]ztool.Net_ReqHandlerFunc{ztool.Net_ReqAddHeaders()},
[]ztool.Net_ResHandlerFunc{func(res *http.Response) (err error) {
var data []byte
data, err = io.ReadAll(res.Body)
if err != nil {
return
}
if res.StatusCode != http.StatusOK {
return errors.New(`failed: ` + res.Status)
}
infoData := mkMap(data)
loger.Debug(`uData: %+v`, infoData)
realQuality = infoData[`bitrate`]
out_u = utils.DelQuery(infoData[`url`])
return
}},
)
if err != nil {
loger.Error(`Request: %s`, err)
msg = sources.ErrHttpReq
return
}
if realQuality != infoFile.H[:len(infoFile.H)-1] {
msg = sources.E_QNotMatch
if !env.Config.Source.ForceFallback {
return
}
}
if ourl != `` && out_u != `` {
ourl = ourl[:24] + out_u
}
return
}
resp := kw_pool.Get().(*playInfo)
defer kw_pool.Put(resp)
err := ztool.Net_Request(
http.MethodGet, `https://mobi.kuwo.cn/mobi.s?f=web&type=convert_url_with_sign&br=128kmp3&format=mp3&rid=`+songMid, nil,
[]ztool.Net_ReqHandlerFunc{ztool.Net_ReqAddHeader(desheader)},
[]ztool.Net_ResHandlerFunc{ztool.Net_ResToStruct(&resp)},
)
if err != nil {
loger.Error(`Request: %s`, err)
msg = sources.ErrHttpReq
return
}
loger.Debug(`tData: %+v`, resp)
if resp.Code != http.StatusOK {
msg = ztool.Str_FastConcat(`failed: `, resp.Msg)
loger.Debug(msg)
return
}
realQuality := strconv.Itoa(resp.Data.Bitrate)
if realQuality != infoFile.H[:len(infoFile.H)-1] && resp.Data.Bitrate != 1 {
msg = sources.E_QNotMatch
if !env.Config.Source.ForceFallback {
return
}
}
ourl = utils.DelQuery(resp.Data.URL)
return
}

View File

@ -13,8 +13,8 @@ type (
Format string `json:"format"` Format string `json:"format"`
P2PAudiosourceid string `json:"p2p_audiosourceid"` P2PAudiosourceid string `json:"p2p_audiosourceid"`
Rid int `json:"rid"` Rid int `json:"rid"`
Source string `json:"source"` // Source string `json:"source"`
URL string `json:"url"` URL string `json:"url"`
} `json:"data"` } `json:"data"`
Msg string `json:"msg"` Msg string `json:"msg"`
} }

View File

@ -40,25 +40,64 @@ var (
// `User-Agent`: `okhttp/3.10.0`, // `User-Agent`: `okhttp/3.10.0`,
} }
bdheader = map[string]string{ bdheader = map[string]string{
`channel`: `qq`, `channel`: `guanfang`,
`plat`: `ar`, `plat`: `ar`,
`net`: `wifi`, `net`: `wifi`,
`ver`: `3.1.2`, `ver`: `3.1.4`,
// `uid`: ``, `api-ver`: `application/json`,
// `devId`: `0`,
`user-agent`: `Dart/2.18 (dart:io)`, //`Dalvik/2.1.0 (Linux; U; Android 7.1.1; OPPO R9sk Build/NMF26F)`,
} }
// bdsreg = regexp.MustCompile(`[^a-zA-Z0-9]`)
) )
func mkMap(data []byte) map[string]string { func mkMap(data []byte) map[string]string {
out := make(map[string]string) out := make(map[string]string)
sep := bytes.Split(data, []byte{13, 10}) sep := bytes.Split(data, []byte{13, 10})
for i, r := 0, len(sep); i < r; i++ { for i, r := 0, len(sep); i < r; i++ {
pat := bytes.Split(sep[i], []byte{61}) var s = sep[i]
if len(pat) == 2 { if p := bytes.IndexByte(s, '='); p != -1 {
out[bytesconv.BytesToString(s[:p])] = bytesconv.BytesToString(s[p+1:])
continue
} else {
out[`_`] += bytesconv.BytesToString(s) + `;`
}
/*pat := bytes.Split(sep[i], []byte{61})
if len(pat) >= 2 {
out[bytesconv.BytesToString(pat[0])] = bytesconv.BytesToString(pat[1]) out[bytesconv.BytesToString(pat[0])] = bytesconv.BytesToString(pat[1])
continue continue
} }
out[`_`] += bytesconv.BytesToString(pat[0]) + `;` out[`_`] += bytesconv.BytesToString(pat[0]) + `;`*/
} }
return out return out
} }
// 波点签名算法
/*func Bdsign(str string, m, m2 map[string]string) *strings.Builder {
var b strings.Builder
b.WriteString(`uid=`)
b.WriteString(env.Config.Custom.Kw_Bd_Uid)
b.WriteByte('&')
b.WriteString(`token=`)
b.WriteString(env.Config.Custom.Kw_Bd_Token)
b.WriteByte('&')
b.WriteString(`timestamp=`)
b.WriteString(strconv.FormatInt(time.Now().UnixMilli(), 10))
for k, v := range m2 {
b.WriteByte('&')
b.WriteString(k)
b.WriteByte('=')
b.WriteString(url.QueryEscape(v))
}
// 取 strings.Builder.buf []byte 地址
pb := (*[]byte)(unsafe.Pointer(uintptr(unsafe.Pointer(&b)) + unsafe.Sizeof((*strings.Builder)(nil))))
charArray := bdsreg.ReplaceAll(*pb, []byte{})
slices.Sort(charArray)
str3 := string(charArray)
fmt.Println(str3)
lowerCase := zcypt.MD5EncStr(`kuwotest` + str3 + `/api/play/music/v2/audioUrl`)
b.WriteByte('&')
b.WriteString(`sign=`)
b.WriteString(lowerCase)
return &b
}*/

View File

@ -343,8 +343,8 @@ func Qlogin_graph(l *logs.Logger) error {
env.Config.Custom.Tx_Enable = true env.Config.Custom.Tx_Enable = true
env.Config.Custom.Tx_Uuin = out6.Req.Data.StrMusicid env.Config.Custom.Tx_Uuin = out6.Req.Data.StrMusicid
env.Config.Custom.Tx_Ukey = out6.Req.Data.Musickey env.Config.Custom.Tx_Ukey = out6.Req.Data.Musickey
env.Config.Custom.Tx_Refresh_Enable = true env.Config.Custom.Tx_Refresh_Enable = false
env.Config.Custom.Tx_Refresh_Interval = time.Date(now.Year(), now.Month(), now.Day()+5, 0, 0, 0, 0, now.Location()).Unix() // env.Config.Custom.Tx_Refresh_Interval = time.Date(now.Year(), now.Month(), now.Day()+5, 0, 0, 0, 0, now.Location()).Unix()
// env.Config.Custom.Tx_RefreshToken = out6.Req.Data.RefreshToken // env.Config.Custom.Tx_RefreshToken = out6.Req.Data.RefreshToken
// env.Config.Custom.Tx_AccessToken = out6.Req.Data.AccessToken // env.Config.Custom.Tx_AccessToken = out6.Req.Data.AccessToken

View File

@ -123,9 +123,18 @@ func refresh(loger *logs.Logger, now int64) error {
// loger.Error(`请求Api失败: %s`, err) // loger.Error(`请求Api失败: %s`, err)
return errors.New(`请求Api失败: ` + err.Error()) return errors.New(`请求Api失败: ` + err.Error())
} }
loger.Debug(`Resp: %+v`, resp)
if resp.Req1.Code != 0 { if resp.Req1.Code != 0 {
switch resp.Req1.Code {
case 1000:
return fmt.Errorf(`%v: Token无效或已过期`, resp.Req1.Code)
case 2000:
return fmt.Errorf(`%v: 该Token不支持刷新`, resp.Req1.Code)
default:
return fmt.Errorf(`%v: 刷新登录失败`, resp.Req1.Code)
}
// loger.Warn("刷新登录失败, code: %v\n响应体: %+v", resp.Req1.Code, resp) // loger.Warn("刷新登录失败, code: %v\n响应体: %+v", resp.Req1.Code, resp)
return fmt.Errorf("刷新登录失败, code: %v\n响应体: %+v", resp.Req1.Code, resp) // return fmt.Errorf("刷新登录失败, code: %v\n响应体: %+v", resp.Req1.Code, resp)
} }
loger.Info(`刷新登录成功`) loger.Info(`刷新登录成功`)
env.Config.Custom.Tx_Uuin = resp.Req1.Data.StrMusicId env.Config.Custom.Tx_Uuin = resp.Req1.Data.StrMusicId

View File

@ -20,7 +20,11 @@ import (
const anonymous_token = `1f5fa7b6a6a9f81a11886e5186fde7fb98e25cf0036d7afd055b980b2261f5464b7f5273fc3921d1262bfec66a19a30c41d8da00c3685f5ace96f0d5a48b6db334d974731083682e3324751bcc9aaf44c3061cd1` const anonymous_token = `1f5fa7b6a6a9f81a11886e5186fde7fb98e25cf0036d7afd055b980b2261f5464b7f5273fc3921d1262bfec66a19a30c41d8da00c3685f5ace96f0d5a48b6db334d974731083682e3324751bcc9aaf44c3061cd1`
var wapiReg = regexp.MustCompile(`\w*api`) var (
wapiReg = regexp.MustCompile(`\w*api`)
csrfReg = regexp.MustCompile(`_csrf=([^(;|$)]+)`)
domaReg = regexp.MustCompile(`\s*Domain=[^(;|$)]+;*`)
)
var userAgentMap = map[string]string{ var userAgentMap = map[string]string{
`mobile`: `Mozilla/5.0 (iPhone; CPU iPhone OS 17_2_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.2 Mobile/15E148 Safari/604.1`, `mobile`: `Mozilla/5.0 (iPhone; CPU iPhone OS 17_2_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.2 Mobile/15E148 Safari/604.1`,
@ -103,8 +107,7 @@ func createRequest(method, url string, data map[string]any, options reqOptions)
switch options.Crypto { switch options.Crypto {
case `weapi`: case `weapi`:
options.Headers[`User-Agent`] = `Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36 Edg/116.0.1938.69` options.Headers[`User-Agent`] = `Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36 Edg/116.0.1938.69`
reg := regexp.MustCompile(`_csrf=([^(;|$)]+)`) csrfToken := csrfReg.FindStringSubmatch(options.Headers[`Cookie`])
csrfToken := reg.FindStringSubmatch(options.Headers[`Cookie`])
if len(csrfToken) > 1 { if len(csrfToken) > 1 {
data[`csrf_token`] = csrfToken[1] data[`csrf_token`] = csrfToken[1]
} else { } else {
@ -189,9 +192,8 @@ func createRequest(method, url string, data map[string]any, options reqOptions)
} }
if err == nil { if err == nil {
answer.Cookie = res.Header[`Set-Cookie`] //res.Header.Values(`set-cookie`) answer.Cookie = res.Header[`Set-Cookie`] //res.Header.Values(`set-cookie`)
reg := regexp.MustCompile(`\s*Domain=[^(;|$)]+;*`)
for i, v := range answer.Cookie { for i, v := range answer.Cookie {
answer.Cookie[i] = reg.ReplaceAllString(v, ``) answer.Cookie[i] = domaReg.ReplaceAllString(v, ``)
} }
if options.Crypto == `eapi` && body[0] != '{' { if options.Crypto == `eapi` && body[0] != '{' {
err = json.Unmarshal(decrypt(body), &answer.Body) err = json.Unmarshal(decrypt(body), &answer.Body)

View File

@ -3,6 +3,14 @@
<!-- #### \# 2024-02-14 v1.0.3-rel (release) <!-- #### \# 2024-02-14 v1.0.3-rel (release)
+ **停止更新:感谢这三个月的陪伴,现因无力维护,停止后续更新,发布最后版本,大家有缘再见** --> + **停止更新:感谢这三个月的陪伴,现因无力维护,停止后续更新,发布最后版本,大家有缘再见** -->
#### \# 2024-06-14 v1.0.3.0614 (dev)
+ 更新编译脚本,支持更多架构
#### \# 2024-05-31 v1.0.3.0531 (dev)
+ Wy源优化模块同步部分更改
+ Kw源测试接口无需白名单包名二次甚至三次查询
+ Kw源允许自定义Des_Source参数
#### \# 2024-05-25 Special Ver (dev) #### \# 2024-05-25 Special Ver (dev)
+ 更新Action构建脚本正式兼容Go1.20(windows7) + 更新Action构建脚本正式兼容Go1.20(windows7)