forked from LagrangeDev/LagrangeGo
-
Notifications
You must be signed in to change notification settings - Fork 0
/
http.go
153 lines (135 loc) · 3.74 KB
/
http.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
package sign
import (
"context"
"encoding/json"
"errors"
"fmt"
"net/http"
"net/url"
"strconv"
"time"
"github.com/2mf8/LagrangeGo/client/http2"
)
var (
signMap = map[string]struct{}{} // 只在启动时初始化, 无并发问题
)
func init() {
signPkgList := []string{
"trpc.o3.ecdh_access.EcdhAccess.SsoEstablishShareKey",
"trpc.o3.ecdh_access.EcdhAccess.SsoSecureAccess",
"trpc.o3.report.Report.SsoReport",
"MessageSvc.PbSendMsg",
// "wtlogin.trans_emp",
"wtlogin.login",
// "trpc.login.ecdh.EcdhService.SsoKeyExchange",
"trpc.login.ecdh.EcdhService.SsoNTLoginPasswordLogin",
"trpc.login.ecdh.EcdhService.SsoNTLoginEasyLogin",
"trpc.login.ecdh.EcdhService.SsoNTLoginPasswordLoginNewDevice",
"trpc.login.ecdh.EcdhService.SsoNTLoginEasyLoginUnusualDevice",
"trpc.login.ecdh.EcdhService.SsoNTLoginPasswordLoginUnusualDevice",
"OidbSvcTrpcTcp.0x11ec_1",
"OidbSvcTrpcTcp.0x758_1",
"OidbSvcTrpcTcp.0x7c2_5",
"OidbSvcTrpcTcp.0x10db_1",
"OidbSvcTrpcTcp.0x8a1_7",
"OidbSvcTrpcTcp.0x89a_0",
"OidbSvcTrpcTcp.0x89a_15",
"OidbSvcTrpcTcp.0x88d_0",
"OidbSvcTrpcTcp.0x88d_14",
"OidbSvcTrpcTcp.0x112a_1",
"OidbSvcTrpcTcp.0x587_74",
"OidbSvcTrpcTcp.0x1100_1",
"OidbSvcTrpcTcp.0x1102_1",
"OidbSvcTrpcTcp.0x1103_1",
"OidbSvcTrpcTcp.0x1107_1",
"OidbSvcTrpcTcp.0x1105_1",
"OidbSvcTrpcTcp.0xf88_1",
"OidbSvcTrpcTcp.0xf89_1",
"OidbSvcTrpcTcp.0xf57_1",
"OidbSvcTrpcTcp.0xf57_106",
"OidbSvcTrpcTcp.0xf57_9",
"OidbSvcTrpcTcp.0xf55_1",
"OidbSvcTrpcTcp.0xf67_1",
"OidbSvcTrpcTcp.0xf67_5",
}
for _, cmd := range signPkgList {
signMap[cmd] = struct{}{}
}
}
func containSignPKG(cmd string) bool {
_, ok := signMap[cmd]
return ok
}
func NewProviderURL(rawUrl string, log func(msg string)) func(string, uint32, []byte) map[string]string {
if rawUrl == "" {
return nil
}
return func(cmd string, seq uint32, buf []byte) map[string]string {
if !containSignPKG(cmd) {
return nil
}
startTime := time.Now().UnixMilli()
resp := signResponse{}
err := httpGet(rawUrl, map[string]string{
"cmd": cmd,
"seq": strconv.Itoa(int(seq)),
"src": fmt.Sprintf("%x", buf),
}, 8*time.Second, &resp)
if err != nil {
log(err.Error())
return nil
}
log(fmt.Sprintf("signed for [%s:%d](%dms)",
cmd, seq, time.Now().UnixMilli()-startTime))
return map[string]string{
"sign": resp.Value.Sign,
"extra": resp.Value.Extra,
"token": resp.Value.Token,
}
}
}
func httpGet(rawUrl string, queryParams map[string]string, timeout time.Duration, target interface{}) error {
u, err := url.Parse(rawUrl)
if err != nil {
return fmt.Errorf("failed to parse URL: %w", err)
}
q := u.Query()
for k, v := range queryParams {
q.Set(k, v)
}
u.RawQuery = q.Encode()
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
req, err := http.NewRequestWithContext(ctx, http.MethodGet, u.String(), nil)
if err != nil {
return fmt.Errorf("failed to create GET request: %w", err)
}
resp, err := http2.TRSClient.Do(req)
if err != nil {
if errors.Is(ctx.Err(), context.DeadlineExceeded) {
return fmt.Errorf("request timed out")
}
resp, err = http2.DefaultClient.Do(req)
if err != nil {
if errors.Is(ctx.Err(), context.DeadlineExceeded) {
return fmt.Errorf("request timed out")
}
return fmt.Errorf("failed to perform GET request: %w", err)
}
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("unexpected status code: %d", resp.StatusCode)
}
if err := json.NewDecoder(resp.Body).Decode(target); err != nil {
return fmt.Errorf("failed to unmarshal JSON response: %w", err)
}
return nil
}
type signResponse struct {
Value struct {
Sign string `json:"sign"`
Extra string `json:"extra"`
Token string `json:"token"`
} `json:"value"`
}