Fix système arriver départ V1
This commit is contained in:
parent
01dd4979d8
commit
d9afa32828
18 changed files with 1367 additions and 291 deletions
|
|
@ -4,6 +4,7 @@ import sqlite3
|
|||
import os
|
||||
import logging
|
||||
from typing import Dict, Optional
|
||||
import asyncio
|
||||
|
||||
kuby_logger = logging.getLogger("KubyBot")
|
||||
|
||||
|
|
@ -12,6 +13,7 @@ class Invites(commands.Cog):
|
|||
self.bot = bot
|
||||
self.db_path = os.path.join(os.path.dirname(__file__), "..", "config.db")
|
||||
self.invite_cache = {} # {guild_id: {code: uses}}
|
||||
self.cache_lock = asyncio.Lock() # Verrou pour éviter les problèmes de concurrence
|
||||
self._init_db()
|
||||
|
||||
def _init_db(self):
|
||||
|
|
@ -38,9 +40,12 @@ class Invites(commands.Cog):
|
|||
async def update_invite_cache(self, guild):
|
||||
try:
|
||||
invites = await guild.invites()
|
||||
self.invite_cache[guild.id] = {invite.code: invite.uses for invite in invites}
|
||||
async with self.cache_lock:
|
||||
self.invite_cache[guild.id] = {invite.code: invite.uses for invite in invites}
|
||||
except disnake.Forbidden:
|
||||
pass
|
||||
kuby_logger.warning(f"[Invites] Impossible de mettre à jour le cache des invitations pour {guild.name} (permissions manquantes)")
|
||||
except Exception as e:
|
||||
kuby_logger.error(f"[Invites] Erreur lors de la mise à jour du cache des invitations pour {guild.name}: {e}")
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_ready(self):
|
||||
|
|
@ -54,24 +59,30 @@ class Invites(commands.Cog):
|
|||
|
||||
@commands.Cog.listener()
|
||||
async def on_invite_create(self, invite):
|
||||
if invite.guild.id not in self.invite_cache:
|
||||
self.invite_cache[invite.guild.id] = {}
|
||||
self.invite_cache[invite.guild.id][invite.code] = invite.uses
|
||||
async with self.cache_lock:
|
||||
if invite.guild.id not in self.invite_cache:
|
||||
self.invite_cache[invite.guild.id] = {}
|
||||
self.invite_cache[invite.guild.id][invite.code] = invite.uses
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_invite_delete(self, invite):
|
||||
if invite.guild.id in self.invite_cache:
|
||||
self.invite_cache[invite.guild.id].pop(invite.code, None)
|
||||
async with self.cache_lock:
|
||||
if invite.guild.id in self.invite_cache:
|
||||
self.invite_cache[invite.guild.id].pop(invite.code, None)
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_member_join(self, member):
|
||||
if member.bot: return
|
||||
|
||||
guild = member.guild
|
||||
old_invites = self.invite_cache.get(guild.id, {})
|
||||
try:
|
||||
old_invites = self.invite_cache.get(guild.id, {})
|
||||
new_invites = await guild.invites()
|
||||
except disnake.Forbidden:
|
||||
kuby_logger.warning(f"[Invites] Impossible de récupérer les invitations pour {guild.name} (permissions manquantes)")
|
||||
return
|
||||
except Exception as e:
|
||||
kuby_logger.error(f"[Invites] Erreur lors de la récupération des invitations pour {guild.name}: {e}")
|
||||
return
|
||||
|
||||
used_invite = None
|
||||
|
|
@ -86,104 +97,159 @@ class Invites(commands.Cog):
|
|||
break
|
||||
|
||||
# Mise à jour du cache
|
||||
self.invite_cache[guild.id] = {invite.code: invite.uses for invite in new_invites}
|
||||
async with self.cache_lock:
|
||||
self.invite_cache[guild.id] = {invite.code: invite.uses for invite in new_invites}
|
||||
|
||||
if used_invite:
|
||||
inviter = used_invite.inviter
|
||||
if inviter:
|
||||
self.record_invite(guild.id, member.id, inviter.id, used_invite.code)
|
||||
kuby_logger.info(f"📥 [Invites] {member} invité par {inviter} ({used_invite.code})")
|
||||
try:
|
||||
self.record_invite(guild.id, member.id, inviter.id, used_invite.code)
|
||||
kuby_logger.info(f"📥 [Invites] {member} invité par {inviter} ({used_invite.code})")
|
||||
except Exception as e:
|
||||
kuby_logger.error(f"[Invites] Erreur lors de l'enregistrement de l'invitation pour {member}: {e}")
|
||||
|
||||
# Modular join message
|
||||
conn = sqlite3.connect(self.db_path)
|
||||
cursor = conn.cursor()
|
||||
cursor.execute('SELECT log_channel_id FROM invite_configs WHERE guild_id = ?', (guild.id,))
|
||||
result = cursor.fetchone()
|
||||
conn.close()
|
||||
|
||||
if result:
|
||||
log_channel = guild.get_channel(result[0])
|
||||
if log_channel:
|
||||
# Determine method
|
||||
method = "invitation standard"
|
||||
if guild.vanity_url_code and used_invite.code == guild.vanity_url_code:
|
||||
method = "lien personnalisé"
|
||||
elif used_invite.max_age == 0:
|
||||
method = "invitation permanente"
|
||||
elif used_invite.temporary:
|
||||
method = "invitation temporaire"
|
||||
elif used_invite.max_uses == 1:
|
||||
method = "invitation à usage unique"
|
||||
|
||||
components = [
|
||||
disnake.ui.Container(
|
||||
disnake.ui.Section(
|
||||
f"Nouveau membre via invitation",
|
||||
accessory=disnake.ui.Thumbnail(member.display_avatar.url)
|
||||
),
|
||||
disnake.ui.Separator(divider=True),
|
||||
disnake.ui.TextDisplay(f"👤 {member.mention} vient de nous rejoindre !"),
|
||||
disnake.ui.TextDisplay(f"🤝 Grâce à {inviter.mention}"),
|
||||
disnake.ui.TextDisplay(f"🔗 Via **{method}**")
|
||||
)
|
||||
]
|
||||
await log_channel.send(components=components)
|
||||
try:
|
||||
conn = sqlite3.connect(self.db_path)
|
||||
cursor = conn.cursor()
|
||||
cursor.execute('SELECT log_channel_id FROM invite_configs WHERE guild_id = ?', (guild.id,))
|
||||
result = cursor.fetchone()
|
||||
conn.close()
|
||||
|
||||
if result:
|
||||
log_channel = guild.get_channel(result[0])
|
||||
if log_channel:
|
||||
# Determine method
|
||||
method = "invitation standard"
|
||||
if guild.vanity_url_code and used_invite.code == guild.vanity_url_code:
|
||||
method = "lien personnalisé"
|
||||
elif used_invite.max_age == 0:
|
||||
method = "invitation permanente"
|
||||
elif used_invite.temporary:
|
||||
method = "invitation temporaire"
|
||||
elif used_invite.max_uses == 1:
|
||||
method = "invitation à usage unique"
|
||||
|
||||
# Récupérer les statistiques de l'inviteur
|
||||
total_invites, current_invites = self.get_invite_stats(guild.id, inviter.id)
|
||||
|
||||
components = [
|
||||
disnake.ui.Container(
|
||||
disnake.ui.Section(
|
||||
f"Nouveau membre via invitation",
|
||||
accessory=disnake.ui.Thumbnail(member.display_avatar.url)
|
||||
),
|
||||
disnake.ui.Separator(divider=True),
|
||||
disnake.ui.TextDisplay(f"👤 {member.mention} vient de nous rejoindre !"),
|
||||
disnake.ui.TextDisplay(f"🤝 Grâce à {inviter.mention}"),
|
||||
disnake.ui.TextDisplay(f"📊 Invitations : {current_invites} membres présents / {total_invites} total"),
|
||||
disnake.ui.TextDisplay(f"🔗 Via **{method}**")
|
||||
)
|
||||
]
|
||||
await log_channel.send(components=components)
|
||||
except Exception as e:
|
||||
kuby_logger.error(f"[Invites] Erreur lors de l'envoi du message de log pour {member}: {e}")
|
||||
|
||||
def record_invite(self, guild_id, member_id, inviter_id, code):
|
||||
conn = sqlite3.connect(self.db_path)
|
||||
cursor = conn.cursor()
|
||||
cursor.execute('''
|
||||
INSERT INTO member_invites (guild_id, member_id, inviter_id, invite_code)
|
||||
VALUES (?, ?, ?, ?)
|
||||
ON CONFLICT(guild_id, member_id) DO UPDATE SET inviter_id=excluded.inviter_id, invite_code=excluded.invite_code
|
||||
''', (guild_id, member_id, inviter_id, code))
|
||||
conn.commit()
|
||||
conn.close()
|
||||
try:
|
||||
conn = sqlite3.connect(self.db_path)
|
||||
cursor = conn.cursor()
|
||||
cursor.execute('''
|
||||
INSERT INTO member_invites (guild_id, member_id, inviter_id, invite_code)
|
||||
VALUES (?, ?, ?, ?)
|
||||
ON CONFLICT(guild_id, member_id) DO UPDATE SET inviter_id=excluded.inviter_id, invite_code=excluded.invite_code
|
||||
''', (guild_id, member_id, inviter_id, code))
|
||||
conn.commit()
|
||||
conn.close()
|
||||
except Exception as e:
|
||||
kuby_logger.error(f"[Invites] Erreur lors de l'enregistrement de l'invitation dans la base de données: {e}")
|
||||
|
||||
def get_inviter_info(self, guild_id, member_id):
|
||||
conn = sqlite3.connect(self.db_path)
|
||||
cursor = conn.cursor()
|
||||
cursor.execute('SELECT inviter_id FROM member_invites WHERE guild_id = ? AND member_id = ?', (guild_id, member_id))
|
||||
result = cursor.fetchone()
|
||||
conn.close()
|
||||
return result[0] if result else None
|
||||
try:
|
||||
conn = sqlite3.connect(self.db_path)
|
||||
cursor = conn.cursor()
|
||||
cursor.execute('SELECT inviter_id FROM member_invites WHERE guild_id = ? AND member_id = ?', (guild_id, member_id))
|
||||
result = cursor.fetchone()
|
||||
conn.close()
|
||||
return result[0] if result else None
|
||||
except Exception as e:
|
||||
kuby_logger.error(f"[Invites] Erreur lors de la récupération de l'inviteur pour le membre {member_id}: {e}")
|
||||
return None
|
||||
|
||||
def get_invite_stats(self, guild_id, user_id):
|
||||
conn = sqlite3.connect(self.db_path)
|
||||
cursor = conn.cursor()
|
||||
cursor.execute('SELECT member_id FROM member_invites WHERE guild_id = ? AND inviter_id = ?', (guild_id, user_id))
|
||||
invited_ids = [row[0] for row in cursor.fetchall()]
|
||||
conn.close()
|
||||
try:
|
||||
conn = sqlite3.connect(self.db_path)
|
||||
cursor = conn.cursor()
|
||||
cursor.execute('SELECT member_id FROM member_invites WHERE guild_id = ? AND inviter_id = ?', (guild_id, user_id))
|
||||
invited_ids = [row[0] for row in cursor.fetchall()]
|
||||
conn.close()
|
||||
|
||||
guild = self.bot.get_guild(guild_id)
|
||||
if not guild: return 0, 0
|
||||
guild = self.bot.get_guild(guild_id)
|
||||
if not guild: return 0, 0
|
||||
|
||||
current_present = 0
|
||||
for mid in invited_ids:
|
||||
if guild.get_member(mid):
|
||||
current_present += 1
|
||||
current_present = 0
|
||||
for mid in invited_ids:
|
||||
if guild.get_member(mid):
|
||||
current_present += 1
|
||||
else:
|
||||
kuby_logger.debug(f"[Invites] Membre invité {mid} non trouvé dans le serveur {guild_id}")
|
||||
|
||||
return len(invited_ids), current_present
|
||||
except Exception as e:
|
||||
kuby_logger.error(f"[Invites] Erreur lors de la récupération des statistiques d'invitations pour {user_id}: {e}")
|
||||
return 0, 0
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_member_remove(self, member):
|
||||
if member.bot: return
|
||||
|
||||
return len(invited_ids), current_present
|
||||
guild = member.guild
|
||||
try:
|
||||
conn = sqlite3.connect(self.db_path)
|
||||
cursor = conn.cursor()
|
||||
cursor.execute('DELETE FROM member_invites WHERE guild_id = ? AND member_id = ?', (guild.id, member.id))
|
||||
conn.commit()
|
||||
conn.close()
|
||||
kuby_logger.info(f"🗑️ [Invites] Enregistrement de l'invitation supprimé pour {member.name} (ID: {member.id}) car il a quitté le serveur.")
|
||||
except Exception as e:
|
||||
kuby_logger.error(f"[Invites] Erreur lors de la suppression de l'enregistrement de l'invitation pour {member.name}: {e}")
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_member_ban(self, guild, user):
|
||||
try:
|
||||
conn = sqlite3.connect(self.db_path)
|
||||
cursor = conn.cursor()
|
||||
cursor.execute('DELETE FROM member_invites WHERE guild_id = ? AND member_id = ?', (guild.id, user.id))
|
||||
conn.commit()
|
||||
conn.close()
|
||||
kuby_logger.info(f"🗑️ [Invites] Enregistrement de l'invitation supprimé pour {user.name} (ID: {user.id}) car il a été banni.")
|
||||
except Exception as e:
|
||||
kuby_logger.error(f"[Invites] Erreur lors de la suppression de l'enregistrement de l'invitation pour {user.name}: {e}")
|
||||
|
||||
@commands.slash_command(name="setinvitechannel", description="Définit le salon des logs d'invitations")
|
||||
@commands.has_permissions(administrator=True)
|
||||
async def set_invite_channel(self, interaction: disnake.ApplicationCommandInteraction, channel: disnake.TextChannel):
|
||||
conn = sqlite3.connect(self.db_path)
|
||||
cursor = conn.cursor()
|
||||
cursor.execute('''
|
||||
INSERT INTO invite_configs (guild_id, log_channel_id)
|
||||
VALUES (?, ?)
|
||||
ON CONFLICT(guild_id) DO UPDATE SET log_channel_id=excluded.log_channel_id
|
||||
''', (interaction.guild_id, channel.id))
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
components = [
|
||||
disnake.ui.Container(
|
||||
disnake.ui.TextDisplay(f"✅ Salon des logs d'invitations défini sur {channel.mention}")
|
||||
)
|
||||
]
|
||||
await interaction.response.send_message(components=components, ephemeral=True)
|
||||
try:
|
||||
conn = sqlite3.connect(self.db_path)
|
||||
cursor = conn.cursor()
|
||||
cursor.execute('''
|
||||
INSERT INTO invite_configs (guild_id, log_channel_id)
|
||||
VALUES (?, ?)
|
||||
ON CONFLICT(guild_id) DO UPDATE SET log_channel_id=excluded.log_channel_id
|
||||
''', (interaction.guild_id, channel.id))
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
components = [
|
||||
disnake.ui.Container(
|
||||
disnake.ui.TextDisplay(f"✅ Salon des logs d'invitations défini sur {channel.mention}")
|
||||
)
|
||||
]
|
||||
await interaction.response.send_message(components=components, ephemeral=True)
|
||||
except Exception as e:
|
||||
kuby_logger.error(f"[Invites] Erreur lors de la configuration du salon des logs d'invitations: {e}")
|
||||
await interaction.response.send_message("❌ Une erreur est survenue lors de la configuration du salon des logs d'invitations.", ephemeral=True)
|
||||
|
||||
@commands.command(name="invitations_debug")
|
||||
async def invites_prefix(self, ctx, user: disnake.Member = None):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue