feat: 支持 HTTP 回调和 WebSocket 长连接两种模式
新增功能: - 通过 FEISHU_MODE 配置切换模式 (http/websocket) - 安装飞书 SDK (@larksuiteoapi/node-sdk) - WebSocket 模式支持内网部署(无需公网 IP) - 新增 WEBSOCKET.md 配置指南 更新: - README.md 添加两种模式说明 - .env.example 添加 FEISHU_MODE 配置 - 健康检查返回当前模式信息
This commit is contained in:
97
src/index.js
97
src/index.js
@@ -8,6 +8,7 @@
|
||||
* 2. 支持交互式卡片上传
|
||||
* 3. 支持命令触发上传
|
||||
* 4. 配置管理
|
||||
* 5. 支持 HTTP 回调和 WebSocket 长连接两种模式
|
||||
*/
|
||||
|
||||
require('dotenv').config();
|
||||
@@ -21,8 +22,14 @@ const { QiniuUploader } = require('./qiniu-uploader');
|
||||
const { UploadCard } = require('./cards/upload-card');
|
||||
const { ConfigCard } = require('./cards/config-card');
|
||||
|
||||
// 飞书 SDK(WebSocket 模式)
|
||||
const { Api, eventSubscription } = require('@larksuiteoapi/node-sdk');
|
||||
|
||||
const app = express();
|
||||
const PORT = process.env.PORT || 3000;
|
||||
const PORT = process.env.PORT || 3030;
|
||||
|
||||
// 运行模式:'http' 或 'websocket'
|
||||
const MODE = (process.env.FEISHU_MODE || 'http').toLowerCase();
|
||||
|
||||
// 中间件
|
||||
app.use(express.json());
|
||||
@@ -299,13 +306,89 @@ app.post('/feishu/event', handleFeishuEvent);
|
||||
|
||||
// 健康检查
|
||||
app.get('/health', (req, res) => {
|
||||
res.json({ status: 'ok', timestamp: new Date().toISOString() });
|
||||
res.json({
|
||||
status: 'ok',
|
||||
timestamp: new Date().toISOString(),
|
||||
mode: MODE,
|
||||
port: PORT
|
||||
});
|
||||
});
|
||||
|
||||
// ============ 启动服务 ============
|
||||
|
||||
app.listen(PORT, () => {
|
||||
log(`🚀 七牛云上传机器人启动`);
|
||||
log(`📍 端口:${PORT}`);
|
||||
log(`🔗 事件地址:https://your-domain.com/feishu/event`);
|
||||
});
|
||||
function startHTTPMode() {
|
||||
app.listen(PORT, () => {
|
||||
log(`🚀 七牛云上传机器人启动 (HTTP 回调模式)`);
|
||||
log(`📍 端口:${PORT}`);
|
||||
log(`🔗 事件地址:http://your-domain.com:${PORT}/feishu/event`);
|
||||
log(`💡 提示:在飞书开放平台配置事件订阅地址为上述地址`);
|
||||
});
|
||||
}
|
||||
|
||||
function startWebSocketMode() {
|
||||
log(`🚀 七牛云上传机器人启动 (WebSocket 长连接模式)`);
|
||||
log(`💡 提示:在飞书开放平台选择 "WebSocket 长连接" 方式`);
|
||||
|
||||
// 创建飞书客户端
|
||||
const client = new Api({
|
||||
appId: process.env.FEISHU_APP_ID,
|
||||
appSecret: process.env.FEISHU_APP_SECRET,
|
||||
});
|
||||
|
||||
// 创建 WebSocket 长连接
|
||||
const ws = eventSubscription({
|
||||
appId: process.env.FEISHU_APP_ID,
|
||||
appSecret: process.env.FEISHU_APP_SECRET,
|
||||
encryptKey: process.env.FEISHU_ENCRYPT_KEY,
|
||||
verificationToken: process.env.FEISHU_VERIFICATION_TOKEN,
|
||||
logLevel: 'info',
|
||||
});
|
||||
|
||||
// 监听消息事件
|
||||
ws.on('im.message.receive_v1', async (data) => {
|
||||
log('收到消息事件');
|
||||
await handleMessage(data);
|
||||
});
|
||||
|
||||
// 监听连接状态
|
||||
ws.on('open', () => {
|
||||
log('✅ WebSocket 连接成功');
|
||||
});
|
||||
|
||||
ws.on('close', () => {
|
||||
log('❌ WebSocket 连接关闭,5 秒后重连...');
|
||||
setTimeout(() => {
|
||||
try {
|
||||
ws.start();
|
||||
} catch (e) {
|
||||
log('重连失败:', e.message);
|
||||
}
|
||||
}, 5000);
|
||||
});
|
||||
|
||||
ws.on('error', (error) => {
|
||||
log('❌ WebSocket 错误:', error.message);
|
||||
});
|
||||
|
||||
// 启动 WebSocket 连接
|
||||
try {
|
||||
ws.start();
|
||||
log('📡 WebSocket 已启动');
|
||||
} catch (error) {
|
||||
log('❌ WebSocket 启动失败:', error.message);
|
||||
log('💡 请检查飞书配置是否正确');
|
||||
}
|
||||
|
||||
// HTTP 服务器仍然运行(用于健康检查)
|
||||
app.listen(PORT, () => {
|
||||
log(`📍 健康检查端口:${PORT}`);
|
||||
log(`🔗 健康检查地址:http://localhost:${PORT}/health`);
|
||||
});
|
||||
}
|
||||
|
||||
// 根据配置启动对应模式
|
||||
if (MODE === 'websocket') {
|
||||
startWebSocketMode();
|
||||
} else {
|
||||
startHTTPMode();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user