241 lines
12 KiB
Python
241 lines
12 KiB
Python
import discord
|
|
from discord.ext import commands
|
|
import logging
|
|
import sys
|
|
import os
|
|
|
|
# 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
|
|
from global_bot_accessor import get_bot_instance
|
|
|
|
log = logging.getLogger(__name__)
|
|
|
|
class WelcomeCog(commands.Cog):
|
|
"""Handles welcome and goodbye messages for guilds."""
|
|
|
|
def __init__(self, bot: commands.Bot):
|
|
self.bot = bot
|
|
print("WelcomeCog: Initializing and registering event listeners")
|
|
|
|
# Check existing event listeners
|
|
print(f"WelcomeCog: Bot event listeners before registration: {self.bot.extra_events}")
|
|
|
|
# Register event listeners
|
|
self.bot.add_listener(self.on_member_join, "on_member_join")
|
|
self.bot.add_listener(self.on_member_remove, "on_member_remove")
|
|
|
|
# Check if event listeners were registered
|
|
print(f"WelcomeCog: Bot event listeners after registration: {self.bot.extra_events}")
|
|
print("WelcomeCog: Event listeners registered")
|
|
|
|
async def on_member_join(self, member: discord.Member):
|
|
"""Sends a welcome message when a new member joins."""
|
|
print(f"WelcomeCog: on_member_join event triggered for {member.name}")
|
|
guild = member.guild
|
|
if not guild:
|
|
print(f"WelcomeCog: Guild not found for member {member.name}")
|
|
return
|
|
|
|
log.debug(f"Member {member.name} joined guild {guild.name} ({guild.id})")
|
|
print(f"WelcomeCog: Member {member.name} joined guild {guild.name} ({guild.id})")
|
|
|
|
# --- Fetch settings ---
|
|
print(f"WelcomeCog: Fetching welcome settings for guild {guild.id}")
|
|
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}!")
|
|
print(f"WelcomeCog: Retrieved settings - channel_id: {welcome_channel_id_str}, message: {welcome_message_template}")
|
|
|
|
# Handle the "__NONE__" marker for potentially unset values
|
|
if not welcome_channel_id_str or welcome_channel_id_str == "__NONE__":
|
|
log.debug(f"Welcome channel not configured for guild {guild.id}")
|
|
print(f"WelcomeCog: 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}")
|
|
# Maybe remove the setting here if the channel is invalid?
|
|
return
|
|
|
|
# --- Format and send message ---
|
|
# Basic formatting, can be expanded
|
|
formatted_message = welcome_message_template.format(
|
|
user=member.mention,
|
|
username=member.name,
|
|
server=guild.name
|
|
)
|
|
|
|
await channel.send(formatted_message)
|
|
log.info(f"Sent welcome message for {member.name} in guild {guild.id}")
|
|
|
|
except ValueError:
|
|
log.error(f"Invalid welcome_channel_id '{welcome_channel_id_str}' configured for guild {guild.id}")
|
|
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."""
|
|
print(f"WelcomeCog: on_member_remove event triggered for {member.name}")
|
|
guild = member.guild
|
|
if not guild:
|
|
print(f"WelcomeCog: Guild not found for member {member.name}")
|
|
return
|
|
|
|
log.debug(f"Member {member.name} left guild {guild.name} ({guild.id})")
|
|
print(f"WelcomeCog: Member {member.name} left guild {guild.name} ({guild.id})")
|
|
|
|
# --- Fetch settings ---
|
|
print(f"WelcomeCog: Fetching goodbye settings for guild {guild.id}")
|
|
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.")
|
|
print(f"WelcomeCog: Retrieved settings - channel_id: {goodbye_channel_id_str}, message: {goodbye_message_template}")
|
|
|
|
# Handle the "__NONE__" marker
|
|
if not goodbye_channel_id_str or goodbye_channel_id_str == "__NONE__":
|
|
log.debug(f"Goodbye channel not configured for guild {guild.id}")
|
|
print(f"WelcomeCog: 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
|
|
|
|
# --- Format and send message ---
|
|
formatted_message = goodbye_message_template.format(
|
|
user=member.mention, # Might not be mentionable after leaving
|
|
username=member.name,
|
|
server=guild.name
|
|
)
|
|
|
|
await channel.send(formatted_message)
|
|
log.info(f"Sent goodbye message for {member.name} in guild {guild.id}")
|
|
|
|
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
|
|
await ctx.send(f"Welcome messages will now be sent to {channel.mention} with the template:\n```\n{message_template}\n```")
|
|
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
|
|
await ctx.send("Welcome messages have been disabled.")
|
|
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
|
|
await ctx.send(f"Goodbye messages will now be sent to {channel.mention} with the template:\n```\n{message_template}\n```")
|
|
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
|
|
await ctx.send("Goodbye messages have been disabled.")
|
|
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}")
|
|
|
|
# Error Handling for this Cog
|
|
@set_welcome.error
|
|
@disable_welcome.error
|
|
@set_goodbye.error
|
|
@disable_goodbye.error
|
|
async def on_command_error(self, ctx: commands.Context, error):
|
|
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 WelcomeCog command '{ctx.command.name}': {error}")
|
|
await ctx.send("An unexpected error occurred. Please check the logs.")
|
|
|
|
|
|
async def setup(bot: commands.Bot):
|
|
# Ensure bot has pools initialized before adding the cog
|
|
print("WelcomeCog setup function called!")
|
|
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.")
|
|
print("WelcomeCog: Bot pools not initialized. Cannot load cog.")
|
|
return # Prevent loading if pools are missing
|
|
|
|
welcome_cog = WelcomeCog(bot)
|
|
await bot.add_cog(welcome_cog)
|
|
print(f"WelcomeCog loaded! Event listeners registered: on_member_join, on_member_remove")
|
|
log.info("WelcomeCog loaded.")
|