]*>([\s\S]*?)<\/p>/gi)]
.map((item) => stripHtml(item[1]))
.filter(Boolean);
const context = paragraphs[0] ?? '';
return {
index: index + 1,
title,
tag,
context: truncateText(context, 120),
};
}).filter((item) => item.title);
}
export function extractKnowledgeItemsFromHtml(html) {
const sectionHtml = extractDailyNewsSectionHtml(html, 'knowledge');
const blocks = extractClassDivBlocks(sectionHtml, 'knowledge-item');
return blocks.map((block, index) => {
const icon = stripHtml(block.match(/
]*>([\s\S]*?)<\/div>/i)?.[1] ?? '');
const title = stripHtml(block.match(/
]*>([\s\S]*?)<\/h4>/i)?.[1] ?? '');
const body = truncateText(
stripHtml(block.match(/
]*>([\s\S]*?)<\/p>/i)?.[1] ?? ''),
180,
);
if (!title) return null;
return { index: index + 1, title: icon ? `${icon} ${title}` : title, body };
}).filter(Boolean);
}
export function extractCardsFromSectionIds(html, sectionIds = []) {
const cards = [];
for (const sectionId of sectionIds) {
const sectionHtml = extractDailyNewsSectionHtml(html, sectionId);
if (!sectionHtml) continue;
cards.push(...extractCardsFromHtmlFragment(sectionHtml));
}
return cards.map((card, index) => ({ ...card, index: index + 1 }));
}
export function buildSectionCardsPushText({
emoji,
label,
dateLabel = '',
cards = [],
maxItems = 5,
includeSummary = false,
publicUrl = '',
cancelId,
unavailableText = '内容正在整理中,稍后会推送到本服务号。',
}) {
const lines = [`${emoji} ${label}${dateLabel ? ` · ${dateLabel}` : ''}`];
const picked = cards.slice(0, Math.max(1, Math.min(10, Number(maxItems) || 5)));
if (!picked.length) {
lines.push('', unavailableText);
} else {
lines.push('');
for (const card of picked) {
const prefix = card.tag ? `[${card.tag}] ` : '';
if (includeSummary && card.context) {
lines.push(`${card.index}. ${prefix}${card.title}`, ` ${card.context}`, '');
} else {
lines.push(`${card.index}. ${prefix}${card.title}`);
}
}
if (includeSummary) {
while (lines.at(-1) === '') lines.pop();
}
}
if (publicUrl) lines.push('', `👉 阅读全文:${publicUrl}`);
if (cancelId) lines.push('', `回复「取消${cancelId}」关闭推送`);
return lines.join('\n');
}
export async function loadTodayNewsMorningHtml({
now = Date.now(),
timezone = 'Asia/Shanghai',
env = process.env,
h5Root = process.cwd(),
pool = null,
} = {}) {
const config = await resolveNewsMorningPushConfig({ pool, env });
const effectiveTimezone = config.timezone || timezone;
if (!config.sourceUserId) {
return { html: null, config, dateLabel: '', publicUrl: '' };
}
const page = findLatestNewsMorningPage({
h5Root,
userId: config.sourceUserId,
slugPattern: config.pageSlugPattern,
date: new Date(now),
timezone: effectiveTimezone,
});
if (
!page?.localPath
|| !fs.existsSync(page.localPath)
|| !isNewsMorningPageForToday(page, { date: new Date(now), timezone: effectiveTimezone })
) {
return { html: null, config, dateLabel: '', publicUrl: '' };
}
const html = fs.readFileSync(page.localPath, 'utf8');
return {
html,
config,
dateLabel: extractDailyNewsHeroDate(html),
publicUrl: buildPublicUrl(config.publicBaseUrl, config.sourceUserId, page.relativePath),
};
}