const { PrismaClient } = require('@prisma/client'); const { ZoneIdAPI } = require('./zoneid-api'); const prisma = new PrismaClient(); const REFRESH_INTERVAL_MS = 3 * 24 * 60 * 60 * 1000; const REFRESH_CHECK_INTERVAL_MS = 6 * 60 * 60 * 1000; async function refreshAccountToken(account) { console.log(`[TokenScheduler] Refreshing token for account: ${account.email}`); if (!account.refreshToken) { console.log(`[TokenScheduler] Account ${account.email} has no refresh token, skipping`); return { success: false, reason: 'no_token' }; } const api = new ZoneIdAPI(); api.setRefreshTokenCookie(account.refreshToken); try { const response = await api.refreshAccessToken(); if (response && response.token) { console.log(`[TokenScheduler] Successfully refreshed token for ${account.email}`); await prisma.account.update({ where: { id: account.id }, data: { updatedAt: new Date() } }); return { success: true }; } return { success: true, note: 'Token validated' }; } catch (err) { console.error(`[TokenScheduler] Failed to refresh token for ${account.email}:`, err.message); if (err.response?.status === 401 || err.message.includes('expired')) { console.log(`[TokenScheduler] Marking account ${account.email} as needing re-authentication`); await prisma.account.update({ where: { id: account.id }, data: { status: 'token_expired' } }); return { success: false, reason: 'token_expired' }; } return { success: false, reason: err.message }; } } async function refreshAllAccountTokens() { console.log('[TokenScheduler] Starting token refresh cycle for all accounts...'); const accounts = await prisma.account.findMany({ where: { status: 'active', refreshToken: { not: null } } }); console.log(`[TokenScheduler] Found ${accounts.length} active accounts with tokens`); const results = { total: accounts.length, success: 0, failed: 0, skipped: 0, details: [] }; for (const account of accounts) { try { await new Promise(r => setTimeout(r, 2000)); const result = await refreshAccountToken(account); if (result.success) { results.success++; } else if (result.reason === 'no_token') { results.skipped++; } else { results.failed++; } results.details.push({ accountId: account.id, email: account.email, ...result }); } catch (err) { console.error(`[TokenScheduler] Unexpected error for ${account.email}:`, err.message); results.failed++; results.details.push({ accountId: account.id, email: account.email, success: false, reason: err.message }); } } console.log(`[TokenScheduler] Refresh cycle complete: ${results.success} success, ${results.failed} failed, ${results.skipped} skipped`); return results; } let schedulerInterval = null; function startTokenScheduler() { if (schedulerInterval) { console.log('[TokenScheduler] Scheduler already running'); return; } console.log(`[TokenScheduler] Starting scheduler (check interval: ${REFRESH_CHECK_INTERVAL_MS / 1000 / 60 / 60} hours)`); setTimeout(() => { refreshAllAccountTokens().catch(err => { console.error('[TokenScheduler] Initial refresh failed:', err.message); }); }, 60000); schedulerInterval = setInterval(() => { refreshAllAccountTokens().catch(err => { console.error('[TokenScheduler] Scheduled refresh failed:', err.message); }); }, REFRESH_CHECK_INTERVAL_MS); console.log('[TokenScheduler] Scheduler started successfully'); } function stopTokenScheduler() { if (schedulerInterval) { clearInterval(schedulerInterval); schedulerInterval = null; console.log('[TokenScheduler] Scheduler stopped'); } } module.exports = { refreshAccountToken, refreshAllAccountTokens, startTokenScheduler, stopTokenScheduler, REFRESH_INTERVAL_MS, REFRESH_CHECK_INTERVAL_MS };