# ╔══════════════════════════════════════════════════════════════════╗ # ║ ║ # ║ ░█▀▀░█▀█░█▀▄░█▀▀░█░█ ░█▀▄░█▀▀░█░█░█▀▀ ║ # ║ ░█░░░█░█░█░█░█▀▀░▄▀▄ ░█░█░█▀▀░▀▄▀░▀▀█ ║ # ║ ░▀▀▀░▀▀▀░▀▀░░▀▀▀░▀░▀ ░▀▀░░▀▀▀░░▀░░▀▀▀ ║ # ║ ║ # ║ © 2026 CodeX Devs — All Rights Reserved ║ # ║ ║ # ║ discord ── https://discord.gg/codexdev ║ # ║ youtube ── https://youtube.com/@CodeXDevs ║ # ║ github ── https://github.com/RayExo ║ # ║ ║ # ╚══════════════════════════════════════════════════════════════════╝ import discord from utils.emoji import ICONS_CHANNEL, ICONS_PLUS, TICK, ZTICK from discord.ext import commands from discord.ui import View, Select, Button import aiosqlite import asyncio import re import json from utils.Tools import * class VariableButton(Button): def __init__(self, author): super().__init__(label="Variables", style=discord.ButtonStyle.secondary) self.author = author async def callback(self, interaction: discord.Interaction): if interaction.user != self.author: await interaction.response.send_message("Only the command author can use this button.", ephemeral=True) return variables = { "{user}": "Mentions the user (e.g., @UserName).", "{user_avatar}": "The user's avatar URL.", "{user_name}": "The user's username.", "{user_id}": "The user's ID number.", "{user_nick}": "The user's nickname in the server.", "{user_joindate}": "The user's join date in the server (formatted as Day, Month Day, Year).", "{user_createdate}": "The user's account creation date (formatted as Day, Month Day, Year).", "{server_name}": "The server's name.", "{server_id}": "The server's ID number.", "{server_membercount}": "The server's total member count.", "{server_icon}": "The server's icon URL." } embed = discord.Embed( title="Available Placeholders", description="Use these placeholders in your welcome message:", color=discord.Color(0xFF0000) ) for var, desc in variables.items(): embed.add_field(name=var, value=desc, inline=False) embed.set_footer(text="Add placeholders directly in the welcome message or embed fields.") await interaction.response.send_message(embed=embed, ephemeral=True) class Welcomer(commands.Cog): def __init__(self, bot): self.bot = bot self.bot.loop.create_task(self._create_table()) async def _create_table(self): async with aiosqlite.connect("db/welcome.db") as db: await db.execute(""" CREATE TABLE IF NOT EXISTS welcome ( guild_id INTEGER PRIMARY KEY, welcome_type TEXT, welcome_message TEXT, channel_id INTEGER, embed_data TEXT, auto_delete_duration INTEGER ) """) await db.commit() @commands.hybrid_group(invoke_without_command=True, name="greet", help="Shows all the greet commands.") @blacklist_check() @ignore_check() async def greet(self, ctx: commands.Context): if ctx.subcommand_passed is None: await ctx.send_help(ctx.command) ctx.command.reset_cooldown(ctx) @greet.command(name="setup", help="Configures a welcome message for new members joining the server. ") @blacklist_check() @ignore_check() @commands.has_permissions(administrator=True) @commands.cooldown(1, 6, commands.BucketType.user) @commands.max_concurrency(1, per=commands.BucketType.default, wait=False) async def greet_setup(self, ctx): async with aiosqlite.connect("db/welcome.db") as db: async with db.execute("SELECT * FROM welcome WHERE guild_id = ?", (ctx.guild.id,)) as cursor: row = await cursor.fetchone() if row: error = discord.Embed(description=f"A welcome message has already been set in {ctx.guild.name}. Use `{ctx.prefix}greet reset` to reconfigure.", color=0xFF0000) error.set_author(name="Error", icon_url="https://cdn.discordapp.com/emojis/1294218790082711553.png") return await ctx.send(embed=error) options_view = View(timeout=600) async def option_callback(interaction: discord.Interaction, button: Button): if interaction.user != ctx.author: await interaction.response.send_message("You cannot interact with this setup.", ephemeral=True) return await interaction.response.defer() if button.custom_id == "simple": await interaction.message.delete() await self.simple_setup(ctx) elif button.custom_id == "embed": await interaction.message.delete() await self.embed_setup(ctx) elif button.custom_id == "cancel": await interaction.message.delete() button_simple = Button(label="Simple", style=discord.ButtonStyle.success, custom_id="simple") button_simple.callback = lambda interaction: option_callback(interaction, button_simple) options_view.add_item(button_simple) button_embed = Button(label="Embed", style=discord.ButtonStyle.success, custom_id="embed") button_embed.callback = lambda interaction: option_callback(interaction, button_embed) options_view.add_item(button_embed) button_cancel = Button(label="Cancel", style=discord.ButtonStyle.danger, custom_id="cancel") button_cancel.callback = lambda interaction: option_callback(interaction, button_cancel) options_view.add_item(button_cancel) embed = discord.Embed( title="Welcome Message Setup", description="Choose the type of welcome message you want to create:", color=0xFF0000 ) embed.add_field( name=" Simple", value="Send a plain text welcome message. You can use placeholders to personalize it.\n\n", inline=False ) embed.add_field( name=" Embed", value="Send a welcome message in an embed format. You can customize the embed with a title, description, image, etc.", inline=False ) embed.set_footer(text="Click the buttons below to choose the welcome message type.", icon_url=self.bot.user.display_avatar.url) await ctx.send(embed=embed, view=options_view) async def simple_setup(self, ctx): setup_view = View(timeout=600) first = View(timeout=600) message_content = [] placeholders = { "user": ctx.author.mention, "user_avatar": ctx.author.avatar.url if ctx.author.avatar else ctx.author.default_avatar.url, "user_name": ctx.author.name, "user_id": ctx.author.id, "user_nick": ctx.author.display_name, "user_joindate": ctx.author.joined_at.strftime("%a, %b %d, %Y"), "user_createdate": ctx.author.created_at.strftime("%a, %b %d, %Y"), "server_name": ctx.guild.name, "server_id": ctx.guild.id, "server_membercount": ctx.guild.member_count, "server_icon": ctx.guild.icon.url if ctx.guild.icon else "https://cdn.discordapp.com/embed/avatars/0.png", "timestamp": discord.utils.format_dt(ctx.message.created_at) } def safe_format(text): placeholders_lower = {k.lower(): v for k, v in placeholders.items()} def replace_var(match): var_name = match.group(1).lower() return str(placeholders_lower.get(var_name, f"{{{var_name}}}")) return re.sub(r"\{(\w+)\}", replace_var, text or "") async def update_preview(content): preview = safe_format(content) await preview_message.edit(content=f"**Preview:** {preview}", view=setup_view) first.add_item(VariableButton(ctx.author)) preview_message = await ctx.send("__**Simple Message Setup**__ \nEnter your welcome message here:", view=first) async def submit_callback(interaction): if interaction.user != ctx.author: await interaction.response.send_message("You cannot interact with this setup.", ephemeral=True) return if message_content: await self._save_welcome_data(ctx.guild.id, "simple", message_content[0]) await interaction.response.send_message(f"{TICK}> Welcome message setup completed!") for item in setup_view.children: item.disabled = True await preview_message.edit(view=setup_view) else: await interaction.response.send_message("No message entered to submit.", ephemeral=True) async def edit_callback(interaction): if interaction.user != ctx.author: await interaction.response.send_message("You cannot interact with this setup.", ephemeral=True) return await interaction.response.defer() await ctx.send("Enter the updated welcome message:") try: msg = await self.bot.wait_for("message", timeout=600, check=lambda m: m.author == ctx.author and m.channel == ctx.channel) message_content.clear() message_content.append(msg.content) await update_preview(msg.content) except asyncio.TimeoutError: await ctx.send("Editing timed out.") async def cancel_callback(interaction): if interaction.user != ctx.author: await interaction.response.send_message("You cannot interact with this setup.", ephemeral=True) return await preview_message.delete() submit_button = Button(label="Submit", style=discord.ButtonStyle.success) submit_button.callback = submit_callback setup_view.add_item(submit_button) edit_button = Button(label="Edit", style=discord.ButtonStyle.primary) edit_button.callback = edit_callback setup_view.add_item(edit_button) setup_view.add_item(VariableButton(ctx.author)) cancel_button = Button(emoji=ICONS_PLUS, style=discord.ButtonStyle.secondary) cancel_button.callback = cancel_callback setup_view.add_item(cancel_button) try: msg = await self.bot.wait_for("message", timeout=600, check=lambda m: m.author == ctx.author and m.channel == ctx.channel) message_content.append(msg.content) await update_preview(msg.content) except asyncio.TimeoutError: await ctx.send("Setup timed out.") async def _save_welcome_data(self, guild_id, welcome_type, message, embed_data=None): async with aiosqlite.connect("db/welcome.db") as db: await db.execute(""" INSERT OR REPLACE INTO welcome (guild_id, welcome_type, welcome_message, embed_data) VALUES (?, ?, ?, ?) """, (guild_id, welcome_type, message, json.dumps(embed_data) if embed_data else None)) await db.commit() async def embed_setup(self, ctx): setup_view = View(timeout=600) embed_data = { "message": None, "title": None, "description": None, "color": None, "footer_text": None, "footer_icon": None, "author_name": None, "author_icon": None, "thumbnail": None, "image": None, } placeholders = { "user": ctx.author.mention, "user_avatar": ctx.author.avatar.url if ctx.author.avatar else ctx.author.default_avatar.url, "user_name": ctx.author.name, "user_id": ctx.author.id, "user_nick": ctx.author.display_name, "user_joindate": ctx.author.joined_at.strftime("%a, %b %d, %Y"), "user_createdate": ctx.author.created_at.strftime("%a, %b %d, %Y"), "server_name": ctx.guild.name, "server_id": ctx.guild.id, "server_membercount": ctx.guild.member_count, "server_icon": ctx.guild.icon.url if ctx.guild.icon else "https://cdn.discordapp.com/embed/avatars/0.png", "timestamp": discord.utils.format_dt(ctx.message.created_at) } def safe_format(text): placeholders_lower = {k.lower(): v for k, v in placeholders.items()} def replace_var(match): var_name = match.group(1).lower() return str(placeholders_lower.get(var_name, f"{{{var_name}}}")) return re.sub(r"\{(\w+)\}", replace_var, text or "") async def update_preview(): content = safe_format(embed_data["message"]) or "Message Content." embed = discord.Embed( title=safe_format(embed_data["title"]) or "", description=safe_format(embed_data["description"]) or "```Customize your welcome embed, take help of variables.```", color=discord.Color(embed_data["color"]) if embed_data["color"] else discord.Color(0x2f3136) ) if embed_data["footer_text"]: embed.set_footer(text=safe_format(embed_data["footer_text"]), icon_url=safe_format(embed_data["footer_icon"]) or None) if embed_data["author_name"]: embed.set_author(name=safe_format(embed_data["author_name"]), icon_url=safe_format(embed_data["author_icon"]) or None) if embed_data["thumbnail"]: embed.set_thumbnail(url=safe_format(embed_data["thumbnail"])) if embed_data["image"]: embed.set_image(url=safe_format(embed_data["image"])) await preview_message.edit(content="**Embed Preview:** " + content, embed=embed, view=setup_view) preview_message = await ctx.send("Configuring embed welcome message...") async def handle_selection(interaction: discord.Interaction): if interaction.user != ctx.author: await interaction.response.send_message("You cannot interact with this setup.", ephemeral=True) return selected_option = select_menu.values[0] await interaction.response.defer() try: if selected_option == "message": await ctx.send("Enter the welcome message content:") msg = await self.bot.wait_for("message", check=lambda m: m.author == ctx.author and m.channel == ctx.channel) embed_data["message"] = msg.content elif selected_option == "title": await ctx.send("Enter the embed title:") msg = await self.bot.wait_for("message", check=lambda m: m.author == ctx.author and m.channel == ctx.channel) embed_data["title"] = msg.content elif selected_option == "description": await ctx.send("Enter the embed description:") msg = await self.bot.wait_for("message", check=lambda m: m.author == ctx.author and m.channel == ctx.channel) embed_data["description"] = msg.content elif selected_option == "color": await ctx.send("Enter a hex color (e.g., #3498db or 3498db):") msg = await self.bot.wait_for("message", check=lambda m: m.author == ctx.author and m.channel == ctx.channel) color_code = msg.content.lstrip("#") if all(c in "0123456789abcdefABCDEF" for c in color_code) and len(color_code) in {3, 6}: embed_data["color"] = int(color_code.lstrip("#"), 16) else: await ctx.send("Invalid color code. Please enter a valid hex color.") elif selected_option in ["footer_text", "footer_icon", "author_name", "author_icon", "thumbnail", "image"]: await ctx.send(f"Enter the URL or text for {selected_option.replace('_', ' ')}:") msg = await self.bot.wait_for("message", check=lambda m: m.author == ctx.author and m.channel == ctx.channel) url_or_text = msg.content if selected_option in ["footer_icon", "author_icon", "thumbnail", "image"]: if url_or_text.startswith("http") or url_or_text in ["{user_avatar}", "{server_icon}"]: embed_data[selected_option] = url_or_text else: await ctx.send("Invalid URL. Please enter a valid image URL or a supported placeholder ({user_avatar} or {server_icon}).") else: embed_data[selected_option] = url_or_text await update_preview() await interaction.followup.send(f"{selected_option.capitalize()} updated.", ephemeral=True) except asyncio.TimeoutError: await ctx.send("You took too long to respond. Please try again.") except Exception as e: await ctx.send(f"An error occurred: {e}") select_menu = Select( placeholder="Choose an option to edit the Embed", options=[ discord.SelectOption(label="Message Content", value="message"), discord.SelectOption(label="Title", value="title"), discord.SelectOption(label="Description", value="description"), discord.SelectOption(label="Color", value="color"), discord.SelectOption(label="Footer Text", value="footer_text"), discord.SelectOption(label="Footer Icon", value="footer_icon"), discord.SelectOption(label="Author Name", value="author_name"), discord.SelectOption(label="Author Icon", value="author_icon"), discord.SelectOption(label="Thumbnail", value="thumbnail"), discord.SelectOption(label="Image", value="image") ] ) select_menu.callback = handle_selection setup_view.add_item(select_menu) async def submit_callback(interaction): if interaction.user != ctx.author: await interaction.response.send_message("You cannot interact with this setup.", ephemeral=True) return if not any(embed_data[key] for key in ["title", "description"]): await interaction.response.send_message("Please provide at least a title or an description before submitting.", ephemeral=True) return await self._save_welcome_data(ctx.guild.id, "embed", embed_data["message"] or "", embed_data) await interaction.response.send_message(f"{TICK}> Embed welcome message setup completed!") for item in setup_view.children: item.disabled = True await preview_message.edit(view=setup_view) submit_button = Button(label="Submit", style=discord.ButtonStyle.success) submit_button.callback = submit_callback setup_view.add_item(submit_button) setup_view.add_item(VariableButton(ctx.author)) async def cancel_callback(interaction): if interaction.user != ctx.author: await interaction.response.send_message("You cannot interact with this setup.", ephemeral=True) return await preview_message.delete() await interaction.response.send_message("Embed setup cancelled.", ephemeral=True) cancel_button = Button(label="Cancel", style=discord.ButtonStyle.danger) cancel_button.callback = cancel_callback setup_view.add_item(cancel_button) await update_preview() @greet.command(name="reset", aliases=["disable"], help="Resets and deletes the current welcome configuration for the server.") @blacklist_check() @ignore_check() @commands.has_permissions(administrator=True) @commands.cooldown(1, 6, commands.BucketType.user) @commands.max_concurrency(1, per=commands.BucketType.default, wait=False) async def greet_reset(self, ctx): async with aiosqlite.connect("db/welcome.db") as db: cursor = await db.execute("SELECT 1 FROM welcome WHERE guild_id = ?", (ctx.guild.id,)) is_set_up = await cursor.fetchone() if not is_set_up: error = discord.Embed(description=f"No welcome message has been set for {ctx.guild.name}! Please set a welcome message first using `{ctx.prefix}greet setup`", color=0xFF0000) error.set_author(name="Greet is not configured!", icon_url="https://cdn.discordapp.com/emojis/1294218790082711553.png") return await ctx.send(embed=error) embed = discord.Embed( title="Are you sure?", description="This will remove all welcome configurations & data related to welcome messages for this server!", color=0xFF0000 ) yes_button = Button(label="Confirm", style=discord.ButtonStyle.danger) no_button = Button(label="Cancel", style=discord.ButtonStyle.secondary) async def yes_button_callback(interaction): if interaction.user != ctx.author: await interaction.response.send_message("Only the command author can confirm this action.", ephemeral=True) return async with aiosqlite.connect("db/welcome.db") as db: await db.execute("DELETE FROM welcome WHERE guild_id = ?", (ctx.guild.id,)) await db.commit() embed.color = discord.Color(0xFF0000) embed.title = f"{TICK}> Success" embed.description = "Welcome message configuration has been successfully reset." await interaction.message.edit(embed=embed, view=None) async def no_button_callback(interaction): if interaction.user != ctx.author: await interaction.response.send_message("Only the command author can cancel this action.", ephemeral=True) return embed.color = discord.Color(0xFF0000) embed.title = "Cancelled" embed.description = "Greet Reset operation has been cancelled." await interaction.message.edit(embed=embed, view=None) yes_button.callback = yes_button_callback no_button.callback = no_button_callback view = View() view.add_item(yes_button) view.add_item(no_button) await ctx.send(embed=embed, view=view) @greet.command(name="channel", help="Sets the channel where welcome messages will be sent.") @blacklist_check() @ignore_check() @commands.has_permissions(administrator=True) @commands.cooldown(1, 6, commands.BucketType.user) @commands.max_concurrency(1, per=commands.BucketType.default, wait=False) async def greet_channel(self, ctx): async with aiosqlite.connect("db/welcome.db") as db: async with db.execute("SELECT welcome_type, channel_id FROM welcome WHERE guild_id = ?", (ctx.guild.id,)) as cursor: result = await cursor.fetchone() welcome_message = result[0] if result else None welcome_channel = ctx.guild.get_channel(result[1]) if result and result[1] else None if not welcome_message: error = discord.Embed(description=f"No welcome message has been set for {ctx.guild.name}! Please set a welcome message first using `{ctx.prefix}greet setup`", color=0xFF0000) error.set_author(name="Greet is not configured!", icon_url="https://cdn.discordapp.com/emojis/1294218790082711553.png") await ctx.send(embed=error) return channels = ctx.guild.text_channels chunk_size = 25 chunks = [channels[i:i + chunk_size] for i in range(0, len(channels), chunk_size)] current_page = 0 def generate_view(page): select_menu = Select( placeholder="Select a channel for welcome messages", options=[ discord.SelectOption(label=channel.name, emoji=ICONS_CHANNEL, value=str(channel.id)) for channel in chunks[page] ] ) async def select_callback(interaction: discord.Interaction): if interaction.user != ctx.author: await interaction.response.send_message("You are not authorized to set the welcome channel.", ephemeral=True) return selected_channel_id = int(select_menu.values[0]) selected_channel = ctx.guild.get_channel(selected_channel_id) async with aiosqlite.connect("db/welcome.db") as db: await db.execute("UPDATE welcome SET channel_id = ? WHERE guild_id = ?", (selected_channel_id, ctx.guild.id)) await db.commit() embed.description = f"Current Welcome Channel: {selected_channel.mention}" await interaction.response.edit_message(embed=embed, view=None) await ctx.send(f"{TICK}> Welcome channel has been set to {selected_channel.mention}") select_menu.callback = select_callback next_button = Button(label="Next List of Channels", style=discord.ButtonStyle.secondary, disabled=page >= len(chunks) - 1) previous_button = Button(label="Previous", style=discord.ButtonStyle.secondary, disabled=page <= 0) async def next_callback(interaction: discord.Interaction): if interaction.user != ctx.author: await interaction.response.send_message("You are not authorized to navigate these menus.", ephemeral=True) return nonlocal current_page current_page += 1 await interaction.response.edit_message(embed=embed, view=generate_view(current_page)) async def previous_callback(interaction: discord.Interaction): if interaction.user != ctx.author: await interaction.response.send_message("You are not authorized to navigate these menus.", ephemeral=True) return nonlocal current_page current_page -= 1 await interaction.response.edit_message(embed=embed, view=generate_view(current_page)) next_button.callback = next_callback previous_button.callback = previous_callback view = View() view.add_item(select_menu) view.add_item(previous_button) view.add_item(next_button) return view embed = discord.Embed( title=f"Welcome Channel for {ctx.guild.name}", description=f"Current Welcome Channel: {welcome_channel.mention if welcome_channel else 'None'}", color=0xFF0000 ) embed.set_footer(text="Use the dropdown menu to select a channel. Navigate pages if needed.") await ctx.send(embed=embed, view=generate_view(current_page)) @greet.command(name="test", help="Sends a test welcome message to preview the setup.") @blacklist_check() @ignore_check() @commands.has_permissions(administrator=True) @commands.cooldown(1, 6, commands.BucketType.user) @commands.max_concurrency(1, per=commands.BucketType.default, wait=False) async def greet_test(self, ctx): async with aiosqlite.connect("db/welcome.db") as db: async with db.execute("SELECT welcome_type, welcome_message, channel_id, embed_data FROM welcome WHERE guild_id = ?", (ctx.guild.id,)) as cursor: row = await cursor.fetchone() if row is None: error = discord.Embed(description=f"No welcome message has been set for {ctx.guild.name}! Please set a welcome message first using `{ctx.prefix}greet setup`", color=0xFF0000) error.set_author(name="Greet is not configured!", icon_url="https://cdn.discordapp.com/emojis/1294218790082711553.png") await ctx.send(embed=error) return welcome_type, welcome_message, channel_id, embed_data = row welcome_channel = self.bot.get_channel(channel_id) if not welcome_channel: error2 = discord.Embed(description=f"Welcome channel not set or invalid. Use `{ctx.prefix}greet channel` to set one.", color=0xFF0000) error2.set_author(name="Channel not set", icon_url="https://cdn.discordapp.com/emojis/1294218790082711553.png") await ctx.send(embed=error2) return placeholders = { "user": ctx.author.mention, "user_avatar": ctx.author.avatar.url if ctx.author.avatar else ctx.author.default_avatar.url, "user_name": ctx.author.name, "user_id": ctx.author.id, "user_nick": ctx.author.display_name, "user_joindate": ctx.author.joined_at.strftime("%a, %b %d, %Y"), "user_createdate": ctx.author.created_at.strftime("%a, %b %d, %Y"), "server_name": ctx.guild.name, "server_id": ctx.guild.id, "server_membercount": ctx.guild.member_count, "server_icon": ctx.guild.icon.url if ctx.guild.icon else "https://cdn.discordapp.com/embed/avatars/0.png", "timestamp": discord.utils.format_dt(ctx.message.created_at) } def safe_format(text): placeholders_lower = {k.lower(): v for k, v in placeholders.items()} def replace_var(match): var_name = match.group(1).lower() return str(placeholders_lower.get(var_name, f"{{{var_name}}}")) return re.sub(r"\{(\w+)\}", replace_var, text or "") if welcome_type == "simple" and welcome_message: await welcome_channel.send(safe_format(welcome_message)) elif welcome_type == "embed" and embed_data: try: embed_info = json.loads(embed_data) color_value = embed_info.get("color", None) embed_color = 0x2f3136 if color_value and isinstance(color_value, str) and color_value.startswith("#"): embed_color = discord.Color(int(color_value.lstrip("#"), 16)) elif isinstance(color_value, int): embed_color = discord.Color(color_value) except (ValueError, SyntaxError, json.JSONDecodeError): await ctx.send("Invalid embed data format. Please reconfigure.") return content = safe_format(embed_info.get("message", "")) or None embed = discord.Embed( title=safe_format(embed_info.get("title", "")), description=safe_format(embed_info.get("description", "")), color=embed_color ) embed.timestamp = discord.utils.utcnow() if embed_info.get("footer_text"): embed.set_footer( text=safe_format(embed_info["footer_text"]), icon_url=safe_format(embed_info.get("footer_icon", "")) ) if embed_info.get("author_name"): embed.set_author( name=safe_format(embed_info["author_name"]), icon_url=safe_format(embed_info.get("author_icon", "")) ) if embed_info.get("thumbnail"): embed.set_thumbnail(url=safe_format(embed_info["thumbnail"])) if embed_info.get("image"): embed.set_image(url=safe_format(embed_info["image"])) await welcome_channel.send(content=content, embed=embed) @greet.command(name="config", help="Shows the current welcome configuration.") @blacklist_check() @ignore_check() @commands.has_permissions(administrator=True) @commands.cooldown(1, 6, commands.BucketType.user) @commands.max_concurrency(1, per=commands.BucketType.default, wait=False) async def greet_config(self, ctx): async with aiosqlite.connect("db/welcome.db") as db: async with db.execute("SELECT * FROM welcome WHERE guild_id = ?", (ctx.guild.id,)) as cursor: row = await cursor.fetchone() if row: _, welcome_type, welcome_message, channel_id, embed_data, auto_delete_duration = row response_type = "Simple" if welcome_type == "simple" else "Embed" embed = discord.Embed( title=f"Greet Configuration for {ctx.guild.name}", color=0xFF0000 ) embed.add_field(name="Response Type", value=response_type, inline=False) if welcome_type == "simple": details = f"Message Content: {welcome_message or 'None'}" embed.add_field(name="Details", value=details[:1024], inline=False) else: embed_details = json.loads(embed_data) if embed_data else {} formatted_embed_data = "\n".join( f"{key.replace('_', ' ').title()}: {value or 'None'}" for key, value in embed_details.items() ) or "None" for i, chunk in enumerate([formatted_embed_data[i:i+1024] for i in range(0, len(formatted_embed_data), 1024)]): embed.add_field(name=f"Embed Data Part {i+1}", value=chunk, inline=False) greet_channel = self.bot.get_channel(channel_id) channel_display = greet_channel.mention if greet_channel else "None" auto_delete_duration = f"{auto_delete_duration} seconds" if auto_delete_duration else "None" embed.add_field(name="Greet Channel", value=channel_display, inline=False) embed.add_field(name="Auto Delete Duration", value=auto_delete_duration, inline=False) await ctx.send(embed=embed) else: error = discord.Embed( description=f"No welcome message has been set for {ctx.guild.name}! Please set a welcome message first using `{ctx.prefix}greet setup`", color=0xFF0000 ) error.set_author(name="Greet is not configured!", icon_url="https://cdn.discordapp.com/emojis/1294218790082711553.png") await ctx.send(embed=error) @greet.command(name="autodelete", aliases=["autodel"], help="Sets the auto-delete duration for the welcome message.") @blacklist_check() @ignore_check() @commands.has_permissions(administrator=True) @commands.cooldown(1, 6, commands.BucketType.user) @commands.max_concurrency(1, per=commands.BucketType.default, wait=False) async def greet_autodelete(self, ctx, time: str): if time.endswith("s"): seconds = int(time[:-1]) if 3 <= seconds <= 300: auto_delete_duration = seconds else: await ctx.send("Auto delete time should be between 3 seconds and 300 seconds.") return elif time.endswith("m"): minutes = int(time[:-1]) if 1 <= minutes <= 5: auto_delete_duration = minutes * 60 else: await ctx.send("Auto delete time should be between 1 minute and 5 minutes.") return else: await ctx.send("Invalid time format. Please use 's' for seconds and 'm' for minutes.") return async with aiosqlite.connect("db/welcome.db") as db: await db.execute(""" UPDATE welcome SET auto_delete_duration = ? WHERE guild_id = ? """, (auto_delete_duration, ctx.guild.id)) await db.commit() await ctx.send(f"{ZTICK} Auto delete duration has been set to **{auto_delete_duration}** seconds.") @greet.command(name="edit", help="Edits the current welcome message settings for the server.") @blacklist_check() @ignore_check() @commands.has_permissions(administrator=True) @commands.cooldown(1, 6, commands.BucketType.user) @commands.max_concurrency(1, per=commands.BucketType.default, wait=False) async def greet_edit(self, ctx): async with aiosqlite.connect("db/welcome.db") as db: async with db.execute("SELECT welcome_type, welcome_message, embed_data FROM welcome WHERE guild_id = ?", (ctx.guild.id,)) as cursor: row = await cursor.fetchone() if row is None: error = discord.Embed(description=f"No welcome message has been set for {ctx.guild.name}! Please set a welcome message first using `{ctx.prefix}greet setup`", color=0xFF0000) error.set_author(name="Greet is not configured!", icon_url="https://cdn.discordapp.com/emojis/1294218790082711553.png") await ctx.send(embed=error) return welcome_type, welcome_message, embed_data = row cancel_flag = False if welcome_type == "simple": embed = discord.Embed( title="Edit Welcome Message", description=f"**Response Type:** Simple\n**Message Content:** {welcome_message or 'None'}", color=0xFF0000 ) edit_button = Button(label="Edit", style=discord.ButtonStyle.primary) cancel_button = Button(label="Cancel", style=discord.ButtonStyle.danger) async def cancel_button_callback(interaction): nonlocal cancel_flag if interaction.user != ctx.author: await interaction.response.send_message("You are not authorized to cancel the setup.", ephemeral=True) return await interaction.response.send_message("Setup has been canceled.", ephemeral=True) cancel_flag = True view.clear_items() await interaction.message.edit(embed=embed, view=view) cancel_button.callback = cancel_button_callback async def edit_button_callback(interaction): if interaction.user != ctx.author: await interaction.response.send_message("You are not authorized to edit the welcome message.", ephemeral=True) return await interaction.response.send_message("Please provide the new welcome message:", ephemeral=True) try: new_message = await self.bot.wait_for( "message", check=lambda m: m.author == ctx.author and m.channel == ctx.channel, timeout=600 ) if cancel_flag: await ctx.send("Setup was canceled. No changes were made.") return await new_message.delete() async with aiosqlite.connect("db/welcome.db") as db: await db.execute("UPDATE welcome SET welcome_message = ? WHERE guild_id = ?", (new_message.content, ctx.guild.id)) await db.commit() embed.description = f"**Response Type:** Simple\n**Message Content:** {new_message.content}" edit_button.disabled = True cancel_button.disabled = True await interaction.message.edit(embed=embed, view=view) await ctx.send("Welcome message has been successfully updated.") except asyncio.TimeoutError: await ctx.send("You took too long to respond.") except Exception as e: await ctx.send(f"An error occurred: {e}") edit_button.callback = edit_button_callback view = View() view.add_item(edit_button) view.add_item(VariableButton(ctx.author)) view.add_item(cancel_button) await ctx.send(embed=embed, view=view) elif welcome_type == "embed": embed_data_json = json.loads(embed_data) if embed_data else {} formatted_embed_data = "\n".join( f"{key.replace('_', ' ').title()}: {value or 'None'}" for key, value in embed_data_json.items() ) or "None" embed = discord.Embed( title="Edit Welcome Message", description=f"**Response Type:** Embed\n**Embed Data:**\n```{formatted_embed_data}```", color=0xFF0000 ) select_menu = Select( placeholder="Select an embed field to edit", options=[ discord.SelectOption(label=field.replace('_', ' ').title(), value=field) for field in embed_data_json.keys() ] ) cancel_button = Button(label="Cancel", style=discord.ButtonStyle.danger) async def cancel_button_callback(interaction): nonlocal cancel_flag if interaction.user != ctx.author: await interaction.response.send_message("You are not authorized to cancel the setup.", ephemeral=True) return await interaction.response.send_message("Setup has been canceled.", ephemeral=True) cancel_flag = True view.clear_items() await interaction.message.edit(embed=embed, view=view) cancel_button.callback = cancel_button_callback async def select_callback(interaction): nonlocal cancel_flag if interaction.user != ctx.author: await interaction.response.send_message("You are not authorized to edit this embed.", ephemeral=True) return selected_option = select_menu.values[0] await interaction.response.defer() while not cancel_flag: try: if selected_option == "message": await ctx.send("Enter the welcome message content:") msg = await self.bot.wait_for("message", check=lambda m: m.author == ctx.author and m.channel == ctx.channel) embed_data_json["message"] = msg.content elif selected_option == "title": await ctx.send("Enter the embed title:") msg = await self.bot.wait_for("message", check=lambda m: m.author == ctx.author and m.channel == ctx.channel) embed_data_json["title"] = msg.content elif selected_option == "description": await ctx.send("Enter the embed description:") msg = await self.bot.wait_for("message", check=lambda m: m.author == ctx.author and m.channel == ctx.channel) embed_data_json["description"] = msg.content elif selected_option == "color": await ctx.send("Enter a hex color (e.g., #3498db or 3498db):") msg = await self.bot.wait_for("message", check=lambda m: m.author == ctx.author and m.channel == ctx.channel) color_code = msg.content.lstrip("#") if all(c in "0123456789abcdefABCDEF" for c in color_code) and len(color_code) in {3, 6}: embed_data_json["color"] = int(color_code.lstrip("#"), 16) else: await ctx.send("Invalid color code. Please enter a valid hex color.") continue elif selected_option in ["footer_text", "footer_icon", "author_name", "author_icon", "thumbnail", "image"]: await ctx.send(f"Enter the URL or text for {selected_option.replace('_', ' ')}:") msg = await self.bot.wait_for("message", check=lambda m: m.author == ctx.author and m.channel == ctx.channel) url_or_text = msg.content if selected_option in ["footer_icon", "author_icon", "thumbnail", "image"]: if url_or_text.startswith("http") or url_or_text in ["{user_avatar}", "{server_icon}"]: embed_data_json[selected_option] = url_or_text else: await ctx.send("Invalid URL. Please enter a valid image URL or a supported placeholder ({user_avatar} or {server_icon}).") continue else: embed_data_json[selected_option] = url_or_text async with aiosqlite.connect("db/welcome.db") as db: await db.execute("UPDATE welcome SET embed_data = ? WHERE guild_id = ?", (json.dumps(embed_data_json), ctx.guild.id)) await db.commit() embed.description = f"**Response Type:** Embed\n**Embed Data:**\n```{json.dumps(embed_data_json, indent=4)}```" await interaction.message.edit(embed=embed, view=None) await ctx.send("Embed data has been successfully updated.") break except asyncio.TimeoutError: await ctx.send("You took too long to respond.") break except Exception as e: await ctx.send(f"An error occurred: {e}") break select_menu.callback = select_callback view = View() view.add_item(select_menu) view.add_item(VariableButton(ctx.author)) view.add_item(cancel_button) await ctx.send(embed=embed, view=view)