#!/usr/bin/env node /** * 推送今日 Agent 生成的 news002 页面到微信草稿箱(非样例 preview)。 */ import process from 'node:process'; import mysql from 'mysql2/promise'; import { loadH5Environment } from './load-env.mjs'; import { loadWechatMpConfig } from '../wechat-mp-config.mjs'; import { createWechatNewsMorningDraftService } from '../wechat-news-morning-draft.mjs'; import { getLocalParts, normalizeTimezone } from '../schedule-time.mjs'; loadH5Environment(import.meta.dirname); const DEFAULT_TANG_USER_ID = 'a70ff537-8908-486e-9b6c-042e07cc25db'; function buildDraftTitle(now = Date.now(), timezone = normalizeTimezone()) { const parts = getLocalParts(now, timezone); return `[news002] 每日新闻早报 · ${parts.year}年${parts.month}月${parts.day}日`; } async function ensureDraftConfig(service) { const current = await service.getConfig(); if (current.sourceUserId && current.enabled) return current; const userId = String(process.env.H5_WECHAT_NEWS_MORNING_DRAFT_USER_ID ?? DEFAULT_TANG_USER_ID).trim(); return service.updateConfig({ enabled: true, sourceUserId: userId, autoPushEnabled: current.autoPushEnabled ?? false, autoGenerateEnabled: current.autoGenerateEnabled ?? false, }, { updatedBy: 'news002-live-push' }); } async function main() { const dryRun = process.argv.includes('--dry-run'); if (!process.env.DATABASE_URL) { console.error('DATABASE_URL missing'); process.exit(1); } const mpConfig = loadWechatMpConfig(process.env); if (!mpConfig.enabled) { console.error('微信服务号未启用'); process.exit(1); } const pool = mysql.createPool({ uri: process.env.DATABASE_URL, connectionLimit: 2 }); const h5Root = process.env.H5_ROOT?.trim() || process.cwd(); const service = createWechatNewsMorningDraftService(pool, { mpConfig, h5Root, memindLibRoot: process.env.MEMIND_LIB_ROOT?.trim() || h5Root, env: process.env, logger: console, }); const config = await ensureDraftConfig(service); const draftTitle = buildDraftTitle(); console.log(JSON.stringify({ dryRun, sourceUserId: config.sourceUserId, templateId: config.templateId ?? null, draftTitle, h5Root, }, null, 2)); const preview = await service.pushDraft({ dryRun: true, requireToday: true, triggeredBy: 'news002-live', articleTitleOverride: draftTitle, }); const htmlPath = preview.preview?.page?.slug ? `${h5Root}/MindSpace/${config.sourceUserId}/public/${preview.preview.page.slug}.html` : null; let hasMasthead = false; let cardCount = 0; if (htmlPath) { try { const fs = await import('node:fs'); const html = fs.readFileSync(htmlPath, 'utf8'); hasMasthead = html.includes('class="masthead"'); cardCount = (html.match(/data-event-key=/g) ?? []).length; } catch { // ignore } } console.log('\n[preview]'); console.log(JSON.stringify({ pageSlug: preview.preview?.page?.slug ?? null, pageUrl: preview.preview?.page?.publicUrl ?? null, title: preview.preview?.article?.title ?? null, contentLength: preview.preview?.article?.content?.length ?? 0, hasMasthead, eventKeyCount: cardCount, }, null, 2)); if (!hasMasthead) { console.error('\n[blocked] 今日页面仍是 news001 或尚未生成 news002(缺少 .masthead)'); await pool.end(); process.exit(2); } if (dryRun) { console.log('\ndry-run:未调用微信 draft/add'); await pool.end(); return; } const result = await service.pushDraft({ requireToday: true, triggeredBy: 'news002-live', articleTitleOverride: draftTitle, }); console.log('\n[success]'); console.log(JSON.stringify({ draftMediaId: result.draftMediaId, pageSlug: result.preview?.page?.slug ?? null, pageUrl: result.preview?.page?.publicUrl ?? null, title: result.preview?.article?.title ?? null, coverSource: result.cover?.source ?? null, runId: result.run?.id ?? null, eventKeyCount: cardCount, }, null, 2)); await pool.end(); } main().catch((error) => { console.error('\n[failed]', error instanceof Error ? error.message : error); if (error?.run) { console.error(JSON.stringify(error.run, null, 2)); } process.exit(1); });