近期文章:如何设置 Telegram 用户名 username及其作用详解
问题描述
最近几个月Telegram代开会员,有些朋友反馈,他被私聊限制了,无法给我发送消息,也有时会遇到双向限制,其实这种情况可以向官方bot申请,也可以创建专属私聊bot,彻底解决这个问题,向官方 bot申诉之前有写过详细申诉教程,点击下方内容查看即可,这里就不赘述了,这篇文章目的是:如何零成本创建属于自己的telegram私聊Bot
Telegram创建属于自己的私聊 Bot,下面是详细步骤:
首先申请Bot API Token
1、向官方 @BotFather 申请一个机器人,获得 Bot API Token,,下面两种方法都要用到这个 API Token.
注意,截图中HTTP API就是 token,不要泄露给任何人
2、发送/setjoingroups
来禁止此Bot被他人添加到群组,发送/setjoingroups
后选择你的 bot,再发送 Disable即可。
创建好了 bot,也有 api token,接下来分别采用下面两种方式创建专属私聊 bot
方案一、使用 @LivegramBot ,创建专属私聊 bot
1、私聊 @LivegramBot
,发送”/addbot”或点击 “Add Bot”,
2、输入申请的 Bot API Token 即可。
LivegramBot缺点如下
- 1、是有广告,必须要购买才能去除
- 2、从技术上讲,使用该方法制作的私聊机器人,聊天内容可以被 @LivegramBot 所有者查看或储存,不保证私聊内容的安全性和隐私性。建议使用下面方案,更安全
方案二、 基于cloudflare worker 零成本实现telegram私聊机器人
好处是:
- 基于cloudflare worker搭建,能够实现以下效果
- 零成本,一个js文件即可完成搭建
- 不需要额外的域名,利用worker自带域名即可
- 基于worker kv实现永久数据储存,数据更加安全
- 稳定,全球cdn转发
搭建方法:
步骤1、从uuidgenerator获取一个随机uuid作为secret
步骤2、从@sosoo获取你的用户id
步骤3、登录cloudflare,左侧菜单点击 Workers和 Pages,创建一个worker
步骤4、创建 -》 创建 Worker -》输入名称 telegrambot
部署之后,点击右上角【继续处理项目】
步骤5、配置worker的变量,在设置-》变量-》添加变量
- 增加一个
ENV_BOT_TOKEN
变量,值为向官方 bot申请的Bot API Token - 增加一个
ENV_BOT_SECRET
变量,数值为从步骤1中获得的secret - 增加一个
ENV_ADMIN_UID
变量,数值为从步骤2中获得的用户id
步骤6、创建一个命名空间为telegrambot
的KV数据库
步骤7、绑定KV数据库,在设置 -> 变量,下滑找到KV 命名空间绑定
:telegrambot
-> telegrambot
步骤8、编辑代码
将worker下面代码全部复制
const TOKEN = ENV_BOT_TOKEN; const WEBHOOK = '/endpoint'; const SECRET = ENV_BOT_SECRET; const ADMIN_UID = ENV_ADMIN_UID; const KV_NAMESPACE = telegrambot; const LAST_USER_KEY = 'last_user'; const USER_MESSAGES_KEY_PREFIX = 'user_message_'; const ADMIN_RESPONSES_KEY_PREFIX = 'admin_response_'; addEventListener('fetch', event => { const url = new URL(event.request.url); if (url.pathname === WEBHOOK) { event.respondWith(handleWebhook(event)); } else if (url.pathname === '/registerWebhook') { event.respondWith(registerWebhook(event, url, WEBHOOK, SECRET)); } else if (url.pathname === '/unRegisterWebhook') { event.respondWith(unRegisterWebhook(event)); } else { event.respondWith(new Response('No handler for this request')); } }); async function handleWebhook(event) { if (event.request.headers.get('X-Telegram-Bot-Api-Secret-Token') !== SECRET) { return new Response('Unauthorized', { status: 403 }); } const update = await event.request.json(); event.waitUntil(onUpdate(update)); return new Response('Ok'); } async function onUpdate(update) { if ('message' in update) { await onMessage(update.message); } } async function onMessage(message) { const chatId = message.chat.id; const userName = message.from.username ? `@${message.from.username}` : message.from.first_name; if (chatId == ADMIN_UID) { const lastUserId = await KV_NAMESPACE.get(LAST_USER_KEY); if (lastUserId) { let responseText = ''; if (message.photo) { const photo = message.photo[message.photo.length - 1]; await sendPhoto(lastUserId, photo.file_id); responseText = `管理员发送了一张图片: ${photo.file_id}`; } else if (message.sticker) { await sendSticker(lastUserId, message.sticker.file_id); responseText = `管理员发送了一张贴纸: ${message.sticker.file_id}`; } else if (message.voice) { await sendVoice(lastUserId, message.voice.file_id); responseText = `管理员发送了一条语音消息: ${message.voice.file_id}`; } else if (message.document) { await sendDocument(lastUserId, message.document.file_id); responseText = `管理员发送了一份文件: ${message.document.file_id}`; } else if (message.video) { await sendVideo(lastUserId, message.video.file_id); responseText = `管理员发送了一段视频: ${message.video.file_id}`; } else if (message.location) { await sendLocation(lastUserId, message.location.latitude, message.location.longitude); responseText = `管理员发送了一个位置: 纬度 ${message.location.latitude}, 经度 ${message.location.longitude}`; } else { const text = message.text || '收到一个非文本消息'; await sendPlainText(lastUserId, text); responseText = text; } await KV_NAMESPACE.put(`${ADMIN_RESPONSES_KEY_PREFIX}${lastUserId}`, responseText); } else { await sendPlainText(ADMIN_UID, '没有最近活跃的用户会话。'); } } else { let userMessageText = ''; if (message.photo) { const photo = message.photo[message.photo.length - 1]; userMessageText = `用户发送了一张图片: ${photo.file_id}`; await sendPhoto(ADMIN_UID, photo.file_id); } else if (message.sticker) { userMessageText = `用户发送了一张贴纸: ${message.sticker.file_id}`; await sendSticker(ADMIN_UID, message.sticker.file_id); } else if (message.voice) { userMessageText = `用户发送了一条语音消息: ${message.voice.file_id}`; await sendVoice(ADMIN_UID, message.voice.file_id); } else if (message.document) { userMessageText = `用户发送了一份文件: ${message.document.file_id}`; await sendDocument(ADMIN_UID, message.document.file_id); } else if (message.video) { userMessageText = `用户发送了一段视频: ${message.video.file_id}`; await sendVideo(ADMIN_UID, message.video.file_id); } else if (message.location) { userMessageText = `用户发送了一个位置: 纬度 ${message.location.latitude}, 经度 ${message.location.longitude}`; await sendLocation(ADMIN_UID, message.location.latitude, message.location.longitude); } else { const text = message.text; userMessageText = text; await sendPlainText(ADMIN_UID, `来自用户 ${userName} 的消息:\n${text}`); } await KV_NAMESPACE.put(`${USER_MESSAGES_KEY_PREFIX}${chatId}`, userMessageText); await KV_NAMESPACE.put(LAST_USER_KEY, chatId); } } async function sendSticker(chatId, fileId) { return (await fetch(apiUrl('sendSticker', { chat_id: chatId, sticker: fileId }))).json(); } async function sendPhoto(chatId, fileId) { return (await fetch(apiUrl('sendPhoto', { chat_id: chatId, photo: fileId }))).json(); } async function sendVoice(chatId, fileId) { return (await fetch(apiUrl('sendVoice', { chat_id: chatId, voice: fileId }))).json(); } async function sendDocument(chatId, fileId) { return (await fetch(apiUrl('sendDocument', { chat_id: chatId, document: fileId }))).json(); } async function sendVideo(chatId, fileId) { return (await fetch(apiUrl('sendVideo', { chat_id: chatId, video: fileId }))).json(); } async function sendLocation(chatId, latitude, longitude) { return (await fetch(apiUrl('sendLocation', { chat_id: chatId, latitude, longitude }))).json(); } async function registerWebhook(event, requestUrl, suffix, secret) { const webhookUrl = `${requestUrl.protocol}//${requestUrl.hostname}${suffix}`; const r = await (await fetch(apiUrl('setWebhook', { url: webhookUrl, secret_token: secret }))).json(); return new Response('ok' in r && r.ok ? 'Ok' : JSON.stringify(r, null, 2)); } async function unRegisterWebhook(event) { const r = await (await fetch(apiUrl('setWebhook', { url: '' }))).json(); return new Response('ok' in r && r.ok ? 'Ok' : JSON.stringify(r, null, 2)); } async function sendPlainText(chatId, text) { return (await fetch(apiUrl('sendMessage', { chat_id: chatId, text }))).json(); } function apiUrl(methodName, params = null) { let query = ''; if (params) { query = '?' + new URLSearchParams(params).toString(); } return `https://api.telegram.org/bot${TOKEN}/${methodName}${query}`; }
步骤 9、替换掉默认代码后,右上角点击部署,然后顶部中间点击 worker.dev进行访问
10、完成bot部署
url后面加上/registerWebhook,进行 webhook注册 (unRegisterWebhoo 取消注册)
备注:如果打不开url就需要翻墙,因为在中国大陆cloudflare worker.dev域名被禁了,也可以给 worker绑定一个域名解决
显示 OK就完成部署了,接下来测试一下私聊bot
测试私聊bot
经过我反复多人测试,已实现文本、图片、贴纸、视频,语音,文件消息都可以发送成功,无延迟。
特点:
- 消息都会保存在 kv库中,安全
- 多人同时发送消息给 bot时,多人发送消息,轻点消息选择回复用户即可
- 多人同时发送消息给 bot时,最后一条消息为当前会话,可以直接回复
大家有什么建议或发现什么bug,可以在群组里讨论👥 Telegram 中文社群