@roomi-fields/notebooklm-mcp 1.3.3 โ 1.3.5
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/README.md +764 -715
- package/dist/__tests__/cleanup-manager.test.d.ts +2 -0
- package/dist/__tests__/cleanup-manager.test.d.ts.map +1 -0
- package/dist/__tests__/cleanup-manager.test.js +341 -0
- package/dist/__tests__/cleanup-manager.test.js.map +1 -0
- package/dist/__tests__/config-parsing.test.d.ts +2 -0
- package/dist/__tests__/config-parsing.test.d.ts.map +1 -0
- package/dist/__tests__/config-parsing.test.js +338 -0
- package/dist/__tests__/config-parsing.test.js.map +1 -0
- package/dist/__tests__/config.test.d.ts +2 -0
- package/dist/__tests__/config.test.d.ts.map +1 -0
- package/dist/__tests__/config.test.js +267 -0
- package/dist/__tests__/config.test.js.map +1 -0
- package/dist/__tests__/errors.test.d.ts +2 -0
- package/dist/__tests__/errors.test.d.ts.map +1 -0
- package/dist/__tests__/errors.test.js +166 -0
- package/dist/__tests__/errors.test.js.map +1 -0
- package/dist/__tests__/logger.test.d.ts +2 -0
- package/dist/__tests__/logger.test.d.ts.map +1 -0
- package/dist/__tests__/logger.test.js +324 -0
- package/dist/__tests__/logger.test.js.map +1 -0
- package/dist/__tests__/page-utils.test.d.ts +2 -0
- package/dist/__tests__/page-utils.test.d.ts.map +1 -0
- package/dist/__tests__/page-utils.test.js +349 -0
- package/dist/__tests__/page-utils.test.js.map +1 -0
- package/dist/__tests__/setup-verification.test.d.ts +2 -0
- package/dist/__tests__/setup-verification.test.d.ts.map +1 -0
- package/dist/__tests__/setup-verification.test.js +15 -0
- package/dist/__tests__/setup-verification.test.js.map +1 -0
- package/dist/__tests__/stealth-utils.test.d.ts +2 -0
- package/dist/__tests__/stealth-utils.test.d.ts.map +1 -0
- package/dist/__tests__/stealth-utils.test.js +413 -0
- package/dist/__tests__/stealth-utils.test.js.map +1 -0
- package/dist/__tests__/types.test.d.ts +2 -0
- package/dist/__tests__/types.test.d.ts.map +1 -0
- package/dist/__tests__/types.test.js +461 -0
- package/dist/__tests__/types.test.js.map +1 -0
- package/dist/auth/auth-manager.d.ts +2 -2
- package/dist/auth/auth-manager.d.ts.map +1 -1
- package/dist/auth/auth-manager.js +187 -180
- package/dist/auth/auth-manager.js.map +1 -1
- package/dist/auto-discovery/auto-discovery.d.ts.map +1 -1
- package/dist/auto-discovery/auto-discovery.js +17 -17
- package/dist/auto-discovery/auto-discovery.js.map +1 -1
- package/dist/cli/de-auth.d.ts +10 -0
- package/dist/cli/de-auth.d.ts.map +1 -0
- package/dist/cli/de-auth.js +47 -0
- package/dist/cli/de-auth.js.map +1 -0
- package/dist/cli/help.d.ts +6 -0
- package/dist/cli/help.d.ts.map +1 -0
- package/dist/cli/help.js +67 -0
- package/dist/cli/help.js.map +1 -0
- package/dist/cli/setup-auth.d.ts +11 -0
- package/dist/cli/setup-auth.d.ts.map +1 -0
- package/dist/cli/setup-auth.js +82 -0
- package/dist/cli/setup-auth.js.map +1 -0
- package/dist/config.d.ts +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +49 -103
- package/dist/config.js.map +1 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +3 -3
- package/dist/errors.js.map +1 -1
- package/dist/http-wrapper.js +96 -172
- package/dist/http-wrapper.js.map +1 -1
- package/dist/index.js +110 -107
- package/dist/index.js.map +1 -1
- package/dist/library/notebook-library.d.ts +2 -2
- package/dist/library/notebook-library.d.ts.map +1 -1
- package/dist/library/notebook-library.js +24 -24
- package/dist/library/notebook-library.js.map +1 -1
- package/dist/session/browser-session.d.ts +4 -4
- package/dist/session/browser-session.d.ts.map +1 -1
- package/dist/session/browser-session.js +62 -58
- package/dist/session/browser-session.js.map +1 -1
- package/dist/session/session-manager.d.ts +3 -3
- package/dist/session/session-manager.d.ts.map +1 -1
- package/dist/session/session-manager.js +14 -14
- package/dist/session/session-manager.js.map +1 -1
- package/dist/session/shared-context-manager.d.ts +2 -2
- package/dist/session/shared-context-manager.d.ts.map +1 -1
- package/dist/session/shared-context-manager.js +62 -58
- package/dist/session/shared-context-manager.js.map +1 -1
- package/dist/tools/index.d.ts +14 -14
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +517 -530
- package/dist/tools/index.js.map +1 -1
- package/dist/types.d.ts +24 -67
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -12
- package/dist/types.js.map +1 -1
- package/dist/utils/cleanup-manager.d.ts +1 -1
- package/dist/utils/cleanup-manager.d.ts.map +1 -1
- package/dist/utils/cleanup-manager.js +90 -92
- package/dist/utils/cleanup-manager.js.map +1 -1
- package/dist/utils/logger.d.ts +1 -2
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/logger.js +15 -15
- package/dist/utils/page-utils.d.ts +1 -1
- package/dist/utils/page-utils.d.ts.map +1 -1
- package/dist/utils/page-utils.js +39 -46
- package/dist/utils/page-utils.js.map +1 -1
- package/dist/utils/stealth-utils.d.ts +2 -2
- package/dist/utils/stealth-utils.d.ts.map +1 -1
- package/dist/utils/stealth-utils.js +13 -13
- package/dist/utils/stealth-utils.js.map +1 -1
- package/docs/CHROME_PROFILE_LIMITATION.md +229 -212
- package/package.json +107 -78
|
@@ -11,32 +11,32 @@
|
|
|
11
11
|
*
|
|
12
12
|
* Based on the Python implementation from auth.py
|
|
13
13
|
*/
|
|
14
|
-
import fs from
|
|
15
|
-
import { existsSync } from
|
|
16
|
-
import path from
|
|
17
|
-
import { CONFIG, NOTEBOOKLM_AUTH_URL } from
|
|
18
|
-
import { log } from
|
|
19
|
-
import { humanType, randomDelay, realisticClick, randomMouseMovement, } from
|
|
14
|
+
import fs from 'fs/promises';
|
|
15
|
+
import { existsSync } from 'fs';
|
|
16
|
+
import path from 'path';
|
|
17
|
+
import { CONFIG, NOTEBOOKLM_AUTH_URL } from '../config.js';
|
|
18
|
+
import { log } from '../utils/logger.js';
|
|
19
|
+
import { humanType, randomDelay, realisticClick, randomMouseMovement, } from '../utils/stealth-utils.js';
|
|
20
20
|
/**
|
|
21
21
|
* Critical cookie names for Google authentication
|
|
22
22
|
*/
|
|
23
23
|
const CRITICAL_COOKIE_NAMES = [
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
24
|
+
'SID',
|
|
25
|
+
'HSID',
|
|
26
|
+
'SSID', // Google session
|
|
27
|
+
'APISID',
|
|
28
|
+
'SAPISID', // API auth
|
|
29
|
+
'OSID',
|
|
30
|
+
'__Secure-OSID', // NotebookLM-specific
|
|
31
|
+
'__Secure-1PSID',
|
|
32
|
+
'__Secure-3PSID', // Secure variants
|
|
33
33
|
];
|
|
34
34
|
export class AuthManager {
|
|
35
35
|
stateFilePath;
|
|
36
36
|
sessionFilePath;
|
|
37
37
|
constructor() {
|
|
38
|
-
this.stateFilePath = path.join(CONFIG.browserStateDir,
|
|
39
|
-
this.sessionFilePath = path.join(CONFIG.browserStateDir,
|
|
38
|
+
this.stateFilePath = path.join(CONFIG.browserStateDir, 'state.json');
|
|
39
|
+
this.sessionFilePath = path.join(CONFIG.browserStateDir, 'session.json');
|
|
40
40
|
}
|
|
41
41
|
// ============================================================================
|
|
42
42
|
// Browser State Management
|
|
@@ -66,7 +66,7 @@ export class AuthManager {
|
|
|
66
66
|
return JSON.stringify(storage);
|
|
67
67
|
});
|
|
68
68
|
await fs.writeFile(this.sessionFilePath, sessionStorageData, {
|
|
69
|
-
encoding:
|
|
69
|
+
encoding: 'utf-8',
|
|
70
70
|
});
|
|
71
71
|
const entries = Object.keys(JSON.parse(sessionStorageData)).length;
|
|
72
72
|
log.success(`โ
Browser state saved (incl. sessionStorage: ${entries} entries)`);
|
|
@@ -76,7 +76,7 @@ export class AuthManager {
|
|
|
76
76
|
}
|
|
77
77
|
}
|
|
78
78
|
else {
|
|
79
|
-
log.success(
|
|
79
|
+
log.success('โ
Browser state saved');
|
|
80
80
|
}
|
|
81
81
|
return true;
|
|
82
82
|
}
|
|
@@ -116,8 +116,8 @@ export class AuthManager {
|
|
|
116
116
|
return null;
|
|
117
117
|
}
|
|
118
118
|
if (await this.isStateExpired()) {
|
|
119
|
-
log.warning(
|
|
120
|
-
log.info(
|
|
119
|
+
log.warning('โ ๏ธ Saved state is expired (>24h old)');
|
|
120
|
+
log.info('๐ก Run setup_auth tool to re-authenticate');
|
|
121
121
|
return null;
|
|
122
122
|
}
|
|
123
123
|
return statePath;
|
|
@@ -127,7 +127,7 @@ export class AuthManager {
|
|
|
127
127
|
*/
|
|
128
128
|
async loadSessionStorage() {
|
|
129
129
|
try {
|
|
130
|
-
const data = await fs.readFile(this.sessionFilePath, { encoding:
|
|
130
|
+
const data = await fs.readFile(this.sessionFilePath, { encoding: 'utf-8' });
|
|
131
131
|
const sessionData = JSON.parse(data);
|
|
132
132
|
log.success(`โ
Loaded sessionStorage (${Object.keys(sessionData).length} entries)`);
|
|
133
133
|
return sessionData;
|
|
@@ -147,13 +147,13 @@ export class AuthManager {
|
|
|
147
147
|
try {
|
|
148
148
|
const cookies = await context.cookies();
|
|
149
149
|
if (cookies.length === 0) {
|
|
150
|
-
log.warning(
|
|
150
|
+
log.warning('โ ๏ธ No cookies found in state');
|
|
151
151
|
return false;
|
|
152
152
|
}
|
|
153
153
|
// Check for Google auth cookies
|
|
154
|
-
const googleCookies = cookies.filter((c) => c.domain.includes(
|
|
154
|
+
const googleCookies = cookies.filter((c) => c.domain.includes('google.com'));
|
|
155
155
|
if (googleCookies.length === 0) {
|
|
156
|
-
log.warning(
|
|
156
|
+
log.warning('โ ๏ธ No Google cookies found');
|
|
157
157
|
return false;
|
|
158
158
|
}
|
|
159
159
|
// Check if important cookies are expired
|
|
@@ -165,7 +165,7 @@ export class AuthManager {
|
|
|
165
165
|
return false;
|
|
166
166
|
}
|
|
167
167
|
}
|
|
168
|
-
log.success(
|
|
168
|
+
log.success('โ
State validation passed');
|
|
169
169
|
return true;
|
|
170
170
|
}
|
|
171
171
|
catch (error) {
|
|
@@ -180,13 +180,13 @@ export class AuthManager {
|
|
|
180
180
|
try {
|
|
181
181
|
const cookies = await context.cookies();
|
|
182
182
|
if (cookies.length === 0) {
|
|
183
|
-
log.warning(
|
|
183
|
+
log.warning('โ ๏ธ No cookies found');
|
|
184
184
|
return false;
|
|
185
185
|
}
|
|
186
186
|
// Find critical cookies
|
|
187
187
|
const criticalCookies = cookies.filter((c) => CRITICAL_COOKIE_NAMES.includes(c.name));
|
|
188
188
|
if (criticalCookies.length === 0) {
|
|
189
|
-
log.warning(
|
|
189
|
+
log.warning('โ ๏ธ No critical auth cookies found');
|
|
190
190
|
return false;
|
|
191
191
|
}
|
|
192
192
|
// Check expiration for each critical cookie
|
|
@@ -204,7 +204,7 @@ export class AuthManager {
|
|
|
204
204
|
}
|
|
205
205
|
}
|
|
206
206
|
if (expiredCookies.length > 0) {
|
|
207
|
-
log.warning(`โ ๏ธ Expired cookies: ${expiredCookies.join(
|
|
207
|
+
log.warning(`โ ๏ธ Expired cookies: ${expiredCookies.join(', ')}`);
|
|
208
208
|
return false;
|
|
209
209
|
}
|
|
210
210
|
log.success(`โ
All ${criticalCookies.length} critical cookies are valid`);
|
|
@@ -245,18 +245,18 @@ export class AuthManager {
|
|
|
245
245
|
*/
|
|
246
246
|
async performLogin(page, sendProgress) {
|
|
247
247
|
try {
|
|
248
|
-
log.info(
|
|
249
|
-
log.warning(
|
|
250
|
-
log.warning(
|
|
251
|
-
log.info(
|
|
248
|
+
log.info('๐ Opening Google login page...');
|
|
249
|
+
log.warning('๐ Please login to your Google account');
|
|
250
|
+
log.warning('โณ Browser will close automatically once you reach NotebookLM');
|
|
251
|
+
log.info('');
|
|
252
252
|
// Progress: Navigating
|
|
253
|
-
await sendProgress?.(
|
|
253
|
+
await sendProgress?.('Navigating to Google login...', 3, 10);
|
|
254
254
|
// Navigate to Google login (redirects to NotebookLM after auth)
|
|
255
255
|
await page.goto(NOTEBOOKLM_AUTH_URL, { timeout: 60000 });
|
|
256
256
|
// Progress: Waiting for login
|
|
257
|
-
await sendProgress?.(
|
|
257
|
+
await sendProgress?.('Waiting for manual login (up to 10 minutes)...', 4, 10);
|
|
258
258
|
// Wait for user to complete login
|
|
259
|
-
log.warning(
|
|
259
|
+
log.warning('โณ Waiting for login (up to 10 minutes)...');
|
|
260
260
|
const checkIntervalMs = 1000; // Check every 1 second
|
|
261
261
|
const maxAttempts = 600; // 10 minutes total
|
|
262
262
|
let lastProgressUpdate = 0;
|
|
@@ -271,34 +271,49 @@ export class AuthManager {
|
|
|
271
271
|
await sendProgress?.(`Waiting for login... (${elapsedSeconds}s elapsed)`, progressStep, 10);
|
|
272
272
|
}
|
|
273
273
|
// โ
SIMPLE: Check if we're on NotebookLM (any path!)
|
|
274
|
-
if (currentUrl.startsWith(
|
|
275
|
-
await sendProgress?.(
|
|
276
|
-
log.success(
|
|
274
|
+
if (currentUrl.startsWith('https://notebooklm.google.com/')) {
|
|
275
|
+
await sendProgress?.('Login successful! NotebookLM detected!', 9, 10);
|
|
276
|
+
log.success('โ
Login successful! NotebookLM URL detected.');
|
|
277
277
|
log.success(`โ
Current URL: ${currentUrl}`);
|
|
278
|
-
//
|
|
279
|
-
|
|
278
|
+
// โ
CRITICAL: Wait for page to fully load before saving cookies
|
|
279
|
+
// NotebookLM needs time to:
|
|
280
|
+
// 1. Complete the OAuth redirect
|
|
281
|
+
// 2. Generate session cookies (__Secure-OSID, etc.)
|
|
282
|
+
// 3. Load the application and establish session
|
|
283
|
+
log.info('โณ Waiting for NotebookLM to fully load (10 seconds)...');
|
|
284
|
+
await sendProgress?.('Waiting for page to fully load...', 9, 10);
|
|
285
|
+
// Wait for network to be idle (no more requests for 500ms)
|
|
286
|
+
try {
|
|
287
|
+
await page.waitForLoadState('networkidle', { timeout: 15000 });
|
|
288
|
+
log.success('โ
Page network is idle');
|
|
289
|
+
}
|
|
290
|
+
catch {
|
|
291
|
+
log.warning('โ ๏ธ Network idle timeout - continuing anyway');
|
|
292
|
+
}
|
|
293
|
+
// Additional buffer to ensure all cookies are set
|
|
294
|
+
await page.waitForTimeout(5000);
|
|
295
|
+
log.success('โ
Page fully loaded, cookies should be set');
|
|
280
296
|
return true;
|
|
281
297
|
}
|
|
282
298
|
// Still on accounts.google.com - log periodically
|
|
283
|
-
if (currentUrl.includes(
|
|
299
|
+
if (currentUrl.includes('accounts.google.com') && attempt % 30 === 0 && attempt > 0) {
|
|
284
300
|
log.warning(`โณ Still waiting... (${elapsedSeconds}s elapsed)`);
|
|
285
301
|
}
|
|
286
302
|
await page.waitForTimeout(checkIntervalMs);
|
|
287
303
|
}
|
|
288
|
-
catch
|
|
289
|
-
log.debug(`[LOGIN] Poll iteration error (non-critical): ${error}`);
|
|
304
|
+
catch {
|
|
290
305
|
await page.waitForTimeout(checkIntervalMs);
|
|
291
306
|
continue;
|
|
292
307
|
}
|
|
293
308
|
}
|
|
294
309
|
// Timeout reached - final check
|
|
295
310
|
const currentUrl = page.url();
|
|
296
|
-
if (currentUrl.startsWith(
|
|
297
|
-
await sendProgress?.(
|
|
298
|
-
log.success(
|
|
311
|
+
if (currentUrl.startsWith('https://notebooklm.google.com/')) {
|
|
312
|
+
await sendProgress?.('Login successful (detected on timeout check)!', 9, 10);
|
|
313
|
+
log.success('โ
Login successful (detected on timeout check)');
|
|
299
314
|
return true;
|
|
300
315
|
}
|
|
301
|
-
log.error(
|
|
316
|
+
log.error('โ Login verification failed - timeout reached');
|
|
302
317
|
log.warning(`Current URL: ${currentUrl}`);
|
|
303
318
|
return false;
|
|
304
319
|
}
|
|
@@ -318,55 +333,55 @@ export class AuthManager {
|
|
|
318
333
|
log.warning(`๐ Attempting automatic login for ${maskedEmail}...`);
|
|
319
334
|
// Log browser visibility
|
|
320
335
|
if (!CONFIG.headless) {
|
|
321
|
-
log.info(
|
|
336
|
+
log.info(' ๐๏ธ Browser is VISIBLE for debugging');
|
|
322
337
|
}
|
|
323
338
|
else {
|
|
324
|
-
log.info(
|
|
339
|
+
log.info(' ๐ Browser is HEADLESS (invisible)');
|
|
325
340
|
}
|
|
326
341
|
log.info(` ๐ Navigating to Google login...`);
|
|
327
342
|
try {
|
|
328
343
|
await page.goto(NOTEBOOKLM_AUTH_URL, {
|
|
329
|
-
waitUntil:
|
|
344
|
+
waitUntil: 'domcontentloaded',
|
|
330
345
|
timeout: CONFIG.browserTimeout,
|
|
331
346
|
});
|
|
332
347
|
log.success(` โ
Page loaded: ${page.url().slice(0, 80)}...`);
|
|
333
348
|
}
|
|
334
|
-
catch
|
|
349
|
+
catch {
|
|
335
350
|
log.warning(` โ ๏ธ Page load timeout (continuing anyway)`);
|
|
336
351
|
}
|
|
337
352
|
const deadline = Date.now() + CONFIG.autoLoginTimeoutMs;
|
|
338
353
|
log.info(` โฐ Auto-login timeout: ${CONFIG.autoLoginTimeoutMs / 1000}s`);
|
|
339
354
|
// Already on NotebookLM?
|
|
340
|
-
log.info(
|
|
355
|
+
log.info(' ๐ Checking if already authenticated...');
|
|
341
356
|
if (await this.waitForNotebook(page, CONFIG.autoLoginTimeoutMs)) {
|
|
342
|
-
log.success(
|
|
357
|
+
log.success('โ
Already authenticated');
|
|
343
358
|
await this.saveBrowserState(context, page);
|
|
344
359
|
return true;
|
|
345
360
|
}
|
|
346
|
-
log.warning(
|
|
361
|
+
log.warning(' โ Not authenticated yet, proceeding with login...');
|
|
347
362
|
// Handle possible account chooser
|
|
348
|
-
log.info(
|
|
363
|
+
log.info(' ๐ Checking for account chooser...');
|
|
349
364
|
if (await this.handleAccountChooser(page, email)) {
|
|
350
|
-
log.success(
|
|
365
|
+
log.success(' โ
Account selected from chooser');
|
|
351
366
|
if (await this.waitForNotebook(page, CONFIG.autoLoginTimeoutMs)) {
|
|
352
|
-
log.success(
|
|
367
|
+
log.success('โ
Automatic login successful');
|
|
353
368
|
await this.saveBrowserState(context, page);
|
|
354
369
|
return true;
|
|
355
370
|
}
|
|
356
371
|
}
|
|
357
372
|
// Email step
|
|
358
|
-
log.info(
|
|
373
|
+
log.info(' ๐ง Entering email address...');
|
|
359
374
|
if (!(await this.fillIdentifier(page, email))) {
|
|
360
375
|
if (await this.waitForNotebook(page, CONFIG.autoLoginTimeoutMs)) {
|
|
361
|
-
log.success(
|
|
376
|
+
log.success('โ
Automatic login successful');
|
|
362
377
|
await this.saveBrowserState(context, page);
|
|
363
378
|
return true;
|
|
364
379
|
}
|
|
365
|
-
log.warning(
|
|
380
|
+
log.warning('โ ๏ธ Email input not detected');
|
|
366
381
|
}
|
|
367
382
|
// Password step (wait until visible)
|
|
368
383
|
let waitAttempts = 0;
|
|
369
|
-
log.warning(
|
|
384
|
+
log.warning(' โณ Waiting for password page to load...');
|
|
370
385
|
while (Date.now() < deadline && !(await this.fillPassword(page, password))) {
|
|
371
386
|
waitAttempts++;
|
|
372
387
|
// Log every 10 seconds (20 attempts * 0.5s)
|
|
@@ -376,21 +391,21 @@ export class AuthManager {
|
|
|
376
391
|
log.warning(` โณ Still waiting for password field... (${secondsWaited}s elapsed, ${secondsRemaining.toFixed(0)}s remaining)`);
|
|
377
392
|
log.info(` ๐ Current URL: ${page.url().slice(0, 100)}`);
|
|
378
393
|
}
|
|
379
|
-
if (page.url().includes(
|
|
380
|
-
log.warning(
|
|
394
|
+
if (page.url().includes('challenge')) {
|
|
395
|
+
log.warning('โ ๏ธ Additional verification required (Google challenge page).');
|
|
381
396
|
return false;
|
|
382
397
|
}
|
|
383
398
|
await page.waitForTimeout(500);
|
|
384
399
|
}
|
|
385
400
|
// Wait for Google redirect after login
|
|
386
|
-
log.info(
|
|
401
|
+
log.info(' ๐ Waiting for Google redirect to NotebookLM...');
|
|
387
402
|
if (await this.waitForRedirectAfterLogin(page, deadline)) {
|
|
388
|
-
log.success(
|
|
403
|
+
log.success('โ
Automatic login successful');
|
|
389
404
|
await this.saveBrowserState(context, page);
|
|
390
405
|
return true;
|
|
391
406
|
}
|
|
392
407
|
// Login failed - diagnose
|
|
393
|
-
log.error(
|
|
408
|
+
log.error('โ Automatic login timed out');
|
|
394
409
|
// Take screenshot for debugging
|
|
395
410
|
try {
|
|
396
411
|
const screenshotPath = path.join(CONFIG.dataDir, `login_failed_${Date.now()}.png`);
|
|
@@ -402,27 +417,27 @@ export class AuthManager {
|
|
|
402
417
|
}
|
|
403
418
|
// Diagnose specific failure reason
|
|
404
419
|
const currentUrl = page.url();
|
|
405
|
-
log.warning(
|
|
406
|
-
if (currentUrl.includes(
|
|
407
|
-
if (currentUrl.includes(
|
|
408
|
-
log.error(
|
|
409
|
-
log.info(
|
|
420
|
+
log.warning(' ๐ Diagnosing failure...');
|
|
421
|
+
if (currentUrl.includes('accounts.google.com')) {
|
|
422
|
+
if (currentUrl.includes('/signin/identifier')) {
|
|
423
|
+
log.error(' โ Still on email page - email input might have failed');
|
|
424
|
+
log.info(' ๐ก Check if email is correct in .env');
|
|
410
425
|
}
|
|
411
|
-
else if (currentUrl.includes(
|
|
412
|
-
log.error(
|
|
413
|
-
log.info(
|
|
426
|
+
else if (currentUrl.includes('/challenge')) {
|
|
427
|
+
log.error(' โ Google requires additional verification (2FA, CAPTCHA, suspicious login)');
|
|
428
|
+
log.info(' ๐ก Try logging in manually first: use setup_auth tool');
|
|
414
429
|
}
|
|
415
|
-
else if (currentUrl.includes(
|
|
416
|
-
log.error(
|
|
417
|
-
log.info(
|
|
430
|
+
else if (currentUrl.includes('/pwd') || currentUrl.includes('/password')) {
|
|
431
|
+
log.error(' โ Still on password page - password input might have failed');
|
|
432
|
+
log.info(' ๐ก Check if password is correct in .env');
|
|
418
433
|
}
|
|
419
434
|
else {
|
|
420
435
|
log.error(` โ Stuck on Google accounts page: ${currentUrl.slice(0, 80)}...`);
|
|
421
436
|
}
|
|
422
437
|
}
|
|
423
|
-
else if (currentUrl.includes(
|
|
438
|
+
else if (currentUrl.includes('notebooklm.google.com')) {
|
|
424
439
|
log.warning(" โ ๏ธ Reached NotebookLM but couldn't detect successful login");
|
|
425
|
-
log.info(
|
|
440
|
+
log.info(' ๐ก This might be a timing issue - try again');
|
|
426
441
|
}
|
|
427
442
|
else {
|
|
428
443
|
log.error(` โ Unexpected page: ${currentUrl.slice(0, 80)}...`);
|
|
@@ -439,24 +454,24 @@ export class AuthManager {
|
|
|
439
454
|
* Matches the simplified approach used in performLogin().
|
|
440
455
|
*/
|
|
441
456
|
async waitForRedirectAfterLogin(page, deadline) {
|
|
442
|
-
log.info(
|
|
457
|
+
log.info(' โณ Waiting for redirect to NotebookLM...');
|
|
443
458
|
while (Date.now() < deadline) {
|
|
444
459
|
try {
|
|
445
460
|
const currentUrl = page.url();
|
|
446
461
|
// Simple check: Are we on NotebookLM?
|
|
447
|
-
if (currentUrl.startsWith(
|
|
448
|
-
log.success(
|
|
462
|
+
if (currentUrl.startsWith('https://notebooklm.google.com/')) {
|
|
463
|
+
log.success(' โ
NotebookLM URL detected!');
|
|
449
464
|
// Short wait to ensure page is loaded
|
|
450
465
|
await page.waitForTimeout(2000);
|
|
451
466
|
return true;
|
|
452
467
|
}
|
|
453
468
|
}
|
|
454
|
-
catch
|
|
455
|
-
|
|
469
|
+
catch {
|
|
470
|
+
// Ignore errors
|
|
456
471
|
}
|
|
457
472
|
await page.waitForTimeout(500);
|
|
458
473
|
}
|
|
459
|
-
log.error(
|
|
474
|
+
log.error(' โ Redirect timeout - NotebookLM URL not reached');
|
|
460
475
|
return false;
|
|
461
476
|
}
|
|
462
477
|
/**
|
|
@@ -471,13 +486,13 @@ export class AuthManager {
|
|
|
471
486
|
try {
|
|
472
487
|
const currentUrl = page.url();
|
|
473
488
|
// Simple check: Are we on NotebookLM?
|
|
474
|
-
if (currentUrl.startsWith(
|
|
475
|
-
log.success(
|
|
489
|
+
if (currentUrl.startsWith('https://notebooklm.google.com/')) {
|
|
490
|
+
log.success(' โ
NotebookLM URL detected');
|
|
476
491
|
return true;
|
|
477
492
|
}
|
|
478
493
|
}
|
|
479
|
-
catch
|
|
480
|
-
|
|
494
|
+
catch {
|
|
495
|
+
// Ignore errors
|
|
481
496
|
}
|
|
482
497
|
await page.waitForTimeout(1000);
|
|
483
498
|
}
|
|
@@ -488,10 +503,10 @@ export class AuthManager {
|
|
|
488
503
|
*/
|
|
489
504
|
async handleAccountChooser(page, email) {
|
|
490
505
|
try {
|
|
491
|
-
const chooser = await page.$$(
|
|
506
|
+
const chooser = await page.$$('div[data-identifier], li[data-identifier]');
|
|
492
507
|
if (chooser.length > 0) {
|
|
493
508
|
for (const item of chooser) {
|
|
494
|
-
const identifier = (await item.getAttribute(
|
|
509
|
+
const identifier = (await item.getAttribute('data-identifier'))?.toLowerCase() || '';
|
|
495
510
|
if (identifier === email.toLowerCase()) {
|
|
496
511
|
await item.click();
|
|
497
512
|
await randomDelay(150, 320);
|
|
@@ -501,17 +516,16 @@ export class AuthManager {
|
|
|
501
516
|
}
|
|
502
517
|
// Click "Use another account"
|
|
503
518
|
await this.clickText(page, [
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
519
|
+
'Use another account',
|
|
520
|
+
'Weiteres Konto hinzufรผgen',
|
|
521
|
+
'Anderes Konto verwenden',
|
|
507
522
|
]);
|
|
508
523
|
await randomDelay(150, 320);
|
|
509
524
|
return false;
|
|
510
525
|
}
|
|
511
526
|
return false;
|
|
512
527
|
}
|
|
513
|
-
catch
|
|
514
|
-
log.debug(`[ACCOUNT_CHOOSER] Error handling account chooser: ${error}`);
|
|
528
|
+
catch {
|
|
515
529
|
return false;
|
|
516
530
|
}
|
|
517
531
|
}
|
|
@@ -519,9 +533,9 @@ export class AuthManager {
|
|
|
519
533
|
* Fill email identifier field with human-like typing
|
|
520
534
|
*/
|
|
521
535
|
async fillIdentifier(page, email) {
|
|
522
|
-
log.info(
|
|
536
|
+
log.info(' ๐ง Looking for email field...');
|
|
523
537
|
const emailSelectors = [
|
|
524
|
-
|
|
538
|
+
'input#identifierId',
|
|
525
539
|
"input[name='identifier']",
|
|
526
540
|
"input[type='email']",
|
|
527
541
|
];
|
|
@@ -530,7 +544,7 @@ export class AuthManager {
|
|
|
530
544
|
for (const selector of emailSelectors) {
|
|
531
545
|
try {
|
|
532
546
|
const candidate = await page.waitForSelector(selector, {
|
|
533
|
-
state:
|
|
547
|
+
state: 'attached',
|
|
534
548
|
timeout: 3000,
|
|
535
549
|
});
|
|
536
550
|
if (!candidate)
|
|
@@ -540,8 +554,7 @@ export class AuthManager {
|
|
|
540
554
|
continue; // Hidden field
|
|
541
555
|
}
|
|
542
556
|
}
|
|
543
|
-
catch
|
|
544
|
-
log.debug(`[EMAIL] Visibility check failed for ${selector}: ${error}`);
|
|
557
|
+
catch {
|
|
545
558
|
continue;
|
|
546
559
|
}
|
|
547
560
|
emailField = candidate;
|
|
@@ -549,13 +562,12 @@ export class AuthManager {
|
|
|
549
562
|
log.success(` โ
Email field visible: ${selector}`);
|
|
550
563
|
break;
|
|
551
564
|
}
|
|
552
|
-
catch
|
|
553
|
-
log.debug(`[EMAIL] Selector ${selector} not found: ${error}`);
|
|
565
|
+
catch {
|
|
554
566
|
continue;
|
|
555
567
|
}
|
|
556
568
|
}
|
|
557
569
|
if (!emailField || !emailSelector) {
|
|
558
|
-
log.warning(
|
|
570
|
+
log.warning(' โน๏ธ No visible email field found (likely pre-filled)');
|
|
559
571
|
log.info(` ๐ Current URL: ${page.url().slice(0, 100)}`);
|
|
560
572
|
return false;
|
|
561
573
|
}
|
|
@@ -569,8 +581,8 @@ export class AuthManager {
|
|
|
569
581
|
await randomDelay(200, 500);
|
|
570
582
|
}
|
|
571
583
|
}
|
|
572
|
-
catch
|
|
573
|
-
|
|
584
|
+
catch {
|
|
585
|
+
// Ignore errors
|
|
574
586
|
}
|
|
575
587
|
// Click to focus
|
|
576
588
|
try {
|
|
@@ -581,37 +593,37 @@ export class AuthManager {
|
|
|
581
593
|
try {
|
|
582
594
|
await emailField.focus();
|
|
583
595
|
}
|
|
584
|
-
catch
|
|
585
|
-
log.error(
|
|
596
|
+
catch {
|
|
597
|
+
log.error(' โ Failed to focus email field');
|
|
586
598
|
return false;
|
|
587
599
|
}
|
|
588
600
|
}
|
|
589
601
|
// โ
FASTER: Programmer typing speed (90-120 WPM from config)
|
|
590
602
|
log.info(` โจ๏ธ Typing email: ${this.maskEmail(email)}`);
|
|
591
603
|
try {
|
|
592
|
-
const wpm = CONFIG.typingWpmMin +
|
|
604
|
+
const wpm = CONFIG.typingWpmMin +
|
|
605
|
+
Math.floor(Math.random() * (CONFIG.typingWpmMax - CONFIG.typingWpmMin + 1));
|
|
593
606
|
await humanType(page, emailSelector, email, { wpm, withTypos: false });
|
|
594
|
-
log.success(
|
|
607
|
+
log.success(' โ
Email typed successfully');
|
|
595
608
|
}
|
|
596
609
|
catch (error) {
|
|
597
610
|
log.error(` โ Typing failed: ${error}`);
|
|
598
611
|
try {
|
|
599
612
|
await page.fill(emailSelector, email);
|
|
600
|
-
log.success(
|
|
613
|
+
log.success(' โ
Filled email using fallback');
|
|
601
614
|
}
|
|
602
|
-
catch
|
|
603
|
-
log.error(` โ Fallback fill also failed: ${fillError}`);
|
|
615
|
+
catch {
|
|
604
616
|
return false;
|
|
605
617
|
}
|
|
606
618
|
}
|
|
607
619
|
// Human "thinking" pause before clicking Next
|
|
608
620
|
await randomDelay(400, 1200);
|
|
609
621
|
// Click Next button
|
|
610
|
-
log.info(
|
|
622
|
+
log.info(' ๐ Looking for Next button...');
|
|
611
623
|
const nextSelectors = [
|
|
612
624
|
"button:has-text('Next')",
|
|
613
625
|
"button:has-text('Weiter')",
|
|
614
|
-
|
|
626
|
+
'#identifierNext',
|
|
615
627
|
];
|
|
616
628
|
let nextClicked = false;
|
|
617
629
|
for (const selector of nextSelectors) {
|
|
@@ -624,25 +636,24 @@ export class AuthManager {
|
|
|
624
636
|
break;
|
|
625
637
|
}
|
|
626
638
|
}
|
|
627
|
-
catch
|
|
628
|
-
log.debug(`[EMAIL] Next button selector ${selector} failed: ${error}`);
|
|
639
|
+
catch {
|
|
629
640
|
continue;
|
|
630
641
|
}
|
|
631
642
|
}
|
|
632
643
|
if (!nextClicked) {
|
|
633
|
-
log.warning(
|
|
634
|
-
await emailField.press(
|
|
644
|
+
log.warning(' โ ๏ธ Button not found, pressing Enter');
|
|
645
|
+
await emailField.press('Enter');
|
|
635
646
|
}
|
|
636
647
|
// Variable delay
|
|
637
648
|
await randomDelay(800, 1500);
|
|
638
|
-
log.success(
|
|
649
|
+
log.success(' โ
Email step complete');
|
|
639
650
|
return true;
|
|
640
651
|
}
|
|
641
652
|
/**
|
|
642
653
|
* Fill password field with human-like typing
|
|
643
654
|
*/
|
|
644
655
|
async fillPassword(page, password) {
|
|
645
|
-
log.info(
|
|
656
|
+
log.info(' ๐ Looking for password field...');
|
|
646
657
|
const passwordSelectors = ["input[name='Passwd']", "input[type='password']"];
|
|
647
658
|
let passwordSelector = null;
|
|
648
659
|
let passwordField = null;
|
|
@@ -655,8 +666,7 @@ export class AuthManager {
|
|
|
655
666
|
break;
|
|
656
667
|
}
|
|
657
668
|
}
|
|
658
|
-
catch
|
|
659
|
-
log.debug(`[PASSWORD] Selector ${selector} not found: ${error}`);
|
|
669
|
+
catch {
|
|
660
670
|
continue;
|
|
661
671
|
}
|
|
662
672
|
}
|
|
@@ -674,21 +684,22 @@ export class AuthManager {
|
|
|
674
684
|
await randomDelay(300, 700);
|
|
675
685
|
}
|
|
676
686
|
}
|
|
677
|
-
catch
|
|
678
|
-
|
|
687
|
+
catch {
|
|
688
|
+
// Ignore errors
|
|
679
689
|
}
|
|
680
690
|
// Click to focus
|
|
681
691
|
if (passwordSelector) {
|
|
682
692
|
await realisticClick(page, passwordSelector, false);
|
|
683
693
|
}
|
|
684
694
|
// โ
FASTER: Programmer typing speed (90-120 WPM from config)
|
|
685
|
-
log.info(
|
|
695
|
+
log.info(' โจ๏ธ Typing password...');
|
|
686
696
|
try {
|
|
687
|
-
const wpm = CONFIG.typingWpmMin +
|
|
697
|
+
const wpm = CONFIG.typingWpmMin +
|
|
698
|
+
Math.floor(Math.random() * (CONFIG.typingWpmMax - CONFIG.typingWpmMin + 1));
|
|
688
699
|
if (passwordSelector) {
|
|
689
700
|
await humanType(page, passwordSelector, password, { wpm, withTypos: false });
|
|
690
701
|
}
|
|
691
|
-
log.success(
|
|
702
|
+
log.success(' โ
Password typed successfully');
|
|
692
703
|
}
|
|
693
704
|
catch (error) {
|
|
694
705
|
log.error(` โ Typing failed: ${error}`);
|
|
@@ -697,11 +708,11 @@ export class AuthManager {
|
|
|
697
708
|
// Human "review" pause before submitting password
|
|
698
709
|
await randomDelay(300, 1000);
|
|
699
710
|
// Click Next button
|
|
700
|
-
log.info(
|
|
711
|
+
log.info(' ๐ Looking for Next button...');
|
|
701
712
|
const pwdNextSelectors = [
|
|
702
713
|
"button:has-text('Next')",
|
|
703
714
|
"button:has-text('Weiter')",
|
|
704
|
-
|
|
715
|
+
'#passwordNext',
|
|
705
716
|
];
|
|
706
717
|
let pwdNextClicked = false;
|
|
707
718
|
for (const selector of pwdNextSelectors) {
|
|
@@ -714,18 +725,17 @@ export class AuthManager {
|
|
|
714
725
|
break;
|
|
715
726
|
}
|
|
716
727
|
}
|
|
717
|
-
catch
|
|
718
|
-
log.debug(`[PASSWORD] Next button selector ${selector} failed: ${error}`);
|
|
728
|
+
catch {
|
|
719
729
|
continue;
|
|
720
730
|
}
|
|
721
731
|
}
|
|
722
732
|
if (!pwdNextClicked) {
|
|
723
|
-
log.warning(
|
|
724
|
-
await passwordField.press(
|
|
733
|
+
log.warning(' โ ๏ธ Button not found, pressing Enter');
|
|
734
|
+
await passwordField.press('Enter');
|
|
725
735
|
}
|
|
726
736
|
// Variable delay
|
|
727
737
|
await randomDelay(800, 1500);
|
|
728
|
-
log.success(
|
|
738
|
+
log.success(' โ
Password step complete');
|
|
729
739
|
return true;
|
|
730
740
|
}
|
|
731
741
|
/**
|
|
@@ -742,8 +752,7 @@ export class AuthManager {
|
|
|
742
752
|
return true;
|
|
743
753
|
}
|
|
744
754
|
}
|
|
745
|
-
catch
|
|
746
|
-
log.debug(`[CLICK_TEXT] Text "${text}" not found or click failed: ${error}`);
|
|
755
|
+
catch {
|
|
747
756
|
continue;
|
|
748
757
|
}
|
|
749
758
|
}
|
|
@@ -753,14 +762,14 @@ export class AuthManager {
|
|
|
753
762
|
* Mask email for logging
|
|
754
763
|
*/
|
|
755
764
|
maskEmail(email) {
|
|
756
|
-
if (!email.includes(
|
|
757
|
-
return
|
|
765
|
+
if (!email.includes('@')) {
|
|
766
|
+
return '***';
|
|
758
767
|
}
|
|
759
|
-
const [name, domain] = email.split(
|
|
768
|
+
const [name, domain] = email.split('@');
|
|
760
769
|
if (name.length <= 2) {
|
|
761
|
-
return `${
|
|
770
|
+
return `${'*'.repeat(name.length)}@${domain}`;
|
|
762
771
|
}
|
|
763
|
-
return `${name[0]}${
|
|
772
|
+
return `${name[0]}${'*'.repeat(name.length - 2)}${name[name.length - 1]}@${domain}`;
|
|
764
773
|
}
|
|
765
774
|
// ============================================================================
|
|
766
775
|
// Additional Helper Methods
|
|
@@ -771,7 +780,7 @@ export class AuthManager {
|
|
|
771
780
|
async loadAuthState(context, statePath) {
|
|
772
781
|
try {
|
|
773
782
|
// Read state.json
|
|
774
|
-
const stateData = await fs.readFile(statePath, { encoding:
|
|
783
|
+
const stateData = await fs.readFile(statePath, { encoding: 'utf-8' });
|
|
775
784
|
const state = JSON.parse(stateData);
|
|
776
785
|
// Add cookies to context
|
|
777
786
|
if (state.cookies) {
|
|
@@ -805,7 +814,7 @@ export class AuthManager {
|
|
|
805
814
|
* If not provided, defaults to true (visible) for setup
|
|
806
815
|
*/
|
|
807
816
|
async performSetup(sendProgress, overrideHeadless) {
|
|
808
|
-
const { chromium } = await import(
|
|
817
|
+
const { chromium } = await import('patchright');
|
|
809
818
|
// Determine headless mode: override or default to true (visible for setup)
|
|
810
819
|
// overrideHeadless contains show_browser value (true = show, false = hide)
|
|
811
820
|
const shouldShowBrowser = overrideHeadless !== undefined ? overrideHeadless : true;
|
|
@@ -814,29 +823,29 @@ export class AuthManager {
|
|
|
814
823
|
const statePath = await this.getValidStatePath();
|
|
815
824
|
const isAuthenticated = statePath !== null;
|
|
816
825
|
if (isAuthenticated) {
|
|
817
|
-
log.info(
|
|
826
|
+
log.info('โ
Already authenticated, skipping setup');
|
|
818
827
|
log.info(" Use 're_auth' tool to switch accounts or re-authenticate");
|
|
819
|
-
await sendProgress?.(
|
|
828
|
+
await sendProgress?.('Already authenticated!', 10, 10);
|
|
820
829
|
return true;
|
|
821
830
|
}
|
|
822
|
-
log.info(
|
|
823
|
-
await sendProgress?.(
|
|
824
|
-
log.info(
|
|
831
|
+
log.info('๐ Preparing for first-time authentication...');
|
|
832
|
+
await sendProgress?.('Preparing browser...', 1, 10);
|
|
833
|
+
log.info('๐ Launching persistent browser for interactive setup...');
|
|
825
834
|
log.info(` ๐ Profile: ${CONFIG.chromeProfileDir}`);
|
|
826
|
-
await sendProgress?.(
|
|
835
|
+
await sendProgress?.('Launching persistent browser...', 2, 10);
|
|
827
836
|
// โ
CRITICAL FIX: Use launchPersistentContext (same as runtime!)
|
|
828
837
|
// This ensures session cookies persist correctly
|
|
829
838
|
const context = await chromium.launchPersistentContext(CONFIG.chromeProfileDir, {
|
|
830
839
|
headless: !shouldShowBrowser, // Use override or default to visible for setup
|
|
831
|
-
channel:
|
|
840
|
+
channel: 'chrome',
|
|
832
841
|
viewport: CONFIG.viewport,
|
|
833
|
-
locale:
|
|
834
|
-
timezoneId:
|
|
842
|
+
locale: 'en-US',
|
|
843
|
+
timezoneId: 'Europe/Berlin',
|
|
835
844
|
args: [
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
845
|
+
'--disable-blink-features=AutomationControlled',
|
|
846
|
+
'--disable-dev-shm-usage',
|
|
847
|
+
'--no-first-run',
|
|
848
|
+
'--no-default-browser-check',
|
|
840
849
|
],
|
|
841
850
|
});
|
|
842
851
|
// Get or create a page
|
|
@@ -847,17 +856,17 @@ export class AuthManager {
|
|
|
847
856
|
if (loginSuccess) {
|
|
848
857
|
// โ
Save browser state to state.json (for validation & backup)
|
|
849
858
|
// Chrome ALSO saves everything to the persistent profile automatically!
|
|
850
|
-
await sendProgress?.(
|
|
859
|
+
await sendProgress?.('Saving authentication state...', 9, 10);
|
|
851
860
|
await this.saveBrowserState(context, page);
|
|
852
861
|
// โ
CRITICAL FIX: Wait for Chrome to flush profile to disk
|
|
853
862
|
// Windows needs time to write persistent data (cookies, cache, session storage, etc.)
|
|
854
863
|
// Without this delay, chrome_profile/ folder remains empty!
|
|
855
|
-
log.info(
|
|
864
|
+
log.info('โณ Waiting for Chrome to finalize profile writes (5 seconds)...');
|
|
856
865
|
await page.waitForTimeout(5000); // 5 seconds buffer for Windows filesystem
|
|
857
|
-
log.success(
|
|
866
|
+
log.success('โ
Setup complete - authentication saved to:');
|
|
858
867
|
log.success(` ๐ State file: ${this.stateFilePath}`);
|
|
859
868
|
log.success(` ๐ Chrome profile: ${CONFIG.chromeProfileDir}`);
|
|
860
|
-
log.info(
|
|
869
|
+
log.info('๐ก Session cookies will now persist across restarts!');
|
|
861
870
|
}
|
|
862
871
|
// Close persistent context
|
|
863
872
|
await context.close();
|
|
@@ -882,13 +891,13 @@ export class AuthManager {
|
|
|
882
891
|
* Use this BEFORE authenticating a new account!
|
|
883
892
|
*/
|
|
884
893
|
async clearAllAuthData() {
|
|
885
|
-
log.warning(
|
|
894
|
+
log.warning('๐๏ธ Clearing ALL authentication data for account switch...');
|
|
886
895
|
let deletedCount = 0;
|
|
887
896
|
// 1. Delete all state files in browser_state_dir
|
|
888
897
|
try {
|
|
889
898
|
const files = await fs.readdir(CONFIG.browserStateDir);
|
|
890
899
|
for (const file of files) {
|
|
891
|
-
if (file.endsWith(
|
|
900
|
+
if (file.endsWith('.json')) {
|
|
892
901
|
await fs.unlink(path.join(CONFIG.browserStateDir, file));
|
|
893
902
|
log.info(` โ
Deleted: ${file}`);
|
|
894
903
|
deletedCount++;
|
|
@@ -912,7 +921,7 @@ export class AuthManager {
|
|
|
912
921
|
log.warning(` โ ๏ธ Could not delete Chrome profile: ${error}`);
|
|
913
922
|
}
|
|
914
923
|
if (deletedCount === 0) {
|
|
915
|
-
log.info(
|
|
924
|
+
log.info(' โน๏ธ No old auth data found (already clean)');
|
|
916
925
|
}
|
|
917
926
|
else {
|
|
918
927
|
log.success(`โ
All auth data cleared (${deletedCount} items) - ready for new account!`);
|
|
@@ -925,19 +934,17 @@ export class AuthManager {
|
|
|
925
934
|
try {
|
|
926
935
|
try {
|
|
927
936
|
await fs.unlink(this.stateFilePath);
|
|
928
|
-
log.debug(`[CLEAR_STATE] Deleted state file: ${this.stateFilePath}`);
|
|
929
937
|
}
|
|
930
|
-
catch
|
|
931
|
-
|
|
938
|
+
catch {
|
|
939
|
+
// File doesn't exist
|
|
932
940
|
}
|
|
933
941
|
try {
|
|
934
942
|
await fs.unlink(this.sessionFilePath);
|
|
935
|
-
log.debug(`[CLEAR_STATE] Deleted session file: ${this.sessionFilePath}`);
|
|
936
943
|
}
|
|
937
|
-
catch
|
|
938
|
-
|
|
944
|
+
catch {
|
|
945
|
+
// File doesn't exist
|
|
939
946
|
}
|
|
940
|
-
log.success(
|
|
947
|
+
log.success('โ
Authentication state cleared');
|
|
941
948
|
return true;
|
|
942
949
|
}
|
|
943
950
|
catch (error) {
|
|
@@ -950,7 +957,7 @@ export class AuthManager {
|
|
|
950
957
|
*/
|
|
951
958
|
async hardResetState() {
|
|
952
959
|
try {
|
|
953
|
-
log.warning(
|
|
960
|
+
log.warning('๐งน Performing HARD RESET of all authentication state...');
|
|
954
961
|
let deletedCount = 0;
|
|
955
962
|
// Delete state file
|
|
956
963
|
try {
|
|
@@ -958,8 +965,8 @@ export class AuthManager {
|
|
|
958
965
|
log.info(` ๐๏ธ Deleted: ${this.stateFilePath}`);
|
|
959
966
|
deletedCount++;
|
|
960
967
|
}
|
|
961
|
-
catch
|
|
962
|
-
|
|
968
|
+
catch {
|
|
969
|
+
// File doesn't exist
|
|
963
970
|
}
|
|
964
971
|
// Delete session file
|
|
965
972
|
try {
|
|
@@ -967,8 +974,8 @@ export class AuthManager {
|
|
|
967
974
|
log.info(` ๐๏ธ Deleted: ${this.sessionFilePath}`);
|
|
968
975
|
deletedCount++;
|
|
969
976
|
}
|
|
970
|
-
catch
|
|
971
|
-
|
|
977
|
+
catch {
|
|
978
|
+
// File doesn't exist
|
|
972
979
|
}
|
|
973
980
|
// Delete entire browser_state_dir
|
|
974
981
|
try {
|
|
@@ -979,11 +986,11 @@ export class AuthManager {
|
|
|
979
986
|
}
|
|
980
987
|
log.info(` ๐๏ธ Deleted: ${CONFIG.browserStateDir}/ (${files.length} files)`);
|
|
981
988
|
}
|
|
982
|
-
catch
|
|
983
|
-
|
|
989
|
+
catch {
|
|
990
|
+
// Directory doesn't exist or empty
|
|
984
991
|
}
|
|
985
992
|
if (deletedCount === 0) {
|
|
986
|
-
log.info(
|
|
993
|
+
log.info(' โน๏ธ No state to delete (already clean)');
|
|
987
994
|
}
|
|
988
995
|
else {
|
|
989
996
|
log.success(`โ
Hard reset complete: ${deletedCount} items deleted`);
|