@floating-live/bilibili 0.15.2 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/index.d.ts +5 -5
- package/index.js +5 -21
- package/package.json +7 -7
- package/parser.d.ts +10 -6
- package/parser.js +472 -422
- package/plugin.d.ts +26 -29
- package/plugin.js +63 -67
- package/room.d.ts +108 -74
- package/room.js +315 -228
- package/types.d.ts +39 -484
- package/types.js +1 -2
- package/utils/fingerprint.d.ts +98 -0
- package/utils/fingerprint.js +642 -0
- package/utils/fp2.d.ts +7 -0
- package/utils/fp2.js +234 -0
- package/utils/index.d.ts +1 -0
- package/utils/index.js +1 -0
- package/utils/lsid.d.ts +1 -0
- package/utils/lsid.js +15 -0
- package/utils/randomImage.d.ts +2 -0
- package/utils/randomImage.js +107 -0
- package/utils/request.d.ts +32 -0
- package/utils/request.js +181 -0
- package/utils/uuid.d.ts +1 -0
- package/utils/uuid.js +45 -0
- package/index.ts +0 -5
- package/parser.ts +0 -433
- package/plugin.ts +0 -103
- package/room.ts +0 -270
- package/tsconfig.json +0 -14
- package/types.ts +0 -503
- package/utils.d.ts +0 -18
- package/utils.js +0 -138
- package/utils.ts +0 -145
package/utils/fp2.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare const x64Add: (m: any[], n: any[]) => number[];
|
|
2
|
+
export declare const x64Multiply: (m: any[], n: number[]) => number[];
|
|
3
|
+
export declare const x64Rotl: (m: any[], n: number) => any[];
|
|
4
|
+
export declare const x64LeftShift: (m: any[], n: number) => any[];
|
|
5
|
+
export declare const x64Xor: (m: any[], n: any[]) => number[];
|
|
6
|
+
export declare const x64Fmix: (h: any[]) => any[];
|
|
7
|
+
export declare const x64hash128: (key: string, seed: number) => string;
|
package/utils/fp2.js
ADDED
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
/// MurmurHash3 related functions
|
|
2
|
+
//
|
|
3
|
+
// Given two 64bit ints (as an array of two 32bit ints) returns the two
|
|
4
|
+
// added together as a 64bit int (as an array of two 32bit ints).
|
|
5
|
+
//
|
|
6
|
+
export const x64Add = function (m, n) {
|
|
7
|
+
m = [m[0] >>> 16, m[0] & 0xffff, m[1] >>> 16, m[1] & 0xffff];
|
|
8
|
+
n = [n[0] >>> 16, n[0] & 0xffff, n[1] >>> 16, n[1] & 0xffff];
|
|
9
|
+
var o = [0, 0, 0, 0];
|
|
10
|
+
o[3] += m[3] + n[3];
|
|
11
|
+
o[2] += o[3] >>> 16;
|
|
12
|
+
o[3] &= 0xffff;
|
|
13
|
+
o[2] += m[2] + n[2];
|
|
14
|
+
o[1] += o[2] >>> 16;
|
|
15
|
+
o[2] &= 0xffff;
|
|
16
|
+
o[1] += m[1] + n[1];
|
|
17
|
+
o[0] += o[1] >>> 16;
|
|
18
|
+
o[1] &= 0xffff;
|
|
19
|
+
o[0] += m[0] + n[0];
|
|
20
|
+
o[0] &= 0xffff;
|
|
21
|
+
return [(o[0] << 16) | o[1], (o[2] << 16) | o[3]];
|
|
22
|
+
};
|
|
23
|
+
//
|
|
24
|
+
// Given two 64bit ints (as an array of two 32bit ints) returns the two
|
|
25
|
+
// multiplied together as a 64bit int (as an array of two 32bit ints).
|
|
26
|
+
//
|
|
27
|
+
export const x64Multiply = function (m, n) {
|
|
28
|
+
m = [m[0] >>> 16, m[0] & 0xffff, m[1] >>> 16, m[1] & 0xffff];
|
|
29
|
+
n = [n[0] >>> 16, n[0] & 0xffff, n[1] >>> 16, n[1] & 0xffff];
|
|
30
|
+
var o = [0, 0, 0, 0];
|
|
31
|
+
o[3] += m[3] * n[3];
|
|
32
|
+
o[2] += o[3] >>> 16;
|
|
33
|
+
o[3] &= 0xffff;
|
|
34
|
+
o[2] += m[2] * n[3];
|
|
35
|
+
o[1] += o[2] >>> 16;
|
|
36
|
+
o[2] &= 0xffff;
|
|
37
|
+
o[2] += m[3] * n[2];
|
|
38
|
+
o[1] += o[2] >>> 16;
|
|
39
|
+
o[2] &= 0xffff;
|
|
40
|
+
o[1] += m[1] * n[3];
|
|
41
|
+
o[0] += o[1] >>> 16;
|
|
42
|
+
o[1] &= 0xffff;
|
|
43
|
+
o[1] += m[2] * n[2];
|
|
44
|
+
o[0] += o[1] >>> 16;
|
|
45
|
+
o[1] &= 0xffff;
|
|
46
|
+
o[1] += m[3] * n[1];
|
|
47
|
+
o[0] += o[1] >>> 16;
|
|
48
|
+
o[1] &= 0xffff;
|
|
49
|
+
o[0] += m[0] * n[3] + m[1] * n[2] + m[2] * n[1] + m[3] * n[0];
|
|
50
|
+
o[0] &= 0xffff;
|
|
51
|
+
return [(o[0] << 16) | o[1], (o[2] << 16) | o[3]];
|
|
52
|
+
};
|
|
53
|
+
//
|
|
54
|
+
// Given a 64bit int (as an array of two 32bit ints) and an int
|
|
55
|
+
// representing a number of bit positions, returns the 64bit int (as an
|
|
56
|
+
// array of two 32bit ints) rotated left by that number of positions.
|
|
57
|
+
//
|
|
58
|
+
export const x64Rotl = function (m, n) {
|
|
59
|
+
n %= 64;
|
|
60
|
+
if (n === 32) {
|
|
61
|
+
return [m[1], m[0]];
|
|
62
|
+
}
|
|
63
|
+
else if (n < 32) {
|
|
64
|
+
return [
|
|
65
|
+
(m[0] << n) | (m[1] >>> (32 - n)),
|
|
66
|
+
(m[1] << n) | (m[0] >>> (32 - n)),
|
|
67
|
+
];
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
n -= 32;
|
|
71
|
+
return [
|
|
72
|
+
(m[1] << n) | (m[0] >>> (32 - n)),
|
|
73
|
+
(m[0] << n) | (m[1] >>> (32 - n)),
|
|
74
|
+
];
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
//
|
|
78
|
+
// Given a 64bit int (as an array of two 32bit ints) and an int
|
|
79
|
+
// representing a number of bit positions, returns the 64bit int (as an
|
|
80
|
+
// array of two 32bit ints) shifted left by that number of positions.
|
|
81
|
+
//
|
|
82
|
+
export const x64LeftShift = function (m, n) {
|
|
83
|
+
n %= 64;
|
|
84
|
+
if (n === 0) {
|
|
85
|
+
return m;
|
|
86
|
+
}
|
|
87
|
+
else if (n < 32) {
|
|
88
|
+
return [(m[0] << n) | (m[1] >>> (32 - n)), m[1] << n];
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
return [m[1] << (n - 32), 0];
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
//
|
|
95
|
+
// Given two 64bit ints (as an array of two 32bit ints) returns the two
|
|
96
|
+
// xored together as a 64bit int (as an array of two 32bit ints).
|
|
97
|
+
//
|
|
98
|
+
export const x64Xor = function (m, n) {
|
|
99
|
+
return [m[0] ^ n[0], m[1] ^ n[1]];
|
|
100
|
+
};
|
|
101
|
+
//
|
|
102
|
+
// Given a block, returns murmurHash3's final x64 mix of that block.
|
|
103
|
+
// (`[0, h[0] >>> 1]` is a 33 bit unsigned right shift. This is the
|
|
104
|
+
// only place where we need to right shift 64bit ints.)
|
|
105
|
+
//
|
|
106
|
+
export const x64Fmix = function (h) {
|
|
107
|
+
h = x64Xor(h, [0, h[0] >>> 1]);
|
|
108
|
+
h = x64Multiply(h, [0xff51afd7, 0xed558ccd]);
|
|
109
|
+
h = x64Xor(h, [0, h[0] >>> 1]);
|
|
110
|
+
h = x64Multiply(h, [0xc4ceb9fe, 0x1a85ec53]);
|
|
111
|
+
h = x64Xor(h, [0, h[0] >>> 1]);
|
|
112
|
+
return h;
|
|
113
|
+
};
|
|
114
|
+
//
|
|
115
|
+
// Given a string and an optional seed as an int, returns a 128 bit
|
|
116
|
+
// hash using the x64 flavor of MurmurHash3, as an unsigned hex.
|
|
117
|
+
//
|
|
118
|
+
export const x64hash128 = function (key, seed) {
|
|
119
|
+
key = key || "";
|
|
120
|
+
seed = seed || 0;
|
|
121
|
+
var remainder = key.length % 16;
|
|
122
|
+
var bytes = key.length - remainder;
|
|
123
|
+
var h1 = [0, seed];
|
|
124
|
+
var h2 = [0, seed];
|
|
125
|
+
var k1 = [0, 0];
|
|
126
|
+
var k2 = [0, 0];
|
|
127
|
+
var c1 = [0x87c37b91, 0x114253d5];
|
|
128
|
+
var c2 = [0x4cf5ad43, 0x2745937f];
|
|
129
|
+
for (var i = 0; i < bytes; i = i + 16) {
|
|
130
|
+
k1 = [
|
|
131
|
+
(key.charCodeAt(i + 4) & 0xff) |
|
|
132
|
+
((key.charCodeAt(i + 5) & 0xff) << 8) |
|
|
133
|
+
((key.charCodeAt(i + 6) & 0xff) << 16) |
|
|
134
|
+
((key.charCodeAt(i + 7) & 0xff) << 24),
|
|
135
|
+
(key.charCodeAt(i) & 0xff) |
|
|
136
|
+
((key.charCodeAt(i + 1) & 0xff) << 8) |
|
|
137
|
+
((key.charCodeAt(i + 2) & 0xff) << 16) |
|
|
138
|
+
((key.charCodeAt(i + 3) & 0xff) << 24),
|
|
139
|
+
];
|
|
140
|
+
k2 = [
|
|
141
|
+
(key.charCodeAt(i + 12) & 0xff) |
|
|
142
|
+
((key.charCodeAt(i + 13) & 0xff) << 8) |
|
|
143
|
+
((key.charCodeAt(i + 14) & 0xff) << 16) |
|
|
144
|
+
((key.charCodeAt(i + 15) & 0xff) << 24),
|
|
145
|
+
(key.charCodeAt(i + 8) & 0xff) |
|
|
146
|
+
((key.charCodeAt(i + 9) & 0xff) << 8) |
|
|
147
|
+
((key.charCodeAt(i + 10) & 0xff) << 16) |
|
|
148
|
+
((key.charCodeAt(i + 11) & 0xff) << 24),
|
|
149
|
+
];
|
|
150
|
+
k1 = x64Multiply(k1, c1);
|
|
151
|
+
k1 = x64Rotl(k1, 31);
|
|
152
|
+
k1 = x64Multiply(k1, c2);
|
|
153
|
+
h1 = x64Xor(h1, k1);
|
|
154
|
+
h1 = x64Rotl(h1, 27);
|
|
155
|
+
h1 = x64Add(h1, h2);
|
|
156
|
+
h1 = x64Add(x64Multiply(h1, [0, 5]), [0, 0x52dce729]);
|
|
157
|
+
k2 = x64Multiply(k2, c2);
|
|
158
|
+
k2 = x64Rotl(k2, 33);
|
|
159
|
+
k2 = x64Multiply(k2, c1);
|
|
160
|
+
h2 = x64Xor(h2, k2);
|
|
161
|
+
h2 = x64Rotl(h2, 31);
|
|
162
|
+
h2 = x64Add(h2, h1);
|
|
163
|
+
h2 = x64Add(x64Multiply(h2, [0, 5]), [0, 0x38495ab5]);
|
|
164
|
+
}
|
|
165
|
+
k1 = [0, 0];
|
|
166
|
+
k2 = [0, 0];
|
|
167
|
+
switch (remainder) {
|
|
168
|
+
case 15:
|
|
169
|
+
k2 = x64Xor(k2, x64LeftShift([0, key.charCodeAt(i + 14)], 48));
|
|
170
|
+
// fallthrough
|
|
171
|
+
case 14:
|
|
172
|
+
k2 = x64Xor(k2, x64LeftShift([0, key.charCodeAt(i + 13)], 40));
|
|
173
|
+
// fallthrough
|
|
174
|
+
case 13:
|
|
175
|
+
k2 = x64Xor(k2, x64LeftShift([0, key.charCodeAt(i + 12)], 32));
|
|
176
|
+
// fallthrough
|
|
177
|
+
case 12:
|
|
178
|
+
k2 = x64Xor(k2, x64LeftShift([0, key.charCodeAt(i + 11)], 24));
|
|
179
|
+
// fallthrough
|
|
180
|
+
case 11:
|
|
181
|
+
k2 = x64Xor(k2, x64LeftShift([0, key.charCodeAt(i + 10)], 16));
|
|
182
|
+
// fallthrough
|
|
183
|
+
case 10:
|
|
184
|
+
k2 = x64Xor(k2, x64LeftShift([0, key.charCodeAt(i + 9)], 8));
|
|
185
|
+
// fallthrough
|
|
186
|
+
case 9:
|
|
187
|
+
k2 = x64Xor(k2, [0, key.charCodeAt(i + 8)]);
|
|
188
|
+
k2 = x64Multiply(k2, c2);
|
|
189
|
+
k2 = x64Rotl(k2, 33);
|
|
190
|
+
k2 = x64Multiply(k2, c1);
|
|
191
|
+
h2 = x64Xor(h2, k2);
|
|
192
|
+
// fallthrough
|
|
193
|
+
case 8:
|
|
194
|
+
k1 = x64Xor(k1, x64LeftShift([0, key.charCodeAt(i + 7)], 56));
|
|
195
|
+
// fallthrough
|
|
196
|
+
case 7:
|
|
197
|
+
k1 = x64Xor(k1, x64LeftShift([0, key.charCodeAt(i + 6)], 48));
|
|
198
|
+
// fallthrough
|
|
199
|
+
case 6:
|
|
200
|
+
k1 = x64Xor(k1, x64LeftShift([0, key.charCodeAt(i + 5)], 40));
|
|
201
|
+
// fallthrough
|
|
202
|
+
case 5:
|
|
203
|
+
k1 = x64Xor(k1, x64LeftShift([0, key.charCodeAt(i + 4)], 32));
|
|
204
|
+
// fallthrough
|
|
205
|
+
case 4:
|
|
206
|
+
k1 = x64Xor(k1, x64LeftShift([0, key.charCodeAt(i + 3)], 24));
|
|
207
|
+
// fallthrough
|
|
208
|
+
case 3:
|
|
209
|
+
k1 = x64Xor(k1, x64LeftShift([0, key.charCodeAt(i + 2)], 16));
|
|
210
|
+
// fallthrough
|
|
211
|
+
case 2:
|
|
212
|
+
k1 = x64Xor(k1, x64LeftShift([0, key.charCodeAt(i + 1)], 8));
|
|
213
|
+
// fallthrough
|
|
214
|
+
case 1:
|
|
215
|
+
k1 = x64Xor(k1, [0, key.charCodeAt(i)]);
|
|
216
|
+
k1 = x64Multiply(k1, c1);
|
|
217
|
+
k1 = x64Rotl(k1, 31);
|
|
218
|
+
k1 = x64Multiply(k1, c2);
|
|
219
|
+
h1 = x64Xor(h1, k1);
|
|
220
|
+
// fallthrough
|
|
221
|
+
}
|
|
222
|
+
h1 = x64Xor(h1, [0, key.length]);
|
|
223
|
+
h2 = x64Xor(h2, [0, key.length]);
|
|
224
|
+
h1 = x64Add(h1, h2);
|
|
225
|
+
h2 = x64Add(h2, h1);
|
|
226
|
+
h1 = x64Fmix(h1);
|
|
227
|
+
h2 = x64Fmix(h2);
|
|
228
|
+
h1 = x64Add(h1, h2);
|
|
229
|
+
h2 = x64Add(h2, h1);
|
|
230
|
+
return (("00000000" + (h1[0] >>> 0).toString(16)).slice(-8) +
|
|
231
|
+
("00000000" + (h1[1] >>> 0).toString(16)).slice(-8) +
|
|
232
|
+
("00000000" + (h2[0] >>> 0).toString(16)).slice(-8) +
|
|
233
|
+
("00000000" + (h2[1] >>> 0).toString(16)).slice(-8));
|
|
234
|
+
};
|
package/utils/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./request";
|
package/utils/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./request";
|
package/utils/lsid.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function generateLsid(): string;
|
package/utils/lsid.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// 模拟Rust的random_string!宏
|
|
2
|
+
function randomString(len, charset) {
|
|
3
|
+
const chars = charset.split("");
|
|
4
|
+
const charsetLength = chars.length;
|
|
5
|
+
return Array.from({ length: len }, () => chars[Math.floor(Math.random() * charsetLength)]).join("");
|
|
6
|
+
}
|
|
7
|
+
// 主函数
|
|
8
|
+
export function generateLsid() {
|
|
9
|
+
const randomPart = randomString(8, "0123456789ABCDEF" // 保持全大写十六进制特征
|
|
10
|
+
);
|
|
11
|
+
const timestampPart = Date.now()
|
|
12
|
+
.toString(16) // 转换为十六进制
|
|
13
|
+
.toUpperCase(); // 保持与Rust的:X格式一致
|
|
14
|
+
return `${randomPart}_${timestampPart}`;
|
|
15
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
// Generated by Deepseek
|
|
2
|
+
/** 生成随机的base64图片数据 */
|
|
3
|
+
export function generateRandomPngBase64() {
|
|
4
|
+
// 生成带过滤头的随机像素数据
|
|
5
|
+
const pixelData = new Uint8Array(20 * (20 * 4 + 1));
|
|
6
|
+
for (let y = 0, offset = 0; y < 20; y++) {
|
|
7
|
+
pixelData[offset++] = 0; // 过滤类型
|
|
8
|
+
for (let x = 0; x < 20; x++) {
|
|
9
|
+
pixelData[offset++] = Math.floor(Math.random() * 256); // R
|
|
10
|
+
pixelData[offset++] = Math.floor(Math.random() * 256); // G
|
|
11
|
+
pixelData[offset++] = Math.floor(Math.random() * 256); // B
|
|
12
|
+
pixelData[offset++] = 255; // A
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
// 计算Adler32校验和
|
|
16
|
+
const computeAdler32 = (data) => {
|
|
17
|
+
let s1 = 1, s2 = 0;
|
|
18
|
+
for (const byte of data) {
|
|
19
|
+
s1 = (s1 + byte) % 65521;
|
|
20
|
+
s2 = (s2 + s1) % 65521;
|
|
21
|
+
}
|
|
22
|
+
return (s2 << 16) | s1;
|
|
23
|
+
};
|
|
24
|
+
// 构造Deflate流
|
|
25
|
+
const deflateStream = new Uint8Array([
|
|
26
|
+
0x78,
|
|
27
|
+
0x01, // Zlib头
|
|
28
|
+
0x00, // BFINAL=0,BTYPE=00(非最后块)
|
|
29
|
+
0x54,
|
|
30
|
+
0x06, // LEN=1620
|
|
31
|
+
0xab,
|
|
32
|
+
0xf9, // NLEN=~1620
|
|
33
|
+
...pixelData,
|
|
34
|
+
...new Uint8Array([
|
|
35
|
+
// Adler32
|
|
36
|
+
(computeAdler32(pixelData) >> 24) & 0xff,
|
|
37
|
+
(computeAdler32(pixelData) >> 16) & 0xff,
|
|
38
|
+
(computeAdler32(pixelData) >> 8) & 0xff,
|
|
39
|
+
computeAdler32(pixelData) & 0xff,
|
|
40
|
+
]),
|
|
41
|
+
]);
|
|
42
|
+
// 计算CRC32
|
|
43
|
+
const computeCRC32 = (data) => {
|
|
44
|
+
let crc = 0xffffffff;
|
|
45
|
+
const table = new Uint32Array(256);
|
|
46
|
+
for (let i = 0; i < 256; i++) {
|
|
47
|
+
let c = i;
|
|
48
|
+
for (let j = 0; j < 8; j++) {
|
|
49
|
+
c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1;
|
|
50
|
+
}
|
|
51
|
+
table[i] = c;
|
|
52
|
+
}
|
|
53
|
+
for (const byte of data) {
|
|
54
|
+
crc = table[(crc ^ byte) & 0xff] ^ (crc >>> 8);
|
|
55
|
+
}
|
|
56
|
+
return crc ^ 0xffffffff;
|
|
57
|
+
};
|
|
58
|
+
// 创建PNG块
|
|
59
|
+
const createChunk = (type, data) => {
|
|
60
|
+
const typeBytes = new TextEncoder().encode(type);
|
|
61
|
+
const length = new Uint8Array(4);
|
|
62
|
+
length[0] = (data.length >> 24) & 0xff;
|
|
63
|
+
length[1] = (data.length >> 16) & 0xff;
|
|
64
|
+
length[2] = (data.length >> 8) & 0xff;
|
|
65
|
+
length[3] = data.length & 0xff;
|
|
66
|
+
const chunkData = new Uint8Array([...typeBytes, ...data]);
|
|
67
|
+
const crc = computeCRC32(chunkData);
|
|
68
|
+
const crcBytes = new Uint8Array(4);
|
|
69
|
+
crcBytes[0] = (crc >> 24) & 0xff;
|
|
70
|
+
crcBytes[1] = (crc >> 16) & 0xff;
|
|
71
|
+
crcBytes[2] = (crc >> 8) & 0xff;
|
|
72
|
+
crcBytes[3] = crc & 0xff;
|
|
73
|
+
return new Uint8Array([...length, ...chunkData, ...crcBytes]);
|
|
74
|
+
};
|
|
75
|
+
// 构建PNG结构
|
|
76
|
+
const signature = new Uint8Array([
|
|
77
|
+
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a,
|
|
78
|
+
]);
|
|
79
|
+
const ihdrData = new Uint8Array([
|
|
80
|
+
0x00,
|
|
81
|
+
0x00,
|
|
82
|
+
0x00,
|
|
83
|
+
0x14, // 宽度20
|
|
84
|
+
0x00,
|
|
85
|
+
0x00,
|
|
86
|
+
0x00,
|
|
87
|
+
0x14, // 高度20
|
|
88
|
+
0x08, // 位深度
|
|
89
|
+
0x06, // 颜色类型(RGBA)
|
|
90
|
+
0x00, // 压缩方法
|
|
91
|
+
0x00, // 滤波方法
|
|
92
|
+
0x00, // 隔行扫描
|
|
93
|
+
]);
|
|
94
|
+
const ihdrChunk = createChunk("IHDR", ihdrData);
|
|
95
|
+
const idatChunk = createChunk("IDAT", deflateStream);
|
|
96
|
+
const iendChunk = createChunk("IEND", new Uint8Array(0));
|
|
97
|
+
// 合并所有数据
|
|
98
|
+
const pngData = new Uint8Array([
|
|
99
|
+
...signature,
|
|
100
|
+
...ihdrChunk,
|
|
101
|
+
...idatChunk,
|
|
102
|
+
...iendChunk,
|
|
103
|
+
]);
|
|
104
|
+
// 转换为Base64
|
|
105
|
+
const base64 = btoa(String.fromCharCode(...pngData));
|
|
106
|
+
return `data:image/png;base64,${base64}`;
|
|
107
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { FpInfo } from "./fingerprint";
|
|
2
|
+
import { RoomBaseInfo } from "../types";
|
|
3
|
+
export declare function getCookie(headers: Headers): string;
|
|
4
|
+
export declare function parseCookieString(str: string): Record<string, string>;
|
|
5
|
+
/** 生成登录二维码 */
|
|
6
|
+
export declare function qrcodeGenerate(options?: FetchOptions): Promise<{
|
|
7
|
+
url: any;
|
|
8
|
+
key: any;
|
|
9
|
+
}>;
|
|
10
|
+
/** 生成登录二维码 */
|
|
11
|
+
export declare function requestFingerSpi(options?: FetchOptions): Promise<Record<"b_3" | "b_4", string>>;
|
|
12
|
+
/** 检测登录二维码 */
|
|
13
|
+
export declare function checkLoginQRcode(key: string, options?: FetchOptions): Promise<[number, string?]>;
|
|
14
|
+
/** 获取并激活buvid的cookie */
|
|
15
|
+
export declare function getActivatedBuvidCookie(fp: FpInfo | null | undefined, options: FetchOptions): Promise<Record<"buvid3" | "_uuid" | "buvid_fp" | "b_lsid", string>>;
|
|
16
|
+
/** 获取指纹相关Cookies */
|
|
17
|
+
export declare function getFingerprintCookie(fp: FpInfo, options: FetchOptions): {
|
|
18
|
+
_uuid: string;
|
|
19
|
+
buvid_fp: string;
|
|
20
|
+
b_lsid: string;
|
|
21
|
+
};
|
|
22
|
+
/** 激活buvid */
|
|
23
|
+
export declare function requestExClimbWuzhi(payload: string, options: FetchOptions): void;
|
|
24
|
+
export declare function getRoomBaseInfo(room_id: number, options?: FetchOptions): Promise<RoomBaseInfo | undefined>;
|
|
25
|
+
export interface FetchOptions {
|
|
26
|
+
/** 自定义fetch函数(适用于请求中转等情况) */
|
|
27
|
+
fetch?: (input: string, init?: RequestInit) => Promise<Response>;
|
|
28
|
+
/** 用户代理字段 */
|
|
29
|
+
userAgent?: string;
|
|
30
|
+
/** cookie字段 */
|
|
31
|
+
cookie?: string;
|
|
32
|
+
}
|
package/utils/request.js
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { Cookies, customFetch, requestBuvidCookie, } from "bilibili-live-danmaku";
|
|
2
|
+
import { fpGet, generateFakeFpInfo, getExClimbWuzhiPayload, } from "./fingerprint";
|
|
3
|
+
import { generateRandomPngBase64 } from "./randomImage";
|
|
4
|
+
import { x64hash128 } from "./fp2";
|
|
5
|
+
import { generateUuid } from "./uuid";
|
|
6
|
+
import { generateLsid } from "./lsid";
|
|
7
|
+
export function getCookie(headers) {
|
|
8
|
+
const cookies = [];
|
|
9
|
+
headers.forEach((val, key) => {
|
|
10
|
+
if (key == "set-cookie") {
|
|
11
|
+
const [c] = val.split(";");
|
|
12
|
+
cookies.push(c);
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
const cookie = cookies.join("; ");
|
|
16
|
+
return cookie;
|
|
17
|
+
}
|
|
18
|
+
export function parseCookieString(str) {
|
|
19
|
+
const cookie = {};
|
|
20
|
+
str.split(";").forEach((item) => {
|
|
21
|
+
if (!item) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
const arr = item.split("=");
|
|
25
|
+
const key = arr[0]?.trim();
|
|
26
|
+
const val = arr[1]?.trim();
|
|
27
|
+
cookie[key] = val;
|
|
28
|
+
});
|
|
29
|
+
return cookie;
|
|
30
|
+
}
|
|
31
|
+
/** 生成登录二维码 */
|
|
32
|
+
export async function qrcodeGenerate(options) {
|
|
33
|
+
const res = await customFetch(options, "https://passport.bilibili.com/x/passport-login/web/qrcode/generate").then((res) => res.json());
|
|
34
|
+
return {
|
|
35
|
+
url: res.data.url,
|
|
36
|
+
key: res.data.qrcode_key,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
/** 生成登录二维码 */
|
|
40
|
+
export async function requestFingerSpi(options) {
|
|
41
|
+
const res = await customFetch(options, "https://api.bilibili.com/x/frontend/finger/spi").then((res) => res.json());
|
|
42
|
+
return res.data;
|
|
43
|
+
}
|
|
44
|
+
/** 检测登录二维码 */
|
|
45
|
+
export async function checkLoginQRcode(key, options) {
|
|
46
|
+
const res = await customFetch(options, `https://passport.bilibili.com/x/passport-login/web/qrcode/poll?qrcode_key=${key}`);
|
|
47
|
+
const { code, message } = (await res.json()).data;
|
|
48
|
+
if (code == 86101) {
|
|
49
|
+
// 未扫码
|
|
50
|
+
return [1];
|
|
51
|
+
}
|
|
52
|
+
else if (code == 86090) {
|
|
53
|
+
// 等待确认
|
|
54
|
+
return [2];
|
|
55
|
+
}
|
|
56
|
+
else if (code == 0) {
|
|
57
|
+
const cookie = getCookie(res.headers);
|
|
58
|
+
return [0, cookie];
|
|
59
|
+
}
|
|
60
|
+
else if (code == 86038) {
|
|
61
|
+
// 二维码失效
|
|
62
|
+
return [-1];
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
// 其他错误
|
|
66
|
+
console.log(`${code} ${message}`);
|
|
67
|
+
throw message;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
function wait(t) {
|
|
71
|
+
return new Promise((res, rej) => {
|
|
72
|
+
const to = setTimeout(() => {
|
|
73
|
+
res(undefined);
|
|
74
|
+
clearTimeout(t);
|
|
75
|
+
}, t);
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
/** 获取并激活buvid的cookie */
|
|
79
|
+
export async function getActivatedBuvidCookie(fp, options) {
|
|
80
|
+
const cookies = new Cookies();
|
|
81
|
+
cookies.append(await requestBuvidCookie({
|
|
82
|
+
...options,
|
|
83
|
+
cookie: cookies.toString(),
|
|
84
|
+
}));
|
|
85
|
+
const { b_4 } = await requestFingerSpi({
|
|
86
|
+
...options,
|
|
87
|
+
cookie: cookies.toString(),
|
|
88
|
+
});
|
|
89
|
+
cookies.set("buvid4", b_4);
|
|
90
|
+
if (!fp) {
|
|
91
|
+
fp = generateFakeFpInfo({
|
|
92
|
+
canvas: generateRandomPngBase64(),
|
|
93
|
+
webgl: generateRandomPngBase64(),
|
|
94
|
+
userAgent: options.userAgent ||
|
|
95
|
+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36 Edg/135.0.0.0",
|
|
96
|
+
platform: "Win32",
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
cookies.append(getFingerprintCookie(fp, {
|
|
100
|
+
...options,
|
|
101
|
+
cookie: cookies.toString(),
|
|
102
|
+
}));
|
|
103
|
+
// await wait(2000);
|
|
104
|
+
const payload = getExClimbWuzhiPayload(fp, {
|
|
105
|
+
uuid: cookies.get("_uuid"),
|
|
106
|
+
timestamp: Date.now().toString(),
|
|
107
|
+
browser_resolution: fpGet(fp, "availableScreenResolution").join("x"),
|
|
108
|
+
abtest: `{"b_ut":null,"home_version":"V8","in_new_ab":true,"ab_version":{"for_ai_home_version":"V8","enable_web_push":"DISABLE","ad_style_version":"NEW","enable_feed_channel":"ENABLE","enable_ai_floor_api":"DISABLE"},"ab_split_num":{"for_ai_home_version":54,"enable_web_push":10,"ad_style_version":54,"enable_feed_channel":54,"enable_ai_floor_api":137},"uniq_page_id":"${Math.floor(Math.random() * 2000000000000)}","is_modern":true}`,
|
|
109
|
+
});
|
|
110
|
+
requestExClimbWuzhi(JSON.stringify(payload), {
|
|
111
|
+
...options,
|
|
112
|
+
cookie: cookies.toString(),
|
|
113
|
+
});
|
|
114
|
+
const cookieRecord = {};
|
|
115
|
+
cookies.forEach((val, k) => {
|
|
116
|
+
cookieRecord[k] = val;
|
|
117
|
+
});
|
|
118
|
+
return cookieRecord;
|
|
119
|
+
}
|
|
120
|
+
/** 获取指纹相关Cookies */
|
|
121
|
+
export function getFingerprintCookie(fp, options) {
|
|
122
|
+
const cookies = new Cookies(options.cookie);
|
|
123
|
+
let _uuid = cookies.get("_uuid");
|
|
124
|
+
let buvid_fp = cookies.get("buvid_fp");
|
|
125
|
+
let b_lsid = cookies.get("b_lsid");
|
|
126
|
+
if (!_uuid) {
|
|
127
|
+
_uuid = generateUuid();
|
|
128
|
+
cookies.set("_uuid", _uuid);
|
|
129
|
+
}
|
|
130
|
+
if (!buvid_fp) {
|
|
131
|
+
const fpString = fp
|
|
132
|
+
.map((e) => {
|
|
133
|
+
return e.value;
|
|
134
|
+
})
|
|
135
|
+
.join("");
|
|
136
|
+
buvid_fp = x64hash128(fpString, 31);
|
|
137
|
+
cookies.set("buvid_fp", buvid_fp);
|
|
138
|
+
}
|
|
139
|
+
if (!b_lsid) {
|
|
140
|
+
b_lsid = generateLsid();
|
|
141
|
+
cookies.set("b_lsid", b_lsid);
|
|
142
|
+
}
|
|
143
|
+
return {
|
|
144
|
+
_uuid,
|
|
145
|
+
buvid_fp,
|
|
146
|
+
b_lsid,
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
/** 激活buvid */
|
|
150
|
+
export function requestExClimbWuzhi(payload, options) {
|
|
151
|
+
customFetch(options, "https://api.bilibili.com/x/internal/gaia-gateway/ExClimbWuzhi", {
|
|
152
|
+
method: "POST",
|
|
153
|
+
body: payload,
|
|
154
|
+
credentials: "include",
|
|
155
|
+
headers: {
|
|
156
|
+
Accept: "*/*",
|
|
157
|
+
"Accept-Encoding": "gzip, deflate, br, zstd",
|
|
158
|
+
"Accept-Language": "zh-CN,zh;q=0.9",
|
|
159
|
+
"Content-Type": "application/json;charset=UTF-8",
|
|
160
|
+
Origin: "https://www.bilibili.com",
|
|
161
|
+
priority: "u=1, i",
|
|
162
|
+
Referer: "https://www.bilibili.com/",
|
|
163
|
+
"Sec-Ch-Ua": `"Microsoft Edge";v="135", "Not-A.Brand";v="8", "Chromium";v="135"`,
|
|
164
|
+
"Sec-Ch-Mobile": "?0",
|
|
165
|
+
"Sec-Ch-Platform": `"Windows"`,
|
|
166
|
+
"Sec-Ch-Dest": "empty",
|
|
167
|
+
"Sec-Ch-Mode": "cors",
|
|
168
|
+
"Sec-Fetch-Site": "same-site",
|
|
169
|
+
},
|
|
170
|
+
}).then((res) => res.json());
|
|
171
|
+
}
|
|
172
|
+
export function getRoomBaseInfo(room_id, options) {
|
|
173
|
+
return customFetch(options, `https://api.live.bilibili.com/xlive/web-room/v1/index/getRoomBaseInfo?room_ids=${room_id}&req_biz=video`)
|
|
174
|
+
.then((res) => res.json())
|
|
175
|
+
.then((data) => data.data)
|
|
176
|
+
.then((data) => {
|
|
177
|
+
for (const k in data.by_room_ids) {
|
|
178
|
+
return data.by_room_ids[k];
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
}
|
package/utils/uuid.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function generateUuid(): string;
|
package/utils/uuid.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// Refactored by Deepseek
|
|
2
|
+
// from `https://github.com/SocialSisterYi/bilibili-API-collect/issues/933#issue-2073916390`
|
|
3
|
+
// Copyright (c) 2024 Hantong Chen(cxw620). MIT license.
|
|
4
|
+
// RE from `https://s1.hdslb.com/bfs/seed/log/report/log-reporter.js`
|
|
5
|
+
// 工具函数代替Rust宏
|
|
6
|
+
const DIGIT_MAP = [
|
|
7
|
+
"1",
|
|
8
|
+
"2",
|
|
9
|
+
"3",
|
|
10
|
+
"4",
|
|
11
|
+
"5",
|
|
12
|
+
"6",
|
|
13
|
+
"7",
|
|
14
|
+
"8",
|
|
15
|
+
"9",
|
|
16
|
+
"A",
|
|
17
|
+
"B",
|
|
18
|
+
"C",
|
|
19
|
+
"D",
|
|
20
|
+
"E",
|
|
21
|
+
"F",
|
|
22
|
+
"10", // 保持原始数据不变
|
|
23
|
+
];
|
|
24
|
+
// 代替random_choice!宏
|
|
25
|
+
function randomChoice(...args) {
|
|
26
|
+
// 参数解析
|
|
27
|
+
const hasSeparator = typeof args[args.length - 2] === "string";
|
|
28
|
+
const [choiceSet, separator, lengths] = hasSeparator
|
|
29
|
+
? [args.pop(), args.pop(), args]
|
|
30
|
+
: [args.pop(), undefined, args];
|
|
31
|
+
// 生成随机段
|
|
32
|
+
const segments = lengths.map((length) => Array.from({ length }, () => choiceSet[Math.floor(Math.random() * choiceSet.length)]).join(""));
|
|
33
|
+
return separator ? segments.join(separator) : segments.join("");
|
|
34
|
+
}
|
|
35
|
+
// 代替now!宏
|
|
36
|
+
function getTimestamp() {
|
|
37
|
+
return Date.now() % 100000;
|
|
38
|
+
}
|
|
39
|
+
// 代替UuidInfoc结构体
|
|
40
|
+
export function generateUuid() {
|
|
41
|
+
const t = getTimestamp().toString().padStart(5, "0");
|
|
42
|
+
// 生成符合原始格式的各个部分
|
|
43
|
+
const parts = [randomChoice(8, 4, 4, 4, 12, "-", DIGIT_MAP), t, "infoc"];
|
|
44
|
+
return parts.join("");
|
|
45
|
+
}
|