Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
116 changes: 93 additions & 23 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,45 @@ 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":
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)
selected: dict = self.option_data.get(key, {})
next_path = [*self.path, chosen_label]
if selected.get("type", "command") == "submenu":
submenu_data = self.bot.config.get("thread_creation_menu_submenus") or {}
submenu_key = selected.get("callback", key)
option_data = submenu_data.get(submenu_key, {})
if not option_data:
home_options = self.bot.config.get("thread_creation_menu_options") or {}
new_view = _ThreadCreationMenuView(
self.bot,
self.outer_thread,
home_options,
self.menu_msg,
path=[],
is_home=True,
)
return await self.menu_msg.edit(view=new_view)
new_view = _ThreadCreationMenuView(
self.bot,
self.outer_thread,
option_data,
self.menu_msg,
path=next_path,
is_home=False,
)
return await self.menu_msg.edit(view=new_view)

self.outer_thread._selected_thread_creation_menu_option = next_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 +2982,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 +3127,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
Loading