discordbot/cogs/settings_cog.py
2025-06-05 21:31:06 -06:00

849 lines
33 KiB
Python

import discord
from discord.ext import commands
import logging
import settings_manager # Assuming settings_manager is accessible
import command_customization # Import command customization utilities
from typing import Optional
log = logging.getLogger(__name__)
# Get CORE_COGS from bot instance
def get_core_cogs(bot):
return getattr(bot, "core_cogs", {"SettingsCog", "HelpCog"})
class SettingsCog(commands.Cog, name="Settings"):
"""Commands for server administrators to configure the bot."""
def __init__(self, bot: commands.Bot):
self.bot = bot
# --- Prefix Management ---
@commands.command(
name="setprefix",
help="Sets the command prefix for this server. Usage: `setprefix <new_prefix>`",
)
@commands.has_permissions(administrator=True)
@commands.guild_only()
async def set_prefix(self, ctx: commands.Context, new_prefix: str):
"""Sets the command prefix for the current guild."""
if not new_prefix:
await ctx.send("Prefix cannot be empty.")
return
if len(new_prefix) > 10: # Arbitrary limit
await ctx.send("Prefix cannot be longer than 10 characters.")
return
if new_prefix.isspace():
await ctx.send("Prefix cannot be just whitespace.")
return
guild_id = ctx.guild.id
success = await settings_manager.set_guild_prefix(guild_id, new_prefix)
if success:
await ctx.send(
f"Command prefix for this server has been set to: `{new_prefix}`"
)
log.info(
f"Prefix updated for guild {guild_id} to '{new_prefix}' by {ctx.author.name}"
)
else:
await ctx.send("Failed to set the prefix. Please check the logs.")
log.error(f"Failed to save prefix for guild {guild_id}")
@commands.command(
name="showprefix", help="Shows the current command prefix for this server."
)
@commands.guild_only()
async def show_prefix(self, ctx: commands.Context):
"""Shows the current command prefix."""
# We need the bot's default prefix as a fallback
# This might need access to the bot instance's initial config or a constant
default_prefix = (
self.bot.command_prefix
) # This might not work if command_prefix is the callable
# Use the constant defined in main.py if possible, or keep a local fallback
default_prefix_fallback = (
"!" # TODO: Get default prefix reliably if needed elsewhere
)
guild_id = ctx.guild.id
current_prefix = await settings_manager.get_guild_prefix(
guild_id, default_prefix_fallback
)
await ctx.send(
f"The current command prefix for this server is: `{current_prefix}`"
)
# --- Cog Management ---
@commands.command(
name="enablecog",
help="Enables a specific module (cog) for this server. Usage: `enablecog <CogName>`",
)
@commands.has_permissions(administrator=True)
@commands.guild_only()
async def enable_cog(self, ctx: commands.Context, cog_name: str):
"""Enables a cog for the current guild."""
# Validate if cog exists
if cog_name not in self.bot.cogs:
await ctx.send(f"Error: Cog `{cog_name}` not found.")
return
core_cogs = get_core_cogs(self.bot)
if cog_name in core_cogs:
await ctx.send(f"Error: Core cog `{cog_name}` cannot be disabled/enabled.")
return
guild_id = ctx.guild.id
success = await settings_manager.set_cog_enabled(
guild_id, cog_name, enabled=True
)
if success:
await ctx.send(f"Module `{cog_name}` has been enabled for this server.")
log.info(
f"Cog '{cog_name}' enabled for guild {guild_id} by {ctx.author.name}"
)
else:
await ctx.send(f"Failed to enable module `{cog_name}`. Check logs.")
log.error(f"Failed to enable cog '{cog_name}' for guild {guild_id}")
@commands.command(
name="disablecog",
help="Disables a specific module (cog) for this server. Usage: `disablecog <CogName>`",
)
@commands.has_permissions(administrator=True)
@commands.guild_only()
async def disable_cog(self, ctx: commands.Context, cog_name: str):
"""Disables a cog for the current guild."""
if cog_name not in self.bot.cogs:
await ctx.send(f"Error: Cog `{cog_name}` not found.")
return
core_cogs = get_core_cogs(self.bot)
if cog_name in core_cogs:
await ctx.send(f"Error: Core cog `{cog_name}` cannot be disabled.")
return
guild_id = ctx.guild.id
success = await settings_manager.set_cog_enabled(
guild_id, cog_name, enabled=False
)
if success:
await ctx.send(f"Module `{cog_name}` has been disabled for this server.")
log.info(
f"Cog '{cog_name}' disabled for guild {guild_id} by {ctx.author.name}"
)
else:
await ctx.send(f"Failed to disable module `{cog_name}`. Check logs.")
log.error(f"Failed to disable cog '{cog_name}' for guild {guild_id}")
@commands.command(
name="listcogs",
help="Lists all available modules (cogs) and their status for this server.",
)
@commands.guild_only()
async def list_cogs(self, ctx: commands.Context):
"""Lists available cogs and their enabled/disabled status."""
guild_id = ctx.guild.id
# Note: Default enabled status might need adjustment based on desired behavior
# If a cog has no entry in the DB, should it be considered enabled or disabled by default?
# Let's assume default_enabled=True for now.
default_behavior = True
embed = discord.Embed(
title="Available Modules (Cogs)", color=discord.Color.blue()
)
lines = []
# Get core cogs from bot instance
core_cogs_list = get_core_cogs(self.bot)
for cog_name in sorted(self.bot.cogs.keys()):
is_enabled = await settings_manager.is_cog_enabled(
guild_id, cog_name, default_enabled=default_behavior
)
status = "✅ Enabled" if is_enabled else "❌ Disabled"
if cog_name in core_cogs_list:
status += " (Core)"
lines.append(f"`{cog_name}`: {status}")
embed.description = "\n".join(lines) if lines else "No cogs found."
await ctx.send(embed=embed)
# --- Command Permission Management (Basic Role-Based) ---
@commands.command(
name="allowcmd",
help="Allows a role to use a specific command. Usage: `allowcmd <command_name> <@Role>`",
)
@commands.has_permissions(administrator=True)
@commands.guild_only()
async def allow_command(
self, ctx: commands.Context, command_name: str, role: discord.Role
):
"""Allows a specific role to use a command."""
command = self.bot.get_command(command_name)
if not command:
await ctx.send(f"Error: Command `{command_name}` not found.")
return
guild_id = ctx.guild.id
role_id = role.id
success = await settings_manager.add_command_permission(
guild_id, command_name, role_id
)
if success:
await ctx.send(
f"Role `{role.name}` is now allowed to use command `{command_name}`."
)
log.info(
f"Permission added for command '{command_name}', role '{role.name}' ({role_id}) in guild {guild_id} by {ctx.author.name}"
)
else:
await ctx.send(
f"Failed to add permission for command `{command_name}`. Check logs."
)
log.error(
f"Failed to add permission for command '{command_name}', role {role_id} in guild {guild_id}"
)
@commands.command(
name="disallowcmd",
help="Disallows a role from using a specific command. Usage: `disallowcmd <command_name> <@Role>`",
)
@commands.has_permissions(administrator=True)
@commands.guild_only()
async def disallow_command(
self, ctx: commands.Context, command_name: str, role: discord.Role
):
"""Disallows a specific role from using a command."""
command = self.bot.get_command(command_name)
if not command:
await ctx.send(f"Error: Command `{command_name}` not found.")
return
guild_id = ctx.guild.id
role_id = role.id
success = await settings_manager.remove_command_permission(
guild_id, command_name, role_id
)
if success:
await ctx.send(
f"Role `{role.name}` is no longer allowed to use command `{command_name}`."
)
log.info(
f"Permission removed for command '{command_name}', role '{role.name}' ({role_id}) in guild {guild_id} by {ctx.author.name}"
)
else:
await ctx.send(
f"Failed to remove permission for command `{command_name}`. Check logs."
)
log.error(
f"Failed to remove permission for command '{command_name}', role {role_id} in guild {guild_id}"
)
# --- Command Customization Management ---
@commands.command(
name="setcmdname",
help="Sets a custom name for a slash command in this server. Usage: `setcmdname <original_name> <custom_name>`",
)
@commands.has_permissions(administrator=True)
@commands.guild_only()
async def set_command_name(
self, ctx: commands.Context, original_name: str, custom_name: str
):
"""Sets a custom name for a slash command in the current guild."""
# Validate the original command exists
command_found = False
for cmd in self.bot.tree.get_commands():
if cmd.name == original_name:
command_found = True
break
if not command_found:
await ctx.send(f"Error: Slash command `{original_name}` not found.")
return
# Validate custom name format (Discord has restrictions on command names)
if not custom_name.islower() or not custom_name.replace("_", "").isalnum():
await ctx.send(
"Error: Custom command names must be lowercase and contain only letters, numbers, and underscores."
)
return
if len(custom_name) < 1 or len(custom_name) > 32:
await ctx.send(
"Error: Custom command names must be between 1 and 32 characters long."
)
return
guild_id = ctx.guild.id
success = await settings_manager.set_custom_command_name(
guild_id, original_name, custom_name
)
if success:
await ctx.send(
f"Command `{original_name}` will now appear as `{custom_name}` in this server.\n"
f"Note: You'll need to restart the bot or use `/sync` for changes to take effect."
)
log.info(
f"Custom command name set for '{original_name}' to '{custom_name}' in guild {guild_id} by {ctx.author.name}"
)
else:
await ctx.send(f"Failed to set custom command name. Check logs.")
log.error(
f"Failed to set custom command name for '{original_name}' in guild {guild_id}"
)
@commands.command(
name="resetcmdname",
help="Resets a slash command to its original name. Usage: `resetcmdname <original_name>`",
)
@commands.has_permissions(administrator=True)
@commands.guild_only()
async def reset_command_name(self, ctx: commands.Context, original_name: str):
"""Resets a slash command to its original name in the current guild."""
guild_id = ctx.guild.id
success = await settings_manager.set_custom_command_name(
guild_id, original_name, None
)
if success:
await ctx.send(
f"Command `{original_name}` has been reset to its original name in this server.\n"
f"Note: You'll need to restart the bot or use `/sync` for changes to take effect."
)
log.info(
f"Custom command name reset for '{original_name}' in guild {guild_id} by {ctx.author.name}"
)
else:
await ctx.send(f"Failed to reset command name. Check logs.")
log.error(
f"Failed to reset command name for '{original_name}' in guild {guild_id}"
)
@commands.command(
name="setgroupname",
help="Sets a custom name for a command group. Usage: `setgroupname <original_name> <custom_name>`",
)
@commands.has_permissions(administrator=True)
@commands.guild_only()
async def set_group_name(
self, ctx: commands.Context, original_name: str, custom_name: str
):
"""Sets a custom name for a command group in the current guild."""
# Validate the original group exists
group_found = False
for cmd in self.bot.tree.get_commands():
# Check if this command is itself a group with the specified name
if (
hasattr(cmd, "name")
and cmd.name == original_name
and hasattr(cmd, "commands")
):
group_found = True
break
# Also check if this is a subcommand of a group with the specified name (for nested groups)
elif (
hasattr(cmd, "parent")
and cmd.parent
and cmd.parent.name == original_name
):
group_found = True
break
if not group_found:
await ctx.send(f"Error: Command group `{original_name}` not found.")
return
# Validate custom name format (Discord has restrictions on command names)
if not custom_name.islower() or not custom_name.replace("_", "").isalnum():
await ctx.send(
"Error: Custom group names must be lowercase and contain only letters, numbers, and underscores."
)
return
if len(custom_name) < 1 or len(custom_name) > 32:
await ctx.send(
"Error: Custom group names must be between 1 and 32 characters long."
)
return
guild_id = ctx.guild.id
success = await settings_manager.set_custom_group_name(
guild_id, original_name, custom_name
)
if success:
await ctx.send(
f"Command group `{original_name}` will now appear as `{custom_name}` in this server.\n"
f"Note: You'll need to restart the bot or use `/sync` for changes to take effect."
)
log.info(
f"Custom group name set for '{original_name}' to '{custom_name}' in guild {guild_id} by {ctx.author.name}"
)
else:
await ctx.send(f"Failed to set custom group name. Check logs.")
log.error(
f"Failed to set custom group name for '{original_name}' in guild {guild_id}"
)
@commands.command(
name="resetgroupname",
help="Resets a command group to its original name. Usage: `resetgroupname <original_name>`",
)
@commands.has_permissions(administrator=True)
@commands.guild_only()
async def reset_group_name(self, ctx: commands.Context, original_name: str):
"""Resets a command group to its original name in the current guild."""
guild_id = ctx.guild.id
success = await settings_manager.set_custom_group_name(
guild_id, original_name, None
)
if success:
await ctx.send(
f"Command group `{original_name}` has been reset to its original name in this server.\n"
f"Note: You'll need to restart the bot or use `/sync` for changes to take effect."
)
log.info(
f"Custom group name reset for '{original_name}' in guild {guild_id} by {ctx.author.name}"
)
else:
await ctx.send(f"Failed to reset group name. Check logs.")
log.error(
f"Failed to reset group name for '{original_name}' in guild {guild_id}"
)
@commands.command(
name="addcmdalias",
help="Adds an alias for a command. Usage: `addcmdalias <original_name> <alias_name>`",
)
@commands.has_permissions(administrator=True)
@commands.guild_only()
async def add_command_alias(
self, ctx: commands.Context, original_name: str, alias_name: str
):
"""Adds an alias for a command in the current guild."""
# Validate the original command exists
command = self.bot.get_command(original_name)
if not command:
await ctx.send(f"Error: Command `{original_name}` not found.")
return
# Validate alias format
if not alias_name.islower() or not alias_name.replace("_", "").isalnum():
await ctx.send(
"Error: Aliases must be lowercase and contain only letters, numbers, and underscores."
)
return
if len(alias_name) < 1 or len(alias_name) > 32:
await ctx.send("Error: Aliases must be between 1 and 32 characters long.")
return
guild_id = ctx.guild.id
success = await settings_manager.add_command_alias(
guild_id, original_name, alias_name
)
if success:
await ctx.send(
f"Added alias `{alias_name}` for command `{original_name}` in this server."
)
log.info(
f"Command alias added for '{original_name}': '{alias_name}' in guild {guild_id} by {ctx.author.name}"
)
else:
await ctx.send(f"Failed to add command alias. Check logs.")
log.error(
f"Failed to add command alias for '{original_name}' in guild {guild_id}"
)
@commands.command(
name="removecmdalias",
help="Removes an alias for a command. Usage: `removecmdalias <original_name> <alias_name>`",
)
@commands.has_permissions(administrator=True)
@commands.guild_only()
async def remove_command_alias(
self, ctx: commands.Context, original_name: str, alias_name: str
):
"""Removes an alias for a command in the current guild."""
guild_id = ctx.guild.id
success = await settings_manager.remove_command_alias(
guild_id, original_name, alias_name
)
if success:
await ctx.send(
f"Removed alias `{alias_name}` for command `{original_name}` in this server."
)
log.info(
f"Command alias removed for '{original_name}': '{alias_name}' in guild {guild_id} by {ctx.author.name}"
)
else:
await ctx.send(f"Failed to remove command alias. Check logs.")
log.error(
f"Failed to remove command alias for '{original_name}' in guild {guild_id}"
)
@commands.command(
name="listcmdaliases", help="Lists all command aliases for this server."
)
@commands.guild_only()
async def list_command_aliases(self, ctx: commands.Context):
"""Lists all command aliases for the current guild."""
guild_id = ctx.guild.id
aliases_dict = await settings_manager.get_all_command_aliases(guild_id)
if aliases_dict is None:
await ctx.send("Failed to retrieve command aliases. Check logs.")
return
if not aliases_dict:
await ctx.send("No command aliases are set for this server.")
return
embed = discord.Embed(title="Command Aliases", color=discord.Color.blue())
for cmd_name, aliases in aliases_dict.items():
embed.add_field(
name=f"Command: {cmd_name}",
value=", ".join([f"`{alias}`" for alias in aliases]),
inline=False,
)
await ctx.send(embed=embed)
@commands.command(
name="listcustomcmds", help="Lists all custom command names for this server."
)
@commands.guild_only()
async def list_custom_commands(self, ctx: commands.Context):
"""Lists all custom command names for the current guild."""
guild_id = ctx.guild.id
cmd_customizations = await settings_manager.get_all_command_customizations(
guild_id
)
group_customizations = await settings_manager.get_all_group_customizations(
guild_id
)
if cmd_customizations is None or group_customizations is None:
await ctx.send("Failed to retrieve command customizations. Check logs.")
return
if not cmd_customizations and not group_customizations:
await ctx.send("No command customizations are set for this server.")
return
embed = discord.Embed(
title="Command Customizations", color=discord.Color.blue()
)
if cmd_customizations:
cmd_text = "\n".join(
[
f"`{orig}` → `{custom['name']}`"
for orig, custom in cmd_customizations.items()
]
)
embed.add_field(name="Custom Command Names", value=cmd_text, inline=False)
if group_customizations:
group_text = "\n".join(
[
f"`{orig}` → `{custom['name']}`"
for orig, custom in group_customizations.items()
]
)
embed.add_field(name="Custom Group Names", value=group_text, inline=False)
await ctx.send(embed=embed)
@commands.command(
name="listgroups", help="Lists all available command groups for debugging."
)
@commands.has_permissions(administrator=True)
@commands.guild_only()
async def list_groups(self, ctx: commands.Context):
"""Lists all available command groups for debugging purposes."""
groups = []
commands_list = []
for cmd in self.bot.tree.get_commands():
# Check if this is a group
if hasattr(cmd, "commands") and hasattr(cmd, "name"):
groups.append(
f"`{cmd.name}` - {getattr(cmd, 'description', 'No description')}"
)
# Check if this is a regular command
elif hasattr(cmd, "name"):
commands_list.append(f"`{cmd.name}`")
embed = discord.Embed(
title="Available Command Groups & Commands", color=discord.Color.green()
)
if groups:
groups_text = "\n".join(
groups[:10]
) # Limit to first 10 to avoid message length issues
if len(groups) > 10:
groups_text += f"\n... and {len(groups) - 10} more groups"
embed.add_field(name="Command Groups", value=groups_text, inline=False)
else:
embed.add_field(
name="Command Groups", value="No groups found", inline=False
)
if commands_list:
commands_text = ", ".join(commands_list[:20]) # Limit to first 20
if len(commands_list) > 20:
commands_text += f", ... and {len(commands_list) - 20} more commands"
embed.add_field(
name="Individual Commands", value=commands_text, inline=False
)
await ctx.send(embed=embed)
@commands.command(
name="synccmds",
help="Syncs slash commands with Discord to apply customizations.",
)
@commands.has_permissions(administrator=True)
@commands.guild_only()
async def sync_commands(self, ctx: commands.Context):
"""Syncs slash commands with Discord to apply customizations."""
try:
guild = ctx.guild
await ctx.send("Syncing commands with Discord... This may take a moment.")
# Use the command_customization module to sync commands with customizations
try:
synced = await command_customization.register_guild_commands(
self.bot, guild
)
await ctx.send(
f"Successfully synced {len(synced)} commands for this server with customizations."
)
log.info(
f"Commands synced with customizations for guild {guild.id} by {ctx.author.name}"
)
except Exception as e:
log.error(f"Failed to sync commands with customizations: {e}")
# Don't fall back to regular sync to avoid command duplication
await ctx.send(
f"Failed to apply customizations. Please check the logs and try again."
)
log.info(
f"Command sync with customizations failed for guild {guild.id}"
)
except Exception as e:
await ctx.send(f"Failed to sync commands: {str(e)}")
log.error(f"Failed to sync commands for guild {ctx.guild.id}: {e}")
# TODO: Add command to list permissions?
# --- Moderation Logging Settings ---
@commands.group(
name="modlogconfig",
help="Configure the integrated moderation logging.",
invoke_without_command=True,
)
@commands.has_permissions(administrator=True)
@commands.guild_only()
async def modlog_config_group(self, ctx: commands.Context):
"""Base command for moderation log configuration. Shows current settings."""
guild_id = ctx.guild.id
enabled = await settings_manager.is_mod_log_enabled(guild_id)
channel_id = await settings_manager.get_mod_log_channel_id(guild_id)
channel = ctx.guild.get_channel(channel_id) if channel_id else None
status = "✅ Enabled" if enabled else "❌ Disabled"
channel_status = (
channel.mention if channel else ("Not Set" if channel_id else "Not Set")
)
embed = discord.Embed(
title="Moderation Logging Configuration", color=discord.Color.teal()
)
embed.add_field(name="Status", value=status, inline=False)
embed.add_field(name="Log Channel", value=channel_status, inline=False)
await ctx.send(embed=embed)
@modlog_config_group.command(
name="enable", help="Enables the integrated moderation logging."
)
@commands.has_permissions(administrator=True)
@commands.guild_only()
async def modlog_enable(self, ctx: commands.Context):
"""Enables the integrated moderation logging for this server."""
guild_id = ctx.guild.id
success = await settings_manager.set_mod_log_enabled(guild_id, True)
if success:
await ctx.send("✅ Integrated moderation logging has been enabled.")
log.info(
f"Moderation logging enabled for guild {guild_id} by {ctx.author.name}"
)
else:
await ctx.send("❌ Failed to enable moderation logging. Please check logs.")
log.error(f"Failed to enable moderation logging for guild {guild_id}")
@modlog_config_group.command(
name="disable", help="Disables the integrated moderation logging."
)
@commands.has_permissions(administrator=True)
@commands.guild_only()
async def modlog_disable(self, ctx: commands.Context):
"""Disables the integrated moderation logging for this server."""
guild_id = ctx.guild.id
success = await settings_manager.set_mod_log_enabled(guild_id, False)
if success:
await ctx.send("❌ Integrated moderation logging has been disabled.")
log.info(
f"Moderation logging disabled for guild {guild_id} by {ctx.author.name}"
)
else:
await ctx.send(
"❌ Failed to disable moderation logging. Please check logs."
)
log.error(f"Failed to disable moderation logging for guild {guild_id}")
@modlog_config_group.command(
name="setchannel",
help="Sets the channel where moderation logs will be sent. Usage: `setchannel #channel`",
)
@commands.has_permissions(administrator=True)
@commands.guild_only()
async def modlog_setchannel(
self, ctx: commands.Context, channel: discord.TextChannel
):
"""Sets the channel for integrated moderation logs."""
guild_id = ctx.guild.id
# Basic check for bot permissions in the target channel
if (
not channel.permissions_for(ctx.guild.me).send_messages
or not channel.permissions_for(ctx.guild.me).embed_links
):
await ctx.send(
f"❌ I need 'Send Messages' and 'Embed Links' permissions in {channel.mention} to send logs there."
)
return
success = await settings_manager.set_mod_log_channel_id(guild_id, channel.id)
if success:
await ctx.send(f"✅ Moderation logs will now be sent to {channel.mention}.")
log.info(
f"Moderation log channel set to {channel.id} for guild {guild_id} by {ctx.author.name}"
)
else:
await ctx.send(
"❌ Failed to set the moderation log channel. Please check logs."
)
log.error(f"Failed to set moderation log channel for guild {guild_id}")
@modlog_config_group.command(
name="unsetchannel",
help="Unsets the moderation log channel (disables sending logs).",
)
@commands.has_permissions(administrator=True)
@commands.guild_only()
async def modlog_unsetchannel(self, ctx: commands.Context):
"""Unsets the channel for integrated moderation logs."""
guild_id = ctx.guild.id
success = await settings_manager.set_mod_log_channel_id(guild_id, None)
if success:
await ctx.send(
"✅ Moderation log channel has been unset. Logs will not be sent to a channel."
)
log.info(
f"Moderation log channel unset for guild {guild_id} by {ctx.author.name}"
)
else:
await ctx.send(
"❌ Failed to unset the moderation log channel. Please check logs."
)
log.error(f"Failed to unset moderation log channel for guild {guild_id}")
# --- Error Handling for this Cog ---
@set_prefix.error
@enable_cog.error
@disable_cog.error
@allow_command.error
@disallow_command.error
@set_command_name.error
@reset_command_name.error
@set_group_name.error
@reset_group_name.error
@add_command_alias.error
@remove_command_alias.error
@list_groups.error
@sync_commands.error
@modlog_config_group.error # Add error handler for the group
@modlog_enable.error
@modlog_disable.error
@modlog_setchannel.error
@modlog_unsetchannel.error
async def on_command_error(self, ctx: commands.Context, error):
# Check if the error originates from the modlogconfig group or its subcommands
if ctx.command and (
ctx.command.name == "modlogconfig"
or (ctx.command.parent and ctx.command.parent.name == "modlogconfig")
):
if isinstance(error, commands.MissingPermissions):
await ctx.send(
"You need Administrator permissions to configure moderation logging."
)
return # Handled
elif isinstance(error, commands.BadArgument):
await ctx.send(
f"Invalid argument. Usage: `{ctx.prefix}help {ctx.command.qualified_name}`"
)
return # Handled
elif isinstance(error, commands.MissingRequiredArgument):
await ctx.send(
f"Missing argument. Usage: `{ctx.prefix}help {ctx.command.qualified_name}`"
)
return # Handled
elif isinstance(error, commands.NoPrivateMessage):
await ctx.send("This command can only be used in a server.")
return # Handled
# Let other errors fall through to the generic handler below
# Generic handlers for other commands in this cog
if isinstance(error, commands.MissingPermissions):
await ctx.send("You need Administrator permissions to use this command.")
elif isinstance(error, commands.BadArgument):
await ctx.send(
f"Invalid argument provided. Check the command help: `{ctx.prefix}help {ctx.command.name}`"
)
elif isinstance(error, commands.MissingRequiredArgument):
await ctx.send(
f"Missing required argument. Check the command help: `{ctx.prefix}help {ctx.command.name}`"
)
elif isinstance(error, commands.NoPrivateMessage):
await ctx.send("This command cannot be used in private messages.")
else:
log.error(
f"Unhandled error in SettingsCog command '{ctx.command.name}': {error}"
)
await ctx.send("An unexpected error occurred. Please check the logs.")
async def setup(bot: commands.Bot):
# Ensure pools are initialized before adding the cog
if getattr(bot, "pg_pool", None) is None or getattr(bot, "redis", None) is None:
log.warning(
"Bot pools not initialized before loading SettingsCog. Cog will not load."
)
return # Prevent loading if pools are missing
await bot.add_cog(SettingsCog(bot))
log.info("SettingsCog loaded.")