# Bot Module Documentation ## Overview The bot module contains all the Telegram bot logic for "Echoes of the Ashes" RPG game. ## Module Structure ### Core Modules - **`handlers.py`** (14KB) - Main message router and utility functions - **`database.py`** - Database operations and queries - **`keyboards.py`** - Telegram keyboard layouts - **`logic.py`** - Game logic and calculations - **`combat.py`** (17KB) - Combat system implementation - **`spawn_manager.py`** - Enemy spawning system - **`utils.py`** - Utility functions and decorators ### Handler Modules (Refactored) Organized by functionality for better maintainability: #### **`action_handlers.py`** (14KB, 367 lines) World interaction and inspection - `get_player_status_text()` - Player status display - `handle_inspect_area()` - Inspect locations - `handle_attack_wandering()` - Attack wandering enemies - `handle_inspect_interactable()` - Inspect objects - `handle_action()` - Perform actions - `handle_main_menu()` - Main menu navigation - `handle_move_menu()` - Movement menu - `handle_move()` - Travel between locations #### **`inventory_handlers.py`** (13KB, 355 lines) Inventory management system - `handle_inventory_menu()` - Show inventory - `handle_inventory_item()` - Item details - `handle_inventory_use()` - Use consumables - `handle_inventory_drop()` - Drop items - `handle_inventory_equip()` - Equip gear - `handle_inventory_unequip()` - Unequip gear #### **`pickup_handlers.py`** (5.1KB, 135 lines) Item collection from world - `handle_pickup_menu()` - Pickup options - `handle_pickup()` - Pick up items #### **`combat_handlers.py`** (6.3KB, 171 lines) Combat action handlers - `handle_combat_attack()` - Attack enemy - `handle_combat_flee()` - Flee combat - `handle_combat_use_item_menu()` - Combat items menu - `handle_combat_use_item()` - Use item in combat - `handle_combat_back()` - Return to combat menu #### **`profile_handlers.py`** (6.0KB, 147 lines) Character progression - `handle_profile()` - View profile - `handle_spend_points_menu()` - Stat points menu - `handle_spend_point()` - Allocate stat points #### **`corpse_handlers.py`** (8.2KB, 234 lines) Looting system - `handle_loot_player_corpse()` - Loot player corpses - `handle_take_corpse_item()` - Take items from player corpse - `handle_scavenge_npc_corpse()` - Scavenge NPC corpses - `handle_scavenge_corpse_item()` - Take items from NPC corpse ## Architecture ### Message Flow ``` Telegram Update ↓ main.py (Application setup) ↓ handlers.py::button_handler (Router) ↓ Specialized Handler (action_handlers, combat_handlers, etc.) ↓ database.py (Data operations) ↓ keyboards.py (UI response) ↓ Response to User ``` ### Handler Pattern All handlers follow a consistent pattern: ```python async def handle_action(query, user_id: int, player: dict, data: list = None): """ Handle specific action. Args: query: Telegram callback query object user_id: Telegram user ID player: Player data dict data: Optional list of parameters from callback_data """ # 1. Validate input # 2. Perform action # 3. Update database # 4. Send response with send_or_edit_with_image() ``` ### Shared Utilities #### `send_or_edit_with_image()` Central function for sending/editing messages with images: ```python await send_or_edit_with_image( query, text="Message text", reply_markup=keyboard, image_path="/path/to/image.png" # Optional ) ``` Features: - Smooth image transitions - Image caching for performance - Automatic fallback to text-only - Edit vs. send detection ## Design Principles ### 1. Separation of Concerns Each module handles a specific domain: - Handlers → User interaction - Database → Data persistence - Logic → Game rules - Combat → Battle mechanics ### 2. Single Responsibility Each function has one clear purpose: - ✅ `handle_inventory_use()` - Use items - ✅ `handle_combat_attack()` - Attack in combat - ❌ ~~One giant function that does everything~~ ### 3. Consistency All handlers: - Accept same parameter pattern - Use async/await - Handle errors gracefully - Log important actions ### 4. Error Handling Centralized in `button_handler`: ```python try: await handle_specific_action(...) except Exception as e: logger.error(f"Error: {e}", exc_info=True) await query.answer("An error occurred.", show_alert=True) ``` ## Adding New Handlers ### Step 1: Create Handler Function ```python # In appropriate *_handlers.py module async def handle_new_action(query, user_id: int, player: dict, data: list): """Handle new action.""" await query.answer() # Your logic here from .handlers import send_or_edit_with_image await send_or_edit_with_image( query, text="Action result", reply_markup=some_keyboard() ) ``` ### Step 2: Import in handlers.py ```python from .your_handlers import handle_new_action ``` ### Step 3: Add Route ```python # In button_handler() elif action_type == "new_action": await handle_new_action(query, user_id, player, data) ``` ### Step 4: Create Keyboard Button ```python # In keyboards.py InlineKeyboardButton( "New Action", callback_data="new_action:param1:param2" ) ``` ## Testing ### Manual Testing 1. Start the bot: `python main.py` 2. Send `/start` to the bot 3. Test each button action 4. Check logs for errors ### Unit Testing (Future) ```python # tests/test_handlers.py async def test_handle_inventory_use(): result = await handle_inventory_use( mock_query, user_id=123, player=mock_player, data=['inventory_use', '1'] ) assert result is not None ``` ## Performance Considerations ### Image Caching Images are cached after first upload: ```python cached_file_id = await database.get_cached_image(image_path) if not cached_file_id: # Upload and cache await database.cache_image(image_path, file_id) ``` ### Database Queries - Use indexed lookups (user_id, location_id) - Batch operations where possible - Async all the way ### Memory - Don't store large objects in memory - Use database for persistence - Clean up old data periodically ## Debugging ### Enable Debug Logging ```python # In main.py logging.basicConfig( level=logging.DEBUG, # Change from INFO format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' ) ``` ### Common Issues **Issue:** Handler not being called - Check callback_data format: `"action_type:param1:param2"` - Verify route exists in `button_handler()` - Check import statement **Issue:** Image not showing - Verify image path exists - Check image cache - Look for upload errors in logs **Issue:** Database errors - Check player exists - Verify foreign key relationships - Look at database schema ## Migration Guide ### From Old handlers.py Old code in backup files: - `backups/handlers_original.py` - `backups/handlers.py.old` All functionality preserved, just reorganized into modules. ## Future Enhancements 1. **Type Hints** - Add proper type annotations 2. **Unit Tests** - Test coverage for all handlers 3. **Decorators** - Common validations (requires_combat, requires_stamina) 4. **Base Classes** - Handler base class with common functionality 5. **Event System** - Decouple actions from responses ## Contributing When adding new features: 1. Choose the appropriate handler module (or create new one) 2. Follow the existing pattern 3. Add docstrings 4. Log important actions 5. Handle errors gracefully 6. Update this documentation ## Questions? See also: - `REFACTORING_NOTES.md` - Refactoring details - `HANDLER_REFACTORING_SUMMARY.md` - Before/after comparison - `README.md` - Project overview