📚 Termux 无root学习系列
阶段一:环境搭建与终端基础 ✅ 已完成
01-05 Termux 安装 → 包管理 → 文件管理 → Vim/tmux
阶段二:编程开发环境 ✅ 已完成
06-09 Python → C/C++ → Node.js → Git
阶段三:网络与远程操作 ✅ 已完成
10-12 SSH → 网络工具 → 代理与安全通信
阶段四:Termux:API 与自动化 ✅ 已完成
13-14 硬件调用 → 定时任务自动化
阶段五:proot-distro 完整 Linux ✅ 已完成
15-17 proot-distro → Jupyter → 桌面环境 VNC
阶段六:AI 与 AIGC 实战 ✅ 已完成
18-20 LLM API → llama.cpp 本地推理 → RAG 知识库
阶段七:安全工具实战 ✅ 已完成
21-23 信息收集 → sqlmap/hydra → 哈希破解与取证
阶段八:自托管服务与综合实战(进行中)
✓ 24 Gitea 私有 Git 服务器与静态站托管
25 Telegram Bot 开发部署(当前篇)
26 Web 爬虫与数据采集管道
阶段九:综合项目与运维(共 2 篇,后续持续更新)

25 Telegram Bot 开发部署

难度:高级 · 阶段八 自托管服务与综合实战 · 前序知识:Python + LLM API
读完本篇你将能:使用 python-telegram-bot v22.7 在 Termux 上开发 24 小时在线的 Telegram 机器人,掌握命令处理、内联按钮、文件传输、AI 对话、定时推送和远程命令执行等功能,并通过白名单机制和环境变量保障 Bot 安全运行。
📑 本文目录
01Bot 创建与基础配置
02python-telegram-bot 入门
03消息处理与命令系统
04内联按钮与回调查询
05实用 Bot 功能开发
06持久化运行与安全
07分级练习
08知识回顾与下一篇预告

01 Bot 创建与基础配置

开发 Telegram Bot 的第一步是通过官方的 BotFather 创建机器人并获取 API Token。这个 Token 是 Bot 的身份证,所有 API 调用都需要带上它。

1.1 通过 @BotFather 创建 Bot

1️⃣ 在 Telegram 中搜索 @BotFather 并开始对话
2️⃣ 发送 /newbot 命令,按提示输入 Bot 名称和用户名(用户名必须以 bot 结尾)
3️⃣ 创建成功后,BotFather 会返回一串 API Token,格式类似 123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11
4️⃣ 保存好这个 Token,后面写代码时要用

1.2 获取自己的 Chat ID

Bot 需要知道给谁发消息。你自己的 Chat ID 可以通过调用 getUpdates API 获取:

Termux
# 先给你的 Bot 随便发一条消息(如 /start)
# 然后调用 getUpdates 接口获取最近的消息
curl -s "https://api.telegram.org/bot<你的TOKEN>/getUpdates" | python3 -m json.tool

返回结果中找到 message.chat.id 字段,那个数字就是你的 Chat ID(通常是一串正整数)。

💡 小贴士
也可以用更简单的方式:搜索 @userinfobot,给它发条消息,它会直接返回你的 ID。Bot Token 和 Chat ID 是 Bot 开发中最重要的两个凭证,务必妥善保管。

1.3 安装 python-telegram-bot

在 Termux 原生环境或 proot Ubuntu 中都可以安装。推荐使用 v22.7 版本(2026 年 6 月最新稳定版),它基于 Python asyncio,完全异步:

Termux
# 安装最新版 python-telegram-bot
pip install python-telegram-bot==22.7
# 验证安装
python3 -c "import telegram; print(telegram.__version__)"
输出
22.7

02 python-telegram-bot 入门

从 v20 开始,python-telegram-bot 全面转向 asyncio 异步架构。这意味着所有 Handler 函数都要用 async def 定义,调用 Bot API 方法时要加 await。

2.1 第一个 Bot:回复 /start

先写一个最简 Bot,收到 /start 命令时回复欢迎消息:

