Group related member information and server statistics into single TextDisplay components. This streamlines the UI layout, reduces the number of elements, and potentially improves rendering efficiency.
655 lines
26 KiB
Python
655 lines
26 KiB
Python
import discord
|
|
from discord.ext import commands
|
|
from discord import ui
|
|
import logging
|
|
import sys
|
|
import os
|
|
from datetime import datetime, timedelta, timezone
|
|
from typing import Literal, Optional
|
|
|
|
# Add the parent directory to sys.path to ensure settings_manager is accessible
|
|
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
import settings_manager
|
|
|
|
log = logging.getLogger(__name__)
|
|
|
|
|
|
# --- Message Component Views ---
|
|
|
|
|
|
class WelcomeMessageView(ui.LayoutView):
|
|
"""An enhanced view for welcome messages with member count and improved styling."""
|
|
|
|
def __init__(self, member: discord.Member, message: str, member_count: int):
|
|
super().__init__(timeout=None)
|
|
|
|
# Use member's color or a nice default
|
|
accent_color = member.color if member.color != discord.Color.default() else discord.Color.green()
|
|
|
|
container = ui.Container(accent_colour=accent_color)
|
|
|
|
# Add a welcome banner/header with avatar
|
|
header_section = ui.Section(
|
|
accessory=ui.Thumbnail(
|
|
media=member.display_avatar.url,
|
|
description="New Member Avatar",
|
|
)
|
|
)
|
|
|
|
# Welcome title with emoji
|
|
header_section.add_item(ui.TextDisplay("🎉 **Welcome to the Server!** 🎉"))
|
|
header_section.add_item(ui.TextDisplay(message))
|
|
|
|
# Add member info to the header section
|
|
# Calculate account age
|
|
account_age = datetime.now(timezone.utc) - member.created_at
|
|
if account_age.days >= 365:
|
|
years = account_age.days // 365
|
|
months = (account_age.days % 365) // 30
|
|
age_str = f"{years} year{'s' if years != 1 else ''}, {months} month{'s' if months != 1 else ''} ago"
|
|
elif account_age.days >= 30:
|
|
months = account_age.days // 30
|
|
age_str = f"{months} month{'s' if months != 1 else ''} ago"
|
|
else:
|
|
age_str = f"{account_age.days} day{'s' if account_age.days != 1 else ''} ago"
|
|
|
|
member_info = (
|
|
f"**Member:** {member.display_name}\n"
|
|
f"**Account Created:** {member.created_at.strftime('%B %d, %Y')}\n"
|
|
f"**Account Age:** {age_str}"
|
|
)
|
|
header_section.add_item(ui.TextDisplay(member_info))
|
|
|
|
# Add server stats to the header section
|
|
server_stats = (
|
|
f"📊 **Server Statistics**\n"
|
|
f"**Total Members:** {member_count:,}\n"
|
|
f"**You are member #{member_count:,}**"
|
|
)
|
|
header_section.add_item(ui.TextDisplay(server_stats))
|
|
|
|
# Add welcome footer
|
|
header_section.add_item(ui.TextDisplay("💬 Feel free to introduce yourself and have fun!"))
|
|
|
|
container.add_item(header_section)
|
|
self.add_item(container)
|
|
|
|
|
|
class GoodbyeMessageView(ui.LayoutView):
|
|
"""An enhanced view for goodbye messages with member count and improved styling."""
|
|
|
|
def __init__(self, member: discord.Member, message: str, member_count: int, reason: str = "left"):
|
|
super().__init__(timeout=None)
|
|
|
|
# Use darker colors for goodbye messages
|
|
if reason == "banned":
|
|
accent_color = discord.Color.red()
|
|
emoji = "🔨"
|
|
title = "Member Banned"
|
|
elif reason == "kicked":
|
|
accent_color = discord.Color.orange()
|
|
emoji = "👢"
|
|
title = "Member Kicked"
|
|
else:
|
|
accent_color = discord.Color.dark_grey()
|
|
emoji = "👋"
|
|
title = "Member Left"
|
|
|
|
container = ui.Container(accent_colour=accent_color)
|
|
|
|
# Header section with avatar
|
|
header_section = ui.Section(
|
|
accessory=ui.Thumbnail(
|
|
media=member.display_avatar.url,
|
|
description="Former Member Avatar",
|
|
)
|
|
)
|
|
|
|
header_section.add_item(ui.TextDisplay(f"{emoji} **{title}** {emoji}"))
|
|
header_section.add_item(ui.TextDisplay(message))
|
|
|
|
# Add member info to the header section
|
|
member_info_parts = [
|
|
f"**Member:** {member.display_name}",
|
|
f"**Username:** {member.name}"
|
|
]
|
|
|
|
# Show join date if available
|
|
if hasattr(member, 'joined_at') and member.joined_at:
|
|
join_date = member.joined_at.strftime('%B %d, %Y')
|
|
time_in_server = datetime.now(timezone.utc) - member.joined_at
|
|
|
|
if time_in_server.days >= 365:
|
|
years = time_in_server.days // 365
|
|
months = (time_in_server.days % 365) // 30
|
|
duration_str = f"{years} year{'s' if years != 1 else ''}, {months} month{'s' if months != 1 else ''}"
|
|
elif time_in_server.days >= 30:
|
|
months = time_in_server.days // 30
|
|
duration_str = f"{months} month{'s' if months != 1 else ''}"
|
|
else:
|
|
duration_str = f"{time_in_server.days} day{'s' if time_in_server.days != 1 else ''}"
|
|
|
|
member_info_parts.append(f"**Joined:** {join_date}")
|
|
member_info_parts.append(f"**Time in Server:** {duration_str}")
|
|
|
|
header_section.add_item(ui.TextDisplay("\n".join(member_info_parts)))
|
|
|
|
# Add server stats to the header section
|
|
server_stats = (
|
|
f"📊 **Server Statistics**\n"
|
|
f"**Current Members:** {member_count:,}"
|
|
)
|
|
header_section.add_item(ui.TextDisplay(server_stats))
|
|
|
|
container.add_item(header_section)
|
|
self.add_item(container)
|
|
|
|
|
|
class WelcomeCog(commands.Cog):
|
|
"""Handles welcome and goodbye messages for guilds."""
|
|
|
|
def __init__(self, bot: commands.Bot):
|
|
self.bot = bot
|
|
self.bot.add_listener(self.on_member_join, "on_member_join")
|
|
self.bot.add_listener(self.on_member_remove, "on_member_remove")
|
|
|
|
async def on_member_join(self, member: discord.Member):
|
|
"""Sends a welcome message when a new member joins."""
|
|
guild = member.guild
|
|
if not guild:
|
|
return
|
|
|
|
log.debug(f"Member {member.name} joined guild {guild.name} ({guild.id})")
|
|
|
|
# --- Fetch settings ---
|
|
welcome_channel_id_str = await settings_manager.get_setting(
|
|
guild.id, "welcome_channel_id"
|
|
)
|
|
welcome_message_template = await settings_manager.get_setting(
|
|
guild.id, "welcome_message", default="Welcome {user} to {server}!"
|
|
)
|
|
|
|
if not welcome_channel_id_str or welcome_channel_id_str == "__NONE__":
|
|
log.debug(f"Welcome channel not configured for guild {guild.id}")
|
|
return
|
|
|
|
try:
|
|
welcome_channel_id = int(welcome_channel_id_str)
|
|
channel = guild.get_channel(welcome_channel_id)
|
|
if not channel or not isinstance(channel, discord.TextChannel):
|
|
log.warning(
|
|
f"Welcome channel ID {welcome_channel_id} not found or not text channel in guild {guild.id}"
|
|
)
|
|
return
|
|
|
|
# --- Format and send message ---
|
|
formatted_message = welcome_message_template.format(
|
|
user=member.mention, username=member.name, server=guild.name
|
|
)
|
|
|
|
# Get current member count
|
|
member_count = guild.member_count or len(guild.members)
|
|
|
|
view = WelcomeMessageView(member, formatted_message, member_count)
|
|
await channel.send(view=view)
|
|
log.info(f"Sent welcome message for {member.name} in guild {guild.id}")
|
|
|
|
except ValueError as e:
|
|
log.error(
|
|
f"ValueError in WelcomeCog for guild {guild.id}: {e}"
|
|
)
|
|
except discord.Forbidden:
|
|
log.error(
|
|
f"Missing permissions to send welcome message in channel {welcome_channel_id} for guild {guild.id}"
|
|
)
|
|
except Exception as e:
|
|
log.exception(f"Error sending welcome message for guild {guild.id}: {e}")
|
|
|
|
async def on_member_remove(self, member: discord.Member):
|
|
"""Sends a goodbye message when a member leaves, is kicked, or is banned."""
|
|
guild = member.guild
|
|
if not guild:
|
|
return
|
|
|
|
log.debug(f"Member {member.name} left guild {guild.name} ({guild.id})")
|
|
|
|
# --- Fetch settings ---
|
|
goodbye_channel_id_str = await settings_manager.get_setting(
|
|
guild.id, "goodbye_channel_id"
|
|
)
|
|
goodbye_message_template = await settings_manager.get_setting(
|
|
guild.id, "goodbye_message", default="{username} has left the server."
|
|
)
|
|
|
|
if not goodbye_channel_id_str or goodbye_channel_id_str == "__NONE__":
|
|
log.debug(f"Goodbye channel not configured for guild {guild.id}")
|
|
return
|
|
|
|
try:
|
|
goodbye_channel_id = int(goodbye_channel_id_str)
|
|
channel = guild.get_channel(goodbye_channel_id)
|
|
if not channel or not isinstance(channel, discord.TextChannel):
|
|
log.warning(
|
|
f"Goodbye channel ID {goodbye_channel_id} not found or not text channel in guild {guild.id}"
|
|
)
|
|
return
|
|
|
|
# --- Determine reason for leaving ---
|
|
reason = "left"
|
|
entry_user = None
|
|
|
|
# Check audit log for kick or ban. We check last 2 minutes just in case of delays.
|
|
try:
|
|
# Check for ban first
|
|
async for entry in guild.audit_logs(
|
|
limit=1,
|
|
action=discord.AuditLogAction.ban,
|
|
after=datetime.now(timezone.utc) - timedelta(minutes=2),
|
|
):
|
|
if entry.target and entry.target.id == member.id:
|
|
reason = "banned"
|
|
entry_user = entry.user
|
|
break
|
|
|
|
# If not banned, check for kick
|
|
if reason == "left":
|
|
async for entry in guild.audit_logs(
|
|
limit=1,
|
|
action=discord.AuditLogAction.kick,
|
|
after=datetime.now(timezone.utc) - timedelta(minutes=2),
|
|
):
|
|
if entry.target and entry.target.id == member.id:
|
|
reason = "kicked"
|
|
entry_user = entry.user
|
|
break
|
|
except discord.Forbidden:
|
|
log.warning(
|
|
f"Missing 'View Audit Log' permissions in guild {guild.id} to determine member remove reason."
|
|
)
|
|
except Exception as e:
|
|
log.error(
|
|
f"Error checking audit log for {member.name} in {guild.id}: {e}"
|
|
)
|
|
|
|
# --- Format and send message ---
|
|
if reason == "left":
|
|
formatted_message = goodbye_message_template.format(
|
|
user=member.mention, # Might not be mentionable after leaving
|
|
username=member.name,
|
|
server=guild.name,
|
|
)
|
|
elif reason == "kicked":
|
|
formatted_message = f"**{member.name}** was kicked from the server"
|
|
if entry_user and entry_user != self.bot.user:
|
|
formatted_message += f" by **{entry_user.name}**"
|
|
formatted_message += "."
|
|
else: # banned
|
|
formatted_message = f"**{member.name}** was banned from the server"
|
|
if entry_user and entry_user != self.bot.user:
|
|
formatted_message += f" by **{entry_user.name}**"
|
|
formatted_message += "."
|
|
|
|
# Get current member count
|
|
member_count = guild.member_count or len(guild.members)
|
|
|
|
view = GoodbyeMessageView(member, formatted_message, member_count, reason)
|
|
await channel.send(view=view)
|
|
log.info(
|
|
f"Sent goodbye message for {member.name} in guild {guild.id} (Reason: {reason})"
|
|
)
|
|
|
|
except ValueError:
|
|
log.error(
|
|
f"Invalid goodbye_channel_id '{goodbye_channel_id_str}' configured for guild {guild.id}"
|
|
)
|
|
except discord.Forbidden:
|
|
log.error(
|
|
f"Missing permissions to send goodbye message in channel {goodbye_channel_id} for guild {guild.id}"
|
|
)
|
|
except Exception as e:
|
|
log.exception(f"Error sending goodbye message for guild {guild.id}: {e}")
|
|
|
|
@commands.command(
|
|
name="setwelcome",
|
|
help="Sets the welcome message and channel. Usage: `setwelcome #channel [message template]`",
|
|
)
|
|
@commands.has_permissions(administrator=True)
|
|
@commands.guild_only()
|
|
async def set_welcome(
|
|
self,
|
|
ctx: commands.Context,
|
|
channel: discord.TextChannel,
|
|
*,
|
|
message_template: str = "Welcome {user} to {server}!",
|
|
):
|
|
"""Sets the channel and template for welcome messages."""
|
|
guild_id = ctx.guild.id
|
|
key_channel = "welcome_channel_id"
|
|
key_message = "welcome_message"
|
|
|
|
# Use settings_manager.set_setting
|
|
success_channel = await settings_manager.set_setting(
|
|
guild_id, key_channel, str(channel.id)
|
|
)
|
|
success_message = await settings_manager.set_setting(
|
|
guild_id, key_message, message_template
|
|
)
|
|
|
|
if success_channel and success_message: # Both need to succeed
|
|
embed = discord.Embed(
|
|
title="✅ Welcome Messages Configured",
|
|
description=f"Welcome messages will now be sent to {channel.mention}",
|
|
color=discord.Color.green()
|
|
)
|
|
embed.add_field(
|
|
name="Message Template",
|
|
value=f"```\n{message_template}\n```",
|
|
inline=False
|
|
)
|
|
embed.add_field(
|
|
name="Available Variables",
|
|
value="`{user}` - Mentions the user\n`{username}` - User's name\n`{server}` - Server name",
|
|
inline=False
|
|
)
|
|
await ctx.send(embed=embed)
|
|
log.info(
|
|
f"Welcome settings updated for guild {guild_id} by {ctx.author.name}"
|
|
)
|
|
else:
|
|
await ctx.send("❌ Failed to save welcome settings. Check logs.")
|
|
log.error(f"Failed to save welcome settings for guild {guild_id}")
|
|
|
|
@commands.command(
|
|
name="disablewelcome", help="Disables welcome messages for this server."
|
|
)
|
|
@commands.has_permissions(administrator=True)
|
|
@commands.guild_only()
|
|
async def disable_welcome(self, ctx: commands.Context):
|
|
"""Disables welcome messages by removing the channel setting."""
|
|
guild_id = ctx.guild.id
|
|
key_channel = "welcome_channel_id"
|
|
key_message = "welcome_message" # Also clear the message template
|
|
|
|
# Use set_setting with None to delete the settings
|
|
success_channel = await settings_manager.set_setting(guild_id, key_channel, None)
|
|
success_message = await settings_manager.set_setting(guild_id, key_message, None)
|
|
|
|
if success_channel and success_message: # Both need to succeed
|
|
embed = discord.Embed(
|
|
title="✅ Welcome Messages Disabled",
|
|
description="Welcome messages have been disabled for this server.",
|
|
color=discord.Color.orange()
|
|
)
|
|
await ctx.send(embed=embed)
|
|
log.info(
|
|
f"Welcome messages disabled for guild {guild_id} by {ctx.author.name}"
|
|
)
|
|
else:
|
|
await ctx.send("❌ Failed to disable welcome messages. Check logs.")
|
|
log.error(f"Failed to disable welcome settings for guild {guild_id}")
|
|
|
|
@commands.command(
|
|
name="setgoodbye",
|
|
help="Sets the goodbye message and channel. Usage: `setgoodbye #channel [message template]`",
|
|
)
|
|
@commands.has_permissions(administrator=True)
|
|
@commands.guild_only()
|
|
async def set_goodbye(
|
|
self,
|
|
ctx: commands.Context,
|
|
channel: discord.TextChannel,
|
|
*,
|
|
message_template: str = "{username} has left the server.",
|
|
):
|
|
"""Sets the channel and template for goodbye messages."""
|
|
guild_id = ctx.guild.id
|
|
key_channel = "goodbye_channel_id"
|
|
key_message = "goodbye_message"
|
|
|
|
# Use settings_manager.set_setting
|
|
success_channel = await settings_manager.set_setting(
|
|
guild_id, key_channel, str(channel.id)
|
|
)
|
|
success_message = await settings_manager.set_setting(
|
|
guild_id, key_message, message_template
|
|
)
|
|
|
|
if success_channel and success_message: # Both need to succeed
|
|
embed = discord.Embed(
|
|
title="✅ Goodbye Messages Configured",
|
|
description=f"Goodbye messages will now be sent to {channel.mention}",
|
|
color=discord.Color.green()
|
|
)
|
|
embed.add_field(
|
|
name="Message Template",
|
|
value=f"```\n{message_template}\n```",
|
|
inline=False
|
|
)
|
|
embed.add_field(
|
|
name="Available Variables",
|
|
value="`{user}` - Mentions the user (may not work after leaving)\n`{username}` - User's name\n`{server}` - Server name",
|
|
inline=False
|
|
)
|
|
embed.add_field(
|
|
name="Note",
|
|
value="Kick and ban messages will override the template with automatic formatting.",
|
|
inline=False
|
|
)
|
|
await ctx.send(embed=embed)
|
|
log.info(
|
|
f"Goodbye settings updated for guild {guild_id} by {ctx.author.name}"
|
|
)
|
|
else:
|
|
await ctx.send("❌ Failed to save goodbye settings. Check logs.")
|
|
log.error(f"Failed to save goodbye settings for guild {guild_id}")
|
|
|
|
@commands.command(
|
|
name="disablegoodbye", help="Disables goodbye messages for this server."
|
|
)
|
|
@commands.has_permissions(administrator=True)
|
|
@commands.guild_only()
|
|
async def disable_goodbye(self, ctx: commands.Context):
|
|
"""Disables goodbye messages by removing the channel setting."""
|
|
guild_id = ctx.guild.id
|
|
key_channel = "goodbye_channel_id"
|
|
key_message = "goodbye_message"
|
|
|
|
# Use set_setting with None to delete the settings
|
|
success_channel = await settings_manager.set_setting(guild_id, key_channel, None)
|
|
success_message = await settings_manager.set_setting(guild_id, key_message, None)
|
|
|
|
if success_channel and success_message: # Both need to succeed
|
|
embed = discord.Embed(
|
|
title="✅ Goodbye Messages Disabled",
|
|
description="Goodbye messages have been disabled for this server.",
|
|
color=discord.Color.orange()
|
|
)
|
|
await ctx.send(embed=embed)
|
|
log.info(
|
|
f"Goodbye messages disabled for guild {guild_id} by {ctx.author.name}"
|
|
)
|
|
else:
|
|
await ctx.send("❌ Failed to disable goodbye messages. Check logs.")
|
|
log.error(f"Failed to disable goodbye settings for guild {guild_id}")
|
|
|
|
# --- Test Commands ---
|
|
@commands.group(
|
|
name="testmessage",
|
|
help="Test the welcome or goodbye messages.",
|
|
invoke_without_command=True,
|
|
)
|
|
@commands.has_permissions(administrator=True)
|
|
@commands.guild_only()
|
|
async def testmessage(self, ctx: commands.Context):
|
|
"""Shows help for the testmessage command group."""
|
|
await ctx.send_help(ctx.command)
|
|
|
|
@testmessage.command(name="welcome")
|
|
async def test_welcome(
|
|
self, ctx: commands.Context, member: Optional[discord.Member] = None
|
|
):
|
|
"""Simulates a member joining to test the welcome message."""
|
|
target_member = member or ctx.author
|
|
await self.on_member_join(target_member)
|
|
|
|
embed = discord.Embed(
|
|
title="🧪 Test Message Sent",
|
|
description=f"Simulated welcome message for {target_member.mention}. Check the configured welcome channel.",
|
|
color=discord.Color.blue()
|
|
)
|
|
await ctx.send(embed=embed, ephemeral=True)
|
|
|
|
@testmessage.command(name="goodbye")
|
|
async def test_goodbye(
|
|
self,
|
|
ctx: commands.Context,
|
|
reason: Literal["left", "kicked", "banned"] = "left",
|
|
member: Optional[discord.Member] = None,
|
|
):
|
|
"""Simulates a member leaving to test the goodbye message."""
|
|
target_member = member or ctx.author
|
|
guild = ctx.guild
|
|
|
|
# --- Fetch settings ---
|
|
goodbye_channel_id_str = await settings_manager.get_setting(
|
|
guild.id, "goodbye_channel_id"
|
|
)
|
|
goodbye_message_template = await settings_manager.get_setting(
|
|
guild.id, "goodbye_message", default="{username} has left the server."
|
|
)
|
|
|
|
if not goodbye_channel_id_str or goodbye_channel_id_str == "__NONE__":
|
|
embed = discord.Embed(
|
|
title="❌ Configuration Error",
|
|
description="Goodbye message channel is not configured.",
|
|
color=discord.Color.red()
|
|
)
|
|
await ctx.send(embed=embed, ephemeral=True)
|
|
return
|
|
|
|
try:
|
|
goodbye_channel_id = int(goodbye_channel_id_str)
|
|
channel = guild.get_channel(goodbye_channel_id)
|
|
if not channel or not isinstance(channel, discord.TextChannel):
|
|
embed = discord.Embed(
|
|
title="❌ Configuration Error",
|
|
description="Configured goodbye channel not found or is not a text channel.",
|
|
color=discord.Color.red()
|
|
)
|
|
await ctx.send(embed=embed, ephemeral=True)
|
|
return
|
|
|
|
# --- Format and send message based on simulated reason ---
|
|
if reason == "left":
|
|
formatted_message = goodbye_message_template.format(
|
|
user=target_member.mention,
|
|
username=target_member.name,
|
|
server=guild.name,
|
|
)
|
|
elif reason == "kicked":
|
|
formatted_message = (
|
|
f"**{target_member.name}** was kicked from the server by **{ctx.author.name}**."
|
|
)
|
|
else: # banned
|
|
formatted_message = (
|
|
f"**{target_member.name}** was banned from the server by **{ctx.author.name}**."
|
|
)
|
|
|
|
# Get current member count
|
|
member_count = guild.member_count or len(guild.members)
|
|
|
|
view = GoodbyeMessageView(target_member, formatted_message, member_count, reason)
|
|
await channel.send(view=view)
|
|
|
|
embed = discord.Embed(
|
|
title="🧪 Test Message Sent",
|
|
description=f"Simulated goodbye message for {target_member.mention} (Reason: {reason}). Check the configured goodbye channel.",
|
|
color=discord.Color.blue()
|
|
)
|
|
await ctx.send(embed=embed, ephemeral=True)
|
|
|
|
except ValueError:
|
|
embed = discord.Embed(
|
|
title="❌ Configuration Error",
|
|
description="Invalid goodbye channel ID configured.",
|
|
color=discord.Color.red()
|
|
)
|
|
await ctx.send(embed=embed, ephemeral=True)
|
|
except discord.Forbidden:
|
|
embed = discord.Embed(
|
|
title="❌ Permission Error",
|
|
description="I don't have permissions to send messages in the configured goodbye channel.",
|
|
color=discord.Color.red()
|
|
)
|
|
await ctx.send(embed=embed, ephemeral=True)
|
|
except Exception as e:
|
|
log.exception(
|
|
f"Error sending test goodbye message for guild {guild.id}: {e}"
|
|
)
|
|
embed = discord.Embed(
|
|
title="❌ Unexpected Error",
|
|
description="An unexpected error occurred. Check the logs for details.",
|
|
color=discord.Color.red()
|
|
)
|
|
await ctx.send(embed=embed, ephemeral=True)
|
|
|
|
# Error Handling for this Cog
|
|
async def cog_command_error(self, ctx: commands.Context, error: commands.CommandError):
|
|
"""Handles errors for all commands in this cog."""
|
|
if isinstance(error, commands.MissingPermissions):
|
|
embed = discord.Embed(
|
|
title="❌ Missing Permissions",
|
|
description="You need Administrator permissions to use this command.",
|
|
color=discord.Color.red()
|
|
)
|
|
await ctx.send(embed=embed, ephemeral=True)
|
|
elif isinstance(error, commands.BadArgument):
|
|
embed = discord.Embed(
|
|
title="❌ Invalid Argument",
|
|
description=f"Invalid argument provided. Check the command help: `{ctx.prefix}help {ctx.command.name}`",
|
|
color=discord.Color.red()
|
|
)
|
|
await ctx.send(embed=embed, ephemeral=True)
|
|
elif isinstance(error, commands.MissingRequiredArgument):
|
|
embed = discord.Embed(
|
|
title="❌ Missing Argument",
|
|
description=f"Missing required argument. Check the command help: `{ctx.prefix}help {ctx.command.name}`",
|
|
color=discord.Color.red()
|
|
)
|
|
await ctx.send(embed=embed, ephemeral=True)
|
|
elif isinstance(error, commands.NoPrivateMessage):
|
|
embed = discord.Embed(
|
|
title="❌ Server Only",
|
|
description="This command cannot be used in private messages.",
|
|
color=discord.Color.red()
|
|
)
|
|
await ctx.send(embed=embed, ephemeral=True)
|
|
else:
|
|
original_error = getattr(error, 'original', error)
|
|
log.error(
|
|
f"Unhandled error in WelcomeCog command '{ctx.command.name}': {original_error}"
|
|
)
|
|
embed = discord.Embed(
|
|
title="❌ Unexpected Error",
|
|
description="An unexpected error occurred. Please check the logs for details.",
|
|
color=discord.Color.red()
|
|
)
|
|
await ctx.send(embed=embed, ephemeral=True)
|
|
|
|
|
|
async def setup(bot: commands.Bot):
|
|
# Ensure bot has pools initialized before adding the cog
|
|
if (
|
|
not hasattr(bot, "pg_pool")
|
|
or not hasattr(bot, "redis")
|
|
or bot.pg_pool is None
|
|
or bot.redis is None
|
|
):
|
|
log.warning(
|
|
"Bot pools not initialized before loading WelcomeCog. Cog will not load."
|
|
)
|
|
return # Prevent loading if pools are missing
|
|
|
|
welcome_cog = WelcomeCog(bot)
|
|
await bot.add_cog(welcome_cog)
|
|
log.info("WelcomeCog loaded.") |