Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alist-org
GitHub Repository: alist-org/alist
Path: blob/main/drivers/lanzou/help.go
1987 views
1
package lanzou
2
3
import (
4
"bytes"
5
"fmt"
6
"net/http"
7
"regexp"
8
"strconv"
9
"strings"
10
"time"
11
"unicode"
12
13
log "github.com/sirupsen/logrus"
14
)
15
16
const DAY time.Duration = 84600000000000
17
18
// 解析时间
19
var timeSplitReg = regexp.MustCompile("([0-9.]*)\\s*([\u4e00-\u9fa5]+)")
20
21
// 如果解析失败,则返回当前时间
22
func MustParseTime(str string) time.Time {
23
lastOpTime, err := time.ParseInLocation("2006-01-02 -07", str+" +08", time.Local)
24
if err != nil {
25
strs := timeSplitReg.FindStringSubmatch(str)
26
lastOpTime = time.Now()
27
if len(strs) == 3 {
28
i, _ := strconv.ParseInt(strs[1], 10, 64)
29
ti := time.Duration(-i)
30
switch strs[2] {
31
case "秒前":
32
lastOpTime = lastOpTime.Add(time.Second * ti)
33
case "分钟前":
34
lastOpTime = lastOpTime.Add(time.Minute * ti)
35
case "小时前":
36
lastOpTime = lastOpTime.Add(time.Hour * ti)
37
case "天前":
38
lastOpTime = lastOpTime.Add(DAY * ti)
39
case "昨天":
40
lastOpTime = lastOpTime.Add(-DAY)
41
case "前天":
42
lastOpTime = lastOpTime.Add(-DAY * 2)
43
}
44
}
45
}
46
return lastOpTime
47
}
48
49
// 解析大小
50
var sizeSplitReg = regexp.MustCompile(`(?i)([0-9.]+)\s*([bkm]+)`)
51
52
// 解析失败返回0
53
func SizeStrToInt64(size string) int64 {
54
strs := sizeSplitReg.FindStringSubmatch(size)
55
if len(strs) < 3 {
56
return 0
57
}
58
59
s, _ := strconv.ParseFloat(strs[1], 64)
60
switch strings.ToUpper(strs[2]) {
61
case "B":
62
return int64(s)
63
case "K":
64
return int64(s * (1 << 10))
65
case "M":
66
return int64(s * (1 << 20))
67
}
68
return 0
69
}
70
71
// 移除注释
72
func RemoveNotes(html string) string {
73
return regexp.MustCompile(`<!--.*?-->|[^:]//.*|/\*.*?\*/`).ReplaceAllStringFunc(html, func(b string) string {
74
if b[1:3] == "//" {
75
return b[:1]
76
}
77
return "\n"
78
})
79
}
80
81
// 清理JS注释
82
func RemoveJSComment(data string) string {
83
var result strings.Builder
84
inComment := false
85
inSingleLineComment := false
86
87
for i := 0; i < len(data); i++ {
88
v := data[i]
89
90
if inSingleLineComment && (v == '\n' || v == '\r') {
91
inSingleLineComment = false
92
result.WriteByte(v)
93
continue
94
}
95
if inComment && v == '*' && i+1 < len(data) && data[i+1] == '/' {
96
inComment = false
97
i++
98
continue
99
}
100
if v == '/' && i+1 < len(data) {
101
nextChar := data[i+1]
102
if nextChar == '*' {
103
inComment = true
104
i++
105
continue
106
} else if nextChar == '/' {
107
inSingleLineComment = true
108
i++
109
continue
110
}
111
}
112
if inComment || inSingleLineComment {
113
continue
114
}
115
result.WriteByte(v)
116
}
117
118
return result.String()
119
}
120
121
var findAcwScV2Reg = regexp.MustCompile(`arg1='([0-9A-Z]+)'`)
122
123
// 在页面被过多访问或其他情况下,有时候会先返回一个加密的页面,其执行计算出一个acw_sc__v2后放入页面后再重新访问页面才能获得正常页面
124
// 若该页面进行了js加密,则进行解密,计算acw_sc__v2,并加入cookie
125
func CalcAcwScV2(html string) (string, error) {
126
log.Debugln("acw_sc__v2", html)
127
acwScV2s := findAcwScV2Reg.FindStringSubmatch(html)
128
if len(acwScV2s) != 2 {
129
return "", fmt.Errorf("无法匹配acw_sc__v2")
130
}
131
return HexXor(Unbox(acwScV2s[1]), "3000176000856006061501533003690027800375"), nil
132
}
133
134
func Unbox(hex string) string {
135
var box = []int{6, 28, 34, 31, 33, 18, 30, 23, 9, 8, 19, 38, 17, 24, 0, 5, 32, 21, 10, 22, 25, 14, 15, 3, 16, 27, 13, 35, 2, 29, 11, 26, 4, 36, 1, 39, 37, 7, 20, 12}
136
var newBox = make([]byte, len(hex))
137
for i := 0; i < len(box); i++ {
138
j := box[i]
139
if len(newBox) > j {
140
newBox[j] = hex[i]
141
}
142
}
143
return string(newBox)
144
}
145
146
func HexXor(hex1, hex2 string) string {
147
out := bytes.NewBuffer(make([]byte, len(hex1)))
148
for i := 0; i < len(hex1) && i < len(hex2); i += 2 {
149
v1, _ := strconv.ParseInt(hex1[i:i+2], 16, 64)
150
v2, _ := strconv.ParseInt(hex2[i:i+2], 16, 64)
151
out.WriteString(strconv.FormatInt(v1^v2, 16))
152
}
153
return out.String()
154
}
155
156
var findDataReg = regexp.MustCompile(`data[:\s]+({[^}]+})`) // 查找json
157
var findKVReg = regexp.MustCompile(`'(.+?)':('?([^' },]*)'?)`) // 拆分kv
158
159
// 根据key查询js变量
160
func findJSVarFunc(key, data string) string {
161
var values []string
162
if key != "sasign" {
163
values = regexp.MustCompile(`var ` + key + `\s*=\s*['"]?(.+?)['"]?;`).FindStringSubmatch(data)
164
} else {
165
matches := regexp.MustCompile(`var `+key+`\s*=\s*['"]?(.+?)['"]?;`).FindAllStringSubmatch(data, -1)
166
if len(matches) == 3 {
167
values = matches[1]
168
} else {
169
if len(matches) > 0 {
170
values = matches[0]
171
}
172
}
173
}
174
if len(values) == 0 {
175
return ""
176
}
177
return values[1]
178
}
179
180
var findFunction = regexp.MustCompile(`(?ims)^function[^{]+`)
181
var findFunctionAll = regexp.MustCompile(`(?is)function[^{]+`)
182
183
// 查找所有方法位置
184
func findJSFunctionIndex(data string, all bool) [][2]int {
185
findFunction := findFunction
186
if all {
187
findFunction = findFunctionAll
188
}
189
190
indexs := findFunction.FindAllStringIndex(data, -1)
191
fIndexs := make([][2]int, 0, len(indexs))
192
193
for _, index := range indexs {
194
if len(index) != 2 {
195
continue
196
}
197
count, data := 0, data[index[1]:]
198
for ii, v := range data {
199
if v == ' ' && count == 0 {
200
continue
201
}
202
if v == '{' {
203
count++
204
}
205
206
if v == '}' {
207
count--
208
}
209
if count == 0 {
210
fIndexs = append(fIndexs, [2]int{index[0], index[1] + ii + 1})
211
break
212
}
213
}
214
}
215
return fIndexs
216
}
217
218
// 删除JS全局方法
219
func removeJSGlobalFunction(html string) string {
220
indexs := findJSFunctionIndex(html, false)
221
block := make([]string, len(indexs))
222
for i, next := len(indexs)-1, len(html); i >= 0; i-- {
223
index := indexs[i]
224
block[i] = html[index[1]:next]
225
next = index[0]
226
}
227
return strings.Join(block, "")
228
}
229
230
// 根据名称获取方法
231
func getJSFunctionByName(html string, name string) (string, error) {
232
indexs := findJSFunctionIndex(html, true)
233
for _, index := range indexs {
234
data := html[index[0]:index[1]]
235
if regexp.MustCompile(`function\s+` + name + `[()\s]+{`).MatchString(data) {
236
return data, nil
237
}
238
}
239
return "", fmt.Errorf("not find %s function", name)
240
}
241
242
// 解析html中的JSON,选择最长的数据
243
func htmlJsonToMap2(html string) (map[string]string, error) {
244
datas := findDataReg.FindAllStringSubmatch(html, -1)
245
var sData string
246
for _, data := range datas {
247
if len(datas) > 0 && len(data[1]) > len(sData) {
248
sData = data[1]
249
}
250
}
251
if sData == "" {
252
return nil, fmt.Errorf("not find data")
253
}
254
return jsonToMap(sData, html), nil
255
}
256
257
// 解析html中的JSON
258
func htmlJsonToMap(html string) (map[string]string, error) {
259
datas := findDataReg.FindStringSubmatch(html)
260
if len(datas) != 2 {
261
return nil, fmt.Errorf("not find data")
262
}
263
return jsonToMap(datas[1], html), nil
264
}
265
266
func jsonToMap(data, html string) map[string]string {
267
var param = make(map[string]string)
268
kvs := findKVReg.FindAllStringSubmatch(data, -1)
269
for _, kv := range kvs {
270
k, v := kv[1], kv[3]
271
if v == "" || strings.Contains(kv[2], "'") || IsNumber(kv[2]) {
272
param[k] = v
273
} else {
274
param[k] = findJSVarFunc(v, html)
275
}
276
}
277
return param
278
}
279
280
func IsNumber(str string) bool {
281
for _, s := range str {
282
if !unicode.IsDigit(s) {
283
return false
284
}
285
}
286
return true
287
}
288
289
var findFromReg = regexp.MustCompile(`data : '(.+?)'`) // 查找from字符串
290
291
// 解析html中的form
292
func htmlFormToMap(html string) (map[string]string, error) {
293
forms := findFromReg.FindStringSubmatch(html)
294
if len(forms) != 2 {
295
return nil, fmt.Errorf("not find file sgin")
296
}
297
return formToMap(forms[1]), nil
298
}
299
300
func formToMap(from string) map[string]string {
301
var param = make(map[string]string)
302
for _, kv := range strings.Split(from, "&") {
303
kv := strings.SplitN(kv, "=", 2)[:2]
304
param[kv[0]] = kv[1]
305
}
306
return param
307
}
308
309
var regExpirationTime = regexp.MustCompile(`e=(\d+)`)
310
311
func GetExpirationTime(url string) (etime time.Duration) {
312
exps := regExpirationTime.FindStringSubmatch(url)
313
if len(exps) < 2 {
314
return
315
}
316
timestamp, err := strconv.ParseInt(exps[1], 10, 64)
317
if err != nil {
318
return
319
}
320
etime = time.Duration(timestamp-time.Now().Unix()) * time.Second
321
return
322
}
323
324
func CookieToString(cookies []*http.Cookie) string {
325
if cookies == nil {
326
return ""
327
}
328
cookieStrings := make([]string, len(cookies))
329
for i, cookie := range cookies {
330
cookieStrings[i] = cookie.Name + "=" + cookie.Value
331
}
332
return strings.Join(cookieStrings, ";")
333
}
334
335