#!/usr/bin/env node /** * 将 news002 样例预览页推送到微信公众号草稿箱(不切换生产模板、不发布 Portal)。 * * 用法(建议在 143 上执行,微信 IP 白名单已覆盖): * node scripts/push-news002-preview-draft.mjs * node scripts/push-news002-preview-draft.mjs --dry-run */ import fs from 'node:fs'; import os from 'node:os'; import path from 'node:path'; import process from 'node:process'; import mysql from 'mysql2/promise'; import { loadH5Environment } from './load-env.mjs'; import { writeNews002PreviewFile } from './preview-news002-template.mjs'; import { loadWechatMpConfig } from '../wechat-mp-config.mjs'; import { createWechatNewsMorningDraftService } from '../wechat-news-morning-draft.mjs'; const PUBLIC_ZONE_DIR = 'public'; loadH5Environment(import.meta.dirname); const DEFAULT_TANG_USER_ID = 'a70ff537-8908-486e-9b6c-042e07cc25db'; 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-preview-script' }); } 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('微信服务号未启用:请确认 H5_WECHAT_MP_ENABLED=1 且 appId/secret/token/publicBaseUrl 齐全'); 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() || path.dirname(import.meta.dirname), env: process.env, logger: console, }); const config = await ensureDraftConfig(service); const previewDir = path.join(os.tmpdir(), 'memind-news002-preview'); const previewPath = path.join(previewDir, 'page.html'); const { context } = writeNews002PreviewFile(previewPath, { previewMode: true }); const relativePath = `${PUBLIC_ZONE_DIR}/${context.slug}.html`; console.log(JSON.stringify({ dryRun, template: 'news002-preview', sourceUserId: config.sourceUserId, productionTemplateId: config.templateId ?? 'news001 (default)', previewPath, previewSlug: context.slug, draftTitle: context.draftTitle, }, null, 2)); const pageOverride = { localPath: previewPath, slug: context.slug, relativePath, isTodayPage: true, }; const preview = await service.pushDraft({ dryRun: true, requireToday: false, triggeredBy: 'news002-preview', pageOverride, articleTitleOverride: context.draftTitle, }); 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: preview.preview?.article?.content?.includes('masthead') ?? false, hasLeadCard: preview.preview?.article?.content?.includes('lead-card') ?? false, }, null, 2)); if (dryRun) { console.log('\ndry-run:未调用微信 draft/add'); await pool.end(); return; } const result = await service.pushDraft({ requireToday: false, triggeredBy: 'news002-preview', pageOverride, articleTitleOverride: context.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, note: '请在微信草稿箱查看 [news002预览] 标题;内容为样例数据,非 Agent 全量生成。', }, 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); });