Telegram双向机器人部署教程

兰科勒布劳恩斯基
2026-02-05 / 0 评论 / 155 阅读 / 正在检测是否收录...

相信许多没有Telegram Premium订阅的人时常被各种各样的垃圾私聊信息骚扰,或者不方便直接和陌生人进行沟通,那么这个双向机器人部署教程于你而言就再适合不过了,它实现的功能就是通过创建聊天,可以实现一对多的聊天,支持消息、语音、表情包和视频的转发,且会标记发信者的username 你可以通过此创建一个客户支持Bot或者纯粹作为自用
下面开始教程,本教程使用Cloudflare Worker进行部署,如果每天只有几百条信息那么是免费的
首先请找到Cloudflare KV数据库,点击这里前往: https://dash.cloudflare.com/workers/kv/namespaces
创建一个名字叫telegrambot的数据库
然后打开 Cloudflare Worker ,随机创建一个Worker即可,然后点击右上角“编辑代码”可以更改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) {
    // 处理管理员消息
    let userChatId;

    if (message.reply_to_message) {
      const repliedMessageId = message.reply_to_message.message_id;
      userChatId = await KV_NAMESPACE.get(`admin_message_${repliedMessageId}`);
      if (!userChatId) {
        await sendPlainText(ADMIN_UID, '无法找到要回复的用户消息。');
        return;
      }
    } else {
      // 获取最后一个活跃的用户
      userChatId = await KV_NAMESPACE.get(LAST_USER_KEY);
      if (!userChatId) {
        await sendPlainText(ADMIN_UID, '没有最近活跃的用户会话。');
        return;
      }
    }

    // 根据管理员发送的消息类型,转发给对应的用户
    let responseText = '';
    if (message.photo) {
      const photo = message.photo[message.photo.length - 1];
      await sendPhoto(userChatId, photo.file_id);
      responseText = `管理员发送了一张图片: ${photo.file_id}`;
    } else if (message.sticker) {
      await sendSticker(userChatId, message.sticker.file_id);
      responseText = `管理员发送了一张贴纸: ${message.sticker.file_id}`;
    } else if (message.voice) {
      await sendVoice(userChatId, message.voice.file_id);
      responseText = `管理员发送了一条语音消息: ${message.voice.file_id}`;
    } else if (message.document) {
      await sendDocument(userChatId, message.document.file_id);
      responseText = `管理员发送了一份文件: ${message.document.file_id}`;
    } else if (message.video) {
      await sendVideo(userChatId, message.video.file_id);
      responseText = `管理员发送了一段视频: ${message.video.file_id}`;
    } else if (message.location) {
      await sendLocation(userChatId, message.location.latitude, message.location.longitude);
      responseText = `管理员发送了一个位置: 纬度 ${message.location.latitude}, 经度 ${message.location.longitude}`;
    } else {
      const text = message.text || '收到一个非文本消息';
      await sendPlainText(userChatId, text);
      responseText = text;
    }
    await KV_NAMESPACE.put(`${ADMIN_RESPONSES_KEY_PREFIX}${userChatId}`, responseText);
  } else {
    // 处理用户消息
    let userMessageText = '';
    let response;
    if (message.photo) {
      const photo = message.photo[message.photo.length - 1];
      userMessageText = `用户发送了一张图片: ${photo.file_id}`;
      response = await sendPhoto(ADMIN_UID, photo.file_id, `来自用户 ${userName} 的图片`);
    } else if (message.sticker) {
      userMessageText = `用户发送了一张贴纸: ${message.sticker.file_id}`;
      response = await sendSticker(ADMIN_UID, message.sticker.file_id);
    } else if (message.voice) {
      userMessageText = `用户发送了一条语音消息: ${message.voice.file_id}`;
      response = await sendVoice(ADMIN_UID, message.voice.file_id);
    } else if (message.document) {
      userMessageText = `用户发送了一份文件: ${message.document.file_id}`;
      response = await sendDocument(ADMIN_UID, message.document.file_id);
    } else if (message.video) {
      userMessageText = `用户发送了一段视频: ${message.video.file_id}`;
      response = await sendVideo(ADMIN_UID, message.video.file_id);
    } else if (message.location) {
      userMessageText = `用户发送了一个位置: 纬度 ${message.location.latitude}, 经度 ${message.location.longitude}`;
      response = await sendLocation(ADMIN_UID, message.location.latitude, message.location.longitude);
    } else {
      const text = message.text || '用户发送了非文本消息';
      userMessageText = text;
      response = await sendPlainText(ADMIN_UID, `来自用户 ${userName} 的消息:\n${text}`);
    }
    // 保存管理员消息ID与用户聊天ID的映射
    if (response && response.result && response.result.message_id) {
      const adminMessageId = response.result.message_id;
      await KV_NAMESPACE.put(`admin_message_${adminMessageId}`, chatId.toString());
    }
    await KV_NAMESPACE.put(`${USER_MESSAGES_KEY_PREFIX}${chatId}`, userMessageText);
    // 更新最后一个活跃的用户
    await KV_NAMESPACE.put(LAST_USER_KEY, chatId.toString());
  }
}