bot.py
import os
from telegram import Update
from telegram.ext import ApplicationBuilder, CommandHandler, ContextTypes
# 从环境变量读取 Token(安全做法)
BOT_TOKEN = os.getenv("TELEGRAM_BOT_TOKEN")
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    """处理 /start 命令"""
    user = update.effective_user
    await update.message.reply_text(
        f"👋 你好 {user.first_name}!\n"
        "我是运行在 Termux 上的 Bot\n"
        "发送 /help 查看所有命令"
    )
def main() -> None:
    """启动 Bot"""
    application = ApplicationBuilder().token(BOT_TOKEN).build()
    # 注册命令处理器
    application.add_handler(CommandHandler("start", start))
    # 启动轮询模式(长连接接收消息)
    application.run_polling()
if __name__ == "__main__":
    main()

运行前先设置环境变量,避免把 Token 硬编码在代码里:

Termux
# 设置环境变量
export TELEGRAM_BOT_TOKEN="你的BotToken"
# 运行 Bot
python3 bot.py

Bot 启动后,在 Telegram 里给它发 /start,就能收到自动回复。按 Ctrl+C 可以停止 Bot。

⚠️ 常见错误
忘记加 await 直接调用 reply_text — v22 全是异步的,不加 await 不会报错但消息也发不出去,这是新手最常踩的坑
✓ 正确:所有调用 Bot API 的方法(send_message、reply_text 等)都必须加 await

03 消息处理与命令系统

Bot 的核心是「收到消息 → 做出响应」的闭环。除了斜杠命令,Bot 还能处理普通文本、图片、文件等各种消息类型。本节介绍常用的消息处理器。

3.1 常用 Handler 类型

Handler 用途 示例
CommandHandler 处理斜杠命令 /start /help
MessageHandler + filters 处理普通消息 文本、图片、文件、语音
CallbackQueryHandler 处理内联按钮点击 InlineKeyboardButton
ConversationHandler 多步对话流程 填表、向导式交互

3.2 添加更多命令

给 Bot 添加 /status 命令,用来查看 Termux 系统状态,以及 /echo 命令回显文字:

bot.py(新增部分)
import subprocess
from telegram.ext import MessageHandler, filters
async def status_cmd(update: Update, context: ContextTypes.DEFAULT_TYPE):
    """查看系统状态"""
    result = subprocess.run(["uptime"], capture_output=True, text=True)
    uptime_info = result.stdout.strip()
    await update.message.reply_text(f"📊 系统状态\n\n{uptime_info}")
async def echo_cmd(update: Update, context: ContextTypes.DEFAULT_TYPE):
    """回显命令参数"""
    text = " ".join(context.args) if context.args else "(没有输入内容)"
    await update.message.reply_text(f"🗣️ 你说:{text}")
async def handle_text(update: Update, context: ContextTypes.DEFAULT_TYPE):
    """处理普通文本消息(非命令)"""
    user_text = update.message.text
    await update.message.reply_text(
        f"收到你的消息:{user_text}\n"
        "发送 /help 查看可用命令"
    )
# 在 main() 中注册
application.add_handler(CommandHandler("status", status_cmd))
application.add_handler(CommandHandler("echo", echo_cmd))
application.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, handle_text))
💡 小贴士
Handler 的注册顺序很重要:越具体的 Handler 放越前面。MessageHandler 必须放在最后,否则它会先匹配到所有消息,导致后面的 CommandHandler 永远不会触发。用 ~filters.COMMAND 可以排除掉斜杠命令消息。

04 内联按钮与回调查询

内联按钮(Inline Keyboard)是 Bot 交互的核心组件,点击按钮会触发 CallbackQuery,Bot 收到后可以更新消息内容、弹出提示或执行操作。

4.1 发送带按钮的消息

用 InlineKeyboardMarkup 和 InlineKeyboardButton 构建按钮,每个按钮绑定一个 callback_data 作为回调标识:

