Skip to content
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions cogs/threadmenu.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,9 @@ def typecheck(m):
if label.lower() == "cancel":
return await ctx.send("Cancelled.")

if label.lower() == "main menu":
return await ctx.send("You cannot use that label.")

if sanitized_label in conf["options"]:
await ctx.send("That option already exists. Use `threadmenu edit` to edit it.")
return
Expand Down
108 changes: 84 additions & 24 deletions core/thread.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,16 +224,12 @@ async def snooze(self, moderator=None, command_used=None, snooze_for=None):
"author_name": (
getattr(m.embeds[0].author, "name", "").split(" (")[0]
if m.embeds and m.embeds[0].author and m.author == self.bot.user
else getattr(m.author, "name", None)
if m.author != self.bot.user
else None
else getattr(m.author, "name", None) if m.author != self.bot.user else None
),
"author_avatar": (
getattr(m.embeds[0].author, "icon_url", None)
if m.embeds and m.embeds[0].author and m.author == self.bot.user
else m.author.display_avatar.url
if m.author != self.bot.user
else None
else m.author.display_avatar.url if m.author != self.bot.user else None
),
}
async for m in channel.history(limit=None, oldest_first=True)
Expand Down Expand Up @@ -849,11 +845,9 @@ async def send_genesis_message():
if getattr(self, "_selected_thread_creation_menu_option", None) and self.bot.config.get(
"thread_creation_menu_selection_log"
):
opt = self._selected_thread_creation_menu_option
path = self._selected_thread_creation_menu_option
try:
log_txt = f"Selected menu option: {opt.get('label')} ({opt.get('type')})"
if opt.get("type") == "command":
log_txt += f" -> {opt.get('callback')}"
log_txt = f"Selected menu path: {' -> '.join(path)}"
await channel.send(embed=discord.Embed(description=log_txt, color=self.bot.mod_color))
except Exception:
logger.warning(
Expand Down Expand Up @@ -2659,29 +2653,44 @@ async def create(
placeholder = "Select an option to contact the staff team."
timeout = 20

options = self.bot.config.get("thread_creation_menu_options") or {}
submenus = self.bot.config.get("thread_creation_menu_submenus") or {}

# Minimal inline view implementation (avoid importing plugin code)

thread.ready = False # not ready yet

class _ThreadCreationMenuSelect(discord.ui.Select):
def __init__(self, outer_thread: Thread):
def __init__(
self,
bot,
outer_thread: Thread,
option_data: dict,
menu_msg: discord.Message,
path: list,
is_home: bool = True,
):
self.bot = bot
self.outer_thread = outer_thread
opts = [
self.option_data = option_data
self.menu_msg = menu_msg
self.path = path
options = [
discord.SelectOption(
label=o["label"],
description=o["description"],
emoji=o["emoji"],
)
for o in options.values()
for o in option_data.values()
]
if not is_home:
options.append(
discord.SelectOption(
label="main menu", description="Return to the main menu", emoji="🏠"
)
)
super().__init__(
placeholder=placeholder,
min_values=1,
max_values=1,
options=opts,
options=options,
)

async def callback(self, interaction: discord.Interaction):
Expand All @@ -2696,8 +2705,35 @@ async def callback(self, interaction: discord.Interaction):
chosen_label = self.values[0]
# Resolve option key
key = chosen_label.lower().replace(" ", "_")
selected = options.get(key)
self.outer_thread._selected_thread_creation_menu_option = selected
if key == "main_menu":
# From a submenu, go back to main menu. This is achieved by rebuilding the view.
option_data = self.bot.config.get("thread_creation_menu_options") or {}
new_view = _ThreadCreationMenuView(
self.bot,
self.outer_thread,
option_data,
self.menu_msg,
path=[],
is_home=True,
)
return await self.menu_msg.edit(view=new_view)
self.path.append(chosen_label)
selected: dict = self.option_data.get(key, {})
if selected.get("type", "command") == "submenu":
# Build new view for submenu
submenu_data = self.bot.config.get("thread_creation_menu_submenus") or {}
option_data = submenu_data.get(key, {})
new_view = _ThreadCreationMenuView(
self.bot,
self.outer_thread,
option_data,
self.menu_msg,
path=self.path,
is_home=False,
)
return await self.menu_msg.edit(view=new_view)

self.outer_thread._selected_thread_creation_menu_option = self.path
# Reflect the selection in the original DM by editing the embed/body
try:
msg = getattr(interaction, "message", None)
Expand Down Expand Up @@ -2936,10 +2972,30 @@ async def callback(self, interaction: discord.Interaction):
ctx_.command.checks = old_checks

class _ThreadCreationMenuView(discord.ui.View):
def __init__(self, outer_thread: Thread):
def __init__(
self,
bot,
outer_thread: Thread,
option_data: dict,
menu_msg: discord.Message,
path: list,
is_home: bool = True,
):
super().__init__(timeout=timeout)
self.outer_thread = outer_thread
self.add_item(_ThreadCreationMenuSelect(outer_thread))
self.path = path
self.menu_msg = menu_msg
self.option_data = option_data
self.add_item(
_ThreadCreationMenuSelect(
bot,
outer_thread,
option_data=option_data,
menu_msg=menu_msg,
path=self.path,
is_home=is_home,
)
)

async def on_timeout(self):
# Timeout -> abort thread creation
Expand Down Expand Up @@ -3061,8 +3117,12 @@ async def on_timeout(self):
embed.set_thumbnail(url=embed_thumb)
except Exception as e:
logger.debug("Thumbnail set failed (ignored): %s", e)
menu_view = _ThreadCreationMenuView(thread)
menu_msg = await recipient.send(embed=embed, view=menu_view)
menu_msg = await recipient.send(embed=embed)
option_data = self.bot.config.get("thread_creation_menu_options") or {}
menu_view = _ThreadCreationMenuView(
self.bot, thread, option_data, menu_msg, path=[], is_home=True
)
menu_msg = await menu_msg.edit(view=menu_view)
# mark thread as pending menu selection
thread._pending_menu = True
# Explicitly attach the message to the view for safety in callbacks
Expand Down Expand Up @@ -3135,10 +3195,10 @@ async def callback(self, interaction: discord.Interaction):
"Failed unsnoozing thread prior to precreate menu selection; continuing.",
exc_info=True,
)
# Define selection variables
chosen_label = self.values[0]
key = chosen_label.lower().replace(" ", "_")
selected = options.get(key)
self.outer_thread._selected_thread_creation_menu_option = selected
# Remove the view
try:
msg = getattr(interaction, "message", None)
Expand Down
Loading