2 Commits

Author SHA1 Message Date
acb71337fa Merge pull request 'feat: add welcome modes including solstira support' (#12) from welcomer into main
Reviewed-on: #12
2025-09-23 01:16:08 -04:00
c2367369f1 feat: add welcome modes including solstira support
Introduces 'normal' and 'solstira' modes to the welcomer cog.
Normal mode retains configurable channel and message.
Solstira mode provides hardcoded channel and complex embed for events.
2025-09-22 23:54:58 -04:00

View File

@@ -1,195 +1,121 @@
# welcomer.py
import discord import discord
from redbot.core import commands, Config from redbot.core import commands, Config
from redbot.core.bot import Red from redbot.core.bot import Red
from typing import Literal
class Welcomer(commands.Cog): class Welcomer(commands.Cog):
""" """
A configurable cog to welcome new users to a server. A configurable cog to automatically welcome new users with multiple modes.
""" """
def __init__(self, bot: Red): def __init__(self, bot: Red):
self.bot = bot 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) self.config = Config.get_conf(self, identifier=1234567890, force_registration=True)
# Define the default settings for each server.
default_guild = { default_guild = {
"welcome_channel": None, # The ID of the channel to send welcomes to "welcome_channel": None,
"welcome_message": "Welcome to the server, {user.mention}!", # Default message "welcome_message": "Welcome to the server, {user.mention}!",
"enabled": False # Whether the system is on or off "enabled": False,
"welcome_mode": "normal" # 'normal' or 'solstira'
} }
# Register the default settings.
self.config.register_guild(**default_guild) self.config.register_guild(**default_guild)
@commands.Cog.listener() @commands.Cog.listener()
async def on_member_join(self, member: discord.Member): async def on_member_join(self, member: discord.Member):
"""
The event listener that runs when a new member joins.
"""
guild = member.guild guild = member.guild
# Check if the welcomer is enabled for this server.
if not await self.config.guild(guild).enabled(): if not await self.config.guild(guild).enabled():
return return
# Get the welcome channel ID from our saved settings. mode = await self.config.guild(guild).welcome_mode()
if mode == "solstira":
# Hardcoded Solstira welcome event
channel_id = 1409965732669948024
else: # Normal mode
channel_id = await self.config.guild(guild).welcome_channel() channel_id = await self.config.guild(guild).welcome_channel()
if not channel_id: if not channel_id:
return # If no channel is set, do nothing. return
# Try to find the channel object in the server.
channel = guild.get_channel(channel_id) 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): if not isinstance(channel, discord.TextChannel):
print(f"Welcomer: Configured channel '{channel.name}' in {guild.name} is not a text channel.")
return return
# Get the custom welcome message from our settings. if not channel.permissions_for(guild.me).send_messages:
message_template = await self.config.guild(guild).welcome_message() return
# Format the message with the new member's info. if mode == "solstira":
# .format() is a safe way to replace placeholders. content = (
f"{member.mention}\n"
f"- `guide` <https://discord.com/channels/1409939326382651/140993936542124073>\n"
f"- <a:f_purpleflower:1409967049561524859> `roles` <@&1409937150>\n"
f"(<https://discord.com/channels/1409939326382651/140996735493797150>)\n"
f"- `psa` (<https://discord.com/channels/1409939326382651/140996779492440732>)"
)
embed = discord.Embed(description="--", color=0x8b9ed7)
try:
await channel.send(content, embed=embed)
except discord.HTTPException:
pass
else: # Normal mode
message_template = await self.config.guild(guild).welcome_message()
formatted_message = message_template.format( formatted_message = message_template.format(
user=member, user=member,
user_mention=member.mention, user_mention=member.mention,
user_name=member.name, user_name=member.name,
server_name=guild.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: try:
await channel.send(formatted_message) await channel.send(formatted_message)
except discord.Forbidden: except discord.HTTPException:
# This is a final safety check in case permissions change suddenly.
pass 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.group(aliases=["wset"]) # type: ignore
@commands.guild_only() # Ensures this command and its subcommands can only be run in a server @commands.guild_only()
@commands.admin_or_permissions(manage_guild=True) @commands.admin_or_permissions(manage_guild=True)
async def welcomeset(self, ctx: commands.Context): async def welcomeset(self, ctx: commands.Context):
""" """Commands for configuring the welcome system."""
Configure the welcomer settings for this server.
"""
pass pass
@welcomeset.command(name="channel", aliases=["chnl"]) @welcomeset.command(name="mode")
async def welcomeset_channel(self, ctx: commands.Context, channel: discord.TextChannel): async def set_welcome_mode(self, ctx: commands.Context, mode: Literal["normal", "solstira"]):
""" """Set the welcome mode for this server.
Set the channel where welcome messages will be sent.
Example: Modes:
[p]welcomeset channel #welcome - `normal`: A simple, configurable welcome message.
- `solstira`: The special, complex welcome event.
""" """
if not ctx.guild: if not ctx.guild:
return # This check satisfies the type checker return
await self.config.guild(ctx.guild).welcome_mode.set(mode.lower())
await ctx.send(f"Welcome mode has been set to **{mode.lower()}**.")
@welcomeset.command(name="channel")
async def set_welcome_channel(self, ctx: commands.Context, channel: discord.TextChannel):
"""(Normal Mode) Set the channel for welcome messages."""
if not ctx.guild:
return
await self.config.guild(ctx.guild).welcome_channel.set(channel.id) await self.config.guild(ctx.guild).welcome_channel.set(channel.id)
await ctx.send(f"The welcome channel has been set to {channel.mention}.") await ctx.send(f"Welcome channel set to {channel.mention}")
@welcomeset.command(name="message", aliases=["msg"]) @welcomeset.command(name="message")
async def welcomeset_message(self, ctx: commands.Context, *, message: str): async def set_welcome_message(self, ctx: commands.Context, *, message: str):
""" """(Normal Mode) Set the welcome message. Use placeholders like {user.mention}."""
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: if not ctx.guild:
return return
await self.config.guild(ctx.guild).welcome_message.set(message) await self.config.guild(ctx.guild).welcome_message.set(message)
await ctx.send(f"The welcome message has been updated.") await ctx.send("Welcome message 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"]) @welcomeset.command(name="toggle")
async def welcomeset_toggle(self, ctx: commands.Context): async def toggle_welcome(self, ctx: commands.Context):
""" """Toggle the welcome system on or off."""
Enable or disable the welcomer system on this server.
"""
if not ctx.guild: if not ctx.guild:
return return
current_status = await self.config.guild(ctx.guild).enabled() current_status = await self.config.guild(ctx.guild).enabled()
new_status = not current_status new_status = not current_status
await self.config.guild(ctx.guild).enabled.set(new_status) await self.config.guild(ctx.guild).enabled.set(new_status)
status_text = "enabled" if new_status else "disabled" status_text = "enabled" if new_status else "disabled"
await ctx.send(f"The welcomer system has been {status_text}.") await ctx.send(f"Welcome 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): async def setup(bot: Red):
await bot.add_cog(Welcomer(bot)) await bot.add_cog(Welcomer(bot))