bot.py(按钮示例)
from telegram import InlineKeyboardButton, InlineKeyboardMarkup
from telegram.ext import CallbackQueryHandler
async def menu_cmd(update: Update, context: ContextTypes.DEFAULT_TYPE):
    """发送主菜单(带按钮)"""
    keyboard = [
        [
            InlineKeyboardButton("📊 系统状态", callback_data="status"),
            InlineKeyboardButton("💾 磁盘使用", callback_data="disk"),
        ],
        [
            InlineKeyboardButton("🌐 天气查询", callback_data="weather"),
            InlineKeyboardButton("ℹ️ 关于", callback_data="about"),
        ],
    ]
    reply_markup = InlineKeyboardMarkup(keyboard)
    await update.message.reply_text(
        "🤖 主菜单\n选择一项功能:",
        reply_markup=reply_markup
    )

4.2 处理按钮回调

用户点击按钮后,Bot 会收到 CallbackQuery,需要用 CallbackQueryHandler 来处理。注意必须调用 answer_callback_query,否则按钮会一直显示加载状态:

bot.py(回调处理)
async def button_callback(update: Update, context: ContextTypes.DEFAULT_TYPE):
    """处理按钮点击回调"""
    query = update.callback_query
    await query.answer()  # 必须先回答回调
    data = query.data
    if data == "status":
        result = subprocess.run(["uptime"], capture_output=True, text=True)
        text = f"📊 系统状态\n\n{result.stdout.strip()}"
    elif data == "disk":
        result = subprocess.run(["df", "-h", "/data"], capture_output=True, text=True)
        text = f"💾 磁盘使用\n\n{result.stdout.strip()}"
    elif data == "about":
        text = "ℹ️ 关于\n\nTermux Bot v1.0\n运行于 Android Termux\npython-telegram-bot v22.7"
    else:
        text = "功能开发中..."
    await query.edit_message_text(text=text)  # 编辑原消息内容
# 在 main() 中注册
application.add_handler(CommandHandler("menu", menu_cmd))
application.add_handler(CallbackQueryHandler(button_callback))
💡 小贴士
edit_message_text 会原地修改消息内容(替换按钮菜单为结果),适合减少聊天记录刷屏。如果想保留原消息直接回复,用 query.message.reply_text()。

05 实用 Bot 功能开发

掌握基础后,来实现几个真正实用的功能:AI 对话助手、文件传输、定时推送消息。这些功能组合起来,就能打造一个强大的个人助手 Bot。

5.1 AI 对话助手

结合第 18 篇学过的 LLM API,给 Bot 加上 AI 对话能力。用户发消息,Bot 调用大模型 API 返回回答:

ai_bot.py
import os
from openai import AsyncOpenAI  # 异步客户端
from telegram import Update
from telegram.ext import ApplicationBuilder, CommandHandler, MessageHandler, filters, ContextTypes
BOT_TOKEN = os.getenv("TELEGRAM_BOT_TOKEN")
API_KEY = os.getenv("OPENAI_API_KEY")
BASE_URL = os.getenv("OPENAI_BASE_URL")
ADMIN_ID = int(os.getenv("ADMIN_CHAT_ID"))
client = AsyncOpenAI(api_key=API_KEY, base_url=BASE_URL)
conversation_history = {}  # 按用户ID保存对话历史
async def chat_with_ai(update: Update, context: ContextTypes.DEFAULT_TYPE):
    """与 AI 对话(仅管理员可用)"""
    user_id = update.effective_user.id
    if user_id != ADMIN_ID:
        await update.message.reply_text("❌ 无权限使用此功能")
        return
    user_text = update.message.text
    status_msg = await update.message.reply_text("🤔 思考中...")
    # 初始化或追加历史
    if user_id not in conversation_history:
        conversation_history[user_id] = []
    conversation_history[user_id].append({"role": "user", "content": user_text})
    try:
        response = await client.chat.completions.create(
            model="gpt-4o-mini",
            messages=conversation_history[user_id][-20:]  # 保留最近20条
        )
        ai_reply = response.choices[0].message.content
        conversation_history[user_id].append({"role": "assistant", "content": ai_reply})
        await status_msg.edit_text(ai_reply)
    except Exception as e:
        await status_msg.edit_text(f"❌ 出错:{str(e)}")

5.2 文件传输与下载

