from __future__ import annotations import logging import discord from discord import app_commands from discord.ext import commands from features import shared logger = logging.getLogger("vision") class Welcome(commands.Cog): def __init__(self, bot: commands.Bot): self.bot = bot self._invites: dict[int, dict[str, int]] = {} @commands.Cog.listener() async def on_ready(self): await self._cache_invites() @commands.Cog.listener() async def on_guild_join(self, guild: discord.Guild): await self._cache_invites_for(guild) @commands.Cog.listener() async def on_member_join(self, member: discord.Member): cfg = shared.section(member.guild.id, "welcome") if not cfg.get("enabled"): return channel_id = cfg.get("channel_id") if not channel_id: return channel = member.guild.get_channel(channel_id) if not channel: return inviter = await self._find_inviter(member) text = cfg.get("message", "**{user}** a rejoint **{guild}** ! ({member_count} membres)") text = text.replace("{user}", member.mention).replace("{guild}", member.guild.name) text = text.replace("{member_count}", str(member.guild.member_count)) text = text.replace("{username}", member.name) embed = discord.Embed(description=text, color=discord.Color.blurple()) embed.set_thumbnail(url=member.display_avatar.url) if inviter: inviter_data = cfg.get("invites", {}).get(str(inviter.id), 0) embed.add_field(name="Invité par", value=f"{inviter.mention} ({inviter_data + 1} invites)") await channel.send(embed=embed) if cfg.get("dm_message"): try: dm_text = cfg["dm_message"].replace("{guild}", member.guild.name) await member.send(dm_text) except discord.HTTPException: pass await self._update_invite_count(member.guild, inviter) async def _find_inviter(self, member: discord.Member) -> discord.Member | None: try: invites = await member.guild.invites() except discord.HTTPException: return None cached = self._invites.get(member.guild.id, {}) for inv in invites: if cached.get(inv.code, 0) < inv.uses: self._invites.setdefault(member.guild.id, {})[inv.code] = inv.uses return inv.inviter self._cache_invites_for(member.guild) return None async def _update_invite_count(self, guild: discord.Guild, inviter: discord.Member | None): if not inviter: return cfg = shared.get(guild.id, "welcome") invites = cfg.get("invites", {}) key = str(inviter.id) invites[key] = invites.get(key, 0) + 1 shared.set(guild.id, "welcome", {**cfg, "invites": invites}) async def _cache_invites(self): for guild in self.bot.guilds: await self._cache_invites_for(guild) async def _cache_invites_for(self, guild: discord.Guild): try: invites = await guild.invites() self._invites[guild.id] = {inv.code: inv.uses for inv in invites} except discord.HTTPException: self._invites[guild.id] = {} @app_commands.command(name="welcome_setup", description="Configurer le message d'arrivée") @app_commands.describe(channel="Canal d'arrivée", message="Message (utilise {user}, {guild}, {member_count})") @app_commands.checks.has_permissions(manage_guild=True) async def welcome_setup(self, interaction: discord.Interaction, channel: discord.TextChannel, message: str = ""): cfg = shared.get(interaction.guild_id, "welcome") cfg["enabled"] = True cfg["channel_id"] = channel.id if message: cfg["message"] = message shared.set(interaction.guild_id, "welcome", cfg) await interaction.response.send_message(f"Message d'arrivée configuré dans {channel.mention}", ephemeral=True) @app_commands.command(name="welcome_disable", description="Désactiver le message d'arrivée") @app_commands.checks.has_permissions(manage_guild=True) async def welcome_disable(self, interaction: discord.Interaction): cfg = shared.get(interaction.guild_id, "welcome") cfg["enabled"] = False shared.set(interaction.guild_id, "welcome", cfg) await interaction.response.send_message("Message d'arrivée désactivé.", ephemeral=True) @app_commands.command(name="invites", description="Voir le nombre d'invitations d'un membre") @app_commands.describe(member="Membre à vérifier") async def invites(self, interaction: discord.Interaction, member: discord.Member): cfg = shared.get(interaction.guild_id, "welcome") invites = cfg.get("invites", {}) count = invites.get(str(member.id), 0) embed = discord.Embed( title=f"Invitations de {member}", description=f"**{count}** invitations", color=discord.Color.blurple(), ) embed.set_thumbnail(url=member.display_avatar.url) await interaction.response.send_message(embed=embed) async def setup(bot: commands.Bot): await bot.add_cog(Welcome(bot))