Skip to content

Commit 55dc8c8

Browse files
committed
threadmenu: submenu navigation fixes
Refactor thread creation menu handling to improve path management and submenu navigation.
1 parent 0945f03 commit 55dc8c8

File tree

2 files changed

+96
-23
lines changed

2 files changed

+96
-23
lines changed

cogs/threadmenu.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,9 @@ def typecheck(m):
178178
if label.lower() == "cancel":
179179
return await ctx.send("Cancelled.")
180180

181+
if label.lower() == "main menu":
182+
return await ctx.send("You cannot use that label.")
183+
181184
if sanitized_label in conf["options"]:
182185
await ctx.send("That option already exists. Use `threadmenu edit` to edit it.")
183186
return

core/thread.py

Lines changed: 93 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -224,16 +224,12 @@ async def snooze(self, moderator=None, command_used=None, snooze_for=None):
224224
"author_name": (
225225
getattr(m.embeds[0].author, "name", "").split(" (")[0]
226226
if m.embeds and m.embeds[0].author and m.author == self.bot.user
227-
else getattr(m.author, "name", None)
228-
if m.author != self.bot.user
229-
else None
227+
else getattr(m.author, "name", None) if m.author != self.bot.user else None
230228
),
231229
"author_avatar": (
232230
getattr(m.embeds[0].author, "icon_url", None)
233231
if m.embeds and m.embeds[0].author and m.author == self.bot.user
234-
else m.author.display_avatar.url
235-
if m.author != self.bot.user
236-
else None
232+
else m.author.display_avatar.url if m.author != self.bot.user else None
237233
),
238234
}
239235
async for m in channel.history(limit=None, oldest_first=True)
@@ -849,11 +845,9 @@ async def send_genesis_message():
849845
if getattr(self, "_selected_thread_creation_menu_option", None) and self.bot.config.get(
850846
"thread_creation_menu_selection_log"
851847
):
852-
opt = self._selected_thread_creation_menu_option
848+
path = self._selected_thread_creation_menu_option
853849
try:
854-
log_txt = f"Selected menu option: {opt.get('label')} ({opt.get('type')})"
855-
if opt.get("type") == "command":
856-
log_txt += f" -> {opt.get('callback')}"
850+
log_txt = f"Selected menu path: {' -> '.join(path)}"
857851
await channel.send(embed=discord.Embed(description=log_txt, color=self.bot.mod_color))
858852
except Exception:
859853
logger.warning(
@@ -2659,29 +2653,44 @@ async def create(
26592653
placeholder = "Select an option to contact the staff team."
26602654
timeout = 20
26612655

2662-
options = self.bot.config.get("thread_creation_menu_options") or {}
2663-
submenus = self.bot.config.get("thread_creation_menu_submenus") or {}
2664-
26652656
# Minimal inline view implementation (avoid importing plugin code)
26662657

26672658
thread.ready = False # not ready yet
26682659

26692660
class _ThreadCreationMenuSelect(discord.ui.Select):
2670-
def __init__(self, outer_thread: Thread):
2661+
def __init__(
2662+
self,
2663+
bot,
2664+
outer_thread: Thread,
2665+
option_data: dict,
2666+
menu_msg: discord.Message,
2667+
path: list,
2668+
is_home: bool = True,
2669+
):
2670+
self.bot = bot
26712671
self.outer_thread = outer_thread
2672-
opts = [
2672+
self.option_data = option_data
2673+
self.menu_msg = menu_msg
2674+
self.path = path
2675+
options = [
26732676
discord.SelectOption(
26742677
label=o["label"],
26752678
description=o["description"],
26762679
emoji=o["emoji"],
26772680
)
2678-
for o in options.values()
2681+
for o in option_data.values()
26792682
]
2683+
if not is_home:
2684+
options.append(
2685+
discord.SelectOption(
2686+
label="main menu", description="Return to the main menu", emoji="🏠"
2687+
)
2688+
)
26802689
super().__init__(
26812690
placeholder=placeholder,
26822691
min_values=1,
26832692
max_values=1,
2684-
options=opts,
2693+
options=options,
26852694
)
26862695

26872696
async def callback(self, interaction: discord.Interaction):
@@ -2696,8 +2705,45 @@ async def callback(self, interaction: discord.Interaction):
26962705
chosen_label = self.values[0]
26972706
# Resolve option key
26982707
key = chosen_label.lower().replace(" ", "_")
2699-
selected = options.get(key)
2700-
self.outer_thread._selected_thread_creation_menu_option = selected
2708+
if key == "main_menu":
2709+
option_data = self.bot.config.get("thread_creation_menu_options") or {}
2710+
new_view = _ThreadCreationMenuView(
2711+
self.bot,
2712+
self.outer_thread,
2713+
option_data,
2714+
self.menu_msg,
2715+
path=[],
2716+
is_home=True,
2717+
)
2718+
return await self.menu_msg.edit(view=new_view)
2719+
selected: dict = self.option_data.get(key, {})
2720+
next_path = [*self.path, chosen_label]
2721+
if selected.get("type", "command") == "submenu":
2722+
submenu_data = self.bot.config.get("thread_creation_menu_submenus") or {}
2723+
submenu_key = selected.get("callback", key)
2724+
option_data = submenu_data.get(submenu_key, {})
2725+
if not option_data:
2726+
home_options = self.bot.config.get("thread_creation_menu_options") or {}
2727+
new_view = _ThreadCreationMenuView(
2728+
self.bot,
2729+
self.outer_thread,
2730+
home_options,
2731+
self.menu_msg,
2732+
path=[],
2733+
is_home=True,
2734+
)
2735+
return await self.menu_msg.edit(view=new_view)
2736+
new_view = _ThreadCreationMenuView(
2737+
self.bot,
2738+
self.outer_thread,
2739+
option_data,
2740+
self.menu_msg,
2741+
path=next_path,
2742+
is_home=False,
2743+
)
2744+
return await self.menu_msg.edit(view=new_view)
2745+
2746+
self.outer_thread._selected_thread_creation_menu_option = next_path
27012747
# Reflect the selection in the original DM by editing the embed/body
27022748
try:
27032749
msg = getattr(interaction, "message", None)
@@ -2936,10 +2982,30 @@ async def callback(self, interaction: discord.Interaction):
29362982
ctx_.command.checks = old_checks
29372983

29382984
class _ThreadCreationMenuView(discord.ui.View):
2939-
def __init__(self, outer_thread: Thread):
2985+
def __init__(
2986+
self,
2987+
bot,
2988+
outer_thread: Thread,
2989+
option_data: dict,
2990+
menu_msg: discord.Message,
2991+
path: list,
2992+
is_home: bool = True,
2993+
):
29402994
super().__init__(timeout=timeout)
29412995
self.outer_thread = outer_thread
2942-
self.add_item(_ThreadCreationMenuSelect(outer_thread))
2996+
self.path = path
2997+
self.menu_msg = menu_msg
2998+
self.option_data = option_data
2999+
self.add_item(
3000+
_ThreadCreationMenuSelect(
3001+
bot,
3002+
outer_thread,
3003+
option_data=option_data,
3004+
menu_msg=menu_msg,
3005+
path=self.path,
3006+
is_home=is_home,
3007+
)
3008+
)
29433009

29443010
async def on_timeout(self):
29453011
# Timeout -> abort thread creation
@@ -3061,8 +3127,12 @@ async def on_timeout(self):
30613127
embed.set_thumbnail(url=embed_thumb)
30623128
except Exception as e:
30633129
logger.debug("Thumbnail set failed (ignored): %s", e)
3064-
menu_view = _ThreadCreationMenuView(thread)
3065-
menu_msg = await recipient.send(embed=embed, view=menu_view)
3130+
menu_msg = await recipient.send(embed=embed)
3131+
option_data = self.bot.config.get("thread_creation_menu_options") or {}
3132+
menu_view = _ThreadCreationMenuView(
3133+
self.bot, thread, option_data, menu_msg, path=[], is_home=True
3134+
)
3135+
menu_msg = await menu_msg.edit(view=menu_view)
30663136
# mark thread as pending menu selection
30673137
thread._pending_menu = True
30683138
# Explicitly attach the message to the view for safety in callbacks

0 commit comments

Comments
 (0)