diff --git a/src/functions/Login.ts b/src/functions/Login.ts index 816282b..a78fe26 100644 --- a/src/functions/Login.ts +++ b/src/functions/Login.ts @@ -362,9 +362,11 @@ export class Login { if (!e || typeof e !== 'object') return false const err = e as { response?: { status?: number }; code?: string } const status = err.response?.status - return status === 502 || status === 503 || status === 504 || + // IMPROVED: More comprehensive retry conditions for OAuth token exchange + return status === 502 || status === 503 || status === 504 || status === 429 || err.code === 'ECONNRESET' || - err.code === 'ETIMEDOUT' + err.code === 'ETIMEDOUT' || + err.code === 'ECONNREFUSED' } const req: AxiosRequestConfig = { @@ -374,7 +376,15 @@ export class Login { data: form.toString() } - const retry = new Retry(this.bot.config.retryPolicy) + // IMPROVED: Use more aggressive retry policy for OAuth token exchange (critical operation) + const oauthRetryPolicy = { + maxAttempts: 5, // Increased from default 3 + baseDelay: 2000, // Increased from default 1000ms + maxDelay: 60000, // 60 seconds max delay + multiplier: 2, + jitter: 0.3 // More jitter to avoid thundering herd + } + const retry = new Retry(oauthRetryPolicy) try { const resp = await retry.run( () => this.bot.axios.request(req), @@ -390,11 +400,11 @@ export class Login { const statusCode = err.response?.status const errMsg = err.message || String(error) if (statusCode) { - this.bot.log(this.bot.isMobile, 'LOGIN-APP', `Token exchange failed with status ${statusCode}: ${errMsg}`, 'error') + this.bot.log(this.bot.isMobile, 'LOGIN-APP', `Token exchange failed after ${oauthRetryPolicy.maxAttempts} retries with status ${statusCode}: ${errMsg}`, 'error') } else { - this.bot.log(this.bot.isMobile, 'LOGIN-APP', `Token exchange failed (network error): ${errMsg}`, 'error') + this.bot.log(this.bot.isMobile, 'LOGIN-APP', `Token exchange failed after ${oauthRetryPolicy.maxAttempts} retries (network error): ${errMsg}`, 'error') } - throw error + throw new Error(`OAuth token exchange failed: ${statusCode ? `HTTP ${statusCode}` : 'Network error'} - ${errMsg}`) } finally { // Always cleanup compromised interval to prevent memory leaks this.cleanupCompromisedInterval() diff --git a/src/util/state/Load.ts b/src/util/state/Load.ts index a4979cb..4bf8a4b 100644 --- a/src/util/state/Load.ts +++ b/src/util/state/Load.ts @@ -393,7 +393,7 @@ export function loadAccounts(): Account[] { const enabledAccounts = allAccounts.filter(acc => acc.enabled !== false) return enabledAccounts } catch (error) { - throw new Error(error as string) + throw new Error(`Failed to load accounts: ${error instanceof Error ? error.message : String(error)}`) } } @@ -443,7 +443,7 @@ export function loadConfig(): Config { return normalized } catch (error) { - throw new Error(error as string) + throw new Error(`Failed to load config: ${error instanceof Error ? error.message : String(error)}`) } } @@ -454,8 +454,8 @@ interface SessionData { export async function loadSessionData(sessionPath: string, email: string, isMobile: boolean, saveFingerprint: ConfigSaveFingerprint): Promise { try { - // Fetch cookie file - const cookieFile = path.join(__dirname, '../browser/', sessionPath, email, `${isMobile ? 'mobile_cookies' : 'desktop_cookies'}.json`) + // FIXED: Use process.cwd() instead of __dirname for sessions (consistent with JobState and SessionLoader) + const cookieFile = path.join(process.cwd(), sessionPath, email, `${isMobile ? 'mobile_cookies' : 'desktop_cookies'}.json`) let cookies: Cookie[] = [] if (fs.existsSync(cookieFile)) { @@ -464,7 +464,7 @@ export async function loadSessionData(sessionPath: string, email: string, isMobi } // Fetch fingerprint file - const baseDir = path.join(__dirname, '../browser/', sessionPath, email) + const baseDir = path.join(process.cwd(), sessionPath, email) const fingerprintFile = path.join(baseDir, `${isMobile ? 'mobile_fingerprint' : 'desktop_fingerprint'}.json`) let fingerprint!: BrowserFingerprintWithHeaders @@ -480,7 +480,7 @@ export async function loadSessionData(sessionPath: string, email: string, isMobi } } catch (error) { - throw new Error(error as string) + throw new Error(`Failed to load session data for ${email}: ${error instanceof Error ? error.message : String(error)}`) } } @@ -488,8 +488,8 @@ export async function saveSessionData(sessionPath: string, browser: BrowserConte try { const cookies = await browser.cookies() - // Fetch path - const sessionDir = path.join(__dirname, '../browser/', sessionPath, email) + // FIXED: Use process.cwd() instead of __dirname for sessions + const sessionDir = path.join(process.cwd(), sessionPath, email) // Create session dir if (!fs.existsSync(sessionDir)) { @@ -504,14 +504,14 @@ export async function saveSessionData(sessionPath: string, browser: BrowserConte return sessionDir } catch (error) { - throw new Error(error as string) + throw new Error(`Failed to save session data for ${email}: ${error instanceof Error ? error.message : String(error)}`) } } export async function saveFingerprintData(sessionPath: string, email: string, isMobile: boolean, fingerprint: BrowserFingerprintWithHeaders): Promise { try { - // Fetch path - const sessionDir = path.join(__dirname, '../browser/', sessionPath, email) + // FIXED: Use process.cwd() instead of __dirname for sessions + const sessionDir = path.join(process.cwd(), sessionPath, email) // Create session dir if (!fs.existsSync(sessionDir)) { @@ -525,6 +525,6 @@ export async function saveFingerprintData(sessionPath: string, email: string, is return sessionDir } catch (error) { - throw new Error(error as string) + throw new Error(`Failed to save fingerprint for ${email}: ${error instanceof Error ? error.message : String(error)}`) } } \ No newline at end of file