From fec940188e5337417d88fcdaa436f9ddbf2d5797 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 14 Mar 2026 18:28:28 +0000 Subject: [PATCH] feat: add /webhook/push-broadcast POST route for Pipeline C feishu broadcast - Add push-broadcast handler in backend/routes/feishu-bot.js with token validation, request parsing, and Feishu IM API message delivery - Wire /webhook/push-broadcast in backend/server.js via route forwarding - Add nginx /webhook/ proxy_pass config in nginx-api-proxy.conf - Update health check to report push_broadcast feature status Co-authored-by: qinfendebingshuo <207279273+qinfendebingshuo@users.noreply.github.com> --- backend-integration/nginx-api-proxy.conf | 10 ++++ backend/routes/feishu-bot.js | 66 ++++++++++++++++++++++++ backend/server.js | 6 +++ 3 files changed, 82 insertions(+) diff --git a/backend-integration/nginx-api-proxy.conf b/backend-integration/nginx-api-proxy.conf index 2527dd67..e24eeabe 100644 --- a/backend-integration/nginx-api-proxy.conf +++ b/backend-integration/nginx-api-proxy.conf @@ -22,6 +22,16 @@ location /api/ps/ { proxy_read_timeout 90s; } +# Webhook 路由 → 后端服务端口 3000(飞书事件回调、广播推送等) +location /webhook/ { + proxy_pass http://127.0.0.1:3000; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Content-Type $content_type; +} + # API 代理转发(通用 AI 聊天) location /api/ { proxy_pass http://127.0.0.1:3721; diff --git a/backend/routes/feishu-bot.js b/backend/routes/feishu-bot.js index 5936123a..55da7e96 100644 --- a/backend/routes/feishu-bot.js +++ b/backend/routes/feishu-bot.js @@ -410,6 +410,71 @@ router.post('/alert', async (req, res) => { } }); +// ══════════════════════════════════════════════════════════ +// 广播推送(Pipeline C 调用) +// ══════════════════════════════════════════════════════════ + +/** + * 接收 Pipeline C 的广播推送请求,转发到飞书聊天窗口 + * POST /push-broadcast (通过 server.js 映射到 /webhook/push-broadcast) + */ +router.post('/push-broadcast', async (req, res) => { + // 1. 验证 token + const token = req.headers['x-push-token']; + if (!process.env.PUSH_BROADCAST_TOKEN || token !== process.env.PUSH_BROADCAST_TOKEN) { + return res.status(401).json({ error: true, message: 'Invalid push token' }); + } + + // 2. 解析请求体 + const { chat_id, sender_open_id, broadcast_title, broadcast_content, broadcast_url } = req.body; + + if (!broadcast_content && !broadcast_title) { + return res.status(400).json({ error: true, message: 'Missing broadcast_title or broadcast_content' }); + } + + const receive_id = chat_id || sender_open_id; + if (!receive_id) { + return res.status(400).json({ error: true, message: 'Missing chat_id or sender_open_id' }); + } + + try { + // 3. 获取飞书 token + const feishuToken = await getFeishuToken(); + + // 4. 构造消息文本 + const urlLine = broadcast_url ? '\n🔗 ' + broadcast_url : ''; + const text = '📡 新广播 ' + (broadcast_title || '') + '\n\n' + (broadcast_content || '') + urlLine; + + // 5. 发送飞书消息(优先 chat_id,备选 open_id) + const receive_id_type = chat_id ? 'chat_id' : 'open_id'; + const msgResult = await httpsRequest({ + hostname: 'open.feishu.cn', + port: 443, + path: '/open-apis/im/v1/messages?receive_id_type=' + receive_id_type, + method: 'POST', + headers: { + 'Authorization': 'Bearer ' + feishuToken, + 'Content-Type': 'application/json', + }, + }, { + receive_id: receive_id, + msg_type: 'text', + content: JSON.stringify({ text }), + }); + + if (msgResult.data && msgResult.data.code === 0) { + console.log('✅ 广播推送成功: ' + broadcast_title + ' → ' + receive_id); + res.json({ success: true, message_id: msgResult.data.data && msgResult.data.data.message_id }); + } else { + console.error('❌ 飞书发送失败:', JSON.stringify(msgResult.data)); + res.status(500).json({ error: true, message: (msgResult.data && msgResult.data.msg) || 'Feishu API error', code: msgResult.data && msgResult.data.code }); + } + } catch (err) { + console.error('❌ push-broadcast error:', err.message); + res.status(500).json({ error: true, message: err.message }); + } +}); + // ══════════════════════════════════════════════════════════ // 健康检查 + 统计 // ══════════════════════════════════════════════════════════ @@ -424,6 +489,7 @@ router.get('/health', (req, res) => { ai_chat: !!process.env.MODEL_API_KEY, collaboration_logging: true, failure_alerting: !!ALERT_CHAT_ID, + push_broadcast: !!process.env.PUSH_BROADCAST_TOKEN, }, github_token_configured: !!GITHUB_TOKEN, feishu_app_configured: !!(FEISHU_APP_ID && FEISHU_APP_SECRET), diff --git a/backend/server.js b/backend/server.js index 3637c1fd..3d799196 100644 --- a/backend/server.js +++ b/backend/server.js @@ -32,6 +32,12 @@ app.get('/', (req, res) => { }); }); +// Pipeline C 广播推送 webhook → 转发到 feishu-bot 路由 +app.post('/webhook/push-broadcast', (req, res, next) => { + req.url = '/push-broadcast'; + feishuBotRoutes(req, res, next); +}); + const PORT = process.env.PORT || 3000; // 飞书 Webhook 处理(旧版兼容入口,新事件请使用 /feishu-bot/event) app.post('/webhook/feishu', (req, res) => {