function apiUrl(methodName) {
  return `https://api.telegram.org/bot${TOKEN}/${methodName}`;
}

async function sendPlainText(chatId, text) {
  const response = await fetch(apiUrl('sendMessage'), {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ chat_id: chatId, text })
  });
  return response.json();
}

async function sendSticker(chatId, fileId) {
  const response = await fetch(apiUrl('sendSticker'), {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ chat_id: chatId, sticker: fileId })
  });
  return response.json();
}

async function sendPhoto(chatId, fileId, caption = '') {
  const response = await fetch(apiUrl('sendPhoto'), {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ chat_id: chatId, photo: fileId, caption })
  });
  return response.json();
}

async function sendVoice(chatId, fileId) {
  const response = await fetch(apiUrl('sendVoice'), {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ chat_id: chatId, voice: fileId })
  });
  return response.json();
}

async function sendDocument(chatId, fileId) {
  const response = await fetch(apiUrl('sendDocument'), {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ chat_id: chatId, document: fileId })
  });
  return response.json();
}

async function sendVideo(chatId, fileId) {
  const response = await fetch(apiUrl('sendVideo'), {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ chat_id: chatId, video: fileId })
  });
  return response.json();
}

async function sendLocation(chatId, latitude, longitude) {
  const response = await fetch(apiUrl('sendLocation'), {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ chat_id: chatId, latitude, longitude })
  });
  return response.json();
}

async function registerWebhook(event, requestUrl, suffix, secret) {
  const webhookUrl = `${requestUrl.protocol}//${requestUrl.hostname}${suffix}`;
  const response = await fetch(apiUrl('setWebhook'), {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ url: webhookUrl, secret_token: secret })
  });
  const r = await response.json();
  return new Response('ok' in r && r.ok ? 'Ok' : JSON.stringify(r, null, 2));
}

async function unRegisterWebhook(event) {
  const response = await fetch(apiUrl('setWebhook'), {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ url: '' })
  });
  const r = await response.json();
  return new Response('ok' in r && r.ok ? 'Ok' : JSON.stringify(r, null, 2));
}

可以看到上面的代码有三个变量 **你必须要更改的,分别是
ENV_BOT_SECRET ENV_BOT_TOKEN 和 ENV_ADMIN_UID**
worker设置
让我们一个个来,请转到 Worker设置——变量和机密——添加+
类型请选择 文本 ,变量名称就先是 ENV_BOT_SECRET
然后访问这个网站: https://www.uuidgenerator.net/ 然后点击生成一个uuid,填写到值里面去,这个任意uuid都行,不重要
然后重复步骤,添加变量 ENV_BOT_TOKEN ,去Telegram的Bot Father里: https://t.me/botfather 自己创建一个机器人,自己取username并命名,然后拿到Token 填到值里面,以后这个就是你的双向机器人了
最后再重复一次步骤,添加变量 ENV_ADMIN_UID ,这个就是你自己的uid了,不知道怎么获取的话用这个bot: https://t.me/GetIDcnBot
获取到的ID填写进值里面
最后,访问一下你的Worker URL,设置Webhook,填入你的Worker URL并在结尾加上/registerWebhook
例如:https://example.workers.dev/registerWebhook
页面返回OK字样设置就成功了
常见问题
其实Telegram上也有双向机器人,但我不推荐使用,因为上面的代码只是执行了简单逻辑让消息互通,并让每个聊天独立,如果可以的话,一些不怀好意的人完全可以直接在服务器上部署,然后写日志或者保存到数据库里,默认监听你所有的聊天,这样就没有隐私了,自己部署终归还是好一些的
另外和第三方TG客户端一样,一些坏双向机器人可能会在你给朋友转账的时候“掉包”收款地址、甚至收款二维码,这些只要想都能做到,所以还是很危险的
希望这篇教程对你有帮助!

0

评论 (0)

取消