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.
This commit is contained in:
2025-09-22 23:54:58 -04:00
parent e552ba7552
commit c2367369f1

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()
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 mode == "solstira":
if not channel.permissions_for(guild.me).send_messages: # Hardcoded Solstira welcome event
# We can't send a message, so we'll just log this internally. channel_id = 1409965732669948024
print(f"Welcomer: No permission to send messages in {channel.name} in {guild.name}.") else: # Normal mode
channel_id = await self.config.guild(guild).welcome_channel()
if not channel_id:
return return
try: channel = guild.get_channel(channel_id)
await channel.send(formatted_message) if not isinstance(channel, discord.TextChannel):
except discord.Forbidden: return
# This is a final safety check in case permissions change suddenly.
pass if not channel.permissions_for(guild.me).send_messages:
except discord.HTTPException as e: return
# 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}") if mode == "solstira":
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(
user=member,
user_mention=member.mention,
user_name=member.name,
server_name=guild.name
)
try:
await channel.send(formatted_message)
except discord.HTTPException:
pass
# 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))