Refactor Shop and UI components to improve timeout handling for interactive views. Update timeout duration to 3 minutes and implement message replies for user feedback upon timeout in ShopView, PurchaseView, and InventoryView.
Some checks are pending
Run pre-commit / Run pre-commit (push) Waiting to run
Some checks are pending
Run pre-commit / Run pre-commit (push) Waiting to run
This commit is contained in:
parent
3ee6707cc5
commit
85de2c70c1
2 changed files with 38 additions and 16 deletions
12
shop/shop.py
12
shop/shop.py
|
@ -129,14 +129,14 @@ class Shop(commands.Cog):
|
||||||
color=discord.Color.blue()
|
color=discord.Color.blue()
|
||||||
)
|
)
|
||||||
view = InventoryView(ctx, inventory)
|
view = InventoryView(ctx, inventory)
|
||||||
await ctx.send(embed=embed, view=view)
|
view.message = await ctx.send(embed=embed, view=view)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
await view.wait()
|
await view.wait()
|
||||||
if view.selected_item: # An item was selected to use
|
if view.selected_item: # An item was selected to use
|
||||||
await self.pending_prompt(ctx, instance, inventory, view.selected_item)
|
await self.pending_prompt(ctx, instance, inventory, view.selected_item)
|
||||||
except asyncio.TimeoutError:
|
except asyncio.TimeoutError:
|
||||||
await ctx.send("Inventory view timed out.", ephemeral=True)
|
pass # Handled by view's on_timeout
|
||||||
|
|
||||||
async def inv_hook(self, user):
|
async def inv_hook(self, user):
|
||||||
"""Inventory Hook for outside cogs
|
"""Inventory Hook for outside cogs
|
||||||
|
@ -244,7 +244,7 @@ class Shop(commands.Cog):
|
||||||
|
|
||||||
view = PurchaseView(ctx, shop, item, item_data)
|
view = PurchaseView(ctx, shop, item, item_data)
|
||||||
embed = view.build_embed()
|
embed = view.build_embed()
|
||||||
await ctx.send(embed=embed, view=view)
|
view.message = await ctx.send(embed=embed, view=view)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
await view.wait()
|
await view.wait()
|
||||||
|
@ -253,7 +253,7 @@ class Shop(commands.Cog):
|
||||||
sm = ShopManager(ctx, instance, user_data)
|
sm = ShopManager(ctx, instance, user_data)
|
||||||
await sm.order(shop, item, view.quantity)
|
await sm.order(shop, item, view.quantity)
|
||||||
except asyncio.TimeoutError:
|
except asyncio.TimeoutError:
|
||||||
await ctx.send("Purchase menu timed out.", ephemeral=True)
|
pass # Handled by view's on_timeout
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# Open interactive shop menu
|
# Open interactive shop menu
|
||||||
|
@ -263,7 +263,7 @@ class Shop(commands.Cog):
|
||||||
color=discord.Color.blue()
|
color=discord.Color.blue()
|
||||||
)
|
)
|
||||||
view = ShopView(ctx, shops)
|
view = ShopView(ctx, shops)
|
||||||
await ctx.send(embed=embed, view=view)
|
view.message = await ctx.send(embed=embed, view=view)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
await view.wait()
|
await view.wait()
|
||||||
|
@ -272,7 +272,7 @@ class Shop(commands.Cog):
|
||||||
sm = ShopManager(ctx, instance, user_data)
|
sm = ShopManager(ctx, instance, user_data)
|
||||||
await sm.order(view.current_shop, view.current_item, view.quantity)
|
await sm.order(view.current_shop, view.current_item, view.quantity)
|
||||||
except asyncio.TimeoutError:
|
except asyncio.TimeoutError:
|
||||||
await ctx.send("Shop menu timed out.", ephemeral=True)
|
pass # Handled by view's on_timeout
|
||||||
|
|
||||||
@commands.max_concurrency(1, commands.BucketType.user)
|
@commands.max_concurrency(1, commands.BucketType.user)
|
||||||
@shop.command()
|
@shop.command()
|
||||||
|
|
42
shop/ui.py
42
shop/ui.py
|
@ -4,15 +4,15 @@ from typing import Optional, List, Dict, Any
|
||||||
from redbot.core.utils.chat_formatting import box, humanize_list
|
from redbot.core.utils.chat_formatting import box, humanize_list
|
||||||
|
|
||||||
class ShopView(View):
|
class ShopView(View):
|
||||||
def __init__(self, ctx, shops: Dict[str, Any], timeout: int = 60):
|
def __init__(self, ctx, shops: Dict[str, Any], timeout: int = 180): # 3 minutes timeout
|
||||||
super().__init__(timeout=timeout)
|
super().__init__(timeout=timeout)
|
||||||
self.ctx = ctx
|
self.ctx = ctx
|
||||||
self.shops = shops
|
self.shops = shops
|
||||||
self.current_shop = None
|
self.current_shop = None
|
||||||
self.current_item = None
|
self.current_item = None
|
||||||
self.quantity = None
|
self.quantity = None
|
||||||
|
self.message = None # Store message for timeout handling
|
||||||
self.setup_shop_select()
|
self.setup_shop_select()
|
||||||
# Add cancel button to a different row
|
|
||||||
cancel_button = Button(label="Cancel", style=discord.ButtonStyle.red, custom_id="cancel", row=4)
|
cancel_button = Button(label="Cancel", style=discord.ButtonStyle.red, custom_id="cancel", row=4)
|
||||||
cancel_button.callback = self.cancel
|
cancel_button.callback = self.cancel
|
||||||
self.add_item(cancel_button)
|
self.add_item(cancel_button)
|
||||||
|
@ -104,14 +104,20 @@ class ShopView(View):
|
||||||
self.quantity = purchase_view.quantity # Store the quantity from purchase view
|
self.quantity = purchase_view.quantity # Store the quantity from purchase view
|
||||||
self.stop() # Stop the shop view since we're done
|
self.stop() # Stop the shop view since we're done
|
||||||
|
|
||||||
|
async def on_timeout(self) -> None:
|
||||||
|
if self.message:
|
||||||
|
await self.message.reply("Shop menu timed out after 3 minutes of inactivity.", mention_author=True)
|
||||||
|
await self.message.edit(view=None)
|
||||||
|
|
||||||
class PurchaseView(View):
|
class PurchaseView(View):
|
||||||
def __init__(self, ctx, shop: str, item: str, item_data: Dict[str, Any], timeout: int = 60):
|
def __init__(self, ctx, shop: str, item: str, item_data: Dict[str, Any], timeout: int = 180): # 3 minutes timeout
|
||||||
super().__init__(timeout=timeout)
|
super().__init__(timeout=timeout)
|
||||||
self.ctx = ctx
|
self.ctx = ctx
|
||||||
self.shop = shop
|
self.shop = shop
|
||||||
self.item = item
|
self.item = item
|
||||||
self.item_data = item_data
|
self.item_data = item_data
|
||||||
self.quantity = None
|
self.quantity = None
|
||||||
|
self.message = None # Store message for timeout handling
|
||||||
|
|
||||||
# Add buttons with explicit row assignments
|
# Add buttons with explicit row assignments
|
||||||
buy_one = Button(label="Buy 1", style=discord.ButtonStyle.green, row=1)
|
buy_one = Button(label="Buy 1", style=discord.ButtonStyle.green, row=1)
|
||||||
|
@ -162,7 +168,7 @@ class PurchaseView(View):
|
||||||
await self.handle_purchase(interaction)
|
await self.handle_purchase(interaction)
|
||||||
|
|
||||||
@button(label="Custom Amount", style=discord.ButtonStyle.blurple, row=1)
|
@button(label="Custom Amount", style=discord.ButtonStyle.blurple, row=1)
|
||||||
async def custom_amount(self, interaction: discord.Interaction, button: Button):
|
async def custom_amount(self, interaction: discord.Interaction):
|
||||||
embed = discord.Embed(
|
embed = discord.Embed(
|
||||||
title="Custom Purchase Amount",
|
title="Custom Purchase Amount",
|
||||||
description="How many would you like to buy? Type a number in chat.",
|
description="How many would you like to buy? Type a number in chat.",
|
||||||
|
@ -178,11 +184,11 @@ class PurchaseView(View):
|
||||||
)
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
msg = await self.ctx.bot.wait_for("message", timeout=30.0, check=check)
|
msg = await self.ctx.bot.wait_for("message", timeout=60.0, check=check) # 1 minute to type amount
|
||||||
self.quantity = int(msg.content)
|
self.quantity = int(msg.content)
|
||||||
await self.handle_purchase(interaction)
|
await self.handle_purchase(interaction)
|
||||||
except asyncio.TimeoutError:
|
except asyncio.TimeoutError:
|
||||||
await interaction.followup.send("Purchase cancelled - took too long to respond.", ephemeral=True)
|
await interaction.message.reply("Custom amount entry timed out after 1 minute.", mention_author=True)
|
||||||
self.stop()
|
self.stop()
|
||||||
|
|
||||||
@button(label="Cancel", style=discord.ButtonStyle.red, row=1)
|
@button(label="Cancel", style=discord.ButtonStyle.red, row=1)
|
||||||
|
@ -227,14 +233,19 @@ class PurchaseView(View):
|
||||||
self.stop()
|
self.stop()
|
||||||
await interaction.response.edit_message(embed=embed, view=None)
|
await interaction.response.edit_message(embed=embed, view=None)
|
||||||
|
|
||||||
|
async def on_timeout(self) -> None:
|
||||||
|
if self.message:
|
||||||
|
await self.message.reply("Purchase menu timed out after 3 minutes of inactivity.", mention_author=True)
|
||||||
|
await self.message.edit(view=None)
|
||||||
|
|
||||||
class InventoryView(View):
|
class InventoryView(View):
|
||||||
def __init__(self, ctx, inventory: Dict[str, Any], timeout: int = 60):
|
def __init__(self, ctx, inventory: Dict[str, Any], timeout: int = 180): # 3 minutes timeout
|
||||||
super().__init__(timeout=timeout)
|
super().__init__(timeout=timeout)
|
||||||
self.ctx = ctx
|
self.ctx = ctx
|
||||||
self.inventory = inventory
|
self.inventory = inventory
|
||||||
self.selected_item = None
|
self.selected_item = None
|
||||||
|
self.message = None # Store message for timeout handling
|
||||||
self.setup_inventory_select()
|
self.setup_inventory_select()
|
||||||
# Add close button to a different row
|
|
||||||
close_button = Button(label="Close", style=discord.ButtonStyle.red, custom_id="close", row=4)
|
close_button = Button(label="Close", style=discord.ButtonStyle.red, custom_id="close", row=4)
|
||||||
close_button.callback = self.close
|
close_button.callback = self.close
|
||||||
self.add_item(close_button)
|
self.add_item(close_button)
|
||||||
|
@ -293,13 +304,19 @@ class InventoryView(View):
|
||||||
else:
|
else:
|
||||||
await interaction.response.edit_message(embed=embed)
|
await interaction.response.edit_message(embed=embed)
|
||||||
|
|
||||||
|
async def on_timeout(self) -> None:
|
||||||
|
if self.message:
|
||||||
|
await self.message.reply("Inventory menu timed out after 3 minutes of inactivity.", mention_author=True)
|
||||||
|
await self.message.edit(view=None)
|
||||||
|
|
||||||
class UseItemView(View):
|
class UseItemView(View):
|
||||||
def __init__(self, ctx, item: str, item_data: Dict[str, Any], timeout: int = 60):
|
def __init__(self, ctx, item: str, item_data: Dict[str, Any], timeout: int = 180): # 3 minutes timeout
|
||||||
super().__init__(timeout=timeout)
|
super().__init__(timeout=timeout)
|
||||||
self.ctx = ctx
|
self.ctx = ctx
|
||||||
self.item = item
|
self.item = item
|
||||||
self.item_data = item_data
|
self.item_data = item_data
|
||||||
self.value = False
|
self.value = False
|
||||||
|
self.message = None # Store message for timeout handling
|
||||||
|
|
||||||
async def interaction_check(self, interaction: discord.Interaction) -> bool:
|
async def interaction_check(self, interaction: discord.Interaction) -> bool:
|
||||||
if interaction.user != self.ctx.author:
|
if interaction.user != self.ctx.author:
|
||||||
|
@ -322,4 +339,9 @@ class UseItemView(View):
|
||||||
async def cancel(self, interaction: discord.Interaction, button: Button):
|
async def cancel(self, interaction: discord.Interaction, button: Button):
|
||||||
self.value = False
|
self.value = False
|
||||||
await interaction.response.edit_message(content="Cancelled.", embed=None, view=None)
|
await interaction.response.edit_message(content="Cancelled.", embed=None, view=None)
|
||||||
self.stop()
|
self.stop()
|
||||||
|
|
||||||
|
async def on_timeout(self) -> None:
|
||||||
|
if self.message:
|
||||||
|
await self.message.reply("Item use menu timed out after 3 minutes of inactivity.", mention_author=True)
|
||||||
|
await self.message.edit(view=None)
|
Loading…
Add table
Reference in a new issue