isididiidid commited on
Commit
d59c7fe
·
verified ·
1 Parent(s): 7a0f917

Update src/CookieManager.js

Browse files
Files changed (1) hide show
  1. src/CookieManager.js +0 -379
src/CookieManager.js CHANGED
@@ -17,385 +17,6 @@ const logger = {
17
  success: (message) => console.log(`\x1b[32m[success] ${message}\x1b[0m`),
18
  };
19
 
20
- class CookieManager {
21
- constructor() {
22
- this.cookieEntries = []; // 存储cookie及其对应的ID
23
- this.currentIndex = 0;
24
- this.initialized = false;
25
- this.maxRetries = 3; // 最大重试次数
26
- this.proxyUrl = process.env.PROXY_URL || "";
27
- }
28
-
29
- /**
30
- * 从文件加载cookie
31
- * @param {string} filePath - cookie文件路径
32
- * @returns {Promise<boolean>} - 是否加载成功
33
- */
34
- async loadFromFile(filePath) {
35
- try {
36
- // 确保文件路径是绝对路径
37
- const absolutePath = path.isAbsolute(filePath)
38
- ? filePath
39
- : path.join(dirname(__dirname), filePath);
40
-
41
- logger.info(`从文件加载cookie: ${absolutePath}`);
42
-
43
- // 检查文件是否存在
44
- if (!fs.existsSync(absolutePath)) {
45
- logger.error(`Cookie文件不存在: ${absolutePath}`);
46
- return false;
47
- }
48
-
49
- // 读取文件内容
50
- const fileContent = fs.readFileSync(absolutePath, 'utf8');
51
-
52
- // 根据文件扩展名处理不同格式
53
- const ext = path.extname(absolutePath).toLowerCase();
54
- let cookieArray = [];
55
-
56
- if (ext === '.json') {
57
- // JSON格式
58
- try {
59
- const jsonData = JSON.parse(fileContent);
60
- if (Array.isArray(jsonData)) {
61
- cookieArray = jsonData;
62
- } else if (jsonData.cookies && Array.isArray(jsonData.cookies)) {
63
- cookieArray = jsonData.cookies;
64
- } else {
65
- logger.error('JSON文件格式错误,应为cookie数组或包含cookies数组的对象');
66
- return false;
67
- }
68
- } catch (error) {
69
- logger.error(`解析JSON文件失败: ${error.message}`);
70
- return false;
71
- }
72
- } else {
73
- // 文本格式,每行一个cookie
74
- cookieArray = fileContent
75
- .split('\n')
76
- .map(line => line.trim())
77
- .filter(line => line && !line.startsWith('#'));
78
- }
79
-
80
- logger.info(`从文件中读取了 ${cookieArray.length} 个cookie`);
81
-
82
- // 初始化cookie
83
- return await this.initialize(cookieArray.join('|'));
84
-
85
- } catch (error) {
86
- logger.error(`从文件加载cookie失败: ${error.message}`);
87
- return false;
88
- }
89
- }
90
-
91
- /**
92
- * 初始化cookie管理器
93
- * @param {string} cookiesString - 以"|"或","分隔的cookie字符串
94
- * @returns {Promise<boolean>} - 是否初始化成功
95
- */
96
- async initialize(cookiesString) {
97
- if (!cookiesString) {
98
- logger.error('未提供cookie字符串');
99
- return false;
100
- }
101
-
102
- // 【已修改】使用正则表达式支持"|"和","两种分隔符
103
- const cookieArray = cookiesString.split(/[|,]/).map(c => c.trim()).filter(c => c);
104
-
105
- if (cookieArray.length === 0) {
106
- logger.error('没有有效的cookie');
107
- return false;
108
- }
109
-
110
- logger.info(`发现 ${cookieArray.length} 个cookie,开始获取对应的ID信息...`);
111
-
112
- // 清空现有条目
113
- this.cookieEntries = [];
114
-
115
- // 为每个cookie获取ID
116
- for (let i = 0; i < cookieArray.length; i++) {
117
- const cookie = cookieArray[i];
118
- logger.info(`正在处理第 ${i+1}/${cookieArray.length} 个cookie...`);
119
-
120
- const result = await this.fetchNotionIds(cookie);
121
- if (result.success) {
122
- this.cookieEntries.push({
123
- cookie,
124
- spaceId: result.spaceId,
125
- userId: result.userId,
126
- valid: true,
127
- lastUsed: 0 // 记录上次使用时间戳
128
- });
129
- logger.success(`第 ${i+1} 个cookie验证成功`);
130
- } else {
131
- if (result.status === 401) {
132
- logger.error(`第 ${i+1} 个cookie无效(401未授权),已跳过`);
133
- } else {
134
- logger.warning(`第 ${i+1} 个cookie验证失败: ${result.error},已跳过`);
135
- }
136
- }
137
- }
138
-
139
- // 检查是否有有效的cookie
140
- if (this.cookieEntries.length === 0) {
141
- logger.error('没有有效的cookie,初始化失败');
142
- return false;
143
- }
144
-
145
- logger.success(`成功初始化 ${this.cookieEntries.length}/${cookieArray.length} 个cookie`);
146
- this.initialized = true;
147
- this.currentIndex = 0;
148
- return true;
149
- }
150
-
151
- /**
152
- * 保存cookie到文件
153
- * @param {string} filePath - 保存路径
154
- * @param {boolean} onlyValid - 是否只保存有效的cookie
155
- * @returns {boolean} - 是否保存成功
156
- */
157
- saveToFile(filePath, onlyValid = true) {
158
- try {
159
- // 确保文件路径是绝对路径
160
- const absolutePath = path.isAbsolute(filePath)
161
- ? filePath
162
- : path.join(dirname(__dirname), filePath);
163
-
164
- // 获取要保存的cookie
165
- const cookiesToSave = onlyValid
166
- ? this.cookieEntries.filter(entry => entry.valid).map(entry => entry.cookie)
167
- : this.cookieEntries.map(entry => entry.cookie);
168
-
169
- // 根据文件扩展名选择保存格式
170
- const ext = path.extname(absolutePath).toLowerCase();
171
-
172
- if (ext === '.json') {
173
- // 保存为JSON格式
174
- const jsonData = {
175
- cookies: cookiesToSave,
176
- updatedAt: new Date().toISOString(),
177
- count: cookiesToSave.length
178
- };
179
- fs.writeFileSync(absolutePath, JSON.stringify(jsonData, null, 2), 'utf8');
180
- } else {
181
- // 保存为文本格式,每行一个cookie
182
- const content = cookiesToSave.join('\n');
183
- fs.writeFileSync(absolutePath, content, 'utf8');
184
- }
185
-
186
- logger.success(`已将 ${cookiesToSave.length} 个cookie保存到文件: ${absolutePath}`);
187
- return true;
188
- } catch (error) {
189
- logger.error(`保存cookie到文件失败: ${error.message}`);
190
- return false;
191
- }
192
- }
193
-
194
- /**
195
- * 获取Notion的空间ID和用户ID
196
- * @param {string} cookie - Notion cookie
197
- * @returns {Promise<Object>} - 包含ID信息的对象
198
- */
199
- async fetchNotionIds(cookie, retryCount = 0) {
200
- if (!cookie) {
201
- return { success: false, error: '未提供cookie' };
202
- }
203
-
204
- try {
205
- // 创建JSDOM实例模拟浏览器环境
206
- const dom = new JSDOM("", {
207
- url: "https://www.notion.so",
208
- referrer: "https://www.notion.so/",
209
- contentType: "text/html",
210
- includeNodeLocations: true,
211
- storageQuota: 10000000,
212
- pretendToBeVisual: true,
213
- userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36"
214
- });
215
-
216
- // 设置全局对象
217
- const { window } = dom;
218
-
219
- // 安全地设置全局对象
220
- if (!global.window) global.window = window;
221
- if (!global.document) global.document = window.document;
222
-
223
- // 设置navigator
224
- if (!global.navigator) {
225
- try {
226
- Object.defineProperty(global, 'navigator', {
227
- value: window.navigator,
228
- writable: true,
229
- configurable: true
230
- });
231
- } catch (navError) {
232
- logger.warning(`无法设置navigator: ${navError.message},继续执行`);
233
- }
234
- }
235
-
236
- // 设置cookie
237
- document.cookie = cookie;
238
-
239
- // 创建fetch选项
240
- const fetchOptions = {
241
- method: 'POST',
242
- headers: {
243
- 'Content-Type': 'application/json',
244
- 'accept': '*/*',
245
- 'accept-language': 'en-US,en;q=0.9',
246
- 'notion-audit-log-platform': 'web',
247
- 'notion-client-version': '23.13.0.3686',
248
- 'origin': 'https://www.notion.so',
249
- 'referer': 'https://www.notion.so/',
250
- 'user-agent': window.navigator.userAgent,
251
- 'Cookie': cookie
252
- },
253
- body: JSON.stringify({}),
254
- };
255
-
256
- // 添加代理配置(如果有)
257
- if (this.proxyUrl) {
258
- const { HttpsProxyAgent } = await import('https-proxy-agent');
259
- fetchOptions.agent = new HttpsProxyAgent(this.proxyUrl);
260
- logger.info(`使用代理: ${this.proxyUrl}`);
261
- }
262
-
263
- // 发送请求
264
- const response = await fetch("https://www.notion.so/api/v3/getSpaces", fetchOptions);
265
-
266
- // 检查响应状态
267
- if (response.status === 401) {
268
- return { success: false, status: 401, error: '未授权,cookie无效' };
269
- }
270
-
271
- if (!response.ok) {
272
- throw new Error(`HTTP error! status: ${response.status}`);
273
- }
274
-
275
- const data = await response.json();
276
-
277
- // 提取用户ID
278
- const userIdKey = Object.keys(data)[0];
279
- if (!userIdKey) {
280
- throw new Error('无法从响应中提取用户ID');
281
- }
282
-
283
- const userId = userIdKey;
284
-
285
- // 提取空间ID
286
- const userRoot = data[userIdKey]?.user_root?.[userIdKey];
287
- const spaceViewPointers = userRoot?.value?.value?.space_view_pointers;
288
-
289
- if (!spaceViewPointers || !Array.isArray(spaceViewPointers) || spaceViewPointers.length === 0) {
290
- throw new Error('在响应中找不到space_view_pointers或spaceId');
291
- }
292
-
293
- const spaceId = spaceViewPointers[0].spaceId;
294
-
295
- if (!spaceId) {
296
- throw new Error('无法从space_view_pointers中提取spaceId');
297
- }
298
-
299
- // 清理全局对象
300
- this.cleanupGlobalObjects();
301
-
302
- return {
303
- success: true,
304
- userId,
305
- spaceId
306
- };
307
-
308
- } catch (error) {
309
- // 清理全局对象
310
- this.cleanupGlobalObjects();
311
-
312
- // 重试逻辑
313
- if (retryCount < this.maxRetries && error.message !== '未授权,cookie无效') {
314
- logger.warning(`获取Notion ID失败,正在重试 (${retryCount + 1}/${this.maxRetries}): ${error.message}`);
315
- return await this.fetchNotionIds(cookie, retryCount + 1);
316
- }
317
-
318
- return {
319
- success: false,
320
- error: error.message
321
- };
322
- }
323
- }
324
-
325
- /**
326
- * 清理全局对象
327
- */
328
- cleanupGlobalObjects() {
329
- try {
330
- if (global.window) delete global.window;
331
- if (global.document) delete global.document;
332
-
333
- // 安全地删除navigator
334
- if (global.navigator) {
335
- try {
336
- delete global.navigator;
337
- } catch (navError) {
338
- // 如果无法删除,尝试将其设置为undefined
339
- try {
340
- Object.defineProperty(global, 'navigator', {
341
- value: undefined,
342
- writable: true,
343
- configurable: true
344
- });
345
- } catch (defineError) {
346
- logger.warning(`无法清理navigator: ${defineError.message}`);
347
- }
348
- }
349
- }
350
- } catch (cleanupError) {
351
- logger.warning(`清理全局对象时出错: ${cleanupError.message}`);
352
- }
353
- }
354
-
355
- /**
356
- * 获取下一个可用的cookie及其ID
357
- * @returns {Object|null} - cookie及其对应的ID,如果没有可用cookie则返回null
358
- */
359
- getNext() {
360
- if (!this.initialized || this.cookieEntries.length === 0) {
361
- return null;
362
- }
363
-
364
- // 轮询选择下一个cookie
365
- const entry = this.cookieEntries[this.currentIndex];
366
-
367
- // 更新索引,实现轮询
368
- this.currentIndex = (this.currentIndex + 1) % this.cookieEntries.length;
369
-
370
- // 更新最后使用时间
371
- entry.lastUsed = Date.now();
372
-
373
- return {
374
- cookie: entry.cookie,
375
- spaceId: entry.spaceId,
376
- userId: entry.userId
377
- };
378
- }
379
-
380
- import { JSDOM } from 'jsdom';
381
- import fetch from 'node-fetch';
382
- import fs from 'fs';
383
- import path from 'path';
384
- import { fileURLToPath } from 'url';
385
- import { dirname } from 'path';
386
-
387
- // 获取当前文件的目录路径
388
- const __filename = fileURLToPath(import.meta.url);
389
- const __dirname = dirname(__filename);
390
-
391
- // 日志配置
392
- const logger = {
393
- info: (message) => console.log(`\x1b[34m[info] ${message}\x1b[0m`),
394
- error: (message) => console.error(`\x1b[31m[error] ${message}\x1b[0m`),
395
- warning: (message) => console.warn(`\x1b[33m[warn] ${message}\x1b[0m`),
396
- success: (message) => console.log(`\x1b[32m[success] ${message}\x1b[0m`),
397
- };
398
-
399
  class CookieManager {
400
  constructor() {
401
  this.cookieEntries = []; // 存储cookie及其对应的ID
 
17
  success: (message) => console.log(`\x1b[32m[success] ${message}\x1b[0m`),
18
  };
19
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  class CookieManager {
21
  constructor() {
22
  this.cookieEntries = []; // 存储cookie及其对应的ID