1- import { Browser , BrowserContext , Page , chromium , Cookie } from 'playwright' ;
2- import { CookieManager } from './cookieManager' ;
1+ import { Browser , BrowserContext , chromium , Cookie , Page } from 'playwright' ;
2+ import { CookieManager } from './cookieManager' ;
33import * as dotenv from 'dotenv' ;
44import * as fs from 'fs' ;
55import * as path from 'path' ;
66import * as os from 'os' ;
7- import { exec } from 'child_process' ;
8- import { promisify } from 'util' ;
97
108dotenv . config ( ) ;
119
12- const execAsync = promisify ( exec ) ;
13-
1410export class AuthManager {
1511 private browser : Browser | null ;
1612 private context : BrowserContext | null ;
@@ -27,15 +23,15 @@ export class AuthManager {
2723 const homeDir = os . homedir ( ) ;
2824 const mcpDir = path . join ( homeDir , '.mcp' ) ;
2925 const rednoteDir = path . join ( mcpDir , 'rednote' ) ;
30-
26+
3127 // Create directories if they don't exist
3228 if ( ! fs . existsSync ( mcpDir ) ) {
3329 fs . mkdirSync ( mcpDir ) ;
3430 }
3531 if ( ! fs . existsSync ( rednoteDir ) ) {
3632 fs . mkdirSync ( rednoteDir ) ;
3733 }
38-
34+
3935 cookiePath = path . join ( rednoteDir , 'cookies.json' ) ;
4036 }
4137
@@ -51,36 +47,12 @@ export class AuthManager {
5147 return this . browser ;
5248 }
5349
54- async getPage ( ) : Promise < Page > {
55- if ( ! this . page ) {
56- const browser = await this . getBrowser ( ) ;
57- this . page = await browser . newPage ( ) ;
58-
59- // Load existing cookies if available
60- const cookies = await this . getCookies ( ) ;
61- if ( cookies . length > 0 ) {
62- await this . page . context ( ) . addCookies ( cookies ) ;
63- }
64- }
65- return this . page ;
66- }
67-
6850 async getCookies ( ) : Promise < Cookie [ ] > {
6951 return await this . cookieManager . loadCookies ( ) ;
7052 }
7153
72- private async handleSecurityVerification ( ) {
73- if ( ! this . page ) return ;
74-
75- const securityUrl = '/web-login/captcha' ;
76- if ( this . page . url ( ) . includes ( securityUrl ) ) {
77- await this . page . waitForTimeout ( 2000 ) ;
78- await this . page . reload ( { waitUntil : 'networkidle' } ) ;
79- }
80- }
81-
8254 async login ( ) : Promise < void > {
83- this . browser = await chromium . launch ( { headless : false } ) ;
55+ this . browser = await chromium . launch ( { headless : false } ) ;
8456 if ( ! this . browser ) {
8557 throw new Error ( 'Failed to launch browser' ) ;
8658 }
@@ -101,8 +73,8 @@ export class AuthManager {
10173
10274 // Navigate to explore page
10375 await this . page . goto ( 'https://www.xiaohongshu.com/explore' , {
104- waitUntil : 'networkidle ' ,
105- timeout : 30000
76+ waitUntil : 'domcontentloaded ' ,
77+ timeout : 10000
10678 } ) ;
10779
10880 // Check if already logged in
@@ -112,7 +84,7 @@ export class AuthManager {
11284 const sidebarUser = document . querySelector ( '.user.side-bar-component .channel' ) ;
11385 return sidebarUser ?. textContent ?. trim ( ) === '我' ;
11486 } ) ;
115-
87+
11688 if ( isLoggedIn ) {
11789 // Already logged in, save cookies and return
11890 const newCookies = await this . context . cookies ( ) ;
@@ -131,32 +103,6 @@ export class AuthManager {
131103 timeout : 10000
132104 } ) ;
133105
134- // save image code
135- // if (qrCodeImage) {
136- // const qrCodeSrc = await qrCodeImage.getAttribute('src');
137- // if (qrCodeSrc) {
138- // // Save QR code image
139- // const qrCodeBuffer = Buffer.from(qrCodeSrc.split(',')[1], 'base64');
140- // const tempDir = process.env.TEMP || process.env.TMP || '/tmp';
141- // const qrCodePath = path.join(tempDir, 'xhs-login-qrcode.png');
142- //
143- // await fs.promises.writeFile(qrCodePath, qrCodeBuffer);
144- //
145- // // Open QR code image with system default viewer
146- // try {
147- // if (process.platform === 'darwin') {
148- // await execAsync(`open ${qrCodePath}`);
149- // } else if (process.platform === 'win32') {
150- // await execAsync(`start ${qrCodePath}`);
151- // } else if (process.platform === 'linux') {
152- // await execAsync(`xdg-open ${qrCodePath}`);
153- // }
154- // } catch (error) {
155- // // Silently handle error
156- // }
157- // }
158- // }
159-
160106 // Wait for user to complete login
161107 await this . page . waitForSelector ( '.user.side-bar-component .channel' , {
162108 timeout : 60000
@@ -191,20 +137,6 @@ export class AuthManager {
191137 }
192138 }
193139
194- async checkLoginStatus ( ) : Promise < boolean > {
195- const page = await this . getPage ( ) ;
196- await page . goto ( 'https://www.xiaohongshu.com' ) ;
197-
198- // Check if login button exists
199- const loginButton = await page . $ ( 'button[data-testid="login-button"], button:has-text("登录"), .login-button' ) ;
200- return ! loginButton ;
201- }
202-
203- async isAuthenticated ( ) : Promise < boolean > {
204- const cookies = await this . cookieManager . loadCookies ( ) ;
205- return cookies . length > 0 ;
206- }
207-
208140 async cleanup ( ) : Promise < void > {
209141 if ( this . page ) await this . page . close ( ) ;
210142 if ( this . context ) await this . context . close ( ) ;
0 commit comments