# welcomer.py import discord from redbot.core import commands, Config from redbot.core.bot import Red class Welcomer(commands.Cog): """ A configurable cog to welcome new users to a server. """ def __init__(self, bot: Red): self.bot = bot # Initialize Red's Config system. This will store our settings. # The "GUILD" identifier means settings will be saved on a per-server basis. self.config = Config.get_conf(self, identifier=1234567890, force_registration=True) # Define the default settings for each server. default_guild = { "welcome_channel": None, # The ID of the channel to send welcomes to "welcome_message": "Welcome to the server, {user.mention}!", # Default message "enabled": False # Whether the system is on or off } # Register the default settings. self.config.register_guild(**default_guild) @commands.Cog.listener() async def on_member_join(self, member: discord.Member): """ The event listener that runs when a new member joins. """ guild = member.guild # Check if the welcomer is enabled for this server. if not await self.config.guild(guild).enabled(): return # Get the welcome channel ID from our saved settings. channel_id = await self.config.guild(guild).welcome_channel() if not channel_id: return # If no channel is set, do nothing. # Try to find the channel object in the server. channel = guild.get_channel(channel_id) if not channel: # The channel might have been deleted. return # Explicitly check if the channel is a TextChannel before trying to send a message. if not isinstance(channel, discord.TextChannel): print(f"Welcomer: Configured channel '{channel.name}' in {guild.name} is not a text channel.") return # Get the custom welcome message from our settings. message_template = await self.config.guild(guild).welcome_message() # Format the message with the new member's info. # .format() is a safe way to replace placeholders. formatted_message = message_template.format( user=member, user_mention=member.mention, user_name=member.name, server_name=guild.name ) # Check if we have permission to send messages in the channel. if not channel.permissions_for(guild.me).send_messages: # We can't send a message, so we'll just log this internally. print(f"Welcomer: No permission to send messages in {channel.name} in {guild.name}.") return try: await channel.send(formatted_message) except discord.Forbidden: # This is a final safety check in case permissions change suddenly. pass except discord.HTTPException as e: # This can happen if the message is too long or there's a Discord API error. print(f"Welcomer: Failed to send welcome message in {guild.name}: {e}") # Create a command group for all our settings commands. @commands.group(aliases=["wset"]) # type: ignore @commands.guild_only() # Ensures this command and its subcommands can only be run in a server @commands.admin_or_permissions(manage_guild=True) async def welcomeset(self, ctx: commands.Context): """ Configure the welcomer settings for this server. """ pass @welcomeset.command(name="channel", aliases=["chnl"]) async def welcomeset_channel(self, ctx: commands.Context, channel: discord.TextChannel): """ Set the channel where welcome messages will be sent. Example: [p]welcomeset channel #welcome """ if not ctx.guild: return # This check satisfies the type checker await self.config.guild(ctx.guild).welcome_channel.set(channel.id) await ctx.send(f"The welcome channel has been set to {channel.mention}.") @welcomeset.command(name="message", aliases=["msg"]) async def welcomeset_message(self, ctx: commands.Context, *, message: str): """ Set the custom welcome message. You can use these placeholders: {user} - The user object. {user_mention} - Pings the user. {user_name} - The user's name. {server_name} - The name of this server. Example: [p]welcomeset message Hello {user_mention}, welcome to {server_name}! """ if not ctx.guild: return await self.config.guild(ctx.guild).welcome_message.set(message) await ctx.send(f"The welcome message has been updated.") # Send a preview of the new message. preview = message.format( user=ctx.author, user_mention=ctx.author.mention, user_name=ctx.author.name, server_name=ctx.guild.name ) await ctx.send(f"**Preview:**\n{preview}") @welcomeset.command(name="toggle", aliases=["on", "off"]) async def welcomeset_toggle(self, ctx: commands.Context): """ Enable or disable the welcomer system on this server. """ if not ctx.guild: return current_status = await self.config.guild(ctx.guild).enabled() new_status = not current_status await self.config.guild(ctx.guild).enabled.set(new_status) status_text = "enabled" if new_status else "disabled" await ctx.send(f"The welcomer system has been {status_text}.") @welcomeset.command(name="settings", aliases=["show", "status"]) async def welcomeset_settings(self, ctx: commands.Context): """ Show the current welcomer settings for this server. """ if not ctx.guild: return settings = await self.config.guild(ctx.guild).all() channel_id = settings['welcome_channel'] channel = ctx.guild.get_channel(channel_id) if channel_id else None message = settings['welcome_message'] enabled = "Enabled" if settings['enabled'] else "Disabled" embed = discord.Embed(title="Welcomer Settings", color=await ctx.embed_color()) embed.add_field(name="Status", value=enabled, inline=False) embed.add_field(name="Channel", value=channel.mention if isinstance(channel, discord.TextChannel) else "Not Set", inline=False) embed.add_field(name="Message", value=f"```{message}```", inline=False) await ctx.send(embed=embed) @welcomeset.command(name="test") async def welcomeset_test(self, ctx: commands.Context): """ Test the welcome message by sending a preview to this channel. """ if not ctx.guild: return message_template = await self.config.guild(ctx.guild).welcome_message() preview = message_template.format( user=ctx.author, user_mention=ctx.author.mention, user_name=ctx.author.name, server_name=ctx.guild.name ) await ctx.send(f"**Welcome Message Preview**:\n{preview}") @welcomeset.command(name="reset") async def welcomeset_reset(self, ctx: commands.Context): """ Reset all welcomer settings to their defaults. """ if not ctx.guild: return await self.config.guild(ctx.guild).clear() await ctx.send("The welcomer settings have been reset to their defaults.") # This function allows Red to load the cog. # It is required in every cog file. async def setup(bot: Red): await bot.add_cog(Welcomer(bot))