#!/usr/bin/env node /** * One-shot proactive WeChat resend for a completed scheduled task page delivery. * Usage: * node scripts/manual-resend-scheduled-task-wechat.mjs --user-id --relative-path public/foo.html [--dry-run] */ import process from 'node:process'; import mysql from 'mysql2/promise'; import { loadH5Environment } from './load-env.mjs'; import { buildScheduledTaskVerifiedHtmlUrls, formatScheduledTaskDeliveryMessage, resendScheduledTaskWechatForReadyPage, } from '../scheduled-task-executor.mjs'; import { loadWechatMpConfig, createWechatMpService } from '../wechat-mp.mjs'; import { createNotificationDispatcher } from '../notification-dispatcher.mjs'; import { createUserAuth } from '../user-auth.mjs'; loadH5Environment(new URL('.', import.meta.url).pathname); function parseArgs(argv) { const args = { userId: '', relativePath: '', dryRun: false, }; for (let i = 0; i < argv.length; i += 1) { const token = argv[i]; if (token === '--user-id') args.userId = String(argv[++i] ?? '').trim(); else if (token === '--relative-path') args.relativePath = String(argv[++i] ?? '').trim(); else if (token === '--dry-run') args.dryRun = true; } return args; } async function main() { const { userId, relativePath, dryRun } = parseArgs(process.argv.slice(2)); if (!userId || !relativePath) { throw new Error('用法: node scripts/manual-resend-scheduled-task-wechat.mjs --user-id --relative-path public/foo.html'); } if (!process.env.DATABASE_URL) { throw new Error('缺少 DATABASE_URL'); } const pool = mysql.createPool({ uri: process.env.DATABASE_URL, connectionLimit: 2 }); const userAuth = createUserAuth(pool); const wechatMpService = createWechatMpService({ config: loadWechatMpConfig(), userAuth, apiFetch: async () => { throw new Error('manual resend does not proxy chat sessions'); }, mysqlPool: pool, }); const notificationDispatcher = createNotificationDispatcher({ sendWechatTextToUser: wechatMpService?.enabled ? (targetUserId, text, options) => wechatMpService.sendTextToUser(targetUserId, text, options) : null, }); if (dryRun) { const verifiedHtmlUrls = buildScheduledTaskVerifiedHtmlUrls(userId, [relativePath]); console.log(JSON.stringify({ mode: 'dry-run', userId, relativePath, verifiedHtmlUrls }, null, 2)); await pool.end(); return; } const sent = await resendScheduledTaskWechatForReadyPage({ pool, userId, relativePath, notificationDispatcher, logger: console, }); console.log(JSON.stringify({ mode: 'apply', userId, relativePath, sent, }, null, 2)); await pool.end(); if (!sent) process.exitCode = 1; } main().catch((error) => { console.error(error); process.exit(1); });