/** * 单任务调试入口 * * 示例: * node debugTask.js dailyTrending --keep-open * node debugTask.js updateProject --keep-open --dry-run * TASK=dailyTrending DEBUG_TASK=true DEBUG_KEEP_OPEN=true node debugTask.js * TASK=updateProject DEBUG_TASK=true DEBUG_KEEP_OPEN=true DEBUG_DRY_RUN=true node debugTask.js */ if (!process.env.DEBUG) { process.env.DEBUG = 'true'; } if (!process.env.DEBUG_TASK) { process.env.DEBUG_TASK = 'true'; } const config = require('./config'); const logger = require('./utils/logger'); const { launchBrowser, createContext } = require('./utils/browser'); const { ensureLogin } = require('./utils/login'); const { safeGoto } = require('./utils/page'); const updateProject = require('./tasks/updateProject'); const dailyShare = require('./tasks/dailyShare'); const dailyCheckIn = require('./tasks/dailyCheckIn'); const dailyTrending = require('./tasks/dailyTrending'); const dailyStar = require('./tasks/dailyStar'); const taskMap = { updateProject: { name: '更新项目', handler: updateProject, }, dailyTrending: { name: '查看热门', handler: dailyTrending, }, trending: { name: '查看热门', handler: dailyTrending, }, dailyShare: { name: '每日分享', handler: dailyShare, }, dailyCheckIn: { name: '每日签到', handler: dailyCheckIn, }, dailyStar: { name: '每日Star', handler: dailyStar, }, }; function getArgs() { const args = process.argv.slice(2); const taskArg = args.find((arg) => !arg.startsWith('--')); const flags = new Set(args.filter((arg) => arg.startsWith('--'))); return { taskKey: process.env.TASK || taskArg, help: flags.has('--help') || flags.has('-h'), keepOpen: process.env.DEBUG_KEEP_OPEN === 'true' || flags.has('--keep-open'), pauseEachStep: process.env.DEBUG_PAUSE_EACH_STEP === 'true' || flags.has('--pause-each-step'), dryRun: process.env.DEBUG_DRY_RUN === 'true' || flags.has('--dry-run'), }; } function printUsage() { logger.info('用法: node debugTask.js [--keep-open] [--pause-each-step] [--dry-run]'); logger.info('兼容用法: TASK= node debugTask.js'); logger.info('可用任务:'); Object.keys(taskMap).forEach((key) => logger.info(` ${key}`)); } async function main() { const args = getArgs(); if (args.help) { printUsage(); return; } const taskKey = args.taskKey; const task = taskMap[taskKey]; if (!task) { printUsage(); throw new Error(`未知或未指定 TASK: ${taskKey || '(empty)'}`); } let browser = null; let context = null; let page = null; try { logger.divider(); logger.info(`===== 单任务调试: ${task.name} (${taskKey}) =====`); browser = await launchBrowser(); const created = await createContext(browser); context = created.context; page = await context.newPage(); logger.divider(); logger.info('===== 登录验证 ====='); await ensureLogin(page, context); logger.divider(); logger.info('===== 打开积分中心 ====='); await safeGoto(page, config.urls.points, { label: '积分中心', timeout: config.navigationTimeout, waitFor: [ '.g-user-avatar', 'text=密码登录', '.novice-task-item-box', ], }); logger.divider(); logger.info(`===== 执行单任务: ${task.name} =====`); await task.handler(page, { debugTask: true, keepOpen: args.keepOpen, pauseEachStep: args.pauseEachStep, dryRun: args.dryRun, }); logger.divider(); logger.info(`✅ 单任务调试完成: ${task.name}`); } catch (err) { logger.divider(); logger.error(`❌ 单任务调试失败: ${err.message}`); logger.error(err.stack || err.message); process.exitCode = 1; } finally { logger.divider(); logger.info('===== 关闭浏览器 ====='); if (browser) { await browser.close().catch((err) => { logger.warn(`关闭浏览器失败: ${err.message}`); }); } } } main();