2026-03-06 10:38:12 +08:00
|
|
|
// 钉钉 Webhook + AI 集成
|
|
|
|
|
const express = require('express');
|
2026-03-06 09:59:01 +08:00
|
|
|
const crypto = require('crypto');
|
2026-03-06 10:38:12 +08:00
|
|
|
require('dotenv').config();
|
2026-03-06 09:59:01 +08:00
|
|
|
|
2026-03-06 10:38:12 +08:00
|
|
|
const app = express();
|
|
|
|
|
app.use(express.json());
|
|
|
|
|
app.use(express.urlencoded({ extended: true }));
|
|
|
|
|
|
2026-03-06 10:52:34 +08:00
|
|
|
// 调用 Kimi API
|
|
|
|
|
async function callKimiAPI(content) {
|
|
|
|
|
const response = await fetch('https://api.moonshot.cn/v1/chat/completions', {
|
|
|
|
|
method: 'POST',
|
|
|
|
|
headers: {
|
|
|
|
|
'Content-Type': 'application/json',
|
|
|
|
|
'Authorization': `Bearer ${process.env.KIMI_API_KEY}`
|
|
|
|
|
},
|
|
|
|
|
body: JSON.stringify({
|
|
|
|
|
model: 'moonshot-v1-8k',
|
|
|
|
|
messages: [
|
|
|
|
|
{ role: 'system', content: '你是之之秋秋,光湖纪元的钉钉机器人助手。' },
|
|
|
|
|
{ role: 'user', content: content }
|
|
|
|
|
]
|
|
|
|
|
})
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const data = await response.json();
|
|
|
|
|
return data.choices[0].message.content;
|
|
|
|
|
}
|
2026-03-06 10:38:12 +08:00
|
|
|
// AI 处理函数
|
|
|
|
|
async function processWithAI(content) {
|
|
|
|
|
// 这里接入 Kimi API
|
|
|
|
|
// 暂时返回测试回复
|
2026-03-06 10:52:34 +08:00
|
|
|
return await callKimiAPI(content);
|
2026-03-06 10:38:12 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 验证签名
|
2026-03-06 09:59:01 +08:00
|
|
|
function verifySign(timestamp, sign) {
|
2026-03-06 10:38:12 +08:00
|
|
|
const secret = process.env.DINGTALK_APP_SECRET;
|
|
|
|
|
const stringToSign = `${timestamp}\n${secret}`;
|
|
|
|
|
const hmac = crypto.createHmac('sha256', secret);
|
2026-03-06 09:59:01 +08:00
|
|
|
hmac.update(stringToSign);
|
2026-03-06 10:38:12 +08:00
|
|
|
return hmac.digest('base64') === sign;
|
2026-03-06 09:59:01 +08:00
|
|
|
}
|
|
|
|
|
|
2026-03-06 10:38:12 +08:00
|
|
|
// Webhook 接收消息
|
|
|
|
|
app.post('/webhook', async (req, res) => {
|
|
|
|
|
console.log('收到消息:', req.body);
|
|
|
|
|
|
|
|
|
|
const { text, senderStaffId, conversationId } = req.body;
|
2026-03-06 09:59:01 +08:00
|
|
|
|
2026-03-06 10:38:12 +08:00
|
|
|
if (text && text.content) {
|
|
|
|
|
// 调用 AI 处理
|
|
|
|
|
const reply = await processWithAI(text.content);
|
|
|
|
|
|
|
|
|
|
// 返回回复
|
|
|
|
|
res.json({
|
|
|
|
|
msgtype: 'text',
|
|
|
|
|
text: {
|
|
|
|
|
content: reply
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
res.json({ msgtype: 'text', text: { content: '收到' } });
|
2026-03-06 09:59:01 +08:00
|
|
|
}
|
2026-03-06 10:38:12 +08:00
|
|
|
});
|
2026-03-06 09:59:01 +08:00
|
|
|
|
2026-03-06 10:38:12 +08:00
|
|
|
// 健康检查
|
|
|
|
|
app.get('/health', (req, res) => {
|
|
|
|
|
res.json({ status: 'ok', time: new Date().toISOString() });
|
|
|
|
|
});
|
2026-03-06 09:59:01 +08:00
|
|
|
|
2026-03-06 10:38:12 +08:00
|
|
|
const PORT = process.env.PORT || 3000;
|
|
|
|
|
app.listen(PORT, () => {
|
|
|
|
|
console.log(`🤖 之之秋秋机器人启动: http://localhost:${PORT}`);
|
|
|
|
|
console.log(`Webhook: http://localhost:${PORT}/webhook`);
|
|
|
|
|
});
|