"""
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
)