| 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))
|
|
|