Node环境下如何为telegrap.js Telegram Bot添加express API路由
Telegraf.js 搭配 Express 实现外部API触发Bot发PDF到频道
核心逻辑:不存在“为Telegraf.js绑定Express路由”的特殊封装。Telegraf仅负责和Telegram服务端通信,Express是独立的HTTP服务,二者运行在同个Node进程时,Express路由的处理逻辑中可以直接调用Bot实例的通信方法,不需要做额外的适配绑定。
实现步骤
1. 安装依赖
需要安装的核心包和功能包:
telegraf:Telegram 官方推荐的Node.js Bot SDKexpress:HTTP路由框架pdfkit:用于内存生成PDF文件,无需写本地临时文件cors:按需安装,处理跨域请求
安装命令:
npm install telegraf express pdfkit cors
2. 初始化服务实例
全局只初始化一次Bot和Express实例,避免重复连接导致的异常:
const { Telegraf } = require('telegraf'); const express = require('express'); const PDFDocument = require('pdfkit'); const cors = require('cors'); // 配置项替换成你自己的参数 const BOT_TOKEN = '你的Telegram Bot Token'; const TARGET_CHANNEL_ID = '目标频道ID,公开频道填@频道用户名,私有频道填-100开头的数字ID'; const PORT = 3000; const bot = new Telegraf(BOT_TOKEN); const app = express(); // 基础中间件 app.use(cors()); app.use(express.json({ limit: '10mb' })); // 调整请求体大小限制适配大参数
3. 编写自定义触发API路由
以POST接口/api/generate-and-send-pdf为例,接口接收JSON参数,生成PDF后直接发送到目标频道:
app.post('/api/generate-and-send-pdf', async (req, res) => { try { // 校验必填参数,按需调整你需要的字段 const { title, content, operator } = req.body; if (!title || !content) { return res.status(400).json({ code: 400, msg: '缺少必填参数:title、content' }); } // 内存中生成PDF流,不写入本地磁盘,减少IO开销和临时文件清理问题 const doc = new PDFDocument(); const chunks = []; doc.on('data', chunk => chunks.push(chunk)); const pdfBuffer = await new Promise((resolve, reject) => { doc.on('end', () => resolve(Buffer.concat(chunks))); doc.on('error', reject); // 自定义PDF排版,按需调整 doc.fontSize(20).text(title, { align: 'center' }); doc.moveDown(); doc.fontSize(12).text(content, { lineGap: 6 }); doc.moveDown(2); doc.fontSize(10).text(`生成时间:${new Date().toLocaleString('zh-CN')}`, { align: 'right' }); if (operator) doc.text(`操作人:${operator}`, { align: 'right' }); doc.end(); }); // 调用Bot能力发送PDF到目标频道 await bot.telegram.sendDocument( TARGET_CHANNEL_ID, { source: pdfBuffer, filename: `${title}.pdf` }, { caption: `文档自动推送:${title}` } ); return res.status(200).json({ code: 200, msg: 'PDF生成并发送成功' }); } catch (err) { console.error('请求处理失败:', err); return res.status(500).json({ code: 500, msg: '服务内部错误', error: err.message }); } });
4. 启动服务
根据部署场景二选一即可:
开发调试:长轮询模式
不需要公网IP,本地就能跑,适合开发阶段调试:
bot.launch().then(() => console.log('Bot长轮询连接成功')); app.listen(PORT, () => { console.log(`服务启动成功,端口:${PORT}`); console.log(`本地触发接口:POST http://localhost:${PORT}/api/generate-and-send-pdf`); }); // 优雅退出 process.once('SIGINT', () => bot.stop('SIGINT')); process.once('SIGTERM', () => bot.stop('SIGTERM'));
生产部署:Webhook模式
性能更好,不需要维持长连接,要求服务有公网可访问的HTTPS域名:
// webhook路径加随机字符串避免被恶意扫描 const WEBHOOK_PATH = `/tg-bot-webhook-${Math.random().toString(36).slice(2)}`; app.use(bot.webhookCallback(WEBHOOK_PATH)); app.listen(PORT, async () => { const webhookUrl = `https://你的公网域名${WEBHOOK_PATH}`; await bot.telegram.setWebhook(webhookUrl); console.log(`服务启动成功,端口:${PORT}`); console.log(`Webhook已配置:${webhookUrl}`); console.log(`线上触发接口:POST https://你的公网域名/api/generate-and-send-pdf`); });
常见踩坑点
- Bot权限:必须把Bot拉进目标频道,设置为管理员,开启「发送消息」「发送文档」权限,否则会抛出403无权限错误
- 频道ID获取:私有频道的ID是-100开头的长数字,可以在长轮询模式下给频道发一条消息,调用
bot.telegram.getUpdates()查看返回的chat.id字段获取 - 文件大小限制:Telegram Bot单次发送的文件最大为50MB,生成的PDF超过限制时需要先上传到对象存储,再调用
sendDocument传文件链接发送 - 接口鉴权:生产环境一定要给自定义API加鉴权逻辑(比如请求头校验固定token),避免被恶意调用刷频道消息
- 实例复用:不要在路由处理函数内初始化Telegraf实例,全局复用同一个实例即可,否则会出现重复接收消息、连接泄漏的问题
内容的提问来源于stack exchange,提问作者Hyperledger Q
相关产品推荐
相关产品推荐

