Implement user-specific interaction checks in ShopView, PurchaseView, and InventoryView to prevent unauthorized access. Update timeout handling to provide clearer feedback messages upon inactivity. Refactor button layout for better organization and improve embed field formatting for item details.
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
35e0ac182d
commit
dab195c57f
1 changed files with 41 additions and 63 deletions
104
shop/ui.py
104
shop/ui.py
|
@ -2,6 +2,7 @@ import discord
|
|||
from discord.ui import View, Select, Button, button, Item
|
||||
from typing import Optional, List, Dict, Any
|
||||
from redbot.core.utils.chat_formatting import box, humanize_list
|
||||
import asyncio
|
||||
|
||||
class ShopView(View):
|
||||
def __init__(self, ctx, shops: Dict[str, Any], timeout: int = 180): # 3 minutes timeout
|
||||
|
@ -50,6 +51,9 @@ class ShopView(View):
|
|||
self.add_item(shop_select)
|
||||
|
||||
async def shop_selected(self, interaction: discord.Interaction):
|
||||
if interaction.user != self.ctx.author:
|
||||
return await interaction.response.send_message("This menu is not for you!", ephemeral=True)
|
||||
|
||||
shop_name = interaction.data["values"][0]
|
||||
self.current_shop = shop_name
|
||||
|
||||
|
@ -89,6 +93,9 @@ class ShopView(View):
|
|||
await interaction.response.edit_message(embed=embed, view=self)
|
||||
|
||||
async def item_selected(self, interaction: discord.Interaction):
|
||||
if interaction.user != self.ctx.author:
|
||||
return await interaction.response.send_message("This menu is not for you!", ephemeral=True)
|
||||
|
||||
item_name = interaction.data["values"][0]
|
||||
self.current_item = item_name
|
||||
item_data = self.shops[self.current_shop]["Items"][item_name]
|
||||
|
@ -106,8 +113,7 @@ class ShopView(View):
|
|||
|
||||
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)
|
||||
await self.message.edit(content="Shop menu timed out after 3 minutes of inactivity.", view=None)
|
||||
|
||||
class PurchaseView(View):
|
||||
def __init__(self, ctx, shop: str, item: str, item_data: Dict[str, Any], timeout: int = 180): # 3 minutes timeout
|
||||
|
@ -120,19 +126,19 @@ class PurchaseView(View):
|
|||
self.message = None # Store message for timeout handling
|
||||
|
||||
# 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=0)
|
||||
buy_one.callback = self.buy_one
|
||||
self.add_item(buy_one)
|
||||
|
||||
buy_five = Button(label="Buy 5", style=discord.ButtonStyle.green, row=1)
|
||||
buy_five = Button(label="Buy 5", style=discord.ButtonStyle.green, row=0)
|
||||
buy_five.callback = self.buy_five
|
||||
self.add_item(buy_five)
|
||||
|
||||
custom = Button(label="Custom Amount", style=discord.ButtonStyle.blurple, row=1)
|
||||
custom = Button(label="Custom Amount", style=discord.ButtonStyle.blurple, row=0)
|
||||
custom.callback = self.custom_amount
|
||||
self.add_item(custom)
|
||||
|
||||
cancel = Button(label="Cancel", style=discord.ButtonStyle.red, row=1)
|
||||
cancel = Button(label="Cancel", style=discord.ButtonStyle.red, row=0)
|
||||
cancel.callback = self.cancel
|
||||
self.add_item(cancel)
|
||||
|
||||
|
@ -148,26 +154,27 @@ class PurchaseView(View):
|
|||
description=self.item_data["Info"],
|
||||
color=discord.Color.blue()
|
||||
)
|
||||
qty = "Infinite" if self.item_data["Qty"] == "--" else self.item_data["Qty"]
|
||||
e.add_field(name="Stock", value=qty, inline=True)
|
||||
|
||||
# First row of fields
|
||||
e.add_field(name="Stock", value="Infinite" if self.item_data["Qty"] == "--" else self.item_data["Qty"], inline=True)
|
||||
e.add_field(name="Cost", value=self.item_data["Cost"], inline=True)
|
||||
e.add_field(name="Type", value=self.item_data["Type"].title(), inline=True)
|
||||
|
||||
# Add role in a new row if it's a role type item
|
||||
if self.item_data["Type"] == "role":
|
||||
e.add_field(name="Role", value=self.item_data["Role"], inline=True)
|
||||
e.add_field(name="Role", value=self.item_data["Role"], inline=False)
|
||||
|
||||
e.set_footer(text="Select a quantity to purchase")
|
||||
return e
|
||||
|
||||
@button(label="Buy 1", style=discord.ButtonStyle.green, row=1)
|
||||
async def buy_one(self, interaction: discord.Interaction, button: Button):
|
||||
async def buy_one(self, interaction: discord.Interaction):
|
||||
self.quantity = 1
|
||||
await self.handle_purchase(interaction)
|
||||
|
||||
@button(label="Buy 5", style=discord.ButtonStyle.green, row=1)
|
||||
async def buy_five(self, interaction: discord.Interaction, button: Button):
|
||||
async def buy_five(self, interaction: discord.Interaction):
|
||||
self.quantity = 5
|
||||
await self.handle_purchase(interaction)
|
||||
|
||||
@button(label="Custom Amount", style=discord.ButtonStyle.blurple, row=1)
|
||||
async def custom_amount(self, interaction: discord.Interaction):
|
||||
embed = discord.Embed(
|
||||
title="Custom Purchase Amount",
|
||||
|
@ -191,8 +198,7 @@ class PurchaseView(View):
|
|||
await interaction.message.reply("Custom amount entry timed out after 1 minute.", mention_author=True)
|
||||
self.stop()
|
||||
|
||||
@button(label="Cancel", style=discord.ButtonStyle.red, row=1)
|
||||
async def cancel(self, interaction: discord.Interaction, button: Button):
|
||||
async def cancel(self, interaction: discord.Interaction):
|
||||
await interaction.response.edit_message(content="Purchase cancelled.", embed=None, view=None)
|
||||
self.stop()
|
||||
|
||||
|
@ -235,8 +241,7 @@ class PurchaseView(View):
|
|||
|
||||
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)
|
||||
await self.message.edit(content="Purchase menu timed out after 3 minutes of inactivity.", view=None)
|
||||
|
||||
class InventoryView(View):
|
||||
def __init__(self, ctx, inventory: Dict[str, Any], timeout: int = 180): # 3 minutes timeout
|
||||
|
@ -281,67 +286,40 @@ class InventoryView(View):
|
|||
self.add_item(inv_select)
|
||||
|
||||
async def item_selected(self, interaction: discord.Interaction):
|
||||
item_name = interaction.data["values"][0]
|
||||
self.selected_item = item_name
|
||||
item_data = self.inventory[item_name]
|
||||
|
||||
embed = discord.Embed(
|
||||
title=item_name,
|
||||
description=item_data["Info"],
|
||||
color=discord.Color.blue()
|
||||
)
|
||||
embed.add_field(name="Quantity", value=item_data["Qty"], inline=True)
|
||||
embed.add_field(name="Type", value=item_data["Type"].title(), inline=True)
|
||||
|
||||
if item_data["Type"] == "role":
|
||||
use_view = UseItemView(self.ctx, item_name, item_data)
|
||||
await interaction.response.edit_message(embed=embed, view=use_view)
|
||||
if interaction.user != self.ctx.author:
|
||||
return await interaction.response.send_message("This menu is not for you!", ephemeral=True)
|
||||
|
||||
# Wait for the use view to complete
|
||||
await use_view.wait()
|
||||
if use_view.value: # If item was used
|
||||
self.stop() # Stop the inventory view
|
||||
else:
|
||||
await interaction.response.edit_message(embed=embed)
|
||||
self.selected_item = interaction.data["values"][0]
|
||||
self.stop()
|
||||
|
||||
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)
|
||||
await self.message.edit(content="Inventory menu timed out after 3 minutes of inactivity.", view=None)
|
||||
|
||||
class UseItemView(View):
|
||||
def __init__(self, ctx, item: str, item_data: Dict[str, Any], timeout: int = 180): # 3 minutes timeout
|
||||
def __init__(self, ctx, item_name: str, timeout: int = 60):
|
||||
super().__init__(timeout=timeout)
|
||||
self.ctx = ctx
|
||||
self.item = item
|
||||
self.item_data = item_data
|
||||
self.value = False
|
||||
self.message = None # Store message for timeout handling
|
||||
self.item_name = item_name
|
||||
self.value = None
|
||||
self.message = None
|
||||
|
||||
async def interaction_check(self, interaction: discord.Interaction) -> bool:
|
||||
@button(label="Use", style=discord.ButtonStyle.green)
|
||||
async def use(self, interaction: discord.Interaction, button: Button):
|
||||
if interaction.user != self.ctx.author:
|
||||
await interaction.response.send_message("This menu is not for you!", ephemeral=True)
|
||||
return False
|
||||
return True
|
||||
|
||||
@button(label="Use Item", style=discord.ButtonStyle.green)
|
||||
async def use_item(self, interaction: discord.Interaction, button: Button):
|
||||
return await interaction.response.send_message("This menu is not for you!", ephemeral=True)
|
||||
self.value = True
|
||||
embed = discord.Embed(
|
||||
title="Using Item",
|
||||
description=f"Processing use of {self.item}...",
|
||||
color=discord.Color.green()
|
||||
)
|
||||
await interaction.response.edit_message(embed=embed, view=None)
|
||||
self.stop()
|
||||
await interaction.response.defer()
|
||||
|
||||
@button(label="Cancel", style=discord.ButtonStyle.red)
|
||||
async def cancel(self, interaction: discord.Interaction, button: Button):
|
||||
if interaction.user != self.ctx.author:
|
||||
return await interaction.response.send_message("This menu is not for you!", ephemeral=True)
|
||||
self.value = False
|
||||
await interaction.response.edit_message(content="Cancelled.", embed=None, view=None)
|
||||
self.stop()
|
||||
|
||||
await interaction.response.defer()
|
||||
|
||||
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)
|
||||
await self.message.edit(content="Item use menu timed out.", view=None)
|
Loading…
Add table
Reference in a new issue