from __future__ import annotations import datetime as dt import re import discord from discord.ext import commands from bot.theme import fancy_header, NEON_CYAN, NEON_PURPLE from bot.i18n import get_cmd_desc from bot.emojis import ui from bot.emojis import ui class ConfigPanelView(discord.ui.View): def __init__(self, cog: "Configuration") -> None: super().__init__(timeout=None) self.cog = cog @discord.ui.button(label="Refresh Panel", style=discord.ButtonStyle.blurple, emoji=ui("refresh"), row=3, custom_id="config_refresh") async def refresh(self, interaction: discord.Interaction, _: discord.ui.Button) -> None: if not interaction.guild: await interaction.response.send_message("This button works only in servers.", ephemeral=True) return embed = await self.cog.build_config_embed(interaction.guild) await interaction.response.edit_message(embed=embed, view=self) @discord.ui.button(label="Toggle AutoMod", style=discord.ButtonStyle.danger, emoji="๐Ÿ›ก๏ธ", row=0, custom_id="config_automod") async def toggle_automod(self, interaction: discord.Interaction, _: discord.ui.Button) -> None: if not interaction.guild: await interaction.response.send_message("Server only.", ephemeral=True) return if not interaction.user.guild_permissions.manage_guild: await interaction.response.send_message("Manage Server permission required.", ephemeral=True) return row = await self.cog.bot.db.fetchone("SELECT automod_enabled FROM guild_config WHERE guild_id = ?", interaction.guild.id) current = row[0] if row else 0 new_val = 0 if current else 1 await self.cog.bot.db.execute( "INSERT INTO guild_config(guild_id, automod_enabled) VALUES (?, ?) ON CONFLICT(guild_id) DO UPDATE SET automod_enabled = excluded.automod_enabled", interaction.guild.id, new_val, ) state = "enabled" if new_val else "disabled" await interaction.response.send_message(f"๐Ÿ›ก๏ธ AutoMod {state}.", ephemeral=True) embed = await self.cog.build_config_embed(interaction.guild) await interaction.message.edit(embed=embed, view=self) @discord.ui.button(label="Toggle Daily", style=discord.ButtonStyle.success, emoji=ui("calendar"), row=0, custom_id="config_daily") async def toggle_daily(self, interaction: discord.Interaction, _: discord.ui.Button) -> None: if not interaction.guild: await interaction.response.send_message("Server only.", ephemeral=True) return if not interaction.user.guild_permissions.manage_guild: await interaction.response.send_message("Manage Server permission required.", ephemeral=True) return row = await self.cog.bot.db.fetchone("SELECT daily_enabled FROM guild_config WHERE guild_id = ?", interaction.guild.id) current = row[0] if row else 0 new_val = 0 if current else 1 await self.cog.bot.db.execute( "INSERT INTO guild_config(guild_id, daily_enabled) VALUES (?, ?) ON CONFLICT(guild_id) DO UPDATE SET daily_enabled = excluded.daily_enabled", interaction.guild.id, new_val, ) state = "enabled" if new_val else "disabled" await interaction.response.send_message(f"๐Ÿ“… Daily message {state}.", ephemeral=True) embed = await self.cog.build_config_embed(interaction.guild) await interaction.message.edit(embed=embed, view=self) @discord.ui.button(label="Toggle Support AI", style=discord.ButtonStyle.primary, emoji=ui("support"), row=0, custom_id="config_support_ai") async def toggle_support_ai(self, interaction: discord.Interaction, _: discord.ui.Button) -> None: if not interaction.guild: await interaction.response.send_message("Server only.", ephemeral=True) return if not interaction.user.guild_permissions.manage_guild: await interaction.response.send_message("Manage Server permission required.", ephemeral=True) return row = await self.cog.bot.db.fetchone("SELECT support_ai_enabled FROM guild_config WHERE guild_id = ?", interaction.guild.id) current = row[0] if row else 0 new_val = 0 if current else 1 await self.cog.bot.db.execute( "INSERT INTO guild_config(guild_id, support_ai_enabled) VALUES (?, ?) ON CONFLICT(guild_id) DO UPDATE SET support_ai_enabled = excluded.support_ai_enabled", interaction.guild.id, new_val, ) state = "enabled" if new_val else "disabled" await interaction.response.send_message(f"๐Ÿ›Ÿ Support AI {state}.", ephemeral=True) embed = await self.cog.build_config_embed(interaction.guild) await interaction.message.edit(embed=embed, view=self) @discord.ui.button(label="Toggle Wisdom", style=discord.ButtonStyle.secondary, emoji=ui("brain"), row=0, custom_id="config_wisdom") async def toggle_wisdom(self, interaction: discord.Interaction, _: discord.ui.Button) -> None: if not interaction.guild: await interaction.response.send_message("Server only.", ephemeral=True) return if not interaction.user.guild_permissions.manage_guild: await interaction.response.send_message("Manage Server permission required.", ephemeral=True) return row = await self.cog.bot.db.fetchone("SELECT wisdom_enabled FROM guild_config WHERE guild_id = ?", interaction.guild.id) current = row[0] if row else 0 new_val = 0 if current else 1 await self.cog.bot.db.execute( "INSERT INTO guild_config(guild_id, wisdom_enabled) VALUES (?, ?) ON CONFLICT(guild_id) DO UPDATE SET wisdom_enabled = excluded.wisdom_enabled", interaction.guild.id, new_val, ) state = "enabled" if new_val else "disabled" await interaction.response.send_message(f"๐Ÿง  Daily wisdom {state}.", ephemeral=True) embed = await self.cog.build_config_embed(interaction.guild) await interaction.message.edit(embed=embed, view=self) @discord.ui.button(label="Set Log Channel", style=discord.ButtonStyle.blurple, emoji="๐Ÿ“", row=1, custom_id="config_log") async def set_log(self, interaction: discord.Interaction, _: discord.ui.Button) -> None: if not interaction.guild: await interaction.response.send_message("Server only.", ephemeral=True) return if not interaction.user.guild_permissions.manage_guild: await interaction.response.send_message("Manage Server permission required.", ephemeral=True) return await interaction.response.send_message( "Select a text channel for logging:", view=ChannelSelectModal(self.cog, interaction.guild.id, "log_channel_id", "๐Ÿ“ Log channel set to"), ephemeral=True, ) @discord.ui.button(label="Set Welcome Channel", style=discord.ButtonStyle.blurple, emoji="๐Ÿ‘‹", row=1, custom_id="config_welcome") async def set_welcome(self, interaction: discord.Interaction, _: discord.ui.Button) -> None: if not interaction.guild: await interaction.response.send_message("Server only.", ephemeral=True) return if not interaction.user.guild_permissions.manage_guild: await interaction.response.send_message("Manage Server permission required.", ephemeral=True) return await interaction.response.send_message( "Select a text channel for welcomes:", view=ChannelSelectModal(self.cog, interaction.guild.id, "welcome_channel_id", "๐Ÿ‘‹ Welcome channel set to"), ephemeral=True, ) @discord.ui.button(label="Set Daily Channel", style=discord.ButtonStyle.blurple, emoji="๐Ÿ“จ", row=1, custom_id="config_daily_ch") async def set_daily_ch(self, interaction: discord.Interaction, _: discord.ui.Button) -> None: if not interaction.guild: await interaction.response.send_message("Server only.", ephemeral=True) return if not interaction.user.guild_permissions.manage_guild: await interaction.response.send_message("Manage Server permission required.", ephemeral=True) return await interaction.response.send_message( "Select a text channel for daily messages:", view=ChannelSelectModal(self.cog, interaction.guild.id, "daily_channel_id", "๐Ÿ“จ Daily channel set to"), ephemeral=True, ) @discord.ui.button(label="Set Poll Channel", style=discord.ButtonStyle.blurple, emoji="๐Ÿ“Š", row=1, custom_id="config_poll_ch") async def set_poll_ch(self, interaction: discord.Interaction, _: discord.ui.Button) -> None: if not interaction.guild: await interaction.response.send_message("Server only.", ephemeral=True) return if not interaction.user.guild_permissions.manage_guild: await interaction.response.send_message("Manage Server permission required.", ephemeral=True) return await interaction.response.send_message( "Select a text channel for polls:", view=ChannelSelectModal(self.cog, interaction.guild.id, "poll_channel_id", "๐Ÿ“Š Poll channel set to"), ephemeral=True, ) @discord.ui.button(label="Set Daily Message", style=discord.ButtonStyle.gray, emoji="โœ๏ธ", row=2, custom_id="config_daily_msg") async def set_daily_msg(self, interaction: discord.Interaction, _: discord.ui.Button) -> None: if not interaction.guild: await interaction.response.send_message("Server only.", ephemeral=True) return if not interaction.user.guild_permissions.manage_guild: await interaction.response.send_message("Manage Server permission required.", ephemeral=True) return await interaction.response.send_modal(DailyMessageModal(self.cog, interaction.guild.id)) @discord.ui.button(label="Test Daily", style=discord.ButtonStyle.gray, emoji="๐Ÿงช", row=2, custom_id="config_test_daily") async def test_daily(self, interaction: discord.Interaction, _: discord.ui.Button) -> None: if not interaction.guild: await interaction.response.send_message("Server only.", ephemeral=True) return row = await self.cog.bot.db.fetchone( "SELECT daily_channel_id, daily_message, daily_title, daily_image_url, daily_button_label, daily_button_url FROM guild_config WHERE guild_id = ?", interaction.guild.id, ) if not row or not row[0]: await interaction.response.send_message("Set a daily channel first.", ephemeral=True) return channel = interaction.guild.get_channel(row[0]) if not channel: await interaction.response.send_message("Configured daily channel no longer exists.", ephemeral=True) return embed = self.cog._build_daily_embed(interaction.guild.name, row[2] or "", row[1] or "", row[3]) view = None if row[4] and row[5]: view = discord.ui.View() view.add_item(discord.ui.Button(label=row[4], url=row[5])) await channel.send(embed=embed, view=view) await interaction.response.send_message(f"โœ… Sent test daily message to {channel.mention}", ephemeral=True) class ChannelSelectModal(discord.ui.View): def __init__(self, cog: "Configuration", guild_id: int, column: str, success_prefix: str) -> None: super().__init__(timeout=300) self.cog = cog self.guild_id = guild_id self.column = column self.success_prefix = success_prefix self.channel_select = discord.ui.ChannelSelect( cls=discord.ui.ChannelSelect, channel_types=[discord.ChannelType.text], placeholder="Select a text channel...", min_values=1, max_values=1, custom_id="channel_select_modal", ) self.channel_select.callback = self._channel_select_callback self.add_item(self.channel_select) async def _channel_select_callback(self, interaction: discord.Interaction) -> None: channel = self.channel_select.values[0] await self.cog.bot.db.execute( f"INSERT INTO guild_config(guild_id, {self.column}) VALUES (?, ?) ON CONFLICT(guild_id) DO UPDATE SET {self.column} = excluded.{self.column}", self.guild_id, channel.id, ) await interaction.response.send_message(f"{self.success_prefix} {channel.mention}", ephemeral=True) class DailyMessageModal(discord.ui.Modal, title="โœ๏ธ Set Daily Message"): message = discord.ui.TextInput( label="Daily Message Text", placeholder="Your daily message here...", required=True, style=discord.TextStyle.paragraph, max_length=500, ) def __init__(self, cog: "Configuration", guild_id: int) -> None: super().__init__(timeout=None) self.cog = cog self.guild_id = guild_id async def on_submit(self, interaction: discord.Interaction) -> None: await self.cog.bot.db.execute( "INSERT INTO guild_config(guild_id, daily_message) VALUES (?, ?) ON CONFLICT(guild_id) DO UPDATE SET daily_message = excluded.daily_message", self.guild_id, str(self.message.value), ) await interaction.response.send_message("๐Ÿ—“๏ธ Daily message text updated.", ephemeral=True) class FreeGameSetupView(discord.ui.View): def __init__(self, cog: "Configuration", guild_id: int, channel_id: int, role_id: int | None = None) -> None: super().__init__(timeout=300) self.cog = cog self.guild_id = guild_id self.channel_id = channel_id self.role_id = role_id self.mention_type = "role" self.platforms = {"epic", "steam", "gog"} async def _save(self, interaction: discord.Interaction) -> None: await self.cog.bot.db.execute( "INSERT INTO guild_config(guild_id, free_games_channel_id, free_games_role_id, free_games_platforms, free_games_mention_type) VALUES (?, ?, ?, ?, ?) " "ON CONFLICT(guild_id) DO UPDATE SET free_games_channel_id=excluded.free_games_channel_id, free_games_role_id=excluded.free_games_role_id, free_games_platforms=excluded.free_games_platforms, free_games_mention_type=excluded.free_games_mention_type", self.guild_id, self.channel_id, self.role_id, ",".join(sorted(self.platforms)), self.mention_type, ) @discord.ui.select( placeholder="Choose stores for alerts", min_values=1, max_values=3, options=[ discord.SelectOption(label="Epic Games", value="epic", emoji="<:animatedarrowgreen:1477261279428087979>"), discord.SelectOption(label="Steam", value="steam", emoji="<:animatedarrowgreen:1477261279428087979>"), discord.SelectOption(label="GOG", value="gog", emoji="<:animatedarrowgreen:1477261279428087979>"), ], ) async def stores(self, interaction: discord.Interaction, select: discord.ui.Select) -> None: self.platforms = set(select.values) await self._save(interaction) await interaction.response.send_message("<:animatedarrowgreen:1477261279428087979> Free games stores updated.", ephemeral=True) @discord.ui.select( placeholder="Choose ping role (optional)", min_values=0, max_values=1, cls=discord.ui.RoleSelect, ) async def role_select(self, interaction: discord.Interaction, select: discord.ui.RoleSelect) -> None: role = select.values[0] if select.values else None self.role_id = role.id if role else None await self._save(interaction) if role: await interaction.response.send_message(f"โœ… Free games role set to {role.mention}", ephemeral=True) else: await interaction.response.send_message("โœ… Free games role cleared.", ephemeral=True) @discord.ui.select( placeholder="Mention style", min_values=1, max_values=1, options=[ discord.SelectOption(label="Role mention", value="role", emoji="๐Ÿท๏ธ"), discord.SelectOption(label="@everyone", value="everyone", emoji="๐Ÿ“ข"), discord.SelectOption(label="@here", value="here", emoji="๐Ÿ“ฃ"), discord.SelectOption(label="No mention", value="none", emoji="๐Ÿ”•"), ], ) async def mention_select(self, interaction: discord.Interaction, select: discord.ui.Select) -> None: self.mention_type = (select.values[0] if select.values else "role").strip().lower() await self._save(interaction) await interaction.response.send_message(f"โœ… Mention type set to `{self.mention_type}`", ephemeral=True) class Configuration(commands.Cog): TIME_RE = re.compile(r"^(?:[01]\d|2[0-3]):[0-5]\d$") def __init__(self, bot: commands.Bot) -> None: self.bot = bot async def cog_load(self) -> None: self.bot.add_view(ConfigPanelView(self)) async def build_config_embed(self, guild: discord.Guild) -> discord.Embed: row = await self.bot.db.fetchone( "SELECT log_channel_id, welcome_channel_id, suggestion_channel_id, automod_enabled, daily_channel_id, " "daily_enabled, daily_message, daily_time, daily_utc_offset, verify_channel_id, verify_role_id, " "daily_title, daily_image_url, daily_button_label, daily_button_url, poll_channel_id, free_games_channel_id, free_games_role_id, " "support_channel_id, support_ai_enabled, wisdom_channel_id, wisdom_enabled, game_news_channel_id, game_news_role_id " "FROM guild_config WHERE guild_id = ?", guild.id, ) values = row if row else (None, None, None, 0, None, 0, "Not set", "09:00", 0, None, None, "๐ŸŒ… Daily Message", None, None, None, None, None, None, None, 0, None, 0, None, None) ( log_id, welcome_id, suggestion_id, automod_enabled, daily_channel_id, daily_enabled, daily_message, daily_time, daily_utc_offset, verify_channel_id, verify_role_id, daily_title, daily_image_url, daily_button_label, daily_button_url, poll_channel_id, free_games_channel_id, free_games_role_id, support_channel_id, support_ai_enabled, wisdom_channel_id, wisdom_enabled, game_news_channel_id, game_news_role_id, ) = values def mention(channel_id: int | None) -> str: return f"<#{channel_id}>" if channel_id else "Not set" embed = discord.Embed(title=fancy_header(f"Settings โ€ข {guild.name}"), color=NEON_CYAN) embed.add_field(name="Log Channel", value=mention(log_id), inline=True) embed.add_field(name="Welcome Channel", value=mention(welcome_id), inline=True) embed.add_field(name="Suggestion Channel", value=mention(suggestion_id), inline=True) embed.add_field(name="Verification Channel", value=mention(verify_channel_id), inline=True) embed.add_field(name="Verification Role", value=f"<@&{verify_role_id}>" if verify_role_id else "Not set", inline=True) embed.add_field(name="AutoMod", value="โœ… On" if automod_enabled else "โŒ Off", inline=True) embed.add_field(name="Daily Channel", value=mention(daily_channel_id), inline=True) embed.add_field(name="Daily Enabled", value="โœ… On" if daily_enabled else "โŒ Off", inline=True) embed.add_field(name="Daily Time", value=f"`{daily_time or '09:00'}`", inline=True) embed.add_field(name="Daily UTC Offset", value=f"`UTC{daily_utc_offset:+d}`", inline=True) embed.add_field(name="Daily Title", value=(daily_title or "๐ŸŒ… Daily Message")[:128], inline=False) embed.add_field(name="Daily Message Text", value=(daily_message or "Not set")[:1024], inline=False) embed.add_field(name="Daily Image URL", value=daily_image_url or "Not set", inline=False) embed.add_field(name="Daily Button", value=f"{daily_button_label or 'Not set'} | {daily_button_url or 'Not set'}", inline=False) embed.add_field(name="Poll Channel", value=mention(poll_channel_id), inline=True) embed.add_field(name="Free Games Channel", value=mention(free_games_channel_id), inline=True) embed.add_field(name="Free Games Role", value=f"<@&{free_games_role_id}>" if free_games_role_id else "Not set", inline=True) embed.add_field(name="Support AI Channel", value=mention(support_channel_id), inline=True) embed.add_field(name="Support AI Enabled", value="โœ… On" if support_ai_enabled else "โŒ Off", inline=True) embed.add_field(name="Wisdom Channel", value=mention(wisdom_channel_id), inline=True) embed.add_field(name="Wisdom Daily", value="โœ… On" if wisdom_enabled else "โŒ Off", inline=True) embed.add_field(name="Game News Channel", value=mention(game_news_channel_id), inline=True) embed.add_field(name="Game News Role", value=f"<@&{game_news_role_id}>" if game_news_role_id else "Not set", inline=True) embed.set_footer(text="Use /set commands to update โ€ข Click Refresh to update panel") return embed def _build_daily_embed(self, guild_name: str, title: str, message_text: str, image_url: str | None) -> discord.Embed: today = dt.datetime.utcnow().date().isoformat() embed = discord.Embed( title=title or "๐ŸŒ… Daily Message", description=message_text or "Have a productive and positive day!", color=discord.Color.gold(), ) if image_url: embed.set_image(url=image_url) embed.set_footer(text=f"{guild_name} โ€ข {today}") return embed @commands.hybrid_group(name="set", fallback="show") @commands.has_permissions(manage_guild=True) async def setgroup(self, ctx: commands.Context) -> None: embed = await self.build_config_embed(ctx.guild) await ctx.reply(embed=embed, view=ConfigPanelView(self)) @setgroup.command(name="log") async def set_log(self, ctx: commands.Context, channel: discord.TextChannel) -> None: await self.bot.db.execute( "INSERT INTO guild_config(guild_id, log_channel_id) VALUES (?, ?) ON CONFLICT(guild_id) DO UPDATE SET log_channel_id = excluded.log_channel_id", ctx.guild.id, channel.id, ) await ctx.reply(f"๐Ÿ“ Log channel set to {channel.mention}") @setgroup.command(name="welcome") async def set_welcome(self, ctx: commands.Context, channel: discord.TextChannel) -> None: await self.bot.db.execute( "INSERT INTO guild_config(guild_id, welcome_channel_id) VALUES (?, ?) ON CONFLICT(guild_id) DO UPDATE SET welcome_channel_id = excluded.welcome_channel_id", ctx.guild.id, channel.id, ) await ctx.reply(f"๐Ÿ‘‹ Welcome channel set to {channel.mention}") @setgroup.command(name="suggestions") async def set_suggestion(self, ctx: commands.Context, channel: discord.TextChannel) -> None: await self.bot.db.execute( "INSERT INTO guild_config(guild_id, suggestion_channel_id) VALUES (?, ?) ON CONFLICT(guild_id) DO UPDATE SET suggestion_channel_id = excluded.suggestion_channel_id", ctx.guild.id, channel.id, ) await ctx.reply(f"๐Ÿ’ก Suggestion channel set to {channel.mention}") @setgroup.command(name="automod") async def set_automod(self, ctx: commands.Context, enabled: bool) -> None: await self.bot.db.execute( "INSERT INTO guild_config(guild_id, automod_enabled) VALUES (?, ?) ON CONFLICT(guild_id) DO UPDATE SET automod_enabled = excluded.automod_enabled", ctx.guild.id, 1 if enabled else 0, ) await ctx.reply(f"๐Ÿ›ก๏ธ AutoMod {'enabled' if enabled else 'disabled'}") @setgroup.command(name="dailychannel") async def set_daily_channel(self, ctx: commands.Context, channel: discord.TextChannel) -> None: await self.bot.db.execute( "INSERT INTO guild_config(guild_id, daily_channel_id) VALUES (?, ?) ON CONFLICT(guild_id) DO UPDATE SET daily_channel_id = excluded.daily_channel_id", ctx.guild.id, channel.id, ) await ctx.reply(f"๐Ÿ“จ Daily message channel set to {channel.mention}") @setgroup.command(name="dailymessage") async def set_daily_message(self, ctx: commands.Context, *, text: str) -> None: await self.bot.db.execute( "INSERT INTO guild_config(guild_id, daily_message) VALUES (?, ?) ON CONFLICT(guild_id) DO UPDATE SET daily_message = excluded.daily_message", ctx.guild.id, text, ) await ctx.reply("๐Ÿ—“๏ธ Daily message text updated.") @setgroup.command(name="dailytitle") async def set_daily_title(self, ctx: commands.Context, *, title: str) -> None: await self.bot.db.execute( "INSERT INTO guild_config(guild_id, daily_title) VALUES (?, ?) ON CONFLICT(guild_id) DO UPDATE SET daily_title = excluded.daily_title", ctx.guild.id, title, ) await ctx.reply("๐Ÿ–‹๏ธ Daily message title updated.") @setgroup.command(name="dailyimage") async def set_daily_image(self, ctx: commands.Context, image_url: str = "") -> None: await self.bot.db.execute( "INSERT INTO guild_config(guild_id, daily_image_url) VALUES (?, ?) ON CONFLICT(guild_id) DO UPDATE SET daily_image_url = excluded.daily_image_url", ctx.guild.id, image_url or None, ) await ctx.reply("๐Ÿ–ผ๏ธ Daily image updated (empty value removes it).") @setgroup.command(name="dailybutton") async def set_daily_button(self, ctx: commands.Context, label: str = "", url: str = "") -> None: await self.bot.db.execute( "INSERT INTO guild_config(guild_id, daily_button_label, daily_button_url) VALUES (?, ?, ?) " "ON CONFLICT(guild_id) DO UPDATE SET daily_button_label = excluded.daily_button_label, daily_button_url = excluded.daily_button_url", ctx.guild.id, label or None, url or None, ) await ctx.reply("๐Ÿ”— Daily button settings updated.") @setgroup.command(name="dailytime") async def set_daily_time(self, ctx: commands.Context, hhmm: str) -> None: hhmm = hhmm.strip() if not self.TIME_RE.fullmatch(hhmm): await ctx.reply("Use time in 24h format `HH:MM` (example: `18:30`).") return await self.bot.db.execute( "INSERT INTO guild_config(guild_id, daily_time) VALUES (?, ?) ON CONFLICT(guild_id) DO UPDATE SET daily_time = excluded.daily_time", ctx.guild.id, hhmm, ) await ctx.reply(f"โฐ Daily message time set to `{hhmm}`") @setgroup.command(name="dailyutc") async def set_daily_utc(self, ctx: commands.Context, offset: int) -> None: if offset < -12 or offset > 14: await ctx.reply("UTC offset must be between `-12` and `+14`.") return await self.bot.db.execute( "INSERT INTO guild_config(guild_id, daily_utc_offset) VALUES (?, ?) ON CONFLICT(guild_id) DO UPDATE SET daily_utc_offset = excluded.daily_utc_offset", ctx.guild.id, offset, ) await ctx.reply(f"๐ŸŒ Daily timezone set to `UTC{offset:+d}`") @setgroup.command(name="dailytest") async def set_daily_test(self, ctx: commands.Context) -> None: row = await self.bot.db.fetchone( "SELECT daily_channel_id, daily_message, daily_title, daily_image_url, daily_button_label, daily_button_url FROM guild_config WHERE guild_id = ?", ctx.guild.id, ) if not row or not row[0]: await ctx.reply("Set a daily channel first with `/set dailychannel`.") return channel = ctx.guild.get_channel(row[0]) if not channel: await ctx.reply("Configured daily channel no longer exists.") return embed = self._build_daily_embed(ctx.guild.name, row[2] or "", row[1] or "", row[3]) view = None if row[4] and row[5]: view = discord.ui.View() view.add_item(discord.ui.Button(label=row[4], url=row[5])) await channel.send(embed=embed, view=view) await ctx.reply(f"โœ… Sent test daily message to {channel.mention}") @setgroup.command(name="dailytoggle") async def set_daily_toggle(self, ctx: commands.Context, enabled: bool) -> None: await self.bot.db.execute( "INSERT INTO guild_config(guild_id, daily_enabled) VALUES (?, ?) ON CONFLICT(guild_id) DO UPDATE SET daily_enabled = excluded.daily_enabled", ctx.guild.id, 1 if enabled else 0, ) await ctx.reply(f"๐Ÿ“… Daily message {'enabled' if enabled else 'disabled'}.") @setgroup.command(name="pollchannel") async def set_poll_channel(self, ctx: commands.Context, channel: discord.TextChannel) -> None: await self.bot.db.execute( "INSERT INTO guild_config(guild_id, poll_channel_id) VALUES (?, ?) ON CONFLICT(guild_id) DO UPDATE SET poll_channel_id = excluded.poll_channel_id", ctx.guild.id, channel.id, ) await ctx.reply(f"๐Ÿ“Š Poll channel set to {channel.mention}") @setgroup.command(name="freegames") async def set_free_games_channel(self, ctx: commands.Context, channel: discord.TextChannel, role: discord.Role | None = None) -> None: await self.bot.db.execute( "INSERT INTO guild_config(guild_id, free_games_channel_id, free_games_role_id) VALUES (?, ?, ?) " "ON CONFLICT(guild_id) DO UPDATE SET free_games_channel_id = excluded.free_games_channel_id, free_games_role_id = excluded.free_games_role_id", ctx.guild.id, channel.id, role.id if role else None, ) mention = f" with role {role.mention}" if role else "" await ctx.reply(f"๐ŸŽ Free games alerts channel set to {channel.mention}{mention}") @setgroup.command(name="gamenews") async def set_game_news(self, ctx: commands.Context, channel: discord.TextChannel, role: discord.Role | None = None) -> None: await self.bot.db.execute( "INSERT INTO guild_config(guild_id, game_news_channel_id, game_news_role_id) VALUES (?, ?, ?) " "ON CONFLICT(guild_id) DO UPDATE SET game_news_channel_id = excluded.game_news_channel_id, game_news_role_id = excluded.game_news_role_id", ctx.guild.id, channel.id, role.id if role else None, ) mention = f" with role {role.mention}" if role else "" await ctx.reply(f"๐Ÿ“ฐ Game news alerts channel set to {channel.mention}{mention}") @setgroup.command(name="supportai") async def set_support_ai(self, ctx: commands.Context, channel: discord.TextChannel, enabled: bool = True) -> None: await self.bot.db.execute( "INSERT INTO guild_config(guild_id, support_channel_id, support_ai_enabled) VALUES (?, ?, ?) " "ON CONFLICT(guild_id) DO UPDATE SET support_channel_id = excluded.support_channel_id, support_ai_enabled = excluded.support_ai_enabled", ctx.guild.id, channel.id, 1 if enabled else 0, ) await ctx.reply(f"๐Ÿ›Ÿ Support AI {'enabled' if enabled else 'disabled'} in {channel.mention}") @setgroup.command(name="wisdom") async def set_wisdom(self, ctx: commands.Context, channel: discord.TextChannel, enabled: bool = True) -> None: await self.bot.db.execute( "INSERT INTO guild_config(guild_id, wisdom_channel_id, wisdom_enabled) VALUES (?, ?, ?) " "ON CONFLICT(guild_id) DO UPDATE SET wisdom_channel_id = excluded.wisdom_channel_id, wisdom_enabled = excluded.wisdom_enabled", ctx.guild.id, channel.id, 1 if enabled else 0, ) await ctx.reply(f"๐Ÿง  Daily wisdom {'enabled' if enabled else 'disabled'} in {channel.mention}") @setgroup.command(name="freegame") async def set_free_game_alias(self, ctx: commands.Context, channel: discord.TextChannel, role: discord.Role | None = None) -> None: await self.set_free_games_channel(ctx, channel, role) @commands.hybrid_command(name="set_freegame", description=get_cmd_desc("commands.tools.set_freegame_desc")) @commands.has_permissions(administrator=True) async def set_freegame_panel(self, ctx: commands.Context, channel: discord.TextChannel, role: discord.Role | None = None) -> None: await self.bot.db.execute( "INSERT INTO guild_config(guild_id, free_games_channel_id, free_games_role_id) VALUES (?, ?, ?) " "ON CONFLICT(guild_id) DO UPDATE SET free_games_channel_id=excluded.free_games_channel_id, free_games_role_id=excluded.free_games_role_id", ctx.guild.id, channel.id, role.id if role else None, ) view = FreeGameSetupView(self, ctx.guild.id, channel.id, role.id if role else None) embed = discord.Embed( title="<:animatedarrowgreen:1477261279428087979> Free Games Setup", description=( f"Channel: {channel.mention}\n" f"Role ping: {role.mention if role else 'None'}\n" "Use menu below to choose stores (Epic/Steam/GOG)." ), color=discord.Color.green(), ) await ctx.reply(embed=embed, view=view) async def setup(bot: commands.Bot) -> None: await bot.add_cog(Configuration(bot))