This commit is contained in:
@@ -0,0 +1,315 @@
|
||||
<div align="center"><a name="readme-top"></a>
|
||||
|
||||
# TGLotteryBot
|
||||
|
||||
**Telegram lottery bot with built-in Mini App - create, announce, and draw lotteries without leaving Telegram**
|
||||
|
||||
**English** · [简体中文](./README.zh-CN.md)
|
||||
|
||||
[![][license-shield]][license-link]
|
||||
[![][python-shield]][python-link]
|
||||
[![][docker-shield]][docker-link]
|
||||
[![][postgres-shield]][postgres-link]
|
||||
|
||||
</div>
|
||||
|
||||
---
|
||||
|
||||
- [✨ Features](#-features)
|
||||
- [🚀 Quick Start](#-quick-start)
|
||||
- [🤖 Bot Setup](#-bot-setup)
|
||||
- [📡 Bot Commands](#-bot-commands)
|
||||
- [💻 Local Development](#-local-development)
|
||||
- [⚙️ Configuration](#️-configuration)
|
||||
- [🐳 Services](#-services)
|
||||
- [📁 Project Structure](#-project-structure)
|
||||
- [🤝 Contributing](#-contributing)
|
||||
- [📝 License](#-license)
|
||||
|
||||
## ✨ Features
|
||||
|
||||
- **Telegram Mini App** - full lottery management UI embedded inside Telegram; no external website required
|
||||
- **Lottery lifecycle** - Draft → Active → Finished flow; prizes stay editable while the lottery is in Draft or Active
|
||||
- **Multi-prize draws** - each lottery supports multiple prizes with independent quantities; the draw algorithm pairs participants with prizes fairly using a shuffle-based random selection
|
||||
- **Membership requirements** - optionally restrict participation to members of specific groups or channels; supports passphrase verification per chat
|
||||
- **Multi-chat announcement** - announce to multiple groups or channels simultaneously; messages stay in sync as lottery details change
|
||||
- **Scheduled auto-draw** - set an exact date and time for the draw to run automatically
|
||||
- **Deep-link joining** - announcement messages carry a `/start lottery_<id>` deep link; users tap once to open the Mini App and join
|
||||
- **Winner notifications** - each winner receives a private congratulatory message from the bot with their prize details
|
||||
- **Invite links** - the bot can generate and cache persistent invite links for required chats; participants see the link before they join
|
||||
|
||||
## 🚀 Quick Start
|
||||
|
||||
**1. Download the required files**
|
||||
|
||||
```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. Configure environment**
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
```
|
||||
|
||||
Open `.env` and fill in the required values:
|
||||
|
||||
```env
|
||||
BOT_TOKEN=123456:ABC-your-bot-token-from-BotFather
|
||||
MINI_APP_URL=https://your-domain.com
|
||||
POSTGRES_PASSWORD=change-me
|
||||
```
|
||||
|
||||
> [!IMPORTANT]
|
||||
> `BOT_TOKEN` and `MINI_APP_URL` are required. The Mini App URL must be an HTTPS address that Telegram can reach. For production, also set `WEBHOOK_URL` and `WEBHOOK_SECRET`.
|
||||
|
||||
**3. Start**
|
||||
|
||||
```bash
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
**4. Register the Mini App**
|
||||
|
||||
In [@BotFather](https://t.me/BotFather), send `/newapp` and point the Web App URL to `https://your-domain.com`. Users can then open the lottery manager directly from bot messages.
|
||||
|
||||
**5. Open the bot**
|
||||
|
||||
Send `/start` to your bot in Telegram to open the Mini App.
|
||||
|
||||
> [!TIP]
|
||||
> For production deployments, set `WEBHOOK_URL` to your public HTTPS URL. Without it, the bot falls back to long-polling, which is fine for development but less efficient in production.
|
||||
|
||||
**Updating to a newer version**
|
||||
|
||||
```bash
|
||||
docker compose pull
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
<div align="right">
|
||||
|
||||
[![][back-to-top]](#readme-top)
|
||||
|
||||
</div>
|
||||
|
||||
## 🤖 Bot Setup
|
||||
|
||||
After adding the bot to your groups or channels, configure the following in [@BotFather](https://t.me/BotFather):
|
||||
|
||||
**Disable Privacy Mode** (`/setprivacy` - Disabled)
|
||||
|
||||
Required if you use passphrase verification. By default, Telegram bots only receive messages that start with `/`. Disabling Privacy Mode allows the bot to read all messages in the group so it can detect passphrases sent by users.
|
||||
|
||||
**Grant Admin rights for anonymous admin detection**
|
||||
|
||||
If your group has anonymous administrators (members who toggled "Hide my name"), Telegram does not expose their user ID to bots via the standard `getChatMember` API. Granting the bot administrator rights in the group allows it to verify anonymous admins when checking membership.
|
||||
|
||||
> [!NOTE]
|
||||
> These settings only affect groups where you use membership requirements or passphrase verification. For channels or public lotteries without requirements, they are not needed.
|
||||
|
||||
<div align="right">
|
||||
|
||||
[![][back-to-top]](#readme-top)
|
||||
|
||||
</div>
|
||||
|
||||
## 📡 Bot Commands
|
||||
|
||||
| Command | Description |
|
||||
|---|---|
|
||||
| `/start` | Open the lottery manager Mini App |
|
||||
| `/newlottery` | Create a new lottery (shortcut into the Mini App) |
|
||||
| `/mylotteries` | View your lotteries |
|
||||
| `/help` | Show help and project info |
|
||||
|
||||
All lottery management (creating, editing, announcing, drawing) happens inside the Mini App. Bot commands are entry points that open the appropriate Mini App screen.
|
||||
|
||||
<div align="right">
|
||||
|
||||
[![][back-to-top]](#readme-top)
|
||||
|
||||
</div>
|
||||
|
||||
## 💻 Local Development
|
||||
|
||||
**Prerequisites:** Docker and Docker Compose
|
||||
|
||||
The project ships a `docker-compose.override.yml` that activates automatically for development:
|
||||
|
||||
- Backend mounts the source tree and runs uvicorn with `--reload`
|
||||
- Frontend runs the Vite dev server with filesystem polling (safe for NAS / network volumes)
|
||||
- nginx serves the Vite output and proxies `/api` and `/webhook` to the backend
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
# Edit .env - set BOT_TOKEN, MINI_APP_URL; leave WEBHOOK_URL empty for polling mode
|
||||
docker compose up --build
|
||||
```
|
||||
|
||||
The development stack is accessible at `http://localhost` (or whatever `PORT` you set).
|
||||
|
||||
Backend hot-reloads on file save. Frontend hot-reloads are handled by Vite.
|
||||
|
||||
<div align="right">
|
||||
|
||||
[![][back-to-top]](#readme-top)
|
||||
|
||||
</div>
|
||||
|
||||
## ⚙️ Configuration
|
||||
|
||||
All configuration is read from environment variables (or `.env` in the project root).
|
||||
|
||||
| Variable | Default | Required | Description |
|
||||
|---|---|---|---|
|
||||
| `BOT_TOKEN` | - | **Yes** | Telegram bot token from [@BotFather](https://t.me/BotFather) |
|
||||
| `MINI_APP_URL` | - | **Yes** | Public HTTPS URL where the Mini App frontend is served |
|
||||
| `WEBHOOK_URL` | *(empty)* | No | Public HTTPS base URL for webhook mode. Leave empty to use long-polling |
|
||||
| `WEBHOOK_SECRET` | *(empty)* | No | Secret token sent by Telegram in the `X-Telegram-Bot-Api-Secret-Token` header |
|
||||
| `POSTGRES_PASSWORD` | `postgres` | No | PostgreSQL password |
|
||||
| `PORT` | `80` | No | Host port exposed by nginx |
|
||||
| `DEBUG` | `false` | No | Enable FastAPI debug mode |
|
||||
| `AVATAR_CACHE_TTL` | `3600` | No | Seconds to cache user and chat avatars server-side |
|
||||
|
||||
> [!WARNING]
|
||||
> Always change `POSTGRES_PASSWORD` and generate a strong `WEBHOOK_SECRET` before exposing the deployment to the internet.
|
||||
|
||||
<div align="right">
|
||||
|
||||
[![][back-to-top]](#readme-top)
|
||||
|
||||
</div>
|
||||
|
||||
## 🐳 Services
|
||||
|
||||
The default compose stack starts four containers:
|
||||
|
||||
| Container | Image | Purpose |
|
||||
|---|---|---|
|
||||
| `backend` | `tglotterybot-backend:latest` | FastAPI REST API + aiogram Telegram bot |
|
||||
| `frontend` | `tglotterybot-frontend:latest` | React + Vite Mini App (built static files) |
|
||||
| `nginx` | `nginx:alpine` | Reverse proxy; routes `/api/*` and `/webhook/*` to backend, everything else to frontend |
|
||||
| `postgres` | `postgres:16-alpine` | PostgreSQL persistent database |
|
||||
|
||||
Persistent data is stored in `./postgres_data/`.
|
||||
|
||||
<div align="right">
|
||||
|
||||
[![][back-to-top]](#readme-top)
|
||||
|
||||
</div>
|
||||
|
||||
## 📁 Project Structure
|
||||
|
||||
```
|
||||
TGLotteryBot/
|
||||
├── backend/ # Python FastAPI + aiogram bot
|
||||
│ ├── app/
|
||||
│ │ ├── main.py # FastAPI app entrypoint + lifespan setup
|
||||
│ │ ├── core/
|
||||
│ │ │ ├── config.py # Pydantic settings (reads from env / .env)
|
||||
│ │ │ ├── database.py # Async SQLAlchemy engine and session factory
|
||||
│ │ │ └── security.py # Telegram initData HMAC-SHA256 validation
|
||||
│ │ ├── api/
|
||||
│ │ │ ├── deps.py # FastAPI dependencies (authentication)
|
||||
│ │ │ ├── schemas.py # Pydantic request / response models
|
||||
│ │ │ └── routers/
|
||||
│ │ │ ├── lotteries.py # Lottery CRUD, draw, and announce endpoints
|
||||
│ │ │ ├── prizes.py # Prize management endpoints
|
||||
│ │ │ ├── participants.py # Join / leave endpoints
|
||||
│ │ │ ├── chats.py # Managed chat list, links, and avatars
|
||||
│ │ │ └── users.py # User profile and avatar endpoints
|
||||
│ │ ├── bot/
|
||||
│ │ │ ├── router.py # aiogram dispatcher and router registration
|
||||
│ │ │ ├── handlers/ # Bot command and event handlers
|
||||
│ │ │ └── keyboards/ # Inline keyboard builders
|
||||
│ │ ├── models/ # SQLAlchemy 2.0 ORM models
|
||||
│ │ │ ├── lottery.py # Lottery (status enum, all lottery fields)
|
||||
│ │ │ ├── prize.py # Prize (name, quantity, sort order)
|
||||
│ │ │ ├── participant.py # Lottery participants
|
||||
│ │ │ ├── winner.py # Draw results
|
||||
│ │ │ ├── user.py # Telegram users
|
||||
│ │ │ ├── managed_chat.py # Groups / channels the bot manages
|
||||
│ │ │ └── passphrase_verification.py
|
||||
│ │ └── services/
|
||||
│ │ ├── draw_service.py # Draw algorithm (shuffle-based, SELECT FOR UPDATE)
|
||||
│ │ └── scheduler.py # Auto-draw scheduler + winner notifications
|
||||
│ ├── alembic/ # Alembic database migrations
|
||||
│ │ └── versions/
|
||||
│ ├── requirements.txt
|
||||
│ └── Dockerfile
|
||||
├── frontend/ # React 18 + Vite Telegram Mini App
|
||||
│ ├── src/
|
||||
│ │ ├── pages/ # Route-level page components
|
||||
│ │ ├── components/ # Shared UI components
|
||||
│ │ ├── hooks/ # Custom React hooks
|
||||
│ │ ├── lib/ # API client, Telegram SDK wrapper, utilities
|
||||
│ │ └── types/ # TypeScript type definitions
|
||||
│ ├── package.json
|
||||
│ ├── vite.config.ts
|
||||
│ ├── Dockerfile # Production build
|
||||
│ └── Dockerfile.dev # Dev server (Vite)
|
||||
├── nginx/
|
||||
│ ├── nginx.conf # Production reverse proxy config
|
||||
│ └── nginx.dev.conf # Development config
|
||||
├── docker-compose.yml # Production service definitions
|
||||
├── docker-compose.override.yml # Development overrides (auto-applied)
|
||||
└── .env.example # Environment variable template
|
||||
```
|
||||
|
||||
<div align="right">
|
||||
|
||||
[![][back-to-top]](#readme-top)
|
||||
|
||||
</div>
|
||||
|
||||
## 🤝 Contributing
|
||||
|
||||
Issues and pull requests are welcome. Please open an issue first for major changes so the direction can be discussed.
|
||||
|
||||
<div align="right">
|
||||
|
||||
[![][back-to-top]](#readme-top)
|
||||
|
||||
</div>
|
||||
|
||||
## 📝 License
|
||||
|
||||
Copyright © 2026 [Stardream](https://git.stdm.moe/Stardream). This project is licensed under the [GNU Affero General Public License v3.0](./LICENSE).
|
||||
|
||||
**Permissions**
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| ✅ | Commercial use |
|
||||
| ✅ | Modification |
|
||||
| ✅ | Distribution |
|
||||
| ✅ | Private use |
|
||||
|
||||
**Conditions**
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| ⚠️ | Disclose source - modified versions must also be open-source |
|
||||
| ⚠️ | Same license - derivative works must use AGPL-3.0 |
|
||||
| ⚠️ | Network use = distribution - if you run a modified version as a network service, you must make the source available to users |
|
||||
| ⚠️ | State changes - modifications must be documented |
|
||||
|
||||
In short: you are free to use, modify, and self-host TGLotteryBot. If you distribute or offer a modified version as a hosted service, you must publish the full source under 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