- 新增 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 同步协议细节
145 lines
3.5 KiB
Go
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
|
|
}
|