Bot 可以接收用户发来的文件并保存到 Termux,也能把 Termux 上的文件发送给用户。这是远程管理手机文件的便捷方式:

bot.py(文件功能)
from telegram.ext import MessageHandler, filters
import os
DOWNLOAD_DIR = "~/bot_downloads"
async def handle_document(update: Update, context: ContextTypes.DEFAULT_TYPE):
    """接收用户发来的文件并保存"""
    document = update.message.document
    file = await context.bot.get_file(document.file_id)
    save_path = os.path.expanduser(
        f"{DOWNLOAD_DIR}/{document.file_name}"
    )
    await file.download_to_drive(save_path)
    await update.message.reply_text(
        f"✅ 文件已保存到:{save_path}\n"
        f"大小:{document.file_size / 1024:.1f} KB"
    )
async def send_file_cmd(update: Update, context: ContextTypes.DEFAULT_TYPE):
    """发送指定路径的文件给用户"""
    if not context.args:
        await update.message.reply_text("用法:/sendfile <文件路径>")
        return
    file_path = os.path.expanduser(context.args[0])
    if os.path.exists(file_path):
        await context.bot.send_document(
            chat_id=update.effective_chat.id,
            document=file_path
        )
    else:
        await update.message.reply_text("❌ 文件不存在")

5.3 定时推送消息

利用 python-telegram-bot 的 JobQueue 可以实现定时任务,比如每天早上推送天气预报、定时提醒等。JobQueue 是内置的,无需额外安装:

bot.py(定时任务)
from telegram.ext import ContextTypes
import datetime
async def daily_reminder(context: ContextTypes.DEFAULT_TYPE):
    """每日定时提醒任务"""
    job = context.job
    now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M")
    await context.bot.send_message(
        chat_id=job.chat_id,
        text=f"⏰ 定时提醒\n\n现在时间:{now}\n"
            "记得喝水、休息眼睛哦~"
    )
async def set_reminder_cmd(update: Update, context: ContextTypes.DEFAULT_TYPE):
    """设置每小时提醒 /remind on | /remind off"""
    chat_id = update.effective_chat.id
    if not context.args:
        await update.message.reply_text("用法:/remind on 或 /remind off")
        return
    action = context.args[0]
    if action == "on":
        # 每 3600 秒(1小时)执行一次
        context.job_queue.run_repeating(
            daily_reminder, interval=3600, first=10, chat_id=chat_id
        )
        await update.message.reply_text("✅ 已开启每小时提醒")
    elif action == "off":
        current_jobs = context.job_queue.get_jobs_by_name("daily_reminder")
        for job in current_jobs:
            job.schedule_removal()
        await update.message.reply_text("❌ 已关闭提醒")
💡 JobQueue 常用方法
run_once 一次性任务
run_repeating 周期性任务(秒级间隔)
run_daily 每日定时任务(指定时间)
run_monthly 每月定时任务

06 持久化运行与安全

Bot 写好了,但手机屏幕一关、Termux 一进后台就被杀掉怎么办?本节讲如何让 Bot 24 小时稳定运行,以及如何做好安全防护,防止 Bot 被滥用。

6.1 tmux + termux-wake-lock 保活

最基础的保活方案:用 tmux 让 Bot 在后台会话中运行,再配合 termux-wake-lock 防止 CPU 休眠:

Termux
# 1. 安装 Termux:API(如未安装)
pkg install termux-api
# 2. 获取唤醒锁(防止 CPU 休眠)
termux-wake-lock
# 3. 创建 tmux 会话并运行 Bot
tmux new -s bot "python3 bot.py"
# 按 Ctrl+B 再按 D 分离会话(Bot 继续后台运行)
# 重新连接会话
tmux attach -t bot

6.2 termux-job-scheduler 定时保活

即使有 wake-lock,Android 系统在内存紧张时仍可能杀掉 Termux。用 termux-job-scheduler 可以每隔一段时间唤醒 Termux 并检查 Bot 是否还在运行,不在就重启:

