""" Inventory-related action handlers. """ import logging from telegram import InlineKeyboardButton, InlineKeyboardMarkup from . import keyboards, logic from data.world_loader import game_world from data.items import ITEMS logger = logging.getLogger(__name__) async def handle_inventory_menu(query, user_id: int, player: dict, data: list = None): """Display player inventory with item management options.""" from .utils import format_stat_bar from .api_client import api_client await query.answer() # Get inventory from API inv_result = await api_client.get_inventory(player['id']) inventory_items = inv_result.get('inventory', []) current_weight, current_volume = logic.calculate_inventory_load(inventory_items) max_weight, max_volume = logic.get_player_capacity(inventory_items, player) text = "šŸŽ’ Your Inventory:\n" text += f"{format_stat_bar('HP', 'ā¤ļø', player['hp'], player['max_hp'])}\n" text += f"{format_stat_bar('Stamina', '⚔', player['stamina'], player['max_stamina'])}\n" text += f"šŸ“Š Weight: {current_weight}/{max_weight} kg\n" text += f"šŸ“¦ Volume: {current_volume}/{max_volume} vol\n" if not inventory_items: text += "\nYour inventory is empty." location = game_world.get_location(player['location_id']) location_image = location.image_path if location else None from .handlers import send_or_edit_with_image await send_or_edit_with_image( query, text=text, reply_markup=keyboards.inventory_keyboard(inventory_items), image_path=location_image ) async def handle_inventory_item(query, user_id: int, player: dict, data: list): """Show details for a specific inventory item. Note: item_db_id is the inventory row id from the API response. We need to get the full inventory and find the item by id. """ from .api_client import api_client await query.answer() item_db_id = int(data[1]) # Get inventory from API inv_result = await api_client.get_inventory(user_id) inventory_items = inv_result.get('inventory', []) # Find the specific item item = next((i for i in inventory_items if i['id'] == item_db_id), None) if not item: await query.answer("Item not found in inventory", show_alert=True) return emoji = item.get('emoji', 'ā”') # Build item details text text = f"{emoji} {item.get('name', 'Unknown')}\n" description = item.get('description') if description: text += f"{description}\n\n" else: text += "\n" text += f"Weight: {item.get('weight', 0)} kg | Volume: {item.get('volume', 0)} vol\n" # Add weapon stats if applicable if item.get('type') == 'weapon': text += f"Damage: {item.get('damage_min', 0)}-{item.get('damage_max', 0)}\n" # Add consumable effects if applicable if item.get('type') == 'consumable': effects = [] if item.get('hp_restore'): effects.append(f"ā¤ļø +{item.get('hp_restore')} HP") if item.get('stamina_restore'): effects.append(f"⚔ +{item.get('stamina_restore')} Stamina") if effects: text += f"Effects: {', '.join(effects)}\n" # Add equipped status if item.get('is_equipped'): text += "\nāœ… Currently Equipped" location = game_world.get_location(player['location_id']) location_image = location.image_path if location else None from .handlers import send_or_edit_with_image await send_or_edit_with_image( query, text=text, reply_markup=keyboards.inventory_item_actions_keyboard( item_db_id, item, item.get('is_equipped', False), item['quantity'] ), image_path=location_image ) async def handle_inventory_use(query, user_id: int, player: dict, data: list): """Use a consumable item from inventory.""" from .utils import format_stat_bar from .api_client import api_client item_db_id = int(data[1]) # Get inventory from API to find the item inv_result = await api_client.get_inventory(user_id) inventory_items = inv_result.get('inventory', []) item = next((i for i in inventory_items if i['id'] == item_db_id), None) if not item: await query.answer("Item not found.", show_alert=False) return if item.get('type') != 'consumable': await query.answer("This item cannot be used.", show_alert=False) return await query.answer() # Use the API to use the item result = await api_client.use_item(user_id, item['item_id']) if not result.get('success'): await query.answer(result.get('message', 'Failed to use item'), show_alert=True) return # Refresh player data to get updated stats player = await api_client.get_player_by_id(user_id) # Get updated inventory inv_result = await api_client.get_inventory(user_id) inventory_items = inv_result.get('inventory', []) current_weight, current_volume = logic.calculate_inventory_load(inventory_items) max_weight, max_volume = logic.get_player_capacity(inventory_items, player) # Build status section with HP/Stamina bars text = "šŸŽ’ Your Inventory:\n" text += f"{format_stat_bar('HP', 'ā¤ļø', player['hp'], player['max_hp'])}\n" text += f"{format_stat_bar('Stamina', '⚔', player['stamina'], player['max_stamina'])}\n" text += f"šŸ“Š Weight: {current_weight}/{max_weight} kg\n" text += f"šŸ“¦ Volume: {current_volume}/{max_volume} vol\n" text += "━━━━━━━━━━━━━━━━━━━━\n" # Build result message from API response text += result.get('message', 'Item used.') location = game_world.get_location(player['location_id']) location_image = location.image_path if location else None from .handlers import send_or_edit_with_image await send_or_edit_with_image( query, text=text, reply_markup=keyboards.inventory_keyboard(inventory_items), image_path=location_image ) async def handle_inventory_drop(query, user_id: int, player: dict, data: list): """Drop an item from inventory to the world.""" from .api_client import api_client item_db_id = int(data[1]) drop_amount_str = data[2] if len(data) > 2 else None # Get inventory to find the item inv_result = await api_client.get_inventory(user_id) inventory_items = inv_result.get('inventory', []) item = next((i for i in inventory_items if i['id'] == item_db_id), None) if not item: await query.answer("Item not found.", show_alert=False) return # Determine how much to drop if drop_amount_str is None or drop_amount_str == "all": drop_amount = item['quantity'] else: drop_amount = min(int(drop_amount_str), item['quantity']) # Use API to drop item result = await api_client.drop_item(user_id, item['item_id'], drop_amount) if result.get('success'): await query.answer(result.get('message', f"Dropped {drop_amount}x {item['name']}"), show_alert=False) else: await query.answer(result.get('message', 'Failed to drop item'), show_alert=True) return # Get updated inventory inv_result = await api_client.get_inventory(user_id) inventory_items = inv_result.get('inventory', []) current_weight, current_volume = logic.calculate_inventory_load(inventory_items) max_weight, max_volume = logic.get_player_capacity(inventory_items, player) text = "šŸŽ’ Your Inventory:\n" text += f"šŸ“Š Weight: {current_weight}/{max_weight} kg\n" text += f"šŸ“¦ Volume: {current_volume}/{max_volume} vol\n\n" if not inventory_items: text += "It's empty." location = game_world.get_location(player['location_id']) location_image = location.image_path if location else None from .handlers import send_or_edit_with_image await send_or_edit_with_image( query, text=text, reply_markup=keyboards.inventory_keyboard(inventory_items), image_path=location_image ) async def handle_inventory_equip(query, user_id: int, player: dict, data: list): """Equip an item from inventory.""" from .api_client import api_client item_db_id = int(data[1]) # Get inventory to find the item inv_result = await api_client.get_inventory(user_id) inventory_items = inv_result.get('inventory', []) item = next((i for i in inventory_items if i['id'] == item_db_id), None) if not item: await query.answer("Item not found.", show_alert=False) return if not item.get('equippable'): await query.answer("This item cannot be equipped.", show_alert=False) return # Use API to equip item result = await api_client.equip_item(user_id, item['item_id']) if not result.get('success'): await query.answer(result.get('message', 'Failed to equip item'), show_alert=True) return await query.answer(result.get('message', f"Equipped {item['name']}!"), show_alert=False) # Refresh the item view emoji = item.get('emoji', 'ā”') text = f"{emoji} {item.get('name', 'Unknown')}\n" description = item.get('description') if description: text += f"{description}\n\n" else: text += "\n" text += f"Weight: {item.get('weight', 0)} kg | Volume: {item.get('volume', 0)} vol\n" if item.get('type') == 'weapon': text += f"Damage: {item.get('damage_min', 0)}-{item.get('damage_max', 0)}\n" text += "\nāœ… Currently Equipped" location = game_world.get_location(player['location_id']) location_image = location.image_path if location else None from .handlers import send_or_edit_with_image await send_or_edit_with_image( query, text=text, reply_markup=keyboards.inventory_item_actions_keyboard( item_db_id, item, True, item['quantity'] ), image_path=location_image ) async def handle_inventory_unequip(query, user_id: int, player: dict, data: list): """Unequip an item.""" from .api_client import api_client item_db_id = int(data[1]) # Get inventory to find the item inv_result = await api_client.get_inventory(user_id) inventory_items = inv_result.get('inventory', []) item = next((i for i in inventory_items if i['id'] == item_db_id), None) if not item: await query.answer("Item not found.", show_alert=False) return # Use API to unequip item result = await api_client.unequip_item(user_id, item['item_id']) if not result.get('success'): await query.answer(result.get('message', 'Failed to unequip item'), show_alert=True) return await query.answer(result.get('message', f"Unequipped {item['name']}."), show_alert=False) # Refresh the item view emoji = item.get('emoji', 'ā”') text = f"{emoji} {item.get('name', 'Unknown')}\n" description = item.get('description') if description: text += f"{description}\n\n" else: text += "\n" text += f"Weight: {item.get('weight', 0)} kg | Volume: {item.get('volume', 0)} vol\n" if item.get('type') == 'weapon': text += f"Damage: {item.get('damage_min', 0)}-{item.get('damage_max', 0)}\n" location = game_world.get_location(player['location_id']) location_image = location.image_path if location else None from .handlers import send_or_edit_with_image await send_or_edit_with_image( query, text=text, reply_markup=keyboards.inventory_item_actions_keyboard( item_db_id, item, False, item['quantity'] ), image_path=location_image )