Files
huya-go/internal/huya/baseinfo.go
T
yml2213 36aadae90a 按 10.13 抓包对齐 WSS:host 自动解析、exp 回传、pingSignal 与兑换记录字段
- 新增 launch.queryHttpDns:类型定义 + HTTPClient.QueryHttpDns + WSSClient.resolveHost(TTL 缓存、多 host 轮询、失败回退默认 host);Host 留空或等于历史默认值即视为自动解析
- WSS 握手 baseinfo 补 tag5=exp 与 tag10 空 customHeaders;UpdateUserExpsReq(cmd23) 改为回传 getConfig 的版本 map(缓存供重连复用)
- 新增 launch.pingSignal:HTTP 预热改走 pingSignal,WSS 预热在建连后探测业务通道(失败仅记日志)
- UserPrizeInfo 补 tag12 orderId/tag14 图标/tag16 prizeId/tag17 shopItemId/tag19 itemId/tag20 ext/tag21 exchangeDate,前端复盘表加订单号列
- taf 补 WriteListString/ReadListString/ReadMapStringInt64/ReadMapStringStruct
- 新增 internal/huya/launch_test.go:用抓包真实报文做字节级夹具(baseinfo 122B、queryHttpDns 请求 93B、记录 308B 等)
- CLI -wss-host 默认改为留空;GUI 设置支持留空并给出占位提示;README/WSS_NOTES 同步协议细节
2026-10-13 20:19:14 +08:00

145 lines
3.5 KiB
Go

package huya
import (
"encoding/base64"
"math/rand"
"net/url"
"huya-go/internal/taf"
)
const (
HTTPHuyaUA = "webh5&0.0.1&websocket&&diypc_52775"
PCUserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " +
"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.0.0 Safari/537.36"
)
type WSConnectParaInfo struct {
UID int64
GUID string
UA string
AppSrc string
MID string
Exp string
TokenType int32
Token string
Cookie string
TraceID string
CustomHeaders map[string]string
}
func NewWSConnectParaInfo(uid int64, guid, cookie string) WSConnectParaInfo {
return WSConnectParaInfo{
UID: uid,
GUID: guid,
UA: HTTPHuyaUA,
AppSrc: "HUYA&ZH&2052",
Cookie: cookie,
TraceID: NewTraceID(),
CustomHeaders: map[string]string{},
}
}
func (i WSConnectParaInfo) WriteTo(w *taf.Writer) error {
if err := w.WriteInt64(0, i.UID); err != nil {
return err
}
if err := w.WriteString(1, i.GUID); err != nil {
return err
}
if err := w.WriteString(2, i.UA); err != nil {
return err
}
if err := w.WriteString(3, i.AppSrc); err != nil {
return err
}
if err := w.WriteString(4, i.MID); err != nil {
return err
}
if err := w.WriteString(5, i.Exp); err != nil {
return err
}
if err := w.WriteInt32(6, int64(i.TokenType)); err != nil {
return err
}
if err := w.WriteString(7, i.Token); err != nil {
return err
}
if err := w.WriteString(8, i.Cookie); err != nil {
return err
}
if err := w.WriteString(9, i.TraceID); err != nil {
return err
}
return w.WriteMapStringString(10, i.CustomHeaders)
}
func NewTraceID() string {
// 与前端 traceId 格式保持一致:hex16:hex16:0:0。
v := rand.Uint64()
s := lowerHex16(v)
return s + ":" + s + ":0:0"
}
func lowerHex16(v uint64) string {
const digits = "0123456789abcdef"
var b [16]byte
for i := 15; i >= 0; i-- {
b[i] = digits[v&0xf]
v >>= 4
}
return string(b[:])
}
func GenerateHTTPBaseinfo(uid int64, guid, cookie string) (string, error) {
info := NewWSConnectParaInfo(uid, guid, cookie)
w := taf.NewWriter()
if err := info.WriteTo(w); err != nil {
return "", err
}
return url.QueryEscape(base64.StdEncoding.EncodeToString(w.Bytes())), nil
}
// GenerateWSSBaseinfo 生成浏览器 WSS 握手里的 baseinfo。
//
// 手动抓包里 WSS 握手带 uid/guid/ua/appSrc/mid/exp/.../customHeaders 共 11 个字段,
// cookie 为空、通过后续 VerifyCookie 命令发送;exp 为 mobileui.getConfig 下发的
// 版本串(形如 "58664.107263"),首次连接时为空。
func GenerateWSSBaseinfo(uid int64, guid, exp string) (string, error) {
w := taf.NewWriter()
if err := w.WriteInt64(0, uid); err != nil {
return "", err
}
if err := w.WriteString(1, guid); err != nil {
return "", err
}
if err := w.WriteString(2, HTTPHuyaUA); err != nil {
return "", err
}
if err := w.WriteString(3, "HUYA&ZH&2052"); err != nil {
return "", err
}
if err := w.WriteString(4, ""); err != nil {
return "", err
}
if err := w.WriteString(5, exp); err != nil {
return "", err
}
if err := w.WriteInt32(6, 0); err != nil {
return "", err
}
if err := w.WriteString(7, ""); err != nil {
return "", err
}
if err := w.WriteString(8, ""); err != nil {
return "", err
}
if err := w.WriteString(9, ""); err != nil {
return "", err
}
if err := w.WriteMapStringString(10, nil); err != nil {
return "", err
}
return url.QueryEscape(base64.StdEncoding.EncodeToString(w.Bytes())), nil
}