Cloudflare 的 worker 运行 telegram bot 自动回复关键字 将回复的消息延迟删除
前言
在群里搞了一个关键字回复机器人. Github 上面大把的项目. 略.
但是一直没有自动延迟删除回复消息的功能.
我的概念里面 worker 是 http 请求时才会运行的, 也就是说, 有人在群里发了消息, 这个worker才会运行. 那自然就做不了延迟删除消息了.
灵感
今天突发奇想, 问了一下AI, "cloudflare 的 worker 怎么实现定时任务".
WOKAO, 原来2022年官方就支持了 Cron Trigger
接下来就是无趣的面向GPT开发
粘贴 的代码是一个基于 cloudflare worker 的 telegram bot.我要实现bot回复的消息延迟5~10分钟删除的功能.我给这个 worker 绑定了一个 KV : BOT_MSG, 用于保存发出的消息的数据.我给这个 worker 设置了定时5分钟的 cron trigger.请改进这段代码
贴一下代码吧.
const TOKEN = 'your_bot_token'const WEBHOOK = '/endpoint'const SECRET = 'you_should_generate_random_string'const DELETE_AFTER_MS = 5 * 60 * 1000 // 5分钟/*** 将已发送的消息存入 KV* key: msg:{delete_at}:{chat_id}:{message_id}*/async function saveMessage(env, chatId, messageId) {const deleteAt = String(Date.now() + DELETE_AFTER_MS).padStart(16, '0')const key = `msg:${deleteAt}:${chatId}:${messageId}`await env.BOT_MSG.put(key, '1', {expirationTtl: 20 * 60 // 20分钟兜底清理})}/*** Cron 触发:删除所有到期的消息*/async function handleScheduled(env) {const now = Date.now()const { keys } = await env.BOT_MSG.list({ prefix: 'msg:' })for (const { name } of keys) {// key 格式: msg:{delete_at}:{chat_id}:{message_id}const [, deleteAt, chatId, messageId] = name.split(':')if (parseInt(deleteAt) <= now) {await deleteMessage(chatId, messageId)await env.BOT_MSG.delete(name)}}}/*** 调用 Telegram API 删除消息*/async function deleteMessage(chatId, messageId) {return (await fetch(apiUrl('deleteMessage', {chat_id: chatId,message_id: messageId}))).json()}// ─── Export ────export default {async fetch(request, env, ctx) {const url = new URL(request.url)if (url.pathname === WEBHOOK) {return handleWebhook(request, env)} else if (url.pathname === '/registerWebhook') {return registerWebhook(url, WEBHOOK, SECRET)} else if (url.pathname === '/unRegisterWebhook') {return unRegisterWebhook()} else {return new Response('No handler for this request')}},async scheduled(event, env, ctx) {ctx.waitUntil(handleScheduled(env))}}// ─── Webhook ────async function handleWebhook(request, env) {if (request.headers.get('X-Telegram-Bot-Api-Secret-Token') !== SECRET) {return new Response('Unauthorized', { status: 403 })}const update = await request.json()await onUpdate(update, env)return new Response('Ok')}async function onUpdate(update, env) {if ('message' in update) {await onMessage(update.message, env)}}// ─── Message Handler ────async function onMessage(message, env) {const text = message.text.toLowerCase();const originalText = message.text;// 检测英文关键词const hasHappy = text.includes('happy');const hasNew = text.includes('new');const hasYear = text.includes('year');if (hasHappy && hasNew && hasYear) {const result = await sendPlainText(message.chat.id, 'Happy New Year to you, too! 🎁', message.message_id);if (result?.ok && result?.result?.message_id) {await saveMessage(env, message.chat.id, result.result.message_id)}return;}// 检测中文关键字const has新 = originalText.includes('新');const has年 = originalText.includes('年');const has快 = originalText.includes('快');const has乐 = originalText.includes('乐');if (has新 && has年 && has快 && has乐) {const result = await sendPlainText(message.chat.id, '也祝你新年快乐! 🧧', message.message_id);if (result?.ok && result?.result?.message_id) {await saveMessage(env, message.chat.id, result.result.message_id)}return;}// 233群的 脚本 关键字const has脚本 = originalText.includes('脚本');if (has脚本) {const replyText = `安装 sing-box 脚本 (第一次运行默认就安装 Reality 协议):<code>bash <(wget -qO- -o- https://github.com/233boy/sing-box/raw/main/install.sh)</code>安装 Xray 脚本 (第一次运行默认就安装 Reality 协议):<code>bash <(wget -qO- -o- https://github.com/233boy/Xray/raw/main/install.sh)</code><tg-spoiler>安装 V2Ray 脚本 (不要用 第一次运行默认装出来的 VMESS+TCP):bash <(wget -qO- -o- https://github.com/233boy/v2ray/raw/master/install.sh)</tg-spoiler>`;const result = await sendPlainText(message.chat.id, replyText, message.message_id);if (result?.ok && result?.result?.message_id) {await saveMessage(env, message.chat.id, result.result.message_id)}return;}}// ─── Telegram API Helpers ────async function sendPlainText(chatId, text, replyToMessageId = null) {return (await fetch(apiUrl('sendMessage', {chat_id: chatId,text,reply_to_message_id: replyToMessageId,parse_mode: 'HTML'}))).json()}async function registerWebhook(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() {const r = await (await fetch(apiUrl('setWebhook', { url: '' }))).json()return new Response('ok' in r && r.ok ? 'Ok' : JSON.stringify(r, null, 2))}function apiUrl(methodName, params = null) {let query = ''if (params) {query = '?' + new URLSearchParams(params).toString()}return `https://api.telegram.org/bot${TOKEN}/${methodName}${query}`}
========
后记
本次用到的GPT是
评论
发表评论