1. 申请 Bot
先在 BotFather 申请一个 Bot,输入 bot 的显示名称和 ID 拿到 Bot Token.
Bot Token 大概长这样子:
66XXXXXX88:AAAAAQQQeeefffpppaaalllnnnppp111ooo拿到新鲜的 Bot Token 之后取出备用。
2. 设定 Webhook
Telegram bot 有两种获取讯息的方式:
Polling(轮询)模式。即 bot 每隔一段时间向 Telegram 服务器拉取讯息。
Webhook 模式。即 Telegram 服务器在收取到讯息的时候向指定的 Webhook 地址发送请求。
由于 Vercel Serverless Function 的特殊性质,我们只能使用 Webhook。 或者说我太低能不会拿 Vercel Serverless Function 写 Polling 模式的 Serverless Bot
为了方便调试,我们需要在本地设定一个 Cloudflare Tunnel,你可以查看这篇博文学到更多:设定 Cloudflare Tunnel
通过 Telegram API 将 Bot 设定为 Webhook 模式:
curl "https://api.telegram.org/bot{token}/setWebhook?url={webhook}"此时我们假定我们已经设定的 Tunnel 跑在 bot-test.ooze.gq,则应该执行
curl "https://api.telegram.org/bot66XXXXXX88:AAAAAQQQeeefffpppaaalllnnnppp111ooo/setWebhook?url=https://bot-test.ooze.gq/api/webhook"如果你收到类似 {"ok":true,"result":true,"description":"Webhook was set"} 的返回结果,则为设置成功。
3. 开发
3.1 回声机器人
执行 mkdir Vercel-Telegram-Bot && cd Vercel-Telegram-Bot 创建并切换到工作目录.
执行 pnpm i node-telegram-bot-api 安装必要的依赖.
执行 mkdir api && touch webhook.js 创建 webhook api.
选择你喜欢的编辑器开始编辑 webhook.js ,下面是一个简单的回声机器人的示范:
const TelegramBot = require("node-telegram-bot-api");
module.exports = async (request, response) => { try { const bot = new TelegramBot(process.env.TELEGRAM_TOKEN); const { body } = request; const { chat: { id }, text } = body.message;
// Echo Bot Example: if (body.message.chat.type === "private" && body.message) { await bot.sendMessage(id, `You have sent **"${text}"**!`, { parse_mode: "Markdown" }); } } catch (error) { console.error("Error to sending message, " + error.toString()); } response.send("OK");};接下来使用 TELEGRAM_TOKEN="66XXXXXX88:AAAAAQQQeeefffpppaaalllnnnppp111ooo" vercel dev 启动开发服务器
如果你以上操作的执行正确,向你的 Bot 发送 /start,此时你应该就会收到 You have sent "/start"! 了
3.2 接入 hitokoto API 示例
由于是 bot, 可能会被用在群里,我们添加一段指令:
const username = process.env.TELEGRAM_BOT_USERNAME || `@${await bot.getMe().username}`;这回优先从环境变量 TELEGRAM_BOT_USERNAME 中获取 Bot 的 username, 如果没有则自动获取。
判断 /hitokoto 指令:
if ( text.toString().startsWith("/hitokoto ") || text.toString() === "/hitokoto" || text.toString().startsWith(`/hitokoto@${username}`)) { // do your job}接下来使用 fetch 从 hitokoto 获取并处理数据:
let hitokotoText = await fetch(`https://v1.hitokoto.cn/?t=${new Date().getTime()}`) .then(res => res.json()) .then(res => { return `「 ${res.hitokoto} 」 \n` + `來自${res.from_who ? res.from_who + "的" : ""}「 ${res.from} 」`; }) .catch(() => { return "API 或者 Bot 爆炸了捏😋" })最后发送:
await bot.sendMessage(id, hitokotoText, { parse_mode: "Markdown" });汇总如下:
const TelegramBot = require("node-telegram-bot-api");
module.exports = async (request, response) => { try { const bot = new TelegramBot(process.env.TELEGRAM_TOKEN); const username = process.env.TELEGRAM_BOT_USERNAME || `@${await bot.getMe().username}`; const { body } = request; const { chat: { id }, text } = body.message;
console.log(text)
// Hitokoto Bot Example: if ( text.toString().startsWith("/hitokoto ") || text.toString() === "/hitokoto" || text.toString().startsWith(`/hitokoto@${username}`) ) { let hitokotoText = await fetch(`https://v1.hitokoto.cn/?t=${new Date().getTime()}`) .then(res => res.json()) .then(res => { return `「 ${res.hitokoto} 」 \n` + `來自${res.from_who ? res.from_who + "的" : ""}「 ${res.from} 」`; }) .catch(() => { return "API 或者 Bot 爆炸了捏😋" }) await bot.sendMessage(id, hitokotoText, { parse_mode: "Markdown" }) } } catch (error) { console.error("Error to sending message, " + error.toString()); } response.send("OK");};4. 部署
我懒得写了,你看着办吧