#!/usr/bin/env node /** * 飞书卡片消息格式化 * 生成可点击链接的富文本卡片 */ const fs = require('fs'); const path = require('path'); const DAILY_DIR = path.join(__dirname, '../../daily'); function getYesterdayDate() { const d = new Date(); d.setDate(d.getDate() - 1); return d.toLocaleDateString('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit', timeZone: 'Asia/Shanghai' }).replace(/\//g, '-'); } function parseMarkdown(markdown) { const lines = markdown.split('\n'); const items = []; let currentTime = ''; let totalItems = 0; // 解析元数据 for (let i = 0; i < lines.length; i++) { const line = lines[i]; if (line.startsWith('> 采集时间:')) { currentTime = line.replace('> 采集时间:', '').trim(); } if (line.startsWith('> 总条目:')) { totalItems = parseInt(line.replace('> 总条目:', '').trim()); } } // 解析新闻条目 const itemRegex = /^(\d+)\.\s+\[([^\]]+)\]\(([^)]+)\)\s+-\s+\*\*([^*]+)\*\*/; let currentItem = null; for (let i = 0; i < lines.length; i++) { const line = lines[i]; const match = line.match(itemRegex); if (match) { if (currentItem) { items.push(currentItem); } // 清理URL let url = match[3]; let title = match[2]; if (url.includes('login?return_to=')) { const realPath = decodeURIComponent(url.split('return_to=')[1]); url = `https://github.com${realPath}`; title = realPath.replace('/', ''); } currentItem = { number: match[1], title: title, url: url, source: match[4], description: '' }; } else if (currentItem && line.trim().startsWith('>') && !line.includes('采集时间') && !line.includes('总条目')) { currentItem.description = line.replace(/^\s*>\s*/, '').trim(); } } if (currentItem) { items.push(currentItem); } return { currentTime, totalItems, items }; } function createFeishuCard(data) { const { currentTime, totalItems, items } = data; const elements = [ { tag: "div", text: { tag: "lark_md", content: `**⏰ 采集时间**: ${currentTime}\n**📊 总条目**: ${totalItems}条` } }, { tag: "hr" } ]; // 添加新闻条目 items.forEach((item, index) => { const num = ['1️⃣', '2️⃣', '3️⃣', '4️⃣', '5️⃣', '6️⃣', '7️⃣', '8️⃣', '9️⃣', '🔟'][index] || `${index + 1}.`; elements.push({ tag: "div", text: { tag: "lark_md", content: `${num} **${item.title}**\n\`${item.source}\`\n> ${item.description}\n[🔗 点击查看详情](${item.url})` } }); // 每条之间加分隔线(除了最后一条) if (index < items.length - 1) { elements.push({ tag: "hr" }); } }); // 添加底部提示 elements.push({ tag: "hr" }); elements.push({ tag: "note", elements: [ { tag: "plain_text", content: "💡 点击链接跳转到GitHub查看详情\n*Generated by AINewsCollector*" } ] }); return { msg_type: "interactive", card: { header: { title: { tag: "plain_text", content: `📰 AI Daily Brief - ${getYesterdayDate()}` }, template: "blue" }, elements: elements } }; } async function main() { const yesterday = getYesterdayDate(); const reportPath = path.join(DAILY_DIR, `${yesterday}.md`); if (!fs.existsSync(reportPath)) { console.log(`❌ 未找到昨日简报: ${reportPath}`); return { success: false, error: 'Report not found' }; } const markdown = fs.readFileSync(reportPath, 'utf8'); const data = parseMarkdown(markdown); const card = createFeishuCard(data); console.log(JSON.stringify(card, null, 2)); return { success: true, date: yesterday, card: card }; } if (require.main === module) { main().catch(console.error); } module.exports = { main, createFeishuCard, parseMarkdown };