Changes: - Add Dockerfile Configuration section with code example - Document Debian-based image choice (python:3.11-slim) - Add all system dependencies (libgl1, libsm6, etc.) - Extend Common Issues with Docker build troubleshooting - New CI/CD section for Gitea Actions - Document both workflows (autobuild and manual) - Add required secrets and registry configuration - Add version history overview
421 lines
12 KiB
Markdown
421 lines
12 KiB
Markdown
# OPENCODE.md - Telegram Sticker Bot
|
|
|
|
## Overview
|
|
This is a Telegram bot for managing sticker packs. Built with python-telegram-bot v22.7, it allows the bot owner to create, manage, and organize sticker sets through an interactive conversation interface.
|
|
|
|
## Architecture
|
|
|
|
### Technology Stack
|
|
- **Python**: 3.11+
|
|
- **Library**: python-telegram-bot v22.7 (supports Bot API 9.5)
|
|
- **Database**: SQLite with aiosqlite for async operations
|
|
- **Image Processing**: Pillow (PIL) for automatic image conversion
|
|
- **Video Processing**: FFmpeg for GIF to WebM conversion
|
|
- **Background Removal**: rembg (local) + remove.bg API (optional)
|
|
- **Container**: Docker + Docker Compose
|
|
- **Base Image**: python:3.11-slim (Debian-based for better compatibility)
|
|
- **Environment**: python-dotenv for configuration
|
|
|
|
### Dockerfile Configuration
|
|
```dockerfile
|
|
FROM python:3.11-slim
|
|
|
|
# System dependencies for OpenCV, FFmpeg and rembg
|
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
ffmpeg \
|
|
libgl1 \
|
|
libglib2.0-0 \
|
|
libsm6 \
|
|
libxext6 \
|
|
libxrender-dev \
|
|
libgomp1 \
|
|
&& rm -rf /var/lib/apt/lists/*
|
|
```
|
|
|
|
**Key points:**
|
|
- Uses `python:3.11-slim` (Debian-based) instead of Alpine for better Python package compatibility
|
|
- Includes OpenCV dependencies: `libgl1`, `libglib2.0-0`, `libsm6`, `libxext6`, `libxrender-dev`
|
|
- Includes `libgomp1` for OpenMP support (required by numba/llvmlite)
|
|
- Non-root user for security
|
|
|
|
### Database Schema
|
|
- **sticker_sets**: Tracks created sticker sets (user_id, set_name, set_title, timestamps)
|
|
- **user_premium**: Caches user premium status with last check timestamp
|
|
- **stickers**: Tracks individual stickers in sets (file_id, emoji, set_name)
|
|
- **api_usage**: Tracks API usage for external services (remove.bg)
|
|
|
|
## Commands
|
|
|
|
### Available Commands
|
|
- `/start` - Start the bot and show main menu
|
|
- `/hilfe` - Display detailed help message
|
|
- `/cancel` - Cancel current conversation
|
|
|
|
## Build/Lint/Test Commands
|
|
|
|
### Docker
|
|
```bash
|
|
# Build and run
|
|
sudo docker-compose up -d --build
|
|
|
|
# View logs
|
|
sudo docker-compose logs -f
|
|
|
|
# Stop
|
|
sudo docker-compose down
|
|
|
|
# Rebuild after changes
|
|
sudo docker-compose up -d --build --force-recreate
|
|
```
|
|
|
|
### Local Development (without Docker)
|
|
```bash
|
|
# Install dependencies
|
|
pip install -r requirements.txt
|
|
|
|
# Run bot
|
|
python bot.py
|
|
|
|
# Run with environment file
|
|
python -c "from bot import main; main()"
|
|
```
|
|
|
|
### Testing
|
|
- No test suite implemented yet
|
|
- Manual testing via Telegram bot interface
|
|
- Use `/cancel` to abort any conversation
|
|
|
|
### Linting
|
|
```bash
|
|
# Optional: Add ruff or flake8
|
|
pip install ruff
|
|
ruff check .
|
|
ruff format .
|
|
```
|
|
|
|
## Code Style Guidelines
|
|
|
|
### Imports
|
|
- Group imports: stdlib, third-party, local
|
|
- Use absolute imports
|
|
- Example:
|
|
```python
|
|
import logging
|
|
from telegram import Update
|
|
from telegram.ext import Application
|
|
from config import BOT_TOKEN
|
|
```
|
|
|
|
### Async/Await
|
|
- All handlers are async (python-telegram-bot v22.x requirement)
|
|
- Database operations use aiosqlite (async)
|
|
- Always await coroutines
|
|
- Example:
|
|
```python
|
|
async def handler(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
|
await update.message.reply_text("Hello")
|
|
```
|
|
|
|
### Types
|
|
- Use type hints where possible
|
|
- Follow telegram library types: Update, ContextTypes, InlineKeyboardMarkup
|
|
- Database functions return Optional[bool], List[Dict[str, Any]]
|
|
|
|
### Naming Conventions
|
|
- Functions: snake_case
|
|
- Constants: UPPER_CASE
|
|
- Classes: PascalCase
|
|
- Private: _prefix
|
|
|
|
### Error Handling
|
|
- Use try-except blocks for API calls
|
|
- Log errors with logger.error()
|
|
- Return success/failure tuples or booleans
|
|
- Always clean up user_data on errors
|
|
|
|
### Conversation States
|
|
- Defined as constants at module level
|
|
- Use range() for sequential states
|
|
- Clear user_data when conversation ends
|
|
- State order: MENU → CREATE_SET_* → SELECT_SET → SET_ACTION → specific actions
|
|
|
|
### Security
|
|
- OWNER_ID check on every /start
|
|
- No group chat support (private only)
|
|
- SQLite for local persistence
|
|
- No secrets in code (use .env)
|
|
|
|
## Key Features
|
|
|
|
### Premium Detection
|
|
- Check via `chat.is_premium` from Telegram API
|
|
- Cached in database with 24h refresh interval
|
|
- Scheduled job using JobQueue
|
|
- Displayed in main menu
|
|
|
|
### Sticker Operations
|
|
|
|
#### 1. Create New Sticker Set
|
|
**Flow:** Name → Title → Emoji → Image
|
|
- 4-step wizard with input validation
|
|
- Automatic image optimization
|
|
- Optional background removal
|
|
|
|
#### 2. Add Existing Sticker Set
|
|
**Flow:** Select "📥 Existierendes hinzufügen" → Enter set name
|
|
- User provides existing sticker set name
|
|
- Bot verifies via `getStickerSet()` API
|
|
- Auto-appends `_by_<bot_username>` if not present
|
|
- Duplicate check prevents double entries
|
|
|
|
#### 3. Add Sticker to Set
|
|
**Supported formats:**
|
|
- **Static images**: PNG, JPG, WebP (automatic conversion to WebP)
|
|
- **GIFs**: Converted to animated video stickers (WebM, max 3 seconds)
|
|
|
|
**Features:**
|
|
- Automatic resizing to 512px
|
|
- Background removal option (if REMOVE_BG_API_KEY configured)
|
|
- GIF trimming for animations > 3 seconds
|
|
|
|
#### 4. Delete Sticker
|
|
- Forward sticker to bot
|
|
- Confirmation before deletion
|
|
|
|
#### 5. Change Emoji
|
|
- Forward sticker → Enter new emoji
|
|
|
|
#### 6. Rename Set
|
|
- Enter new title (max 64 characters)
|
|
|
|
#### 7. Delete Set
|
|
- Confirmation required
|
|
- Cannot be undone
|
|
|
|
### Automatic Image Processing
|
|
All uploaded images are automatically converted to Telegram sticker format:
|
|
- **Resize**: One dimension set to 512px (other ≤512px), maintaining aspect ratio
|
|
- **Format conversion**: Converted to WebP with transparency (RGBA)
|
|
- **Compression**: Quality adjusted automatically (60-95) to stay under 3MB
|
|
- **Supported formats**: PNG, JPG, JPEG, WebP, GIF, BMP, TIFF
|
|
- **Quality**: Uses LANCZOS resampling for best results
|
|
|
|
### Background Removal (Hybrid)
|
|
|
|
#### Local Processing (rembg)
|
|
- **Cost**: Free, runs on server
|
|
- **Method**: U²Net deep learning model
|
|
- **First run**: Downloads model (~180MB)
|
|
- **Speed**: Depends on image size
|
|
|
|
#### Remove.bg API (Optional)
|
|
- **Cost**: 50 free calls/month, then paid
|
|
- **Configuration**: Set REMOVE_BG_API_KEY in .env
|
|
- **Retry logic**: 3 attempts with delays (2s, 5s, 10s)
|
|
- **Limit tracking**: Stored in database, resets monthly
|
|
- **Fallback**: Automatically falls back to local on API errors
|
|
|
|
#### User Interface
|
|
```
|
|
Without API key:
|
|
Image → [Auto: Local processing] → Emoji → Done
|
|
|
|
With API key:
|
|
Image → Selection:
|
|
├─ [🤖 Local (free)]
|
|
├─ [☁️ API (45/50)] or [☁️ API (50/50) ⚠️ Limit]
|
|
└─ [⏭️ Skip removal]
|
|
|
|
If API fails/limit reached:
|
|
❌ Remove.bg API limit reached (50/50)
|
|
|
|
[🤖 Process locally instead]
|
|
[⏭️ Without background removal]
|
|
[❌ Cancel]
|
|
```
|
|
|
|
### GIF to Video Sticker Conversion
|
|
- **Format**: WebM with VP9 codec
|
|
- **Resolution**: 512px (one side), other ≤512px
|
|
- **FPS**: 30 frames per second
|
|
- **Duration**: Maximum 3 seconds
|
|
- **File size**: Maximum 256KB
|
|
- **Compression**: Automatic quality adjustment
|
|
- **Trimming**: User confirmation for GIFs > 3s
|
|
|
|
## Environment Variables
|
|
|
|
```bash
|
|
# Required
|
|
BOT_TOKEN=your_telegram_bot_token
|
|
OWNER_ID=your_telegram_user_id
|
|
|
|
# Optional
|
|
DATABASE_PATH=/app/data/sticker_bot.db
|
|
PREMIUM_CHECK_INTERVAL=24 # Hours, default: 24
|
|
|
|
# Optional: Remove.bg API for background removal
|
|
# 50 free calls/month
|
|
REMOVE_BG_API_KEY=your_remove_bg_api_key
|
|
```
|
|
|
|
## Useful Commands
|
|
|
|
```bash
|
|
# Check bot is running
|
|
sudo docker ps | grep stickerbot
|
|
|
|
# View logs
|
|
sudo docker-compose logs -f
|
|
|
|
# Database inspection
|
|
sqlite3 data/sticker_bot.db ".tables"
|
|
sqlite3 data/sticker_bot.db "SELECT * FROM sticker_sets;"
|
|
sqlite3 data/sticker_bot.db "SELECT * FROM api_usage;"
|
|
|
|
# Reset database
|
|
rm data/sticker_bot.db
|
|
|
|
# Rebuild container
|
|
sudo docker-compose up -d --build --force-recreate
|
|
```
|
|
|
|
## Important Notes
|
|
|
|
### Sticker Requirements
|
|
- **Static stickers**: 512x512px, WebP format, max 3MB
|
|
- **Animated stickers**: WebM (VP9), 512px one side, max 3s, max 256KB
|
|
- **Emoji**: One per sticker (can be changed later)
|
|
|
|
### Set Names
|
|
- Must end with `_by_<bot_username>` (handled automatically)
|
|
- 1-64 characters
|
|
- Only alphanumeric and underscores for short name
|
|
|
|
### Limits
|
|
- **Regular sets**: Max 120 stickers
|
|
- **Emoji sets**: Max 200 stickers
|
|
- **API calls**: 50/month for remove.bg (free tier)
|
|
|
|
### Best Practices
|
|
- Send images as file (not compressed photo) for best quality
|
|
- Use /start to return to main menu anytime
|
|
- Use /cancel to abort current operation
|
|
- Database persists in `./data/` volume
|
|
|
|
## API Methods Used
|
|
|
|
### Telegram Bot API
|
|
- `create_new_sticker_set()` - Create sticker sets
|
|
- `add_sticker_to_set()` - Add stickers
|
|
- `delete_sticker_from_set()` - Remove stickers
|
|
- `set_sticker_emoji_list()` - Change emoji
|
|
- `set_sticker_set_title()` - Rename set
|
|
- `delete_sticker_set()` - Delete entire set
|
|
- `get_sticker_set()` - Retrieve set info (for existing sets)
|
|
- `get_chat()` - Check premium status
|
|
|
|
### External APIs
|
|
- **Remove.bg API**: `POST https://api.remove.bg/v1.0/removebg` - Background removal
|
|
|
|
## Common Issues
|
|
|
|
1. **Import errors in IDE**: Install requirements.txt (`pip install -r requirements.txt`)
|
|
2. **Database locked**: Only one process should access SQLite at a time
|
|
3. **Sticker creation fails**: Check image format (must be valid image file)
|
|
4. **Premium check fails**: User must have started bot first
|
|
5. **API limit reached**: Check current usage with `/hilfe` or in database
|
|
6. **Background removal slow**: First run downloads ML model (~180MB)
|
|
7. **GIF conversion fails**: Ensure GIF is under 10MB before upload
|
|
8. **Docker build fails with Alpine**: We use `python:3.11-slim` (Debian) instead of Alpine because rembg requires compilation tools that don't work well with Alpine's musl libc
|
|
|
|
## Troubleshooting
|
|
|
|
### Docker Build Issues
|
|
If the Docker build fails with package errors:
|
|
```bash
|
|
# The Dockerfile uses Debian-based python:3.11-slim
|
|
# NOT Alpine - this is intentional for better Python package compatibility
|
|
|
|
# Check Dockerfile has correct base image:
|
|
grep "FROM" Dockerfile
|
|
# Should show: FROM python:3.11-slim
|
|
```
|
|
|
|
### Bot not responding
|
|
```bash
|
|
# Check if container is running
|
|
sudo docker ps | grep stickerbot
|
|
|
|
# Check logs for errors
|
|
sudo docker-compose logs -f
|
|
```
|
|
|
|
### Database issues
|
|
```bash
|
|
# Reset database (removes all data)
|
|
rm data/sticker_bot.db
|
|
sudo docker-compose restart
|
|
```
|
|
|
|
### API issues
|
|
- Verify REMOVE_BG_API_KEY is correct
|
|
- Check API usage in database: `sqlite3 data/sticker_bot.db "SELECT * FROM api_usage;"`
|
|
- API automatically falls back to local processing on errors
|
|
|
|
## CI/CD with Gitea Actions
|
|
|
|
The project includes automated Docker builds via Gitea Actions.
|
|
|
|
### Workflow Files
|
|
|
|
**`.gitea/workflows/docker-autobuild.yaml`** - Automatic builds on push
|
|
- Triggers on push to `main` or `master` branch
|
|
- Builds and pushes to local registry: `192.168.88.201:5000`
|
|
- Tags: `latest` and `v{run_number}-autobuild`
|
|
- Features:
|
|
- Path ignores for markdown/docs changes
|
|
- Docker Buildx with layer caching
|
|
- Automatic cleanup after build
|
|
|
|
**`.gitea/workflows/docker-build.yaml`** - Manual builds
|
|
- Triggered manually via Gitea web interface
|
|
- Options:
|
|
- Custom version tag (e.g., `1.0.0`, `v1.0.0`)
|
|
- Additional tags (comma-separated, e.g., `stable,production`)
|
|
- Toggle `latest` tag
|
|
- Features:
|
|
- Flexible versioning
|
|
- Multiple tag support
|
|
- Docker layer caching
|
|
|
|
### Required Secrets
|
|
|
|
Configure these in Gitea repository settings:
|
|
- `REGISTRY_USERNAME` - Username for Docker registry
|
|
- `REGISTRY_PASSWORD` - Password for Docker registry
|
|
|
|
### Registry Configuration
|
|
|
|
Default registry: `192.168.88.201:5000`
|
|
|
|
To change the registry, edit both workflow files:
|
|
```yaml
|
|
REGISTRY="your-registry:port"
|
|
```
|
|
|
|
## Version History
|
|
|
|
See git log for detailed commit history:
|
|
```bash
|
|
git log --oneline
|
|
```
|
|
|
|
Current features:
|
|
- ✅ Telegram Sticker Bot with full management capabilities
|
|
- ✅ Automatic image optimization (WebP conversion)
|
|
- ✅ GIF to Video Sticker conversion
|
|
- ✅ Background removal (local + API)
|
|
- ✅ Existing sticker set import
|
|
- ✅ Gitea Actions CI/CD
|