` 深链接,用户点击即可打开 Mini App 并参与
- **私信通知中奖者** - 每位中奖者将收到机器人发来的私信,包含中奖奖品详情
- **邀请链接管理** - 机器人可生成并缓存所需群组的永久邀请链接,用户加入前即可查看
## 🚀 快速开始
**1. 下载所需文件**
```bash
curl -LO https://git.stdm.moe/Stardream/TGLotteryBot/raw/branch/main/docker-compose.yml
curl -LO https://git.stdm.moe/Stardream/TGLotteryBot/raw/branch/main/.env.example
mkdir -p nginx
curl -o nginx/nginx.conf https://git.stdm.moe/Stardream/TGLotteryBot/raw/branch/main/nginx/nginx.conf
```
**2. 配置环境变量**
```bash
cp .env.example .env
```
编辑 `.env`,填入必填项:
```env
BOT_TOKEN=123456:ABC-your-bot-token-from-BotFather
MINI_APP_URL=https://your-domain.com
POSTGRES_PASSWORD=change-me
```
> [!IMPORTANT]
> `BOT_TOKEN` 和 `MINI_APP_URL` 为必填项。Mini App URL 必须是 Telegram 可访问的 HTTPS 地址。生产环境还需设置 `WEBHOOK_URL` 和 `WEBHOOK_SECRET`。
**3. 启动服务**
```bash
docker compose up -d
```
**4. 注册 Mini App**
在 [@BotFather](https://t.me/BotFather) 发送 `/newapp`,将 Web App URL 指向 `https://your-domain.com`,用户即可从消息中直接打开抽奖管理界面。
**5. 使用机器人**
在 Telegram 中向你的机器人发送 `/start`,即可打开 Mini App。
> [!TIP]
> 生产部署时建议设置 `WEBHOOK_URL` 为公网 HTTPS 地址。不设置则退回长轮询模式,适合开发但生产效率较低。
**更新到新版本**
```bash
docker compose pull
docker compose up -d
```
[![][back-to-top]](#readme-top)
## 🤖 Bot 配置
将 Bot 添加到群组或频道后,需要在 [@BotFather](https://t.me/BotFather) 中进行以下配置:
**关闭隐私模式**(`/setprivacy` - Disabled)
使用口令验证时必须关闭。Telegram Bot 默认只接收以 `/` 开头的消息,关闭隐私模式后 Bot 才能读取群组中的所有消息,从而识别用户发送的口令。
**授予管理员权限以识别匿名管理员**
如果群组中存在匿名管理员(开启了"隐藏管理员身份"的成员),Telegram 不会通过标准 `getChatMember` API 暴露其用户 ID。将 Bot 设为群组管理员后,Bot 才能在验证成员资格时识别匿名管理员。
> [!NOTE]
> 以上设置仅对使用了成员资格验证或口令验证的群组有效,频道或无参与要求的公开抽奖不需要这些配置。
[![][back-to-top]](#readme-top)
## 📡 Bot 命令
| 命令 | 说明 |
|---|---|
| `/start` | 打开抽奖管理 Mini App |
| `/newlottery` | 创建新抽奖(直接跳转至 Mini App 创建页) |
| `/mylotteries` | 查看我的抽奖列表 |
| `/help` | 查看帮助与项目信息 |
所有抽奖管理操作(创建、编辑、发布、开奖)均在 Mini App 内完成,Bot 命令是进入对应页面的入口。
[![][back-to-top]](#readme-top)
## 💻 本地开发
**前置条件:** Docker 和 Docker Compose
项目内置 `docker-compose.override.yml`,启动时自动生效:
- 后端挂载源码目录,uvicorn 开启 `--reload` 热重载
- 前端运行 Vite 开发服务器,使用文件轮询模式(适配 NAS / 网络文件系统)
- nginx 提供 Vite 构建产物,并将 `/api` 和 `/webhook` 反向代理到后端
```bash
cp .env.example .env
# 编辑 .env,填入 BOT_TOKEN、MINI_APP_URL;WEBHOOK_URL 留空使用轮询模式
docker compose up --build
```
开发环境通过 `http://localhost`(或你设置的 `PORT`)访问。
保存后端文件后自动热重载,前端热更新由 Vite 处理。
[![][back-to-top]](#readme-top)
## ⚙️ 配置说明
所有配置通过环境变量读取(或项目根目录的 `.env` 文件)。
| 变量 | 默认值 | 必填 | 说明 |
|---|---|---|---|
| `BOT_TOKEN` | - | **是** | 从 [@BotFather](https://t.me/BotFather) 获取的 Telegram 机器人 Token |
| `MINI_APP_URL` | - | **是** | Mini App 前端的公网 HTTPS 地址 |
| `WEBHOOK_URL` | *(空)* | 否 | Webhook 模式的公网 HTTPS 基础地址,留空则使用长轮询 |
| `WEBHOOK_SECRET` | *(空)* | 否 | Telegram 在 `X-Telegram-Bot-Api-Secret-Token` 请求头中发送的密钥 |
| `POSTGRES_PASSWORD` | `postgres` | 否 | PostgreSQL 密码 |
| `PORT` | `80` | 否 | nginx 对外暴露的端口 |
| `DEBUG` | `false` | 否 | 启用 FastAPI 调试模式 |
| `AVATAR_CACHE_TTL` | `3600` | 否 | 用户和群组头像的服务端缓存时间(秒) |
> [!WARNING]
> 对外部署前务必修改 `POSTGRES_PASSWORD` 并生成强随机的 `WEBHOOK_SECRET`。
[![][back-to-top]](#readme-top)
## 🐳 服务容器
默认 Compose 配置启动四个容器:
| 容器 | 镜像 | 用途 |
|---|---|---|
| `backend` | `tglotterybot-backend:latest` | FastAPI REST API + aiogram Telegram 机器人 |
| `frontend` | `tglotterybot-frontend:latest` | React + Vite Mini App(静态文件) |
| `nginx` | `nginx:alpine` | 反向代理;`/api/*` 和 `/webhook/*` 转发至后端,其余请求转发至前端 |
| `postgres` | `postgres:16-alpine` | PostgreSQL 持久化数据库 |
持久化数据存储在 `./postgres_data/`。
[![][back-to-top]](#readme-top)
## 📁 项目结构
```
TGLotteryBot/
├── backend/ # Python FastAPI + aiogram 机器人
│ ├── app/
│ │ ├── main.py # FastAPI 应用入口 + 生命周期管理
│ │ ├── core/
│ │ │ ├── config.py # Pydantic 配置(从环境变量 / .env 读取)
│ │ │ ├── database.py # 异步 SQLAlchemy 引擎与会话工厂
│ │ │ └── security.py # Telegram initData HMAC-SHA256 验证
│ │ ├── api/
│ │ │ ├── deps.py # FastAPI 依赖项(身份认证)
│ │ │ ├── schemas.py # Pydantic 请求 / 响应模型
│ │ │ └── routers/
│ │ │ ├── lotteries.py # 抽奖 CRUD、开奖、公告端点
│ │ │ ├── prizes.py # 奖品管理端点
│ │ │ ├── participants.py # 参与 / 退出端点
│ │ │ ├── chats.py # 托管群组列表、链接、头像
│ │ │ └── users.py # 用户信息与头像端点
│ │ ├── bot/
│ │ │ ├── router.py # aiogram 调度器与路由注册
│ │ │ ├── handlers/ # Bot 命令与事件处理器
│ │ │ └── keyboards/ # 内联键盘构建器
│ │ ├── models/ # SQLAlchemy 2.0 ORM 模型
│ │ │ ├── lottery.py # 抽奖(状态枚举、所有抽奖字段)
│ │ │ ├── prize.py # 奖品(名称、数量、排序)
│ │ │ ├── participant.py # 参与者
│ │ │ ├── winner.py # 开奖结果
│ │ │ ├── user.py # Telegram 用户
│ │ │ ├── managed_chat.py # 机器人管理的群组 / 频道
│ │ │ └── passphrase_verification.py
│ │ └── services/
│ │ ├── draw_service.py # 开奖算法(双重随机 + SELECT FOR UPDATE)
│ │ └── scheduler.py # 定时自动开奖 + 中奖通知
│ ├── alembic/ # Alembic 数据库迁移
│ │ └── versions/
│ ├── requirements.txt
│ └── Dockerfile
├── frontend/ # React 18 + Vite Telegram Mini App
│ ├── src/
│ │ ├── pages/ # 路由级页面组件
│ │ ├── components/ # 通用 UI 组件
│ │ ├── hooks/ # 自定义 React Hooks
│ │ ├── lib/ # API 客户端、Telegram SDK 封装、工具函数
│ │ └── types/ # TypeScript 类型定义
│ ├── package.json
│ ├── vite.config.ts
│ ├── Dockerfile # 生产构建
│ └── Dockerfile.dev # 开发服务器(Vite)
├── nginx/
│ ├── nginx.conf # 生产环境反向代理配置
│ └── nginx.dev.conf # 开发环境配置
├── docker-compose.yml # 生产服务定义
├── docker-compose.override.yml # 开发覆盖配置(自动生效)
└── .env.example # 环境变量模板
```
[![][back-to-top]](#readme-top)
## 🤝 贡献
欢迎提交 Issue 和 Pull Request。重大变更请先开 Issue 讨论方向。
[![][back-to-top]](#readme-top)
## 📝 许可证
Copyright © 2026 [Stardream](https://git.stdm.moe/Stardream)。本项目采用 [GNU Affero General Public License v3.0](./LICENSE) 许可证。
**权利**
| | |
|---|---|
| ✅ | 商业使用 |
| ✅ | 修改 |
| ✅ | 分发 |
| ✅ | 私人使用 |
**条件**
| | |
|---|---|
| ⚠️ | 公开源码 - 修改后的版本也必须开源 |
| ⚠️ | 相同许可证 - 衍生作品必须使用 AGPL-3.0 |
| ⚠️ | 网络使用 = 分发 - 若将修改版本作为网络服务运行,必须向用户提供源码 |
| ⚠️ | 标注修改 - 修改内容必须记录在案 |
简而言之:你可以自由使用、修改和自托管 TGLotteryBot。若将修改版本作为托管服务分发或提供,必须以 AGPL-3.0 发布完整源码。
---
[back-to-top]: https://img.shields.io/badge/-BACK_TO_TOP-black?style=flat-square
[license-shield]: https://img.shields.io/badge/许可证-AGPL--3.0-white?labelColor=black&style=flat-square
[license-link]: ./LICENSE
[python-shield]: https://img.shields.io/badge/python-3.12-blue?labelColor=black&logo=python&logoColor=white&style=flat-square
[python-link]: https://www.python.org/
[docker-shield]: https://img.shields.io/badge/docker-compose-2496ED?labelColor=black&logo=docker&logoColor=white&style=flat-square
[docker-link]: https://docs.docker.com/compose/
[postgres-shield]: https://img.shields.io/badge/postgres-16-336791?labelColor=black&logo=postgresql&logoColor=white&style=flat-square
[postgres-link]: https://www.postgresql.org/