本地启动请优先看 LOCAL_SETUP.md。这个文档只讲本地安装、登录、启动和验证,已忽略 Docker。
这个项目基于 Telegram 用户账号会话和 Telethon,把 bot 菜单操作包装成可供外部系统调用的 HTTP API,并支持本地运行、后台运行和 Docker 部署。
当前支持的内部业务动作:
⚡️ Plus直充🚀 Pro 20x直充💰 查余额/进度🎟 兑换卡密⬅️ 返回
- 首次手动登录 Telegram,会话保存到本地
.session - 前台启动 API 服务,便于调试和看日志
- 后台启动 API 服务,适合 Windows 本机长期常驻
- Docker 前台常驻运行,适合服务器或面板部署
- API Key 鉴权
- 串行队列执行 Telegram 流程,避免并发请求导致对话串台
- 可配置队列上限,队满后直接拒绝新请求
- 支持独立取消接口,直接发送
⬅️ 返回 - 支持按
requestId查询任务状态与最终结果 - 支持每日定时自动兑换固定卡密
main.pyCLI 入口,支持serve、login、daemonapi_server.pyFastAPI 接口层telegram_service.pyTelegram 会话、消息监听与消息发送workflow_service.py激活、查询余额、兑换卡密工作流job_queue.py串行任务队列config.example.json配置模板
uv sync先复制配置模板:
Copy-Item .\config.example.json .\config.json然后填写这些关键字段:
api_idapi_hashphonebot_usernameproxyapi.api_key
api.hostAPI 监听地址,默认127.0.0.1api.portAPI 监听端口,默认8000api.api_key外部调用接口时使用的鉴权密钥api.queue_max_size最大等待队列长度,当前正在执行的任务不计入这里scheduled_redeem.enabled是否启用每日定时兑换任务scheduled_redeem.card_code定时兑换时自动提交的固定卡密scheduled_redeem.times每日执行时间列表,使用HH:MM格式,按服务所在机器本地时区计算workflow.prompt_timeout_seconds等待 bot 返回“请输入 accessToken / 卡密”提示的超时时间workflow.result_timeout_seconds提交 accessToken 或卡密后等待最终结果的超时时间workflow.back_text流程结束后用于返回主菜单的文本,默认⬅️ 返回
如果你不想把真实 API Key 写进配置文件,也可以使用环境变量:
$env:GPT_BOT_API_KEY = "replace_with_your_api_key"当 config.json 里的 api.api_key 为空时,程序会自动读取 GPT_BOT_API_KEY。
"scheduled_redeem": {
"enabled": true,
"card_code": "SHARED-1D8286F94F66",
"times": [
"00:00",
"00:05"
]
}说明:
- 启用后,服务会在每日指定时间自动执行与
POST /api/v1/redeem等价的兑换工作流 - 定时任务会复用现有串行队列,因此不会和手动 API 请求并发串台
首次运行时,需要先完成 Telegram 登录授权。你可以直接用主入口:
uv run .\main.py如果当前本地还没有授权会话,启动过程中会要求输入:
- 登录验证码
- 二次验证密码,如果账号开启了 2FA
你也可以显式执行登录命令:
uv run .\main.py login --config .\config.json登录成功后,会在当前目录生成本地会话文件,例如:
gpt_bot_session.session
前台运行,适合调试:
uv run .\main.py serve --config .\config.json如果你省略 serve,默认也会进入前台服务模式:
uv run .\main.py --config .\config.json后台运行命令:
uv run .\main.py daemon start --config .\config.json查看状态:
uv run .\main.py daemon status --config .\config.json停止后台服务:
uv run .\main.py daemon stop --config .\config.json后台运行时会使用:
- PID 文件:
.runtime/gpt-bot.pid - 日志文件:
.runtime/gpt-bot.log
Docker 方案默认把运行数据放到容器内的 /data 目录。你只需要把本地 ./data 挂载进去,就能同时持久化:
config.json.session会话文件.runtime日志和 PID 文件
New-Item -ItemType Directory -Force .\data
Copy-Item .\config.example.json .\data\config.json
Copy-Item .\.env.example .\.env然后编辑:
.\data\config.json.\.env
建议做法:
data/config.json里可以把api.api_key留空- 真实 API Key 放到
.env的GPT_BOT_API_KEY
docker build -t gpt-bot .首次必须先登录一次,生成 Telegram 会话文件:
docker compose run --rm -it gpt-bot login --config /data/config.json登录成功后,会话文件会写到本地 .\data\ 目录。
docker compose up -d查看日志:
docker compose logs -f gpt-bot停止服务:
docker compose down镜像默认执行:
uv run python main.py serve --config /data/config.json --non-interactive --host 0.0.0.0说明:
- 容器内不建议使用
daemon - 容器场景直接前台运行即可,由 Docker 负责拉起和重启
--non-interactive会阻止服务模式下弹出交互登录,所以首次一定要先执行login
如果你本地没有 Docker 环境,可以直接使用仓库里的 GitHub Actions 自动构建镜像。
工作流文件:
.github/workflows/docker-publish.yml
触发方式:
- 推送到
main或master - 推送
v*标签 - 在 GitHub Actions 页面手动点
Run workflow
镜像会被发布到:
ghcr.io/你的GitHub用户名/你的仓库名
例如你的仓库是 https://github.com/foo/gpt-bot,镜像地址就是:
ghcr.io/foo/gpt-bot:latest
- 把当前项目代码 push 到 GitHub。
- 打开仓库的
Actions页面。 - 等待
Publish Docker Image工作流执行完成。 - 到仓库右侧或个人主页的
Packages查看镜像。 - 如果你想让别人无需登录直接拉取,把这个 package 改成
Public。
如果镜像是公开的,别人可以直接拉取:
docker pull ghcr.io/你的GitHub用户名/你的仓库名:latest如果镜像是私有的,需要先登录:
docker login ghcr.io
docker pull ghcr.io/你的GitHub用户名/你的仓库名:latest别人拉到镜像后,可以这样运行:
docker run -d \
--name gpt-bot \
-p 8000:8000 \
-e GPT_BOT_API_KEY=your_api_key \
-v $(pwd)/data:/data \
ghcr.io/你的GitHub用户名/你的仓库名:latest首次登录仍然需要交互式执行一次:
docker run --rm -it \
-v $(pwd)/data:/data \
ghcr.io/你的GitHub用户名/你的仓库名:latest \
login --config /data/config.json如果你本地配置写的是:
{
"proxy": {
"enabled": true,
"addr": "127.0.0.1",
"port": 7890
}
}那么在 Docker 里通常不能直接使用宿主机的 127.0.0.1。Windows 和 Docker Desktop 常见做法是把代理地址改成:
host.docker.internal
例如:
{
"proxy": {
"enabled": true,
"proxy_type": "http",
"addr": "host.docker.internal",
"port": 7890
}
}这些文件不要提交到仓库:
config.json*.session*.session-journal.env.runtime/.venv/
当前仓库已经通过 .gitignore 和 .dockerignore 处理了这些常见敏感文件。
推荐上传的文件包括:
main.pyapi_server.pytelegram_service.pyworkflow_service.pyjob_queue.pyapp_config.pyschemas.pypyproject.tomluv.lockDockerfiledocker-compose.yml.dockerignoreconfig.example.json.env.exampleREADME.md
所有业务接口都需要 API Key。
推荐请求头:
X-API-Key: your_api_key也支持:
Authorization: Bearer your_api_keyPOST /api/v1/activate/plus
Content-Type: application/json
X-API-Key: your_api_key请求体:
{
"accessToken": "your_access_token"
}内部流程:
- 发送
⚡️ Plus直充 - 等待
请发送 accessToken 或付款链接 - 发送
accessToken - 等待处理结果
POST /api/v1/activate/*结束时不立即发送⬅️ 返回- 只要已收到“已收到请求 / 处理中 / 请稍候”等中间态消息,接口就立即返回
requestId - 具体激活状态通过
GET /api/v1/requests/{requestId}查询 - 当首次查询到该
requestId已进入终态时,服务会触发一次⬅️ 返回用于把菜单复原
POST /api/v1/activate/team
Content-Type: application/json
X-API-Key: your_api_key请求体:
{
"accessToken": "your_access_token"
}内部流程与 plus 激活一致,只是入口按钮不同。
补充说明:
- 只要 accessToken 已发送且收到“已收到请求 / 处理中 / 请稍候”等中间态消息,激活接口就立即返回
state: running、success: true、status: processing - 如果首个响应已经拿到终态结果,接口会直接返回对应
state,成功场景通常是state: completed - 除处理中提示外,其余未识别消息一律直接按失败返回,通常表现为
success: false、status: unknown - 具体激活状态请使用返回的
requestId调用GET /api/v1/requests/{requestId}查询
GET /api/v1/balance
X-API-Key: your_api_key内部流程:
- 发送
💰 查余额/进度 - 等待余额结果
- 返回余额文本
POST /api/v1/redeem
Content-Type: application/json
X-API-Key: your_api_key请求体:
{
"cardCode": "your_card_code"
}内部流程:
- 发送
🎟 兑换卡密 - 等待
请发送卡密 - 发送卡密参数
- 等待兑换结果
- 自动发送
⬅️ 返回 - 返回结果给 API 调用方
补充说明:
- 若机器人返回“充值成功”、“充值完成”或“已增加 x 次 / 增加 x 次”这类字样,接口会返回成功结果,
status为success - 除处理中提示外,其余兑换返回一律按失败处理,
status为failed
POST /api/v1/cancel
X-API-Key: your_api_key内部流程:
- 直接发送
⬅️ 返回 - 不进入工作流队列
- 不等待 bot 返回结果
- 立即返回发送结果给 API 调用方
GET /api/v1/status
X-API-Key: your_api_key返回当前:
- Telegram 是否已连接
- 当前等待队列长度
- 队列上限
- 正在执行的请求 ID
- 正在执行的动作名称
GET /api/v1/requests/{requestId}
X-API-Key: your_api_key返回状态可能包括:
queuedrunningcompletedfailedcancelled
对接建议:
POST /api/v1/activate/plus和POST /api/v1/activate/team会返回当前state;若是state: running且status: processing,只表示机器人已接单并进入处理中,不代表最终激活成功。- 调用方应继续使用
GET /api/v1/requests/{requestId}轮询最终结果。 - 当首次查询到终态
requestId时,服务会顺带触发一次⬅️ 返回复原菜单;同一个requestId只触发一次。 - 当
GET /api/v1/requests/{requestId}的state仍为queued或running时,success会返回null,不要把它当成最终成功。 - 最终成功建议按
state=completed && success=true && status=success判断。 - 最终失败建议按
state=completed && success=false,或state=failed,或state=cancelled判断。
当前生效的激活文案判定:
- 中间态文案:
已收到请求正在生成生成支付链接正在处理处理中当前状态次查询请稍候请等待- 以及匹配
当前状态:...、第 n 次查询的文本
- 成功文案:
- 配置关键词:
升级成功 - 代码兜底:包含
成功、已升级、升级完成,且不包含请求
- 配置关键词:
- 失败文案:
- 配置关键词:
Token 无效或已过期、Token 无效、额度已退回 - 代码兜底:包含
无效、过期、退回、失败、重试、重新获取
- 配置关键词:
- 取消文案:
已取消
- 未识别文案:
- 直接按失败处理,通常表现为
success=false、status=unknown - 示例:
余额不足。可点击 ⭐ 获取额度 进行充值,或联系 @Pehlicg 获取充值码。
- 直接按失败处理,通常表现为
GET /healthz这个接口不需要鉴权,只返回进程存活状态。
curl -X POST "http://127.0.0.1:8000/api/v1/activate/plus" \
-H "Content-Type: application/json" \
-H "X-API-Key: your_api_key" \
-d "{\"accessToken\":\"your_access_token\"}"curl "http://127.0.0.1:8000/api/v1/balance" \
-H "X-API-Key: your_api_key"curl "http://127.0.0.1:8000/api/v1/requests/your_request_id" \
-H "X-API-Key: your_api_key"curl -X POST "http://127.0.0.1:8000/api/v1/cancel" \
-H "X-API-Key: your_api_key"curl -X POST "http://127.0.0.1:8000/api/v1/redeem" \
-H "Content-Type: application/json" \
-H "X-API-Key: your_api_key" \
-d "{\"cardCode\":\"your_card_code\"}"- 这个项目使用的是 Telegram 用户账号会话,不是 Bot Token
- 同一时间只允许一个 Telegram 工作流在执行,其他请求会排队
- 如果等待队列达到
api.queue_max_size,新请求会直接返回429 - 如果 bot 长时间不返回下一步提示或最终结果,接口会返回超时错误
- 如果客户端自己超时断开,可以继续用
requestId轮询任务状态和最终结果 - 若当前网络无法直连 Telegram,需要正确配置代理
- 代理模式下如果依赖不完整,请重新执行
uv sync - 当前环境下首次登录一定要先生成
.session,否则serve --non-interactive会直接报未授权