自建 Telegram 图床机器人 + Cloudflare Pages 免费部署教程
无需服务器 永久免费运行
https://www.xiaoqikeji.com/index.php/archives/63/
🚀 自建 Telegram 图床机器人 + Cloudflare Pages 免费部署教程
本文教你 0 成本 搭建一个 Telegram 图床机器人,实现 图片自动上传 + 自定义域名,全部挂在 Cloudflare Pages 上,无需服务器,一次部署即可永久免费运行。🧩 项目介绍
这个项目的核心思路:
- 用户向 Telegram 机器人发送图片
- 机器人将图片转存到免费图床
111666.best
- 自动返回可直接外链的图片地址、Markdown 和 BBCode 链接
✅ 完全免费:Cloudflare Pages + 111666 图床
✅ 无服务器:Worker 脚本直接跑在 Cloudflare 上
✅ 可绑定自定义域名:轻松伪装为自己的图床⚡️ 准备工作
搭建前,你需要:
Telegram Bot Token
- 打开 @BotFather,输入
/newbot
创建机器人按提示取名后,BotFather 会返回
BOT_TOKEN
,形如:1234567890:ABCDEFxxxxxxx
图床 AUTH\_TOKEN
- 前往 https://111666.best/ 注册登录
- 在个人中心 → 获取 Auth-Token
Cloudflare 账号
- 用于部署 Pages(免费计划即可)
🔨 部署到 Cloudflare Pages
1️⃣ 创建 Pages 项目
- 登录 Cloudflare Dashboard
- 选择 Pages → 创建项目 → 直接上传
- 项目名称随意,例如:
telegram-image-bot
构建设置:
- 框架:无
- 构建命令:留空
- 输出目录:
/
- 上传一个空文件(例如
index.html
),完成初始化部署2️⃣ 部署机器人代码
Cloudflare Pages 支持 Functions,我们直接写 Worker 脚本。
进入 Functions → 编辑代码,将下列代码粘贴进去。版本一:默认图床版(无需自定义域名)
将以下代码命名为functions/index.js
,替换 BOT\_TOKEN 和 AUTH\_TOKEN 后直接保存即可。// Created by rocket, improved by ChatGPT // Original: https://www.nodeseek.com/post-170862-1 const TELEGRAM_BOT_TOKEN = '替换成你的bot_token'; const AUTH_TOKEN = '替换成你的Auth-Token'; const TELEGRAM_API_URL = `https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}`; const IMAGE_UPLOAD_URL = 'https://i.111666.best/image'; export default { async fetch(request) { const url = new URL(request.url); // 手动设置 Webhook if (url.pathname === '/setWebhook') { const webhookUrl = `${url.protocol}//${url.host}/webhook`; const webhookResponse = await setWebhook(webhookUrl); return webhookResponse.ok ? new Response(`Webhook set to ${webhookUrl}`) : new Response(`Failed: ${JSON.stringify(webhookResponse)}`, { status: 500 }); } // 接收 Telegram 消息 if (url.pathname === '/webhook' && request.method === 'POST') { try { const update = await request.json(); const chatId = update.message?.chat?.id; if (!chatId) return new Response('No chat', { status: 200 }); // 用户发送文本 if (update.message.text) { await sendMessage(chatId, '请发给我一张图片'); return new Response('Asked for image', { status: 200 }); } // 用户发送图片 if (update.message.photo) { await sendMessage(chatId, '图片收到,正在上传中...'); const photoArray = update.message.photo; const fileId = photoArray[photoArray.length - 1].file_id; const fileUrl = await getFileUrl(fileId); const uploadResponse = await uploadImage(fileUrl); if (uploadResponse.ok) { const imageUrl = `https://i.111666.best${uploadResponse.src}`; await sendImageMessage(chatId, imageUrl); } else { await sendMessage(chatId, '图片上传失败,请稍后再试。'); } return new Response('Processed', { status: 200 }); } } catch (err) { console.error("Webhook error:", err); return new Response('Error', { status: 500 }); } } return new Response('Not Found', { status: 404 }); } }; // 发送文本 async function sendMessage(chatId, text) { await fetch(`${TELEGRAM_API_URL}/sendMessage`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ chat_id: chatId, text }) }); } // 发送图片+链接 async function sendImageMessage(chatId, imageUrl) { const markdownLink = ``; const bbcodeLink = `[img]${imageUrl}[/img]`; const message = `<b>Direct Link</b>\n<pre>${imageUrl}</pre>\n\n<b>Markdown</b>\n<pre>${markdownLink}</pre>\n\n<b>BBCode</b>\n<pre>${bbcodeLink}</pre>`; await fetch(`${TELEGRAM_API_URL}/sendPhoto`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ chat_id: chatId, photo: imageUrl, caption: message, parse_mode: "HTML" }) }); } async function getFileUrl(fileId) { const res = await fetch(`${TELEGRAM_API_URL}/getFile?file_id=${fileId}`); const data = await res.json(); const path = data.result.file_path; return `https://api.telegram.org/file/bot${TELEGRAM_BOT_TOKEN}/${path}`; } async function uploadImage(url) { const img = await fetch(url); const blob = await img.blob(); const formData = new FormData(); formData.append('image', blob, 'image.jpg'); const res = await fetch(IMAGE_UPLOAD_URL, { method: 'POST', headers: { 'Auth-Token': AUTH_TOKEN }, body: formData }); const result = await res.json(); return res.ok && result.ok ? { ok: true, src: result.src } : { ok: false }; } async function setWebhook(webhookUrl) { const res = await fetch(`${TELEGRAM_API_URL}/setWebhook`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ url: webhookUrl }) }); return res.json(); }
要先手动访问一次 /setWebhook
3️⃣ 绑定自定义域名(可选)
如果你想让图片链接显示为自己的域名,例如
https://img.xxx.com/image/xxx.jpg
,需要 两段代码:(1) Bot Worker(返回自定义域名链接)
与默认版类似,但加上
CUSTOM_DOMAIN
:// Bot Worker const TELEGRAM_BOT_TOKEN = '替换成你的bot_token'; const AUTH_TOKEN = '替换成你的Auth-Token'; const TELEGRAM_API_URL = `https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}`; const IMAGE_UPLOAD_URL = 'https://i.111666.best/image'; const CUSTOM_DOMAIN = 'https://更改为自己的域名'; export default { async fetch(request) { const url = new URL(request.url); // 设置 Webhook if (url.pathname === '/setWebhook') { const webhookUrl = `${url.protocol}//${url.host}/webhook`; const webhookResponse = await setWebhook(webhookUrl); if (webhookResponse.ok) { return new Response(`Webhook set successfully to ${webhookUrl}`, { status: 200 }); } else { return new Response(`Failed to set webhook: ${JSON.stringify(webhookResponse)}`, { status: 500 }); } } // 接收 Telegram Webhook if (url.pathname === '/webhook' && request.method === 'POST') { try { const update = await request.json(); if (update.message) { const chatId = update.message.chat.id; if (update.message.text) { await sendMessage(chatId, '请发给我一张图片'); return new Response('Asked for image', { status: 200 }); } if (update.message.photo) { await sendMessage(chatId, '图片收到,正在上传中...'); const photoArray = update.message.photo; const fileId = photoArray[photoArray.length - 1].file_id; const fileUrl = await getFileUrl(fileId); const uploadResponse = await uploadImage(fileUrl); if (uploadResponse.ok) { // ✅ 返回自定义域名 let imageUrl = `${CUSTOM_DOMAIN}${uploadResponse.src}`; await sendImageMessage(chatId, imageUrl); return new Response('Image processed and uploaded', { status: 200 }); } else { await sendMessage(chatId, '图片上传失败,请稍后再试。'); return new Response('Upload failed', { status: 500 }); } } } return new Response('No message found', { status: 200 }); } catch (err) { console.error("Webhook error:", err); return new Response('Error processing request', { status: 500 }); } } return new Response('Not found', { status: 404 }); } }; // ------------------- Helper Functions ------------------- async function sendMessage(chatId, text) { await fetch(`${TELEGRAM_API_URL}/sendMessage`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ chat_id: chatId, text }) }); } async function sendImageMessage(chatId, imageUrl) { const markdownLink = ``; const bbcodeLink = `[img]${imageUrl}[/img]`; const messageText = `<b>Direct Link</b>\n<pre>${imageUrl}</pre>\n\n<b>Markdown</b>\n<pre>${markdownLink}</pre>\n\n<b>BBCode</b>\n<pre>${bbcodeLink}</pre>`; await fetch(`${TELEGRAM_API_URL}/sendPhoto`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ chat_id: chatId, photo: imageUrl, caption: messageText, parse_mode: "HTML" }) }); } async function getFileUrl(fileId) { const res = await fetch(`${TELEGRAM_API_URL}/getFile?file_id=${fileId}`); const data = await res.json(); if (!data.ok) throw new Error("Failed to get file path"); const filePath = data.result.file_path; return `https://api.telegram.org/file/bot${TELEGRAM_BOT_TOKEN}/${filePath}`; } async function uploadImage(imageUrl) { const imageResponse = await fetch(imageUrl); const buffer = await imageResponse.arrayBuffer(); const blob = new Blob([buffer]); const formData = new FormData(); formData.append('image', blob, 'image.jpg'); const res = await fetch(IMAGE_UPLOAD_URL, { method: 'POST', headers: { 'Auth-Token': AUTH_TOKEN }, body: formData }); const result = await res.json(); if (res.ok && result.ok) { return { ok: true, src: result.src }; } else { console.error("Upload failed:", result); return { ok: false }; } } async function setWebhook(webhookUrl) { const res = await fetch(`${TELEGRAM_API_URL}/setWebhook`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ url: webhookUrl }) }); return res.json(); }
(2) 反代 Worker(转发图片请求)
将下列代码部署到同一个 Pages 项目,用来代理
111666.best
图片:export default { async fetch(request) { const url = new URL(request.url); if (url.pathname.startsWith("/image/")) { const target = `https://i.111666.best${url.pathname}`; const res = await fetch(target, { headers: { "Referer": "https://i.111666.best/", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0 Safari/537.36" } }); const buffer = await res.arrayBuffer(); return new Response(buffer, { status: res.status, headers: { "Content-Type": res.headers.get("Content-Type") || "image/jpeg", "Cache-Control": "public, max-age=86400", "Content-Disposition": "inline", "Access-Control-Allow-Origin": "*" } }); } return new Response("Not Found", { status: 404 }); } }
然后在 Cloudflare → DNS 中:
添加 CNAME:
img CNAME xxx.pages.dev
- 打开 SSL/TLS → 选择 灵活模式
🕹 启动机器人
部署完成后,在浏览器访问一次:
https://你的Pages域名/setWebhook
返回
Webhook set successfully
表示绑定成功。之后,直接给机器人发送图片,就能自动获得:
- ✅ Direct Link:图片直链
- ✅ Markdown:可用于博客、GitHub
- ✅ BBCode:适用于论坛发帖
💡 实际效果
功能 说明 速度 CF 全球加速,访问飞快 存储 依托 111666 图床,图片长期稳定 成本 0 元搭建,0 元维护 已构建机器人:https://t.me/xiaoqituchuangbot
通过 Cloudflare Pages + Telegram Bot + 免费图床,你可以 零成本 搭建一个全球加速的个人图床,且支持 自定义域名,完美适配博客/论坛/笔记场景。
如果对你有帮助,不妨收藏/分享,让更多人告别付费图床! 🚀