音乐播放器
星霜的笔记
 
文章 标签
41

Powered by Gridea | Theme: Fog
载入天数...
载入时分秒...
总访问量:  |   访问人数:

Cloudflare 搭建 TG 私聊机器人

源码LloydAsp/nfd: No Fraud / Node Forward Bot

特点

  • 基于 Workers 搭建,只要你的配额够,CF 不拉闸,那么就不存在跑路的问题。
  • 0 成本,连域名都不需要。
  • 接入反欺诈系统,当聊天对象有诈骗历史时,自动发出提醒。
  • 支持屏蔽用户,避免被骚扰。

搭建方法

首先去 @BotFather 创建一个新机器人,获取一个 API KEY(Token)。
然后使用 /setjoingroups 命令禁止机器人被添加到群组。
找一个获取 UUID 的网站,随机获取一个 UUID。
使用 @userinfobot 获取你的 TGID(或者 username_to_id_bot)。
然后前往 Cloudflare 控制台,创建一个示例 Workers。
然后在设置中添加环境变量。

  • ENV_BOT_TOKEN 变量,值为 Bot 的 Token
  • ENV_BOT_SECRET 变量,值为 UUID
  • ENV_ADMIN_UID 变量,值为 TGID

新建一个名字叫做 nfd 的 KV 数据库然后绑定 nfd = nfd。
回到上面,快速编辑里面编辑代码。

代码一

本文件 内容全部复制即可。
修改后保存并部署即可。
然后访问 https://demoworkers.dev/registerWebhook 注册 WebSoket 即可。
使用方法

  • 当其他用户给 bot 发消息,会被转发到 bot 创建者
  • 用户回复普通文字给转发的消息时,会回复到原消息发送者
  • 用户回复/block, /unblock, /checkblock 等命令会执行相关指令,不会回复到原消息发送者

