# 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 - **Environment**: python-dotenv for configuration ### Project Structure ``` stickerbot/ ├── bot.py # Main bot with ConversationHandler ├── config.py # Configuration and environment loading ├── database.py # SQLite database operations ├── sticker_manager.py # Sticker management utilities ├── image_processor.py # Automatic image conversion ├── gif_processor.py # GIF to WebM conversion ├── background_remover.py # Background removal (local + API) ├── requirements.txt # Python dependencies ├── Dockerfile # Docker image configuration ├── docker-compose.yml # Docker Compose configuration ├── .env.example # Environment template └── data/ # Persistent data directory ``` ### 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_` 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_` (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 ## Troubleshooting ### 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