diff --git a/action.go b/action.go index 9b085ca..b3abf86 100644 --- a/action.go +++ b/action.go @@ -12,6 +12,7 @@ import ( "path/filepath" "runtime" "strings" + "unicode" ) const ( @@ -23,7 +24,10 @@ const ( args_home = `/home/runner` // 用户目录 ) -var workDir string +var ( + workDir string + homeDir string +) func init() { if runtime.GOOS != `linux` { @@ -32,21 +36,35 @@ func init() { } workDir, _ = os.Getwd() fmt.Println(`运行目录:`, workDir) + homeDir = os.Getenv(`HOME`) + if homeDir == `` { + homeDir = args_home + } + fmt.Println(`用户目录:`, homeDir) } type ( + // 架构参数 [v2] list_vers map[string]struct { Tags string } - list_arch map[string]struct { - AR string - CC string - CXX string - Vers list_vers + // CGO参数 [nil] + list_cgos struct { + AR string + CC string + CXX string } + // 架构列表 [amd64] + list_arch map[string]struct { + Cgos *list_cgos + Vers list_vers + Venv string // 覆盖架构参数名 'mipsle'->'GOMIPS' + } + // 目标系统 [linux] list_goos map[string]struct { Arch list_arch } + // 编译环境 [go1.20.14] list_conf map[string]struct { Args []string GoOS list_goos @@ -66,9 +84,24 @@ type param struct { GoIns string // 指令 GOAMD64=v2 Args []string // 参数 ldflags Tag string // 标志 go_json - AR string - CC string - CXX string + Cgos *list_cgos + Venv 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() { @@ -79,9 +112,11 @@ func main() { `linux`: { Arch: list_arch{ `amd64`: { - AR: `x86_64-linux-gnu-ar`, - CC: `x86_64-linux-gnu-gcc`, - CXX: `x86_64-linux-gnu-g++`, + Cgos: &list_cgos{ + AR: `x86_64-linux-gnu-ar`, + CC: `x86_64-linux-gnu-gcc`, + CXX: `x86_64-linux-gnu-g++`, + }, Vers: list_vers{ `v1`: { Tags: `go_json`, @@ -98,9 +133,11 @@ func main() { }, }, `arm`: { - AR: `arm-linux-gnueabihf-gcc-ar`, - CC: `arm-linux-gnueabihf-gcc`, - CXX: `arm-linux-gnueabihf-cpp`, + Cgos: &list_cgos{ + AR: `arm-linux-gnueabihf-gcc-ar`, + CC: `arm-linux-gnueabihf-gcc`, + CXX: `arm-linux-gnueabihf-cpp`, + }, Vers: list_vers{ `5`: { Tags: `go_json`, @@ -114,23 +151,70 @@ func main() { }, }, `arm64`: { - AR: `aarch64-linux-gnu-gcc-ar`, - CC: `aarch64-linux-gnu-gcc`, - CXX: `aarch64-linux-gnu-cpp`, + Cgos: &list_cgos{ + AR: `aarch64-linux-gnu-gcc-ar`, + CC: `aarch64-linux-gnu-gcc`, + CXX: `aarch64-linux-gnu-cpp`, + }, Vers: list_vers{ ``: { 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`: { Arch: list_arch{ `amd64`: { - AR: `x86_64-w64-mingw32-ar`, - CC: `x86_64-w64-mingw32-gcc`, - CXX: `x86_64-w64-mingw32-cpp`, + Cgos: &list_cgos{ + AR: `x86_64-w64-mingw32-ar`, + CC: `x86_64-w64-mingw32-gcc`, + CXX: `x86_64-w64-mingw32-cpp`, + }, Vers: list_vers{ `v2`: { Tags: `go_json`, @@ -148,9 +232,11 @@ func main() { `android`: { Arch: list_arch{ `amd64`: { - AR: args_home + `/android-ndk-r26b/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar`, - CC: args_home + `/android-ndk-r26b/toolchains/llvm/prebuilt/linux-x86_64/bin/x86_64-linux-android24-clang`, - CXX: args_home + `/android-ndk-r26b/toolchains/llvm/prebuilt/linux-x86_64/bin/x86_64-linux-android24-clang++`, + Cgos: &list_cgos{ + AR: home(`android-ndk-r26b/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar`), + 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`, @@ -158,9 +244,11 @@ func main() { }, }, `arm64`: { - AR: args_home + `/android-ndk-r26b/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar`, - CC: args_home + `/android-ndk-r26b/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android24-clang`, - CXX: args_home + `/android-ndk-r26b/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android24-clang++`, + Cgos: &list_cgos{ + AR: home(`android-ndk-r26b/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar`), + 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`, @@ -168,9 +256,11 @@ func main() { }, }, `386`: { - AR: args_home + `/android-ndk-r26b/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar`, - CC: args_home + `/android-ndk-r26b/toolchains/llvm/prebuilt/linux-x86_64/bin/i686-linux-android24-clang`, - CXX: args_home + `/android-ndk-r26b/toolchains/llvm/prebuilt/linux-x86_64/bin/i686-linux-android24-clang++`, + Cgos: &list_cgos{ + AR: home(`android-ndk-r26b/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar`), + 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`, @@ -178,9 +268,33 @@ func main() { }, }, `arm`: { - AR: args_home + `/android-ndk-r26b/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar`, - CC: args_home + `/android-ndk-r26b/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi24-clang`, - CXX: args_home + `/android-ndk-r26b/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi24-clang++`, + Cgos: &list_cgos{ + AR: home(`android-ndk-r26b/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar`), + 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{ ``: { Tags: `go_json`, @@ -189,27 +303,22 @@ func main() { }, }, }, - // `darwin`: { - // Arch: list_arch{ - // `amd64`: { - // CC: ``, - // }, - // `arm64`: { - // CC: ``, - // }, - // }, - // }, }, }, - args_home + `/go/bin/go1.20.14`: { - Args: def_args, + home(`go/bin/go1.20.14`): { + Args: []string{ + `-trimpath`, `-buildvcs=false`, + `-ldflags`, `-s -w`, + }, GoOS: list_goos{ `windows`: { Arch: list_arch{ `amd64`: { - AR: `x86_64-w64-mingw32-ar`, - CC: `x86_64-w64-mingw32-gcc`, - CXX: `x86_64-w64-mingw32-cpp`, + Cgos: &list_cgos{ + AR: `x86_64-w64-mingw32-ar`, + CC: `x86_64-w64-mingw32-gcc`, + CXX: `x86_64-w64-mingw32-cpp`, + }, Vers: list_vers{ `v1`: { Tags: `go_json`, @@ -237,8 +346,24 @@ func main() { `, args_name, args_path, args_zpak) // 解析配置文件 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 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 { // 构建程序二进制 if err := build(¶m{ @@ -248,9 +373,8 @@ func main() { GoIns: goIns, Args: conf_list.Args, Tag: vers_list.Tags, - AR: arch_list.AR, - CC: arch_list.CC, - CXX: arch_list.CXX, + Cgos: arch_list.Cgos, + Venv: arch_list.Venv, }); err != nil { fmt.Println(`err:`, err) } @@ -262,15 +386,6 @@ func main() { } 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 b.WriteString(args_name) // lx-source @@ -278,7 +393,17 @@ func build(p *param) (err error) { b.WriteString(p.GoOS) // lx-source-linux b.WriteByte('-') // lx-source-linux- 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` { b.WriteByte('-') // lx-source-linux-amd64v2- 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{ `GOOS=` + p.GoOS, `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 { err = cmd.Wait() diff --git a/src/env/env.go b/src/env/env.go index 53a307f..de10de8 100644 --- a/src/env/env.go +++ b/src/env/env.go @@ -12,7 +12,7 @@ import ( ) const ( - Version = `1.0.3.0518` + Version = `1.0.3.0614` ) var ( @@ -124,6 +124,7 @@ type ( Kw_Bd_DevId string `comment:"field user.device_id"` // kw kwdes Kw_Des_Type string `comment:"返回格式 0: text, 1: json"` + Kw_Des_Source string `comment:"query source"` Kw_Des_Header string `comment:"请求头 User-Agent"` // kg diff --git a/src/sources/custom/kw/player.go b/src/sources/custom/kw/player.go index c4185ce..f1cc9ed 100644 --- a/src/sources/custom/kw/player.go +++ b/src/sources/custom/kw/player.go @@ -1,15 +1,19 @@ package kw import ( + "errors" "io" "lx-source/src/env" "lx-source/src/sources" "lx-source/src/sources/custom/utils" "net/http" "strconv" + "strings" "sync" "github.com/ZxwyWebSite/ztool" + "github.com/ZxwyWebSite/ztool/x/bytesconv" + "github.com/ZxwyWebSite/ztool/zcypt" ) var ( @@ -19,6 +23,7 @@ var ( parsemod bool convtype string + desource string // desParse func([]byte, *playInfo) error // desParse func(any) ztool.Net_ResHandlerFunc ) @@ -36,11 +41,13 @@ func init() { ) { loger.Fatal(`使用bdapi且验证参数为空`) } + // bdheader[`token`] = env.Config.Custom.Kw_Bd_Token bdheader[`uid`] = env.Config.Custom.Kw_Bd_Uid bdheader[`devId`] = env.Config.Custom.Kw_Bd_DevId kw_pool = &sync.Pool{New: func() any { return new(kwApi_Song) }} Url = bdapi case `1`, `kwdes`: + Url = kwdes switch env.Config.Custom.Kw_Des_Type { case `0`, `text`: loger.Debug(`use kwdes text`) @@ -51,12 +58,20 @@ func init() { convtype = `convert_url_with_sign` // desParse = ztool.Net_ResToStruct parsemod = true + case `2`, `anti`: + loger.Debug(`use kwdes anti`) + Url = manti default: loger.Fatal(`未定义的返回格式,请检查配置 [Custom].Kw_Des_Type`) } desheader[`User-Agent`] = env.Config.Custom.Kw_Des_Header 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: loger.Fatal(`未定义的接口模式,请检查配置 [Custom].Kw_Mode`) } @@ -92,7 +107,7 @@ func bdapi(songMid, quality string) (ourl, msg string) { loger.Debug(`Resp: %+v`, resp) if resp.Code != 200 || resp.Data.AudioInfo.Bitrate == `1` { // jx.Debug(`Kw, Err: %#v`, resp) - msg = ztool.Str_FastConcat(`failed: `, resp.Msg) + msg = ztool.Str_FastConcat(strconv.Itoa(resp.Code), `: `, resp.Msg) return } 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( `https://mobi.kuwo.cn/mobi.s?f=kuwo&q=`, 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¬race=0&priority=bitrate&network=WIFI&mode=down`, + `&source=`, desource, `&type=`, convtype, `&br=`, infoFile.H, infoFile.E, `&format=`, infoFile.E, `&rid=`, songMid, - `¬race=0&priority=bitrate&network=WIFI&mode=down`, )), ) if parsemod { @@ -131,6 +146,7 @@ func kwdes(songMid, quality string) (ourl, msg string) { msg = sources.ErrHttpReq return } + resp.Data.URL = utils.DelQuery(resp.Data.URL) loger.Debug(`Resp: %+v`, resp) if resp.Code != http.StatusOK { msg = ztool.Str_FastConcat(`failed: `, resp.Msg) @@ -144,7 +160,7 @@ func kwdes(songMid, quality string) (ourl, msg string) { 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 } ztool.Net_Request(http.MethodGet, target_url, nil, @@ -179,3 +195,133 @@ func kwdes(songMid, quality string) (ourl, msg string) { ) 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 +} diff --git a/src/sources/custom/kw/types.go b/src/sources/custom/kw/types.go index 812413d..ba9bc74 100644 --- a/src/sources/custom/kw/types.go +++ b/src/sources/custom/kw/types.go @@ -13,8 +13,8 @@ type ( Format string `json:"format"` P2PAudiosourceid string `json:"p2p_audiosourceid"` Rid int `json:"rid"` - Source string `json:"source"` - URL string `json:"url"` + // Source string `json:"source"` + URL string `json:"url"` } `json:"data"` Msg string `json:"msg"` } diff --git a/src/sources/custom/kw/utils.go b/src/sources/custom/kw/utils.go index e547486..e96ba75 100644 --- a/src/sources/custom/kw/utils.go +++ b/src/sources/custom/kw/utils.go @@ -40,25 +40,64 @@ var ( // `User-Agent`: `okhttp/3.10.0`, } bdheader = map[string]string{ - `channel`: `qq`, + `channel`: `guanfang`, `plat`: `ar`, `net`: `wifi`, - `ver`: `3.1.2`, - // `uid`: ``, - // `devId`: `0`, + `ver`: `3.1.4`, + `api-ver`: `application/json`, + + `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 { out := make(map[string]string) sep := bytes.Split(data, []byte{13, 10}) for i, r := 0, len(sep); i < r; i++ { - pat := bytes.Split(sep[i], []byte{61}) - if len(pat) == 2 { + var s = sep[i] + 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]) continue } - out[`_`] += bytesconv.BytesToString(pat[0]) + `;` + out[`_`] += bytesconv.BytesToString(pat[0]) + `;`*/ } 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 +}*/ diff --git a/src/sources/custom/tx/login.go b/src/sources/custom/tx/login.go index 5b0acdb..5a2b241 100644 --- a/src/sources/custom/tx/login.go +++ b/src/sources/custom/tx/login.go @@ -343,8 +343,8 @@ func Qlogin_graph(l *logs.Logger) error { env.Config.Custom.Tx_Enable = true env.Config.Custom.Tx_Uuin = out6.Req.Data.StrMusicid env.Config.Custom.Tx_Ukey = out6.Req.Data.Musickey - env.Config.Custom.Tx_Refresh_Enable = true - 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_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_RefreshToken = out6.Req.Data.RefreshToken // env.Config.Custom.Tx_AccessToken = out6.Req.Data.AccessToken diff --git a/src/sources/custom/tx/refresh.go b/src/sources/custom/tx/refresh.go index 2e8e449..dc4b4a9 100644 --- a/src/sources/custom/tx/refresh.go +++ b/src/sources/custom/tx/refresh.go @@ -123,9 +123,18 @@ func refresh(loger *logs.Logger, now int64) error { // loger.Error(`请求Api失败: %s`, err) return errors.New(`请求Api失败: ` + err.Error()) } + loger.Debug(`Resp: %+v`, resp) 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) - return fmt.Errorf("刷新登录失败, code: %v\n响应体: %+v", resp.Req1.Code, resp) + // return fmt.Errorf("刷新登录失败, code: %v\n响应体: %+v", resp.Req1.Code, resp) } loger.Info(`刷新登录成功`) env.Config.Custom.Tx_Uuin = resp.Req1.Data.StrMusicId diff --git a/src/sources/custom/wy/modules/core_request.go b/src/sources/custom/wy/modules/core_request.go index aafbaf1..86fc5be 100644 --- a/src/sources/custom/wy/modules/core_request.go +++ b/src/sources/custom/wy/modules/core_request.go @@ -20,7 +20,11 @@ import ( 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{ `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 { 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` - reg := regexp.MustCompile(`_csrf=([^(;|$)]+)`) - csrfToken := reg.FindStringSubmatch(options.Headers[`Cookie`]) + csrfToken := csrfReg.FindStringSubmatch(options.Headers[`Cookie`]) if len(csrfToken) > 1 { data[`csrf_token`] = csrfToken[1] } else { @@ -189,9 +192,8 @@ func createRequest(method, url string, data map[string]any, options reqOptions) } if err == nil { answer.Cookie = res.Header[`Set-Cookie`] //res.Header.Values(`set-cookie`) - reg := regexp.MustCompile(`\s*Domain=[^(;|$)]+;*`) for i, v := range answer.Cookie { - answer.Cookie[i] = reg.ReplaceAllString(v, ``) + answer.Cookie[i] = domaReg.ReplaceAllString(v, ``) } if options.Crypto == `eapi` && body[0] != '{' { err = json.Unmarshal(decrypt(body), &answer.Body) diff --git a/update.md b/update.md index c76f303..bf63e16 100644 --- a/update.md +++ b/update.md @@ -3,6 +3,14 @@ +#### \# 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) + 更新Action构建脚本,正式兼容Go1.20(windows7)