实施指南
技术研究 人工智能 Telegram
1. 在 Telegram 中搜索 2. 发送 命令 3. 按提示输入 Bot 名称(如 My Deploy Bot) 4. 输入 Bot 用户名(必须以 结尾,如 ) 5. 保存返回的 Bot Token(格式:)
前置条件
在开始实施之前,请确保已准备以下内容:
- Telegram 账号 - 用于创建和管理 Bot
- GitHub 账号 - 拥有目标仓库的管理权限
- Cloudflare 账号 - 免费注册,用于部署 Worker
- GitHub Personal Access Token - 具有
actions:write权限
步骤 1:创建 Telegram Bot
1.1 通过 BotFather 创建 Bot
- 在 Telegram 中搜索
@BotFather - 发送
/newbot命令 - 按提示输入 Bot 名称(如 “My Deploy Bot”)
- 输入 Bot 用户名(必须以
bot结尾,如mydeploy_bot) - 保存返回的 Bot Token(格式:
123456789:ABCdefGHIjklMNOpqrsTUVwxyz)
1.2 配置 Slash Commands
发送 /setcommands 给 BotFather,然后输入:
deploy - 部署应用到指定环境
build - 触发构建工作流
status - 查看最近工作流状态
help - 显示帮助信息
这将启用 Telegram 的自动补全菜单,提升用户体验。
1.3 获取 Chat ID
需要获取允许使用命令的 Chat ID:
- 将 Bot 添加到目标群组或频道
- 群组中发送任意消息
- 访问:
https://api.telegram.org/bot<YOUR_BOT_TOKEN>/getUpdates - 从 JSON 响应中找到
chat.id字段
安全提示:记录 Chat ID 时,注意区分:
- 个人聊天:正数(如
123456789) - 群组:负数(如
-123456789) - 超级群组/频道:以
-100开头(如-1001234567890)
步骤 2:准备 GitHub 环境
2.1 创建 GitHub Token
- 访问 GitHub Settings → Developer settings → Personal access tokens → Fine-grained tokens
- 点击 “Generate new token”
- 设置 Token 名称(如 “Telegram Bot Integration”)
- 选择 “Only select repositories”,勾选目标仓库
- 权限设置:
- Actions: Read and write
- Contents: Read-only
- 点击生成并立即复制 Token(只显示一次)
2.2 创建 Actions 工作流
在目标仓库创建 .github/workflows/deploy.yml:
name: Deploy via Telegram
on:
workflow_dispatch:
inputs:
environment:
description: '目标环境'
required: true
type: choice
options:
- staging
- production
default: 'staging'
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup environment
run: |
echo "Starting deployment to ${{ github.event.inputs.environment }}"
- name: Run deployment
run: |
# 替换为你的部署脚本
echo "Deploying..."
sleep 5 # 模拟部署
echo "Deployment complete!"
- name: Notify Telegram
if: always()
uses: appleboy/telegram-action@master
with:
to: ${{ secrets.TELEGRAM_CHAT_ID }}
token: ${{ secrets.TELEGRAM_BOT_TOKEN }}
format: markdown
message: |
📦 *Deployment ${{ job.status == 'success' && '✅ Succeeded' || '❌ Failed' }}*
• Environment: `${{ github.event.inputs.environment }}`
• Commit: `${{ github.sha }}`
• Branch: `${{ github.ref_name }}`
• Actor: ${{ github.actor }}
[View Run](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})
2.3 配置 GitHub Secrets
在仓库 Settings → Secrets and variables → Actions 中添加:
| Secret Name | Value |
|---|---|
TELEGRAM_BOT_TOKEN | 步骤 1 获取的 Bot Token |
TELEGRAM_CHAT_ID | 步骤 1 获取的 Chat ID |
步骤 3:部署 Cloudflare Worker
3.1 安装 Wrangler CLI
npm install -g wrangler
wrangler login
3.2 创建 Worker 项目
mkdir telegram-github-webhook
cd telegram-github-webhook
wrangler init --yes
3.3 编写 Worker 代码
编辑 src/index.js:
export default {
async fetch(request, env, ctx) {
const url = new URL(request.url);
if (url.pathname === '/webhook' && request.method === 'POST') {
return handleWebhook(request, env);
}
if (url.pathname === '/health') {
return new Response('OK', { status: 200 });
}
return new Response('Not Found', { status: 404 });
}
};
async function handleWebhook(request, env) {
// 验证 Webhook Secret
const secretToken = request.headers.get('X-Telegram-Bot-Api-Secret-Token');
if (secretToken !== env.WEBHOOK_SECRET) {
console.log('Invalid secret token');
return new Response('Unauthorized', { status: 401 });
}
let update;
try {
update = await request.json();
} catch (e) {
return new Response('Invalid JSON', { status: 400 });
}
// 验证消息
if (!update.message || !update.message.text) {
return new Response('OK');
}
const text = update.message.text.trim();
const chatId = update.message.chat.id;
// 权限检查
const allowedChats = env.ALLOWED_CHAT_IDS ? env.ALLOWED_CHAT_IDS.split(',') : [];
if (allowedChats.length > 0 && !allowedChats.includes(chatId.toString())) {
await sendMessage(env.BOT_TOKEN, chatId, '⛔ 未授权的用户');
return new Response('OK');
}
// 解析命令
if (!text.startsWith('/')) {
return new Response('OK');
}
const parts = text.slice(1).split(' ');
const command = parts[0];
const args = parts.slice(1);
// 路由命令
switch (command) {
case 'deploy':
return handleDeploy(chatId, args, env);
case 'build':
return handleBuild(chatId, args, env);
case 'status':
return handleStatus(chatId, env);
case 'help':
case 'start':
return handleHelp(chatId, env);
default:
await sendMessage(env.BOT_TOKEN, chatId, '❓ 未知命令,发送 /help 查看帮助');
return new Response('OK');
}
}
async function handleDeploy(chatId, args, env) {
const environment = args[0] || 'staging';
if (!['staging', 'production'].includes(environment)) {
await sendMessage(env.BOT_TOKEN, chatId, '❌ 环境参数错误。可用选项:staging, production');
return new Response('OK');
}
await sendMessage(env.BOT_TOKEN, chatId, `🚀 正在触发 ${environment} 环境部署...`);
try {
const response = await triggerGitHubWorkflow(env, 'deploy.yml', { environment });
if (response.ok) {
await sendMessage(env.BOT_TOKEN, chatId, `✅ 部署已触发!环境:*${environment}*\n稍后会收到完成通知。`);
} else {
const error = await response.text();
await sendMessage(env.BOT_TOKEN, chatId, `❌ 触发失败:${error}`);
}
} catch (error) {
console.error('Deploy error:', error);
await sendMessage(env.BOT_TOKEN, chatId, `❌ 错误:${error.message}`);
}
return new Response('OK');
}
async function handleBuild(chatId, args, env) {
await sendMessage(env.BOT_TOKEN, chatId, '🔨 正在触发构建...');
try {
const response = await triggerGitHubWorkflow(env, 'build.yml', {});
if (response.ok) {
await sendMessage(env.BOT_TOKEN, chatId, '✅ 构建已触发!');
} else {
const error = await response.text();
await sendMessage(env.BOT_TOKEN, chatId, `❌ 触发失败:${error}`);
}
} catch (error) {
console.error('Build error:', error);
await sendMessage(env.BOT_TOKEN, chatId, `❌ 错误:${error.message}`);
}
return new Response('OK');
}
async function handleStatus(chatId, env) {
await sendMessage(env.BOT_TOKEN, chatId, '请直接在 GitHub 查看工作流状态。');
return new Response('OK');
}
async function handleHelp(chatId, env) {
const helpText = `
🤖 *GitHub Actions Bot 帮助*
可用命令:
\/deploy [environment] - 部署应用
示例:\/deploy staging
示例:\/deploy production
\/build - 触发构建工作流
\/status - 查看状态(开发中)
\/help - 显示此帮助
`;
await sendMessage(env.BOT_TOKEN, chatId, helpText);
return new Response('OK');
}
async function triggerGitHubWorkflow(env, workflowFile, inputs) {
const url = `https://api.github.com/repos/${env.GITHUB_OWNER}/${env.GITHUB_REPO}/actions/workflows/${workflowFile}/dispatches`;
return fetch(url, {
method: 'POST',
headers: {
'Authorization': `Bearer ${env.GITHUB_TOKEN}`,
'Accept': 'application/vnd.github+json',
'X-GitHub-Api-Version': '2022-11-28',
'Content-Type': 'application/json'
},
body: JSON.stringify({
ref: 'main',
inputs: inputs
})
});
}
async function sendMessage(token, chatId, text) {
try {
await fetch(`https://api.telegram.org/bot${token}/sendMessage`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
chat_id: chatId,
text: text,
parse_mode: 'Markdown'
})
});
} catch (error) {
console.error('Send message error:', error);
}
}
3.4 配置环境变量
编辑 wrangler.toml:
name = "telegram-github-webhook"
main = "src/index.js"
compatibility_date = "2024-01-01"
[vars]
GITHUB_OWNER = "your-github-username"
GITHUB_REPO = "your-repo-name"
ALLOWED_CHAT_IDS = "123456789,-123456789" # 允许的 Chat ID,逗号分隔
# Secrets(通过 wrangler secret put 设置,不要写在文件中)
# BOT_TOKEN
# GITHUB_TOKEN
# WEBHOOK_SECRET
3.5 部署并设置 Secrets
# 部署 Worker
wrangler deploy
# 设置 Secrets(交互式输入,不会显示在命令历史中)
wrangler secret put BOT_TOKEN
# 输入:你的 Telegram Bot Token
wrangler secret put GITHUB_TOKEN
# 输入:你的 GitHub Fine-grained Token
wrangler secret put WEBHOOK_SECRET
# 输入:随机生成的密钥(至少 20 位字符)
3.6 记录 Worker URL
部署完成后,记录 Worker 的 URL:
https://telegram-github-webhook.your-subdomain.workers.dev
步骤 4:配置 Telegram Webhook
使用 curl 命令设置 Webhook:
curl -X POST "https://api.telegram.org/bot<YOUR_BOT_TOKEN>/setWebhook" \
-H "Content-Type: application/json" \
-d '{
"url": "https://telegram-github-webhook.your-subdomain.workers.dev/webhook",
"secret_token": "<YOUR_WEBHOOK_SECRET>",
"max_connections": 40
}'
验证 Webhook 状态:
curl "https://api.telegram.org/bot<YOUR_BOT_TOKEN>/getWebhookInfo"
步骤 5:测试验证
5.1 基础测试
- 在 Telegram 中向 Bot 发送
/help - 应收到帮助信息
5.2 部署测试
- 发送
/deploy staging - 应收到确认消息:“部署已触发”
- 前往 GitHub Actions 页面,确认工作流已启动
- 等待工作流完成,确认收到 Telegram 通知
5.3 错误场景测试
- 发送未知命令:应提示帮助信息
- 从非授权 Chat ID 发送:应提示未授权
- 部署到不存在的环境:应提示参数错误
故障排查
问题 1:收不到消息
检查清单:
- Webhook URL 是否正确设置?
- Worker URL 是否可访问?(访问
https://your-worker/health) - Cloudflare Workers 日志是否有错误?(
wrangler tail)
问题 2:GitHub API 返回 404
可能原因:
- 仓库名称或所有者拼写错误
- 工作流文件路径错误
- GitHub Token 权限不足
问题 3:GitHub API 返回 422
可能原因:
- 工作流文件不存在于默认分支
inputs参数与工作流定义不匹配
问题 4:Telegram 消息发送失败
检查点:
- Bot Token 是否正确
- Chat ID 是否有效
- 消息格式是否符合 Markdown 规范
安全加固建议
-
定期轮换 Token
- GitHub Token:每 90 天更换一次
- Telegram Bot Token:如泄露立即通过 BotFather 撤销
-
限制 IP 访问
- 在 Worker 中添加 Telegram IP 白名单验证
- Telegram Bot API 的 IP 范围:官方文档
-
审计日志
- 启用 Cloudflare Workers Analytics
- 记录所有命令执行日志
下一步扩展
- 添加更多命令(如
/rollback、/logs) - 集成 Cloudflare KV 存储命令历史
- 添加工作流状态轮询,主动推送结果
- 支持多仓库管理
参考资料
- Wrangler CLI Documentation - Wrangler 官方文档
- GitHub Actions Workflow Syntax - 工作流语法参考
- Telegram Bot API - Webhook - Webhook 配置 API
- appleboy/telegram-action - Actions 通知插件