代码二

 <span role="presentation">const TOKEN = ENV_BOT_TOKEN // Get it from @BotFather</span>
 <span role="presentation">const WEBHOOK = '/endpoint'</span>
 <span role="presentation">const SECRET = ENV_BOT_SECRET // A-Z, a-z, 0-9, _ and -</span>
 <span role="presentation">const ADMIN_UID = ENV_ADMIN_UID // your user id, get it from https://t.me/username_to_id_bot</span>
 <span role="presentation">​</span>
 <span role="presentation">const NOTIFY_INTERVAL = 3600 * 1000;</span>
 <span role="presentation">const fraudDb = 'https://raw.githubusercontent.com/LloydAsp/nfd/main/data/fraud.db';</span>
 <span role="presentation">const notificationUrl = 'https://raw.githubusercontent.com/LloydAsp/nfd/main/data/notification.txt'</span>
 <span role="presentation">const startMsgUrl = 'https://raw.githubusercontent.com/LloydAsp/nfd/main/data/startMessage.md';</span>
 <span role="presentation">​</span>
 <span role="presentation">const enable_notification = true</span>
 <span role="presentation">/**</span>
 <span role="presentation"> * Return url to telegram api, optionally with parameters added</span>
 <span role="presentation"> */</span>
 <span role="presentation">function apiUrl (methodName, params = null) {</span>
 <span role="presentation">  let query = ''</span>
 <span role="presentation">  if (params) {</span>
 <span role="presentation">    query = '?' + new URLSearchParams(params).toString()</span>
 <span role="presentation">  }</span>
 <span role="presentation">  return `https://api.telegram.org/bot${TOKEN}/${methodName}${query}`</span>
 <span role="presentation">}</span>
 <span role="presentation">​</span>
 <span role="presentation">function requestTelegram(methodName, body, params = null){</span>
 <span role="presentation">  return fetch(apiUrl(methodName, params), body)</span>
 <span role="presentation">    .then(r => r.json())</span>
 <span role="presentation">}</span>
 <span role="presentation">​</span>
 <span role="presentation">function makeReqBody(body){</span>
 <span role="presentation">  return {</span>
 <span role="presentation">    method:'POST',</span>
 <span role="presentation">    headers:{</span>
 <span role="presentation">      'content-type':'application/json'</span>
 <span role="presentation">    },</span>
 <span role="presentation">    body:JSON.stringify(body)</span>
 <span role="presentation">  }</span>
 <span role="presentation">}</span>
 <span role="presentation">​</span>
 <span role="presentation">function sendMessage(msg = {}){</span>
 <span role="presentation">  return requestTelegram('sendMessage', makeReqBody(msg))</span>
 <span role="presentation">}</span>
 <span role="presentation">​</span>
 <span role="presentation">function copyMessage(msg = {}){</span>
 <span role="presentation">  return requestTelegram('copyMessage', makeReqBody(msg))</span>
 <span role="presentation">}</span>
 <span role="presentation">​</span>
 <span role="presentation">function forwardMessage(msg){</span>
 <span role="presentation">  return requestTelegram('forwardMessage', makeReqBody(msg))</span>
 <span role="presentation">}</span>
 <span role="presentation">​</span>
 <span role="presentation">/**</span>
 <span role="presentation"> * Wait for requests to the worker</span>
 <span role="presentation"> */</span>
 <span role="presentation">addEventListener('fetch', event => {</span>
 <span role="presentation">  const url = new URL(event.request.url)</span>
 <span role="presentation">  if (url.pathname === WEBHOOK) {</span>
 <span role="presentation">    event.respondWith(handleWebhook(event))</span>
 <span role="presentation">  } else if (url.pathname === '/registerWebhook') {</span>
 <span role="presentation">    event.respondWith(registerWebhook(event, url, WEBHOOK, SECRET))</span>
 <span role="presentation">  } else if (url.pathname === '/unRegisterWebhook') {</span>
 <span role="presentation">    event.respondWith(unRegisterWebhook(event))</span>
 <span role="presentation">  } else {</span>
 <span role="presentation">    event.respondWith(new Response('No handler for this request'))</span>
 <span role="presentation">  }</span>
 <span role="presentation">})</span>
 <span role="presentation">​</span>
 <span role="presentation">/**</span>
 <span role="presentation"> * Handle requests to WEBHOOK</span>
 <span role="presentation"> * https://core.telegram.org/bots/api#update</span>
 <span role="presentation"> */</span>
 <span role="presentation">async function handleWebhook (event) {</span>
 <span role="presentation">  // Check secret</span>
 <span role="presentation">  if (event.request.headers.get('X-Telegram-Bot-Api-Secret-Token') !== SECRET) {</span>
 <span role="presentation">    return new Response('Unauthorized', { status: 403 })</span>
 <span role="presentation">  }</span>
 <span role="presentation">​</span>
 <span role="presentation">  // Read request body synchronously</span>
 <span role="presentation">  const update = await event.request.json()</span>
 <span role="presentation">  // Deal with response asynchronously</span>
 <span role="presentation">  event.waitUntil(onUpdate(update))</span>
 <span role="presentation">​</span>
 <span role="presentation">  return new Response('Ok')</span>
 <span role="presentation">}</span>
 <span role="presentation">​</span>
 <span role="presentation">/**</span>
 <span role="presentation"> * Handle incoming Update</span>
 <span role="presentation"> * https://core.telegram.org/bots/api#update</span>
 <span role="presentation"> */</span>
 <span role="presentation">async function onUpdate (update) {</span>
 <span role="presentation">  if ('message' in update) {</span>
 <span role="presentation">    await onMessage(update.message)</span>
 <span role="presentation">  }</span>
 <span role="presentation">}</span>
 <span role="presentation">​</span>
 <span role="presentation">/**</span>
 <span role="presentation"> * Handle incoming Message</span>
 <span role="presentation"> * https://core.telegram.org/bots/api#message</span>
 <span role="presentation"> */</span>
 <span role="presentation">async function onMessage (message) {</span>
 <span role="presentation">  if(message.text === '/start'){</span>
 <span role="presentation">    let startMsg = await fetch(startMsgUrl).then(r => r.text())</span>
 <span role="presentation">    return sendMessage({</span>
 <span role="presentation">      chat_id:message.chat.id,</span>
 <span role="presentation">      text:startMsg,</span>
 <span role="presentation">    })</span>
 <span role="presentation">  }</span>
 <span role="presentation">  if(message.chat.id.toString() === ADMIN_UID){</span>
 <span role="presentation">    if(!message?.reply_to_message?.chat){</span>
 <span role="presentation">      return sendMessage({</span>
 <span role="presentation">        chat_id:ADMIN_UID,</span>
 <span role="presentation">        text:'使用方法,回复转发的消息,并发送回复消息,或者`/block`、`/unblock`、`/checkblock`等指令'</span>
 <span role="presentation">      })</span>
 <span role="presentation">    }</span>
 <span role="presentation">    if(/^\/block$/.exec(message.text)){</span>
 <span role="presentation">      return handleBlock(message)</span>
 <span role="presentation">    }</span>
 <span role="presentation">    if(/^\/unblock$/.exec(message.text)){</span>
 <span role="presentation">      return handleUnBlock(message)</span>
 <span role="presentation">    }</span>
 <span role="presentation">    if(/^\/checkblock$/.exec(message.text)){</span>
 <span role="presentation">      return checkBlock(message)</span>
 <span role="presentation">    }</span>
 <span role="presentation">    let guestChantId = await nfd.get('msg-map-' + message?.reply_to_message.message_id,</span>
 <span role="presentation">                                      { type: "json" })</span>
 <span role="presentation">    return copyMessage({</span>
 <span role="presentation">      chat_id: guestChantId,</span>
 <span role="presentation">      from_chat_id:message.chat.id,</span>
 <span role="presentation">      message_id:message.message_id,</span>
 <span role="presentation">    })</span>
 <span role="presentation">  }</span>
 <span role="presentation">  return handleGuestMessage(message)</span>
 <span role="presentation">}</span>
 <span role="presentation">​</span>
 <span role="presentation">async function handleGuestMessage(message){</span>
 <span role="presentation">  let chatId = message.chat.id;</span>
 <span role="presentation">  let isblocked = await nfd.get('isblocked-' + chatId, { type: "json" })</span>
 <span role="presentation">  </span>
 <span role="presentation">  if(isblocked){</span>
 <span role="presentation">    return sendMessage({</span>
 <span role="presentation">      chat_id: chatId,</span>
 <span role="presentation">      text:'Your are blocked'</span>
 <span role="presentation">    })</span>
 <span role="presentation">  }</span>
 <span role="presentation">​</span>
 <span role="presentation">  let forwardReq = await forwardMessage({</span>
 <span role="presentation">    chat_id:ADMIN_UID,</span>
 <span role="presentation">    from_chat_id:message.chat.id,</span>
 <span role="presentation">    message_id:message.message_id</span>
 <span role="presentation">  })</span>
 <span role="presentation">  console.log(JSON.stringify(forwardReq))</span>
 <span role="presentation">  if(forwardReq.ok){</span>
 <span role="presentation">    await nfd.put('msg-map-' + forwardReq.result.message_id, chatId)</span>
 <span role="presentation">  }</span>
 <span role="presentation">  return handleNotify(message)</span>
 <span role="presentation">}</span>
 <span role="presentation">​</span>
 <span role="presentation">async function handleNotify(message){</span>
 <span role="presentation">  // 先判断是否是诈骗人员,如果是,则直接提醒</span>
 <span role="presentation">  // 如果不是,则根据时间间隔提醒:用户id,交易注意点等</span>
 <span role="presentation">  let chatId = message.chat.id;</span>
 <span role="presentation">  if(await isFraud(chatId)){</span>
 <span role="presentation">    return sendMessage({</span>
 <span role="presentation">      chat_id: ADMIN_UID,</span>
 <span role="presentation">      text:`检测到骗子,UID${chatId}`</span>
 <span role="presentation">    })</span>
 <span role="presentation">  }</span>
 <span role="presentation">  if(enable_notification){</span>
 <span role="presentation">    let lastMsgTime = await nfd.get('lastmsg-' + chatId, { type: "json" })</span>
 <span role="presentation">    if(!lastMsgTime || Date.now() - lastMsgTime > NOTIFY_INTERVAL){</span>
 <span role="presentation">      await nfd.put('lastmsg-' + chatId, Date.now())</span>
 <span role="presentation">      return sendMessage({</span>
 <span role="presentation">        chat_id: ADMIN_UID,</span>
 <span role="presentation">        text:await fetch(notificationUrl).then(r => r.text())</span>
 <span role="presentation">      })</span>
 <span role="presentation">    }</span>
 <span role="presentation">  }</span>
 <span role="presentation">}</span>
 <span role="presentation">​</span>
 <span role="presentation">async function handleBlock(message){</span>
 <span role="presentation">  let guestChantId = await nfd.get('msg-map-' + message.reply_to_message.message_id,</span>
 <span role="presentation">                                      { type: "json" })</span>
 <span role="presentation">  if(guestChantId === ADMIN_UID){</span>
 <span role="presentation">    return sendMessage({</span>
 <span role="presentation">      chat_id: ADMIN_UID,</span>
 <span role="presentation">      text:'不能屏蔽自己'</span>
 <span role="presentation">    })</span>
 <span role="presentation">  }</span>
 <span role="presentation">  await nfd.put('isblocked-' + guestChantId, true)</span>
 <span role="presentation">​</span>
 <span role="presentation">  return sendMessage({</span>
 <span role="presentation">    chat_id: ADMIN_UID,</span>
 <span role="presentation">    text: `UID:${guestChantId}屏蔽成功`,</span>
 <span role="presentation">  })</span>
 <span role="presentation">}</span>
 <span role="presentation">​</span>
 <span role="presentation">async function handleUnBlock(message){</span>
 <span role="presentation">  let guestChantId = await nfd.get('msg-map-' + message.reply_to_message.message_id,</span>
 <span role="presentation">  { type: "json" })</span>
 <span role="presentation">​</span>
 <span role="presentation">  await nfd.put('isblocked-' + guestChantId, false)</span>
 <span role="presentation">​</span>
 <span role="presentation">  return sendMessage({</span>
 <span role="presentation">    chat_id: ADMIN_UID,</span>
 <span role="presentation">    text:`UID:${guestChantId}解除屏蔽成功`,</span>
 <span role="presentation">  })</span>
 <span role="presentation">}</span>
 <span role="presentation">​</span>
 <span role="presentation">async function checkBlock(message){</span>
 <span role="presentation">  let guestChantId = await nfd.get('msg-map-' + message.reply_to_message.message_id,</span>
 <span role="presentation">  { type: "json" })</span>
 <span role="presentation">  let blocked = await nfd.get('isblocked-' + guestChantId, { type: "json" })</span>
 <span role="presentation">​</span>
 <span role="presentation">  return sendMessage({</span>
 <span role="presentation">    chat_id: ADMIN_UID,</span>
 <span role="presentation">    text: `UID:${guestChantId}` + (blocked ? '被屏蔽' : '没有被屏蔽')</span>
 <span role="presentation">  })</span>
 <span role="presentation">}</span>
 <span role="presentation">​</span>
 <span role="presentation">/**</span>
 <span role="presentation"> * Send plain text message</span>
 <span role="presentation"> * https://core.telegram.org/bots/api#sendmessage</span>
 <span role="presentation"> */</span>
 <span role="presentation">async function sendPlainText (chatId, text) {</span>
 <span role="presentation">  return sendMessage({</span>
 <span role="presentation">    chat_id: chatId,</span>
 <span role="presentation">    text</span>
 <span role="presentation">  })</span>
 <span role="presentation">}</span>
 <span role="presentation">​</span>
 <span role="presentation">/**</span>
 <span role="presentation"> * Set webhook to this worker's url</span>
 <span role="presentation"> * https://core.telegram.org/bots/api#setwebhook</span>
 <span role="presentation"> */</span>
 <span role="presentation">async function registerWebhook (event, requestUrl, suffix, secret) {</span>
 <span role="presentation">  // https://core.telegram.org/bots/api#setwebhook</span>
 <span role="presentation">  const webhookUrl = `${requestUrl.protocol}//${requestUrl.hostname}${suffix}`</span>
 <span role="presentation">  const r = await (await fetch(apiUrl('setWebhook', { url: webhookUrl, secret_token: secret }))).json()</span>
 <span role="presentation">  return new Response('ok' in r && r.ok ? 'Ok' : JSON.stringify(r, null, 2))</span>
 <span role="presentation">}</span>
 <span role="presentation">​</span>
 <span role="presentation">/**</span>
 <span role="presentation"> * Remove webhook</span>
 <span role="presentation"> * https://core.telegram.org/bots/api#setwebhook</span>
 <span role="presentation"> */</span>
 <span role="presentation">async function unRegisterWebhook (event) {</span>
 <span role="presentation">  const r = await (await fetch(apiUrl('setWebhook', { url: '' }))).json()</span>
 <span role="presentation">  return new Response('ok' in r && r.ok ? 'Ok' : JSON.stringify(r, null, 2))</span>
 <span role="presentation">}</span>
 <span role="presentation">​</span>
 <span role="presentation">async function isFraud(id){</span>
 <span role="presentation">  id = id.toString()</span>
 <span role="presentation">  let db = await fetch(fraudDb).then(r => r.text())</span>
 <span role="presentation">  let arr = db.split('\n').filter(v => v)</span>
 <span role="presentation">  console.log(JSON.stringify(arr))</span>
 <span role="presentation">  let flag = arr.filter(v => v === id).length !== 0</span>
 <span role="presentation">  console.log(flag)</span>
 <span role="presentation">  return flag</span>
 <span role="presentation">}</span>

修改后保存并部署即可。
然后访问 https://demo.demo.workers.dev/UUID 注册 WebSoket 即可。
私聊机器人,各项功能运行正常即可。