Files
echoes-of-the-ash/docs/development/BOT_MODULE.md
Joan 861f3b8a36 Add visual progress bars and refactor handler modules
- Implement visual HP/Stamina/XP bars using Unicode characters (██░)
- Refactor handlers.py (1308 → 377 lines) into specialized modules:
  * action_handlers.py - World interaction and status display
  * inventory_handlers.py - Inventory management
  * combat_handlers.py - Combat actions
  * profile_handlers.py - Character stats with visual bars
  * corpse_handlers.py - Looting system
  * pickup_handlers.py - Item collection
- Add utility functions: create_progress_bar(), format_stat_bar()
- Organize all documentation into docs/ structure
- Create comprehensive documentation index with navigation
- Add UI examples showing before/after visual improvements
2025-10-19 00:23:44 +02:00

299 lines
7.5 KiB
Markdown

# 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