fix
This commit is contained in:
182
src/lib/server/scheduler.ts
Normal file
182
src/lib/server/scheduler.ts
Normal file
@@ -0,0 +1,182 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { getBrowser } from './browser';
|
||||
|
||||
export interface SchedulerConfig {
|
||||
enabled: boolean;
|
||||
intervalHours: number;
|
||||
}
|
||||
|
||||
interface SchedulerState {
|
||||
intervalId: NodeJS.Timer | null;
|
||||
lastRenewalTime: number | null;
|
||||
isRenewing: boolean;
|
||||
}
|
||||
|
||||
const state: SchedulerState = {
|
||||
intervalId: null,
|
||||
lastRenewalTime: null,
|
||||
isRenewing: false
|
||||
};
|
||||
|
||||
/**
|
||||
* Get scheduler configuration from environment variables
|
||||
*/
|
||||
function getConfig(): SchedulerConfig {
|
||||
const enabled = process.env.AUTH_SCHEDULER_ENABLED === 'true';
|
||||
const intervalHours = parseInt(process.env.AUTH_SCHEDULER_INTERVAL_HOURS || '12', 10);
|
||||
|
||||
return {
|
||||
enabled,
|
||||
intervalHours
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve authentication storage path
|
||||
*/
|
||||
function resolveAuthPath(): string {
|
||||
const authPathDocker = '/app/secrets/auth.json';
|
||||
const authPathLocal = './secrets/auth.json';
|
||||
|
||||
if (fs.existsSync(authPathDocker)) {
|
||||
return authPathDocker;
|
||||
}
|
||||
|
||||
if (fs.existsSync(authPathLocal)) {
|
||||
return authPathLocal;
|
||||
}
|
||||
|
||||
// Default to local path if neither exists yet
|
||||
return authPathLocal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renew Instagram authentication by loading existing auth and refreshing the session
|
||||
* Inspired by gen-auth.js - reuses existing stored credentials without manual input
|
||||
*/
|
||||
async function renewInstagramAuth(): Promise<boolean> {
|
||||
if (state.isRenewing) {
|
||||
console.log('[Scheduler] Auth renewal already in progress, skipping');
|
||||
return false;
|
||||
}
|
||||
|
||||
const authPath = resolveAuthPath();
|
||||
|
||||
if (!fs.existsSync(authPath)) {
|
||||
console.warn('[Scheduler] No existing auth.json found. Run gen-auth.js first to set up initial authentication.');
|
||||
return false;
|
||||
}
|
||||
|
||||
state.isRenewing = true;
|
||||
|
||||
try {
|
||||
console.log('[Scheduler] Starting Instagram authentication renewal...');
|
||||
console.log(`[Scheduler] Loading existing auth from: ${authPath}`);
|
||||
|
||||
const browser = await getBrowser();
|
||||
// Load existing authentication state
|
||||
const context = await browser.newContext({ storageState: authPath });
|
||||
const page = await context.newPage();
|
||||
|
||||
// Navigate to Instagram homepage - the existing auth will be used automatically
|
||||
await page.goto('https://www.instagram.com/', { waitUntil: 'domcontentloaded' });
|
||||
|
||||
// Wait for the "Home" icon to appear (indicates successful login)
|
||||
try {
|
||||
await page.waitForSelector('svg[aria-label="Home"]', { timeout: 30000 });
|
||||
console.log('[Scheduler] Successfully authenticated with Instagram');
|
||||
} catch (e) {
|
||||
console.warn('[Scheduler] Home icon not found - session may be expired or invalid');
|
||||
await page.close();
|
||||
await context.close();
|
||||
state.isRenewing = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Save the refreshed authentication state
|
||||
const authDir = path.dirname(authPath);
|
||||
|
||||
// Ensure directory exists
|
||||
if (!fs.existsSync(authDir)) {
|
||||
fs.mkdirSync(authDir, { recursive: true });
|
||||
}
|
||||
|
||||
// Update auth.json with refreshed session
|
||||
await context.storageState({ path: authPath });
|
||||
|
||||
await page.close();
|
||||
await context.close();
|
||||
|
||||
state.lastRenewalTime = Date.now();
|
||||
console.log(`[Scheduler] Instagram authentication renewed successfully at ${new Date().toISOString()}`);
|
||||
console.log(`[Scheduler] Auth state updated at: ${authPath}`);
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('[Scheduler] Instagram authentication renewal failed:', error);
|
||||
return false;
|
||||
} finally {
|
||||
state.isRenewing = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the authentication renewal scheduler
|
||||
*/
|
||||
export async function startScheduler(): Promise<void> {
|
||||
const config = getConfig();
|
||||
|
||||
if (!config.enabled) {
|
||||
console.log('[Scheduler] Authentication scheduler is disabled (set AUTH_SCHEDULER_ENABLED=true to enable)');
|
||||
return;
|
||||
}
|
||||
|
||||
if (state.intervalId !== null) {
|
||||
console.warn('[Scheduler] Scheduler is already running');
|
||||
return;
|
||||
}
|
||||
|
||||
const intervalMs = config.intervalHours * 60 * 60 * 1000;
|
||||
|
||||
console.log(`[Scheduler] Starting authentication scheduler with ${config.intervalHours}h interval`);
|
||||
|
||||
// Schedule periodic renewals
|
||||
state.intervalId = setInterval(async () => {
|
||||
await renewInstagramAuth();
|
||||
}, intervalMs);
|
||||
|
||||
// Ensure interval is not blocking (set it as unreferenceable so it doesn't keep the process alive)
|
||||
if (state.intervalId.unref) {
|
||||
state.intervalId.unref();
|
||||
}
|
||||
|
||||
// Optional: Perform initial renewal on startup (uncomment to enable)
|
||||
// await renewInstagramAuth();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop the authentication renewal scheduler
|
||||
*/
|
||||
export async function stopScheduler(): Promise<void> {
|
||||
if (state.intervalId === null) {
|
||||
console.log('[Scheduler] Scheduler is not running');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('[Scheduler] Stopping authentication scheduler...');
|
||||
clearInterval(state.intervalId);
|
||||
state.intervalId = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get scheduler status information
|
||||
*/
|
||||
export function getSchedulerStatus() {
|
||||
return {
|
||||
running: state.intervalId !== null,
|
||||
lastRenewalTime: state.lastRenewalTime ? new Date(state.lastRenewalTime).toISOString() : null,
|
||||
isRenewing: state.isRenewing,
|
||||
config: getConfig()
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user