Skip to content
Merged
Changes from 2 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
134 changes: 133 additions & 1 deletion cogs/utility.py
Original file line number Diff line number Diff line change
Expand Up @@ -1382,7 +1382,7 @@ def _parse_level(name):

@permissions.command(name="override")
@checks.has_permissions(PermissionLevel.OWNER)
async def permissions_override(self, ctx, command_name: str.lower, *, level_name: str):
async def permissions_override(self, ctx, command_name: str.lower, *, level_name: str = None):
"""
Change a permission level for a specific command.

Expand All @@ -1396,8 +1396,16 @@ async def permissions_override(self, ctx, command_name: str.lower, *, level_name
- `{prefix}perms remove override reply`
- `{prefix}perms remove override plugin enabled`

You can also override multiple commands at once using:
- `{prefix}perms override bulk`

You can retrieve a single or all command level override(s), see`{prefix}help permissions get`.
Comment thread
sebkuip marked this conversation as resolved.
"""
if command_name == "bulk":
Comment thread
sebkuip marked this conversation as resolved.
return await self._bulk_override_flow(ctx)

if level_name is None:
raise commands.MissingRequiredArgument(DummyParam("level_name"))

command = self.bot.get_command(command_name)
if command is None:
Expand Down Expand Up @@ -1432,6 +1440,130 @@ async def permissions_override(self, ctx, command_name: str.lower, *, level_name
)
return await ctx.send(embed=embed)

async def _bulk_override_flow(self, ctx):
await ctx.send(
"Please list the commands you want to override. "
"You can list multiple commands separated by spaces or newlines.\n"
"Example: `ban, kick, mod`."
Comment thread
lorenzo132 marked this conversation as resolved.
Outdated
)

try:
msg = await self.bot.wait_for(
"message",
check=lambda m: m.author == ctx.author and m.channel == ctx.channel,
timeout=120.0,
)
except asyncio.TimeoutError:
return await ctx.send("Timed out.")
Comment thread
lorenzo132 marked this conversation as resolved.
Outdated

raw_commands = msg.content.replace(",", " ").replace("\n", " ").split(" ")
# Filter empty strings from split
raw_commands = [c for c in raw_commands if c.strip()]
Comment thread
sebkuip marked this conversation as resolved.

found_commands = []
invalid_commands = []

for cmd_name in raw_commands:
cmd = self.bot.get_command(cmd_name)
Comment thread
lorenzo132 marked this conversation as resolved.
if cmd:
Comment thread
lorenzo132 marked this conversation as resolved.
found_commands.append(cmd)
else:
invalid_commands.append(cmd_name)

Comment thread
lorenzo132 marked this conversation as resolved.
if invalid_commands:
embed = discord.Embed(
title="Invalid Commands Found",
description=f"The following commands were not found:\n`{', '.join(invalid_commands)}`\n\n"
"Do you want to continue with the valid commands? (y/n)",
Comment thread
lorenzo132 marked this conversation as resolved.
Outdated
color=self.bot.error_color,
)
await ctx.send(embed=embed)
try:
msg = await self.bot.wait_for(
"message",
check=lambda m: m.author == ctx.author and m.channel == ctx.channel,
timeout=60.0,
)
if msg.content.lower() not in ("y", "yes"):
return await ctx.send("Aborted.")
Comment thread
lorenzo132 marked this conversation as resolved.
Outdated
except asyncio.TimeoutError:
return await ctx.send("Timed out.")
Comment thread
lorenzo132 marked this conversation as resolved.
Outdated

if not found_commands:
return await ctx.send("No valid commands provided. Aborting.")

# Expand subcommands
final_commands = set()

def add_command_recursive(cmd):
final_commands.add(cmd)
if hasattr(cmd, "commands"):
for sub in cmd.commands:
add_command_recursive(sub)

for cmd in found_commands:
add_command_recursive(cmd)

await ctx.send(
Comment thread
lorenzo132 marked this conversation as resolved.
Outdated
f"Found {len(final_commands)} commands (including subcommands).\n"
"What permission level should these commands be set to? (e.g. `Owner`, `Admin`, `Moderator`, `Supporter`, `User`)"
)

try:
msg = await self.bot.wait_for(
"message",
check=lambda m: m.author == ctx.author and m.channel == ctx.channel,
timeout=60.0,
)
except asyncio.TimeoutError:
return await ctx.send("Timed out.")
Comment thread
lorenzo132 marked this conversation as resolved.
Outdated

level_name = msg.content
level = self._parse_level(level_name)
if level == PermissionLevel.INVALID:
return await ctx.send(f"Invalid permission level: `{level_name}`. Aborting.")
Comment thread
lorenzo132 marked this conversation as resolved.
Outdated

# Confirmation
command_list_str = ", ".join(
f"`{c.qualified_name}`" for c in sorted(final_commands, key=lambda x: x.qualified_name)
)

# Truncate if too long for embed description
if len(command_list_str) > 2000:
Comment thread
lorenzo132 marked this conversation as resolved.
Outdated
command_list_str = command_list_str[:1997] + "..."

embed = discord.Embed(
Comment thread
lorenzo132 marked this conversation as resolved.
title="Confirm Bulk Override",
description=f"**Level:** {level.name}\n\n**Commands:**\n{command_list_str}\n\n"
"Type `confirm` to apply these changes or `cancel` to abort.",
Comment thread
lorenzo132 marked this conversation as resolved.
Outdated
color=self.bot.main_color,
)
await ctx.send(embed=embed)

try:
msg = await self.bot.wait_for(
"message",
check=lambda m: m.author == ctx.author
and m.channel == ctx.channel
and m.content.lower() in ("confirm", "cancel"),
timeout=30.0,
)
except asyncio.TimeoutError:
return await ctx.send("Timed out. No changes applied.")

if msg.content.lower() == "cancel":
return await ctx.send("Aborted.")

# Apply changes
count = 0
Comment thread
lorenzo132 marked this conversation as resolved.
Outdated
for cmd in final_commands:
self.bot.config["override_command_level"][cmd.qualified_name] = level.name
count += 1

Comment thread
sebkuip marked this conversation as resolved.
await self.bot.config.update()
Comment thread
lorenzo132 marked this conversation as resolved.

await ctx.send(f"Successfully updated permissions for {count} commands.")
Comment thread
lorenzo132 marked this conversation as resolved.
Outdated

@permissions.command(name="add", usage="[command/level] [name] [user/role]")
@checks.has_permissions(PermissionLevel.OWNER)
async def permissions_add(
Expand Down
Loading