环境要求
- Python 3.10 ~ 3.13(推荐 3.11;3.14 不支持,pyrogram 会因
asyncio.get_event_loop()变更报错) - 系统依赖:
ffmpeg(上传前重新编码视频,不装就只能重命名) - Python 依赖:
pyrogram==2.0.106、TgCrypto(强烈建议,不装慢 3~10 倍)、Pillow(图片重编码)、qrcode(扫码登录,可选)、flask(可选的健康页)
# Debian / Ubuntu
apt update && apt install -y python3 python3-venv ffmpeg
# CentOS / Rocky / Alma
dnf install -y python3 python3-pip ffmpeg准备凭据
- API ID / API HASH:打开 https://my.telegram.org →
API development tools创建应用。 - Bot Token:找 @BotFather 发送
/newbot,得到123456789:AAE...。 - 机器人头像(可选):BotFather 发送
/setuserpic,上传仓库里的img/1.png
(Telegram 不允许通过 API 修改机器人头像,只能这样设置;网页首页会自动显示该图)。
变量说明
环境变量优先于 config.json,二者选其一即可。
| 变量 | 必填 | 说明 |
|---|---|---|
TOKEN | 是 | @BotFather 的机器人 Token |
ID | 是 | my.telegram.org 的 api_id(纯数字) |
HASH | 是 | my.telegram.org 的 api_hash |
OWNER_ID | 建议填 | 管理员用户 ID(纯数字,单个);默认只有这个人能用机器人 |
ALLOW_PUBLIC | 否 | true 时对所有人公开可用;默认 false(只服务 OWNER_ID) |
PUBLIC_MAX_FILE_SIZE | 否 | 非管理员用户单个文件的大小上限(单位 MB);默认 0 = 不限制 |
MAX_RANGE | 否 | 单个链接最多处理条数,默认 100,0 为不限 |
DELAY | 否 | 每条之间的间隔秒数,默认 3 |
PROXY | 否 | 代理,如 socks5://user:pass@host:port(机房 IP 登录易被风控,建议配住宅代理) |
ALBUM_WORKERS | 否 | 相册并发下载数,默认 3(1 = 串行) |
RELAY_MODE | 否 | auto(默认,先转发再复制)/ forward / copy / off |
TEMP_MAX_AGE | 否 | 临时文件最长保留秒数,默认 3600 |
CLEANUP_INTERVAL | 否 | 定时清理间隔秒数,默认 1800 |
TRANSCODE_MODE | 否 | 上传前是否重新编码媒体以改变文件哈希,默认 true |
VIDEO_CRF | 否 | 视频重编码质量,默认 24(越小越清晰、文件越大) |
IMAGE_QUALITY | 否 | 图片重存 JPEG 质量,默认 92 |
TRANSCODE_TIMEOUT | 否 | 单个文件转码超时秒数,默认 3600 |
DEVICE_PROFILE | 否 | 设备指纹模式:auto(默认,按用户 ID 确定性选机型)/ random |
DEVICE_MODEL | 否 | 留空 = 从画像池选;填写则强制使用该机型 |
SYSTEM_VERSION | 否 | 同上,例如 SDK 34 |
APP_VERSION | 否 | 同上,例如 11.2.3 (5274) |
LANG_CODE | 否 | Telegram 语言包代码,例如 zh-hans |
SYSTEM_LANG_CODE | 否 | 系统语言,例如 zh-CN |
键名大小写不敏感(Allow_Public、allow_public都能识别)。
config.json 示例(仓库里的模板已清空密钥,填好即可用):
{
"TOKEN": "123456789:AAE...",
"ID": "1234567",
"HASH": "abcdef0123456789abcdef0123456789",
"OWNER_ID": "123456789",
"ALLOW_PUBLIC": false,
"PUBLIC_MAX_FILE_SIZE": 0,
"MAX_RANGE": 100,
"DELAY": 3
}部署
项目放到哪个目录都可以(/opt、/home/xxx、/root都行),
下面用<APP_DIR>表示你实际放项目的绝对路径。部署前先在项目目录里执行一次pwd确认。
本地 / 服务器(虚拟环境)
# 1) 把代码放到你想放的位置(已经放好了就直接 cd 进去)
mkdir -p /home/tgbot && cd /home/tgbot
git clone https://github.com/lhl77/Save-Restricted-Bot.git
cd Save-Restricted-Bot
# 2) 记住这个绝对路径,后面 supervisor 要用
pwd
# 例如输出 /home/tgbot/Save-Restricted-Bot,那 <APP_DIR> 就是这个
# 3) 创建虚拟环境并安装依赖
python3.12 -m venv .venv312 # 3.10 ~ 3.13 均可
.venv312/bin/pip install -U pip
.venv312/bin/pip install -r requirements.txt如果没有python3.10-python3.13可以运行:
# 1) 安装 uv 并让当前终端能找到它:
curl -LsSf https://astral.sh/uv/install.sh | sh
export PATH="$HOME/.local/bin:$PATH"
# 2) 安装python3.12,安装虚拟环境并安装依赖
uv python install 3.12
uv venv --python 3.12 .venv312
uv pip install --python .venv312/bin/python -r requirements.txt
# 3) 激活虚拟环境
source .venv312/bin/activate
python --version前台直接启动(-u 关闭缓冲,日志实时输出):
cd <APP_DIR> # 换成你刚才 pwd 出来的目录
.venv312/bin/python -u main.py用 Supervisor 常驻运行(推荐)
先在项目目录里打印出可直接复制的两行配置值:
# 在当前终端里先 cd 到项目目录,然后执行:
APP_DIR=$(pwd)
echo "directory=$APP_DIR"
echo "command=$APP_DIR/.venv312/bin/python -u main.py"新建 /etc/supervisor/conf.d/save-restricted-bot.conf,把上面输出的两行填进去
(<APP_DIR> 必须替换成真实绝对路径,不能写 ~ 或相对路径):
[program:save-restricted-bot]
directory=<APP_DIR>
command=<APP_DIR>/.venv312/bin/python -u main.py
user=root
autostart=true
autorestart=true
startsecs=10
startretries=3
stopsignal=TERM
stopasgroup=true
killasgroup=true
redirect_stderr=true
stdout_logfile=/var/log/save-restricted-bot.log
stdout_logfile_maxbytes=10MB
stdout_logfile_backups=5
; 环境变量(二选一:这里写,或者直接填 config.json)
environment=TOKEN="123456789:AAE...",ID="1234567",HASH="abcdef0123456789abcdef0123456789",OWNER_ID="123456789"如果你的配置写在 config.json 里,把 environment= 这一行删掉即可。
生效与日常管理:
sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl status save-restricted-bot
sudo supervisorctl restart save-restricted-bot
tail -f /var/log/save-restricted-bot.log注意事项:
directory必须是项目根目录,command里的 python 路径也必须是该项目里的 venv,
两者任一写错 supervisor 会直接FATAL;- 用户登录后的会话写在项目目录的
sessions.json中,不要把工作目录放在会被清空的临时目录; redirect_stderr=true会把异常也写进同一个日志,排查更方便;- 只想看机器人是否在跑:
sudo supervisorctl status save-restricted-bot(RUNNING即正常); - 启动失败先看日志:
tail -n 50 /var/log/save-restricted-bot.log,
最常见原因是用了~、相对路径或 venv 目录名不对; 如需网页首页(
app.py),再加一段:[program:save-restricted-bot-web] directory=<APP_DIR> command=<APP_DIR>/.venv312/bin/python -u app.py environment=PORT="8000" autostart=true autorestart=true redirect_stderr=true stdout_logfile=/var/log/save-restricted-bot-web.log
Docker
docker build -t save-restricted-bot .
docker run -d --name srb \
-e TOKEN=... -e ID=... -e HASH=... -e OWNER_ID=... \
-v "$(pwd)/sessions.json:/app/sessions.json" \
save-restricted-botsessions.json不存在时先touch sessions.json再挂载,避免被创建成目录。
启动日志会依次打印:版本号、权限模式(仅管理员 / 公开)、会话数量、
TgCrypto 检测、非管理员单文件上限、机器人账号、命令同步结果。
使用流程
- 直接发链接即可:公开频道不需要登录,机器人会自己转发/复制。
遇到私有群组 / 受限内容 / 机器人不在其中的会话时,先绑定账号再重发链接:
/login→ 弹出两个按钮:「手机号登录」/「扫码登录」- 扫码登录(推荐,完全不需要验证码):
/login qr→ 手机 Telegram → 设置 → 设备 → 连接设备 → 扫二维码。
二维码过期才原地刷新(不会刷屏);账号在别的数据中心(DC)时会自动切换并提示。 - 手机号登录:
/login phone→ 发送+8613800138000→ 验证码 →(如有)两步验证密码。
验证码可能是 Telegram App 内消息(官方账号发的那条)也可能是短信,机器人会告诉你去看哪里;
建议一位一位加空格输入(例如1 2 3 4 5),避免被 Telegram 当成复制粘贴而拦截。 - 或
/login <会话字符串>直接使用已有 session string(发送后机器人会自动删除该消息)。
/id查看自己的用户 ID,/logout解绑并删除会话,/cancel取消进行中的登录。- 邀请链接
https://t.me/+xxxx可让你的会话加入该群,之后再发消息链接。
支持的链接格式
| 类型 | 示例 |
|---|---|
| 公开频道 / 群组 | https://t.me/username/123 |
| 私有频道 / 群组 | https://t.me/c/3568041317/1331 |
| 论坛话题(新群组) | https://t.me/c/3568041317/1/1331?single |
| 评论区(下载评论本身) | https://t.me/username/123?comment=456 |
| 机器人聊天 | https://t.me/b/botusername/4321 |
| 批量 | https://t.me/username/1001-1010 |
| 邀请链接 | https://t.me/+AbCdEfGhIjK |
一条消息可发多个链接,按顺序处理;链接后紧跟文字或标点也能识别。
相册发任意一条的链接即可整组发送,带 ?single 只发这一条。
验证码一直提示失效?
如果手机收到 Telegram 通知「Incomplete login attempt … this code was previously shared」,
说明 验证码本身是对的,但 Telegram 判定它“被分享过”,于是直接作废。
最常见的原因是把「Login code」消息转发到了别处(包括转发给机器人)。
正确做法:
- 不要转发、不要截图,看数字后手动敲出来(逐位加空格更安全);
- 删掉之前转发的消息;
- 等 10~30 分钟再试(越连续重试风控越严);
- 还是不行就直接用扫码登录,这条路径不经过验证码。
权限与公开使用
机器人默认只服务 OWNER_ID 本人,没有多用户白名单。
| 配置 | 效果 |
|---|---|
OWNER_ID 已填,ALLOW_PUBLIC: false(默认) | 只有管理员本人能用,其他人收到「这个机器人只供管理员本人使用」 |
ALLOW_PUBLIC: true | 对所有人公开可用 |
OWNER_ID 未填且非公开 | 拒绝所有人(启动日志会告警) |
限制别人的下载量
公开模式下可以限制非管理员用户的单文件大小:
{
"ALLOW_PUBLIC": true,
"PUBLIC_MAX_FILE_SIZE": 50
}- 单位 MB,
0(默认)= 不限制; OWNER_ID本人不受这个限制,设成 1 MB 你也能下 2 GB 的文件;- 超限时机器人会在下载之先就拒绝,不会白消耗流量;相册里只要有一个文件超限就整组跳过。
ID 格式
OWNER_ID:单个用户 ID,纯数字,不带@,也不能写用户名。"OWNER_ID": "123456789"- 怎么拿到自己的 ID:给机器人发送
/id,它会回复你的用户 ID:123456789,
并告诉你当前是「管理员」还是「公开模式」; - 修改后重启机器人生效。
安全提示
说明:被转发进机器人会话的消息不会被再次处理(避免“转发→再转发”的循环);如需处理请直接发送链接文本。
sessions.json里是完整账号凭证(等同于手机登录态),文件权限已设为 600 且已加入.gitignore,请勿泄露或提交。config.json里有TOKEN与api_hash,填好真实密钥后不要提交到仓库;
令牌泄露请立即到 @BotFather/revoke重新生成。ALLOW_PUBLIC: true会让任何人都能用你的机器人。如果服务器带宽/账号资源有限,
建议同时用PUBLIC_MAX_FILE_SIZE限制单文件大小,或保持默认的仅管理员模式。- 公开模式下会话仍然按用户隔离:每个人
/login绑定的是自己的账号,
只能下载自己有权访问的内容。 - 建议使用小号登录;
/logout会从服务器删除该会话。 - 机器人运行在机房 IP 时,登录更容易触发 Telegram 风控,建议配置
PROXY(住宅代理)。 - 本工具仅供个人备份自己有权访问的内容,请遵守 Telegram 服务条款与当地法律。
本文章采用 CC BY-NC-SA 4.0 协议授权,转载请注明来源。
文章名称:Telegram 受限内容转发机器人文档 - 中文增强版 by LHL
文章链接:https://blog.lhl.one/artical/1365.html