bot_watchdog.sh
#!/data/data/com.termux/files/usr/bin/bash
BOT_SCRIPT="~/bot/bot.py"
BOT_TOKEN=$(cat ~/.bot_token)
LOG_FILE="~/bot/watchdog.log"
# 检查 Bot 进程是否存在
if pgrep -f "python3 bot.py" > /dev/null; then
    echo "$(date): Bot is running" >> $LOG_FILE
else
    echo "$(date): Bot not found, restarting..." >> $LOG_FILE
    cd ~/bot
    TELEGRAM_BOT_TOKEN=$BOT_TOKEN nohup python3 bot.py &
fi
Termux
# 设置定时任务:每 15 分钟执行一次看门狗脚本
termux-job-scheduler --script ~/bot/bot_watchdog.sh \
  --period-ms 900000 --network unmetered
# 查看已安排的任务
termux-job-scheduler --pending

6.3 安全防护要点

🔐 Token 安全:绝对不要把 Bot Token 硬编码在代码里或上传到 Git 仓库。用环境变量或独立配置文件(加入 .gitignore)管理。
👤 用户白名单:所有敏感操作(执行命令、查看文件、AI 对话)都要校验 user.id 是否在白名单中,防止陌生人滥用你的 Bot。
⚠️ 命令执行要谨慎:如果 Bot 有执行 shell 命令的功能(如 /shell),务必限制白名单用户,并对命令做过滤,禁止 rm -rf / 等危险操作。
📝 日志记录:给 Bot 加上日志功能,记录谁在什么时候发了什么命令,出问题时方便排查。
bot.py(白名单装饰器示例)
from functools import wraps
ALLOWED_USERS = {123456789, 987654321}  # 允许的用户ID集合
def admin_only(func):
    """管理员权限装饰器"""
    @wraps(func)
    async def wrapper(update: Update, context: ContextTypes.DEFAULT_TYPE):
        user_id = update.effective_user.id
        if user_id not in ALLOWED_USERS:
            await update.message.reply_text("🚫 无权限")
            return
        return await func(update, context)
    return wrapper
# 使用方式
@admin_only
async def shell_cmd(update: Update, context: ContextTypes.DEFAULT_TYPE):
    ...  # 只有白名单用户能执行

07 分级练习

⭐ 入门级(必做)
用 @BotFather 创建一个属于你自己的 Bot,记录好 Token 和 Chat ID。然后用 python-telegram-bot 写一个能回复 /start 和 /help 命令的最简 Bot,在 Termux 上跑起来并测试收发消息。
⭐⭐ 进阶级(建议完成)
给 Bot 添加内联按钮菜单,至少实现 3 个功能按钮(如系统状态、磁盘使用、关于),点击后能正确显示对应信息。同时实现文件上传下载功能——给 Bot 发一个文件,能保存到 Termux 指定目录。
⭐⭐⭐ 高手级(挑战一下)
实现完整的 AI 对话 Bot:接入 LLM API,支持多轮对话历史,使用白名单机制限制只有你自己能用。再加上定时推送功能(每天早上 8 点推送一条每日问候或天气预报),并用 tmux + termux-wake-lock 让 Bot 后台持续运行。

08 知识回顾与下一篇预告

📌 本篇知识要点

① BotFather 创建机器人 → 获取 Token → getUpdates 获取 Chat ID
② python-telegram-bot v22.7 全异步架构:async def + await
③ 四种核心 Handler:CommandHandler、MessageHandler、CallbackQueryHandler、ConversationHandler
④ 内联按钮:InlineKeyboardMarkup + InlineKeyboardButton,回调必须 answer()
⑤ 三大实用功能:AI 对话(AsyncOpenAI)、文件传输(get_file + send_document)、定时推送(JobQueue)
⑥ 持久化保活:tmux + termux-wake-lock + termux-job-scheduler 看门狗

📖 下一篇预告

26 Web 爬虫与数据采集管道
学完 Bot 开发,下一篇我们转向数据采集——用 Python 在 Termux 上构建 Web 爬虫。从 requests + BeautifulSoup 的基础爬虫,到 Scrapy 框架的进阶用法,再到数据清洗和管道化处理,把网上的公开数据变成你自己的结构化数据库。敬请期待!