# TGLotteryBot **Telegram 抽奖机器人,内置 Mini App - 无需离开 Telegram 即可创建、发布和开奖** [English](./README.md) · **简体中文** [![][license-shield]][license-link] [![][python-shield]][python-link] [![][docker-shield]][docker-link] [![][postgres-shield]][postgres-link]
--- - [✨ 功能特性](#-功能特性) - [🚀 快速开始](#-快速开始) - [🤖 Bot 配置](#-bot-配置) - [📡 Bot 命令](#-bot-命令) - [💻 本地开发](#-本地开发) - [⚙️ 配置说明](#️-配置说明) - [🐳 服务容器](#-服务容器) - [📁 项目结构](#-项目结构) - [🤝 贡献](#-贡献) - [📝 许可证](#-许可证) ## ✨ 功能特性 - **Telegram Mini App** - 完整的抽奖管理界面直接嵌入 Telegram,无需外部网站 - **抽奖生命周期** - 草稿 → 进行中 → 已结束的状态流转;草稿和进行中状态均可编辑奖品 - **多奖品抽奖** - 每个抽奖可设置多个奖品,每个奖品单独配置数量;开奖算法通过双重随机打乱实现公平分配 - **入群验证** - 可限制只有特定群组或频道的成员才能参与,支持对每个群组单独设置口令验证 - **多群同步公告** - 同时向多个群组或频道发布公告,抽奖信息修改后消息自动同步 - **定时自动开奖** - 设定具体日期和时间,到时自动开奖 - **深链接参与** - 公告消息附带 `/start lottery_` 深链接,用户点击即可打开 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/