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 }