This commit is contained in:
+315
@@ -0,0 +1,315 @@
|
||||
<div align="center"><a name="readme-top"></a>
|
||||
|
||||
# TGLotteryBot
|
||||
|
||||
**Telegram 抽奖机器人,内置 Mini App - 无需离开 Telegram 即可创建、发布和开奖**
|
||||
|
||||
[English](./README.md) · **简体中文**
|
||||
|
||||
[![][license-shield]][license-link]
|
||||
[![][python-shield]][python-link]
|
||||
[![][docker-shield]][docker-link]
|
||||
[![][postgres-shield]][postgres-link]
|
||||
|
||||
</div>
|
||||
|
||||
---
|
||||
|
||||
- [✨ 功能特性](#-功能特性)
|
||||
- [🚀 快速开始](#-快速开始)
|
||||
- [🤖 Bot 配置](#-bot-配置)
|
||||
- [📡 Bot 命令](#-bot-命令)
|
||||
- [💻 本地开发](#-本地开发)
|
||||
- [⚙️ 配置说明](#️-配置说明)
|
||||
- [🐳 服务容器](#-服务容器)
|
||||
- [📁 项目结构](#-项目结构)
|
||||
- [🤝 贡献](#-贡献)
|
||||
- [📝 许可证](#-许可证)
|
||||
|
||||
## ✨ 功能特性
|
||||
|
||||
- **Telegram Mini App** - 完整的抽奖管理界面直接嵌入 Telegram,无需外部网站
|
||||
- **抽奖生命周期** - 草稿 → 进行中 → 已结束的状态流转;草稿和进行中状态均可编辑奖品
|
||||
- **多奖品抽奖** - 每个抽奖可设置多个奖品,每个奖品单独配置数量;开奖算法通过双重随机打乱实现公平分配
|
||||
- **入群验证** - 可限制只有特定群组或频道的成员才能参与,支持对每个群组单独设置口令验证
|
||||
- **多群同步公告** - 同时向多个群组或频道发布公告,抽奖信息修改后消息自动同步
|
||||
- **定时自动开奖** - 设定具体日期和时间,到时自动开奖
|
||||
- **深链接参与** - 公告消息附带 `/start lottery_<id>` 深链接,用户点击即可打开 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
|
||||
```
|
||||
|
||||
<div align="right">
|
||||
|
||||
[![][back-to-top]](#readme-top)
|
||||
|
||||
</div>
|
||||
|
||||
## 🤖 Bot 配置
|
||||
|
||||
将 Bot 添加到群组或频道后,需要在 [@BotFather](https://t.me/BotFather) 中进行以下配置:
|
||||
|
||||
**关闭隐私模式**(`/setprivacy` - Disabled)
|
||||
|
||||
使用口令验证时必须关闭。Telegram Bot 默认只接收以 `/` 开头的消息,关闭隐私模式后 Bot 才能读取群组中的所有消息,从而识别用户发送的口令。
|
||||
|
||||
**授予管理员权限以识别匿名管理员**
|
||||
|
||||
如果群组中存在匿名管理员(开启了"隐藏管理员身份"的成员),Telegram 不会通过标准 `getChatMember` API 暴露其用户 ID。将 Bot 设为群组管理员后,Bot 才能在验证成员资格时识别匿名管理员。
|
||||
|
||||
> [!NOTE]
|
||||
> 以上设置仅对使用了成员资格验证或口令验证的群组有效,频道或无参与要求的公开抽奖不需要这些配置。
|
||||
|
||||
<div align="right">
|
||||
|
||||
[![][back-to-top]](#readme-top)
|
||||
|
||||
</div>
|
||||
|
||||
## 📡 Bot 命令
|
||||
|
||||
| 命令 | 说明 |
|
||||
|---|---|
|
||||
| `/start` | 打开抽奖管理 Mini App |
|
||||
| `/newlottery` | 创建新抽奖(直接跳转至 Mini App 创建页) |
|
||||
| `/mylotteries` | 查看我的抽奖列表 |
|
||||
| `/help` | 查看帮助与项目信息 |
|
||||
|
||||
所有抽奖管理操作(创建、编辑、发布、开奖)均在 Mini App 内完成,Bot 命令是进入对应页面的入口。
|
||||
|
||||
<div align="right">
|
||||
|
||||
[![][back-to-top]](#readme-top)
|
||||
|
||||
</div>
|
||||
|
||||
## 💻 本地开发
|
||||
|
||||
**前置条件:** 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 处理。
|
||||
|
||||
<div align="right">
|
||||
|
||||
[![][back-to-top]](#readme-top)
|
||||
|
||||
</div>
|
||||
|
||||
## ⚙️ 配置说明
|
||||
|
||||
所有配置通过环境变量读取(或项目根目录的 `.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`。
|
||||
|
||||
<div align="right">
|
||||
|
||||
[![][back-to-top]](#readme-top)
|
||||
|
||||
</div>
|
||||
|
||||
## 🐳 服务容器
|
||||
|
||||
默认 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/`。
|
||||
|
||||
<div align="right">
|
||||
|
||||
[![][back-to-top]](#readme-top)
|
||||
|
||||
</div>
|
||||
|
||||
## 📁 项目结构
|
||||
|
||||
```
|
||||
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 # 环境变量模板
|
||||
```
|
||||
|
||||
<div align="right">
|
||||
|
||||
[![][back-to-top]](#readme-top)
|
||||
|
||||
</div>
|
||||
|
||||
## 🤝 贡献
|
||||
|
||||
欢迎提交 Issue 和 Pull Request。重大变更请先开 Issue 讨论方向。
|
||||
|
||||
<div align="right">
|
||||
|
||||
[![][back-to-top]](#readme-top)
|
||||
|
||||
</div>
|
||||
|
||||
## 📝 许可证
|
||||
|
||||
Copyright © 2026 [Stardream](https://git.stdm.moe/Stardream)。本项目采用 [GNU Affero General Public License v3.0](./LICENSE) 许可证。
|
||||
|
||||
**权利**
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| ✅ | 商业使用 |
|
||||
| ✅ | 修改 |
|
||||
| ✅ | 分发 |
|
||||
| ✅ | 私人使用 |
|
||||
|
||||
**条件**
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| ⚠️ | 公开源码 - 修改后的版本也必须开源 |
|
||||
| ⚠️ | 相同许可证 - 衍生作品必须使用 AGPL-3.0 |
|
||||
| ⚠️ | 网络使用 = 分发 - 若将修改版本作为网络服务运行,必须向用户提供源码 |
|
||||
| ⚠️ | 标注修改 - 修改内容必须记录在案 |
|
||||
|
||||
简而言之:你可以自由使用、修改和自托管 TGLotteryBot。若将修改版本作为托管服务分发或提供,必须以 AGPL-3.0 发布完整源码。
|
||||
|
||||
---
|
||||
|
||||
<!-- LINK GROUP -->
|
||||
[back-to-top]: https://img.shields.io/badge/-BACK_TO_TOP-black?style=flat-square
|
||||
[license-shield]: https://img.shields.io/badge/license-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/
|
||||
Reference in New Issue
Block a user