Compare commits
10
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
942b23c956 | ||
|
|
651773e63d | ||
|
|
3450cd031c | ||
|
|
60b90edcb3 | ||
|
|
252e169af5 | ||
|
|
179876d2ce | ||
|
|
830ce61796 | ||
|
|
5709b1c0a3 | ||
|
|
11348bda39 | ||
|
|
f7e85bac69 |
+37
-2
@@ -7,7 +7,7 @@ from webapp import webapp
|
||||
from database import db
|
||||
from database.helpers import ConfigurationHelper
|
||||
from database.models import Configuration, Humeur, Commande
|
||||
from discord import Message, TextChannel, Member, VoiceChannel
|
||||
from discord import Message, TextChannel, Member, VoiceChannel, app_commands
|
||||
from discordbot.humblebundle import checkHumbleBundleAndNotify
|
||||
from discordbot.freeloot import checkFreeLootAndNotify
|
||||
from discordbot.moderation import (
|
||||
@@ -21,7 +21,9 @@ from discordbot.moderation import (
|
||||
handle_ban_list_command,
|
||||
handle_staff_help_command,
|
||||
handle_timeout_command,
|
||||
handle_say_command
|
||||
handle_say_command,
|
||||
handle_transfer_command,
|
||||
transfer_message_context_menu
|
||||
)
|
||||
from discordbot.welcome import sendWelcomeMessage, sendLeaveMessage, updateInviteCache
|
||||
from discordbot.youtube import checkYouTubeVideos
|
||||
@@ -29,10 +31,39 @@ from discordbot.auto_rooms import on_voice_state_update_auto_rooms, on_raw_react
|
||||
from protondb import searhProtonDb
|
||||
|
||||
class DiscordBot(discord.Client):
|
||||
def __init__(self, *, intents: discord.Intents):
|
||||
super().__init__(intents=intents)
|
||||
self.tree = app_commands.CommandTree(self)
|
||||
self.synced = False
|
||||
|
||||
async def setup_hook(self):
|
||||
self.tree.add_command(transfer_message_context_menu)
|
||||
logging.info("Commande contextuelle 'Déplacer le message' ajoutée au CommandTree")
|
||||
|
||||
async def on_ready(self):
|
||||
logging.info(f'Connecté en tant que {self.user} (ID: {self.user.id})')
|
||||
webapp.config["BOT_STATUS"]["discord_connected"] = True
|
||||
webapp.config["BOT_STATUS"]["discord_guild_count"] = len(self.guilds)
|
||||
|
||||
if not self.synced:
|
||||
try:
|
||||
logging.info("Synchronisation des commandes d'application en cours...")
|
||||
|
||||
for guild in self.guilds:
|
||||
try:
|
||||
synced = await self.tree.sync(guild=guild)
|
||||
logging.info(f"✅ {len(synced)} commande(s) synchronisée(s) pour le serveur '{guild.name}' (ID: {guild.id})")
|
||||
except Exception as e:
|
||||
logging.error(f"❌ Erreur lors de la synchronisation pour {guild.name}: {e}")
|
||||
|
||||
synced_global = await self.tree.sync()
|
||||
logging.info(f"✅ {len(synced_global)} commande(s) synchronisée(s) globalement")
|
||||
|
||||
self.synced = True
|
||||
logging.info("🎉 Synchronisation complète terminée - Les commandes sont maintenant disponibles !")
|
||||
except Exception as e:
|
||||
logging.error(f"❌ Erreur lors de la synchronisation des commandes: {e}")
|
||||
|
||||
for c in self.get_all_channels() :
|
||||
logging.info(f'{c.id} {c.name}')
|
||||
|
||||
@@ -167,6 +198,10 @@ async def on_message(message: Message):
|
||||
await handle_say_command(message, bot)
|
||||
return
|
||||
|
||||
if command_name in ['!transfert', '!transfer', '!move']:
|
||||
await handle_transfer_command(message, bot)
|
||||
return
|
||||
|
||||
if command_name in ['!aide', '!help']:
|
||||
await handle_staff_help_command(message, bot)
|
||||
return
|
||||
|
||||
+542
-2
@@ -4,12 +4,14 @@ import time
|
||||
import os
|
||||
import re
|
||||
import discord
|
||||
import io
|
||||
from datetime import datetime, timezone, timedelta
|
||||
from zoneinfo import ZoneInfo
|
||||
from database import db
|
||||
from database.helpers import ConfigurationHelper
|
||||
from database.models import ModerationEvent
|
||||
from discord import Message
|
||||
from discord import Message, TextChannel, ForumChannel, Thread, app_commands
|
||||
from discord.ui import Modal, TextInput, View, Select, ChannelSelect
|
||||
|
||||
def _get_local_tz():
|
||||
tz_name = os.environ.get('APP_TZ') or os.environ.get('TZ') or 'Europe/Paris'
|
||||
@@ -1055,7 +1057,15 @@ async def handle_staff_help_command(message: Message, bot):
|
||||
value=(
|
||||
"• `!say #channel message`\n"
|
||||
" Envoie un message en tant que bot\n"
|
||||
" Ex: `!say #annonces Nouvelle fonctionnalité !`"
|
||||
" Ex: `!say #annonces Nouvelle fonctionnalité !`\n\n"
|
||||
"• `!transfert #canal message_id [raison]`\n"
|
||||
" Transfère un message vers un autre canal\n"
|
||||
" *Alias: !transfer, !move*\n"
|
||||
" Ex: `!transfert #entraide 123456789012345678`\n"
|
||||
" Ex: `!transfert #général https://discord.com/channels/.../...`\n"
|
||||
" Le message sera envoyé comme si c'était l'auteur original\n"
|
||||
" Supporte les canaux textuels, threads et forums (crée un post)\n"
|
||||
" Pour les forums, la raison devient le titre du post"
|
||||
),
|
||||
inline=False
|
||||
)
|
||||
@@ -1405,3 +1415,533 @@ async def handle_say_command(message: Message, bot):
|
||||
except Exception as e:
|
||||
logging.error(f"Erreur lors de l'envoi du message: {e}")
|
||||
|
||||
async def handle_transfer_command(message: Message, bot):
|
||||
if not has_staff_role(message.author.roles):
|
||||
await send_access_denied(message.channel)
|
||||
return
|
||||
|
||||
parts = message.content.split(maxsplit=3)
|
||||
|
||||
if len(parts) < 3:
|
||||
embed = discord.Embed(
|
||||
title="📋 Utilisation de la commande",
|
||||
description="**Syntaxe :** `!transfert #canal message_id [raison]` ou `!transfert #canal lien_message [raison]`",
|
||||
color=discord.Color.blue()
|
||||
)
|
||||
embed.add_field(
|
||||
name="Exemples",
|
||||
value=(
|
||||
"• `!transfert #entraide 123456789012345678`\n"
|
||||
"• `!transfert #general https://discord.com/channels/.../...`\n"
|
||||
"• `!transfert #entraide 123456789012345678 Message posté dans le mauvais canal`"
|
||||
),
|
||||
inline=False
|
||||
)
|
||||
embed.add_field(
|
||||
name="Aliases",
|
||||
value="`!transfert`, `!transfer`, `!move`",
|
||||
inline=False
|
||||
)
|
||||
embed.add_field(
|
||||
name="💡 Astuce",
|
||||
value="Faites un clic droit sur un message → Copier l'identifiant du message, ou copiez le lien du message",
|
||||
inline=False
|
||||
)
|
||||
msg = await message.channel.send(embed=embed)
|
||||
asyncio.create_task(delete_after_delay(msg))
|
||||
return
|
||||
|
||||
target_channel = None
|
||||
if message.channel_mentions:
|
||||
target_channel = message.channel_mentions[0]
|
||||
else:
|
||||
try:
|
||||
channel_id = int(parts[1].strip('<#>'))
|
||||
target_channel = bot.get_channel(channel_id)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
if not target_channel:
|
||||
embed = discord.Embed(
|
||||
title="❌ Erreur",
|
||||
description="Canal de destination invalide. Mentionnez un canal avec #canal.",
|
||||
color=discord.Color.red()
|
||||
)
|
||||
msg = await message.channel.send(embed=embed)
|
||||
asyncio.create_task(delete_after_delay(msg))
|
||||
return
|
||||
|
||||
if not isinstance(target_channel, (TextChannel, ForumChannel, Thread)):
|
||||
embed = discord.Embed(
|
||||
title="❌ Erreur",
|
||||
description=f"Le transfert n'est pas supporté vers ce type de canal. Utilisez un canal textuel, un forum ou un thread.",
|
||||
color=discord.Color.red()
|
||||
)
|
||||
msg = await message.channel.send(embed=embed)
|
||||
asyncio.create_task(delete_after_delay(msg))
|
||||
return
|
||||
|
||||
message_id = None
|
||||
source_channel = message.channel
|
||||
|
||||
if 'discord.com/channels/' in parts[2]:
|
||||
try:
|
||||
link_parts = parts[2].split('/')
|
||||
source_channel_id = int(link_parts[-2])
|
||||
message_id = int(link_parts[-1])
|
||||
source_channel = bot.get_channel(source_channel_id)
|
||||
|
||||
if not source_channel:
|
||||
embed = discord.Embed(
|
||||
title="❌ Erreur",
|
||||
description="Canal source introuvable.",
|
||||
color=discord.Color.red()
|
||||
)
|
||||
msg = await message.channel.send(embed=embed)
|
||||
asyncio.create_task(delete_after_delay(msg))
|
||||
return
|
||||
except (ValueError, IndexError):
|
||||
embed = discord.Embed(
|
||||
title="❌ Erreur",
|
||||
description="Lien de message invalide.",
|
||||
color=discord.Color.red()
|
||||
)
|
||||
msg = await message.channel.send(embed=embed)
|
||||
asyncio.create_task(delete_after_delay(msg))
|
||||
return
|
||||
else:
|
||||
try:
|
||||
message_id = int(parts[2])
|
||||
except ValueError:
|
||||
embed = discord.Embed(
|
||||
title="❌ Erreur",
|
||||
description="ID de message invalide. Utilisez un ID numérique ou un lien Discord.",
|
||||
color=discord.Color.red()
|
||||
)
|
||||
msg = await message.channel.send(embed=embed)
|
||||
asyncio.create_task(delete_after_delay(msg))
|
||||
return
|
||||
|
||||
try:
|
||||
original_message = await source_channel.fetch_message(message_id)
|
||||
except discord.NotFound:
|
||||
embed = discord.Embed(
|
||||
title="❌ Erreur",
|
||||
description="Message introuvable. Vérifiez l'ID ou le lien.",
|
||||
color=discord.Color.red()
|
||||
)
|
||||
msg = await message.channel.send(embed=embed)
|
||||
asyncio.create_task(delete_after_delay(msg))
|
||||
return
|
||||
except discord.Forbidden:
|
||||
embed = discord.Embed(
|
||||
title="❌ Erreur",
|
||||
description="Je n'ai pas la permission d'accéder à ce message.",
|
||||
color=discord.Color.red()
|
||||
)
|
||||
msg = await message.channel.send(embed=embed)
|
||||
asyncio.create_task(delete_after_delay(msg))
|
||||
return
|
||||
|
||||
reason = parts[3] if len(parts) > 3 else "Message posté dans le mauvais canal"
|
||||
|
||||
content = original_message.content
|
||||
embeds = original_message.embeds
|
||||
files_to_send = []
|
||||
|
||||
for attachment in original_message.attachments:
|
||||
try:
|
||||
file_data = await attachment.read()
|
||||
files_to_send.append(discord.File(
|
||||
fp=io.BytesIO(file_data),
|
||||
filename=attachment.filename
|
||||
))
|
||||
except Exception as e:
|
||||
logging.error(f"Erreur lors du téléchargement de la pièce jointe: {e}")
|
||||
|
||||
transferred_message = None
|
||||
|
||||
if isinstance(target_channel, ForumChannel):
|
||||
try:
|
||||
post_title = f"{original_message.author.display_name} - "
|
||||
if reason and reason != "Message posté dans le mauvais canal":
|
||||
remaining_length = 100 - len(post_title)
|
||||
post_title += reason[:remaining_length]
|
||||
elif content and len(content) > 0:
|
||||
remaining_length = 100 - len(post_title)
|
||||
post_title += content[:remaining_length]
|
||||
else:
|
||||
post_title += "Message transféré"
|
||||
|
||||
if len(post_title) > 100:
|
||||
post_title = post_title[:97] + "..."
|
||||
|
||||
transfer_notice = f"**Message original de {original_message.author.mention}**\n"
|
||||
transfer_notice += f"*Ce message a été transféré par un membre du staff depuis {source_channel.mention}*\n"
|
||||
transfer_notice += "─" * 50 + "\n\n"
|
||||
|
||||
full_content = transfer_notice + (content or "")
|
||||
|
||||
thread = await target_channel.create_thread(
|
||||
name=post_title,
|
||||
content=full_content,
|
||||
embeds=embeds[:10] if embeds else [],
|
||||
files=files_to_send,
|
||||
reason=f"Transfert depuis {source_channel.name} par {message.author.name}"
|
||||
)
|
||||
transferred_message = thread.message
|
||||
|
||||
except discord.HTTPException as e:
|
||||
logging.error(f"Erreur lors de la création du post dans le forum: {e}")
|
||||
embed = discord.Embed(
|
||||
title="❌ Erreur",
|
||||
description=f"Une erreur est survenue lors de la création du post dans le forum: {str(e)}",
|
||||
color=discord.Color.red()
|
||||
)
|
||||
msg = await message.channel.send(embed=embed)
|
||||
asyncio.create_task(delete_after_delay(msg))
|
||||
return
|
||||
|
||||
else:
|
||||
webhooks = await target_channel.webhooks()
|
||||
webhook = None
|
||||
|
||||
for wh in webhooks:
|
||||
if wh.user == bot.user:
|
||||
webhook = wh
|
||||
break
|
||||
|
||||
if not webhook:
|
||||
try:
|
||||
webhook = await target_channel.create_webhook(name="Mamie Henriette - Transfert")
|
||||
except discord.Forbidden:
|
||||
embed = discord.Embed(
|
||||
title="❌ Erreur",
|
||||
description="Je n'ai pas la permission de créer un webhook dans le canal de destination.",
|
||||
color=discord.Color.red()
|
||||
)
|
||||
msg = await message.channel.send(embed=embed)
|
||||
asyncio.create_task(delete_after_delay(msg))
|
||||
return
|
||||
|
||||
try:
|
||||
transferred_message = await webhook.send(
|
||||
content=content,
|
||||
username=original_message.author.display_name,
|
||||
avatar_url=original_message.author.display_avatar.url,
|
||||
embeds=embeds[:10] if embeds else [],
|
||||
files=files_to_send,
|
||||
allowed_mentions=discord.AllowedMentions.none(),
|
||||
wait=True
|
||||
)
|
||||
except discord.HTTPException as e:
|
||||
logging.error(f"Erreur lors du transfert du message: {e}")
|
||||
embed = discord.Embed(
|
||||
title="❌ Erreur",
|
||||
description=f"Une erreur est survenue lors du transfert du message: {str(e)}",
|
||||
color=discord.Color.red()
|
||||
)
|
||||
msg = await message.channel.send(embed=embed)
|
||||
asyncio.create_task(delete_after_delay(msg))
|
||||
return
|
||||
|
||||
try:
|
||||
await original_message.delete()
|
||||
except discord.Forbidden:
|
||||
logging.warning(f"Impossible de supprimer le message original (ID: {message_id})")
|
||||
|
||||
transfer_details = f"De {source_channel.name} vers {target_channel.name}"
|
||||
if isinstance(target_channel, ForumChannel):
|
||||
transfer_details += " (forum)"
|
||||
|
||||
transfer_event = ModerationEvent(
|
||||
type='transfer',
|
||||
username=original_message.author.name,
|
||||
discord_id=str(original_message.author.id),
|
||||
created_at=datetime.now(timezone.utc),
|
||||
reason=f"{reason} | {transfer_details}",
|
||||
staff_id=str(message.author.id),
|
||||
staff_name=message.author.name
|
||||
)
|
||||
db.session.add(transfer_event)
|
||||
_commit_with_retry()
|
||||
|
||||
local_now = _to_local(datetime.now(timezone.utc))
|
||||
destination_info = target_channel.mention if isinstance(target_channel, (TextChannel, Thread)) else f"le forum {target_channel.name}"
|
||||
|
||||
embed = discord.Embed(
|
||||
title="✅ Message transféré",
|
||||
description=f"Le message de **{original_message.author.name}** a été transféré vers {destination_info}",
|
||||
color=discord.Color.green(),
|
||||
timestamp=datetime.now(timezone.utc)
|
||||
)
|
||||
embed.add_field(name="👤 Auteur original", value=f"{original_message.author.mention}", inline=True)
|
||||
embed.add_field(name="📤 Canal source", value=source_channel.mention, inline=True)
|
||||
embed.add_field(name="📥 Canal destination", value=destination_info, inline=True)
|
||||
embed.add_field(name="🛡️ Modérateur", value=message.author.mention, inline=True)
|
||||
embed.add_field(name="📝 Raison", value=reason, inline=False)
|
||||
|
||||
if isinstance(target_channel, ForumChannel):
|
||||
embed.add_field(name="ℹ️ Type", value="Nouveau post créé dans le forum", inline=False)
|
||||
|
||||
confirmation_msg = await source_channel.send(embed=embed)
|
||||
asyncio.create_task(delete_after_delay(confirmation_msg))
|
||||
|
||||
log_embed = discord.Embed(
|
||||
title="📨 Transfert de message",
|
||||
description=f"Un message de **{original_message.author.name}** a été transféré",
|
||||
color=discord.Color.blue(),
|
||||
timestamp=datetime.now(timezone.utc)
|
||||
)
|
||||
log_embed.add_field(name="👤 Auteur original", value=f"{original_message.author.name}\n`{original_message.author.id}`", inline=True)
|
||||
log_embed.add_field(name="🛡️ Modérateur", value=f"**{message.author.name}**", inline=True)
|
||||
log_embed.add_field(name="📅 Date et heure", value=local_now.strftime('%d/%m/%Y à %H:%M'), inline=True)
|
||||
log_embed.add_field(name="📤 De", value=source_channel.mention, inline=True)
|
||||
log_embed.add_field(name="📥 Vers", value=f"{target_channel.name} ({type(target_channel).__name__})", inline=True)
|
||||
log_embed.add_field(name="📝 Raison", value=reason, inline=False)
|
||||
|
||||
preview = content[:100] + "..." if content and len(content) > 100 else content
|
||||
if preview:
|
||||
log_embed.add_field(name="💬 Aperçu du message", value=preview, inline=False)
|
||||
|
||||
log_embed.set_footer(text=f"ID Auteur: {original_message.author.id} • Serveur: {message.guild.name}")
|
||||
|
||||
await send_to_moderation_log_channel(bot, log_embed)
|
||||
|
||||
await safe_delete_message(message)
|
||||
|
||||
class TransferReasonModal(Modal, title="Raison du transfert"):
|
||||
reason = TextInput(
|
||||
label="Raison / Titre du post (forum)",
|
||||
placeholder="Pour les forums, ceci devient le titre du post",
|
||||
required=False,
|
||||
max_length=200,
|
||||
style=discord.TextStyle.paragraph
|
||||
)
|
||||
|
||||
def __init__(self, message: discord.Message, bot, target_channel, selected_tags=None):
|
||||
super().__init__()
|
||||
self.message = message
|
||||
self.bot = bot
|
||||
self.target_channel = target_channel
|
||||
self.selected_tags = selected_tags or []
|
||||
|
||||
async def on_submit(self, interaction: discord.Interaction):
|
||||
await interaction.response.defer(ephemeral=True)
|
||||
|
||||
reason = self.reason.value.strip() if self.reason.value else "Message posté dans le mauvais canal"
|
||||
target_channel = self.target_channel
|
||||
source_channel = self.message.channel
|
||||
content = self.message.content
|
||||
embeds = self.message.embeds
|
||||
files_to_send = []
|
||||
|
||||
for attachment in self.message.attachments:
|
||||
try:
|
||||
file_data = await attachment.read()
|
||||
files_to_send.append(discord.File(
|
||||
fp=io.BytesIO(file_data),
|
||||
filename=attachment.filename
|
||||
))
|
||||
except Exception as e:
|
||||
logging.error(f"Erreur lors du téléchargement de la pièce jointe: {e}")
|
||||
|
||||
transferred_message = None
|
||||
|
||||
if isinstance(target_channel, ForumChannel):
|
||||
try:
|
||||
post_title = f"{self.message.author.display_name} - "
|
||||
if reason and reason != "Message posté dans le mauvais canal":
|
||||
remaining_length = 100 - len(post_title)
|
||||
post_title += reason[:remaining_length]
|
||||
elif content and len(content) > 0:
|
||||
remaining_length = 100 - len(post_title)
|
||||
post_title += content[:remaining_length]
|
||||
else:
|
||||
post_title += "Message transféré"
|
||||
|
||||
if len(post_title) > 100:
|
||||
post_title = post_title[:97] + "..."
|
||||
|
||||
transfer_notice = f"**Message original de {self.message.author.mention}**\n"
|
||||
transfer_notice += f"*Ce message a été transféré par un membre du staff depuis {source_channel.mention}*\n"
|
||||
transfer_notice += "─" * 50 + "\n\n"
|
||||
|
||||
full_content = transfer_notice + (content or "")
|
||||
|
||||
thread = await target_channel.create_thread(
|
||||
name=post_title,
|
||||
content=full_content,
|
||||
embeds=embeds[:10] if embeds else [],
|
||||
files=files_to_send,
|
||||
applied_tags=self.selected_tags,
|
||||
reason=f"Transfert depuis {source_channel.name} par {interaction.user.name}"
|
||||
)
|
||||
transferred_message = thread.message
|
||||
|
||||
if self.selected_tags:
|
||||
tag_names = ", ".join([tag.name for tag in self.selected_tags])
|
||||
logging.info(f"Post créé avec les tags: {tag_names}")
|
||||
|
||||
except discord.HTTPException as e:
|
||||
logging.error(f"Erreur lors de la création du post dans le forum: {e}")
|
||||
await interaction.followup.send(f"❌ Erreur lors de la création du post: {str(e)}", ephemeral=True)
|
||||
return
|
||||
else:
|
||||
webhooks = await target_channel.webhooks()
|
||||
webhook = None
|
||||
|
||||
for wh in webhooks:
|
||||
if wh.user == self.bot.user:
|
||||
webhook = wh
|
||||
break
|
||||
|
||||
if not webhook:
|
||||
try:
|
||||
webhook = await target_channel.create_webhook(name="Mamie Henriette - Transfert")
|
||||
except discord.Forbidden:
|
||||
await interaction.followup.send("❌ Je n'ai pas la permission de créer un webhook dans le canal de destination.", ephemeral=True)
|
||||
return
|
||||
|
||||
try:
|
||||
transferred_message = await webhook.send(
|
||||
content=content,
|
||||
username=self.message.author.display_name,
|
||||
avatar_url=self.message.author.display_avatar.url,
|
||||
embeds=embeds[:10] if embeds else [],
|
||||
files=files_to_send,
|
||||
allowed_mentions=discord.AllowedMentions.none(),
|
||||
wait=True
|
||||
)
|
||||
except discord.HTTPException as e:
|
||||
logging.error(f"Erreur lors du transfert du message: {e}")
|
||||
await interaction.followup.send(f"❌ Erreur lors du transfert: {str(e)}", ephemeral=True)
|
||||
return
|
||||
|
||||
try:
|
||||
await self.message.delete()
|
||||
except discord.Forbidden:
|
||||
logging.warning(f"Impossible de supprimer le message original (ID: {self.message.id})")
|
||||
|
||||
transfer_details = f"De {source_channel.name} vers {target_channel.name}"
|
||||
if isinstance(target_channel, ForumChannel):
|
||||
transfer_details += " (forum)"
|
||||
|
||||
transfer_event = ModerationEvent(
|
||||
type='transfer',
|
||||
username=self.message.author.name,
|
||||
discord_id=str(self.message.author.id),
|
||||
created_at=datetime.now(timezone.utc),
|
||||
reason=f"{reason} | {transfer_details}",
|
||||
staff_id=str(interaction.user.id),
|
||||
staff_name=interaction.user.name
|
||||
)
|
||||
db.session.add(transfer_event)
|
||||
_commit_with_retry()
|
||||
|
||||
destination_info = target_channel.mention if isinstance(target_channel, (TextChannel, Thread)) else f"le forum {target_channel.name}"
|
||||
|
||||
await interaction.followup.send(
|
||||
f"✅ Message de **{self.message.author.name}** transféré vers {destination_info}",
|
||||
ephemeral=True
|
||||
)
|
||||
|
||||
local_now = _to_local(datetime.now(timezone.utc))
|
||||
log_embed = discord.Embed(
|
||||
title="📨 Transfert de message",
|
||||
description=f"Un message de **{self.message.author.name}** a été transféré",
|
||||
color=discord.Color.blue(),
|
||||
timestamp=datetime.now(timezone.utc)
|
||||
)
|
||||
log_embed.add_field(name="👤 Auteur original", value=f"{self.message.author.name}\n`{self.message.author.id}`", inline=True)
|
||||
log_embed.add_field(name="🛡️ Modérateur", value=f"**{interaction.user.name}**", inline=True)
|
||||
log_embed.add_field(name="📅 Date et heure", value=local_now.strftime('%d/%m/%Y à %H:%M'), inline=True)
|
||||
log_embed.add_field(name="📤 De", value=source_channel.mention, inline=True)
|
||||
log_embed.add_field(name="📥 Vers", value=f"{target_channel.name} ({type(target_channel).__name__})", inline=True)
|
||||
log_embed.add_field(name="📝 Raison", value=reason, inline=False)
|
||||
|
||||
preview = content[:100] + "..." if content and len(content) > 100 else content
|
||||
if preview:
|
||||
log_embed.add_field(name="💬 Aperçu du message", value=preview, inline=False)
|
||||
|
||||
log_embed.set_footer(text=f"ID Auteur: {self.message.author.id} • Serveur: {interaction.guild.name}")
|
||||
|
||||
await send_to_moderation_log_channel(self.bot, log_embed)
|
||||
|
||||
class ForumTagSelect(Select):
|
||||
def __init__(self, message: discord.Message, bot, target_channel: ForumChannel):
|
||||
options = []
|
||||
for tag in target_channel.available_tags[:25]:
|
||||
options.append(discord.SelectOption(
|
||||
label=tag.name,
|
||||
value=str(tag.id),
|
||||
emoji=tag.emoji if tag.emoji else None
|
||||
))
|
||||
|
||||
super().__init__(
|
||||
placeholder="Sélectionnez un ou plusieurs tags...",
|
||||
options=options,
|
||||
min_values=1,
|
||||
max_values=min(5, len(options))
|
||||
)
|
||||
self.message = message
|
||||
self.bot = bot
|
||||
self.target_channel = target_channel
|
||||
|
||||
async def callback(self, interaction: discord.Interaction):
|
||||
selected_tags = []
|
||||
for tag_id_str in self.values:
|
||||
tag_id = int(tag_id_str)
|
||||
tag = discord.utils.get(self.target_channel.available_tags, id=tag_id)
|
||||
if tag:
|
||||
selected_tags.append(tag)
|
||||
|
||||
modal = TransferReasonModal(self.message, self.bot, self.target_channel, selected_tags)
|
||||
await interaction.response.send_modal(modal)
|
||||
|
||||
class ForumTagView(View):
|
||||
def __init__(self, message: discord.Message, bot, target_channel: ForumChannel):
|
||||
super().__init__(timeout=180)
|
||||
self.add_item(ForumTagSelect(message, bot, target_channel))
|
||||
|
||||
class TransferChannelSelect(ChannelSelect):
|
||||
def __init__(self, message: discord.Message, bot):
|
||||
super().__init__(
|
||||
placeholder="Sélectionnez le canal de destination...",
|
||||
channel_types=[discord.ChannelType.text, discord.ChannelType.forum, discord.ChannelType.public_thread, discord.ChannelType.private_thread],
|
||||
min_values=1,
|
||||
max_values=1
|
||||
)
|
||||
self.message = message
|
||||
self.bot = bot
|
||||
|
||||
async def callback(self, interaction: discord.Interaction):
|
||||
selected_channel = self.values[0]
|
||||
target_channel = self.bot.get_channel(selected_channel.id)
|
||||
|
||||
if not target_channel:
|
||||
await interaction.response.send_message("❌ Impossible de récupérer le canal sélectionné.", ephemeral=True)
|
||||
return
|
||||
|
||||
if isinstance(target_channel, ForumChannel) and target_channel.available_tags:
|
||||
view = ForumTagView(self.message, self.bot, target_channel)
|
||||
await interaction.response.send_message("🏷️ Sélectionnez un ou plusieurs tags pour ce post :", view=view, ephemeral=True)
|
||||
else:
|
||||
modal = TransferReasonModal(self.message, self.bot, target_channel)
|
||||
await interaction.response.send_modal(modal)
|
||||
|
||||
class TransferView(View):
|
||||
def __init__(self, message: discord.Message, bot):
|
||||
super().__init__(timeout=180)
|
||||
self.add_item(TransferChannelSelect(message, bot))
|
||||
|
||||
@app_commands.context_menu(name="Déplacer le message")
|
||||
@app_commands.default_permissions(manage_messages=True)
|
||||
async def transfer_message_context_menu(interaction: discord.Interaction, message: discord.Message):
|
||||
if not has_staff_role(interaction.user.roles):
|
||||
await interaction.response.send_message("❌ Vous n'avez pas les permissions nécessaires pour utiliser cette commande.", ephemeral=True)
|
||||
return
|
||||
|
||||
view = TransferView(message, interaction.client)
|
||||
await interaction.response.send_message("📨 Sélectionnez le canal de destination :", view=view, ephemeral=True)
|
||||
|
||||
|
||||
@@ -95,6 +95,10 @@
|
||||
<code class="text-slate-700 dark:text-slate-300 font-mono">!banlist</code>
|
||||
<span class="text-slate-500 dark:text-slate-400">Liste des utilisateurs bannis</span>
|
||||
</div>
|
||||
<div class="px-5 py-3 flex flex-col sm:flex-row sm:items-start gap-1 sm:gap-4">
|
||||
<code class="text-slate-700 dark:text-slate-300 font-mono">!transfert #canal message_id</code>
|
||||
<span class="text-slate-500 dark:text-slate-400">Transfère un message vers un autre canal (textuel, thread ou forum)</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</details>
|
||||
@@ -129,6 +133,10 @@
|
||||
<span class="text-xs font-medium text-yellow-600 dark:text-yellow-400">Warn</span>
|
||||
{% elif mod_event.type == 'unban' %}
|
||||
<span class="text-xs font-medium text-green-600 dark:text-green-400">Unban</span>
|
||||
{% elif mod_event.type == 'transfer' %}
|
||||
<span class="text-xs font-medium text-blue-600 dark:text-blue-400">Transfert</span>
|
||||
{% elif mod_event.type == 'timeout' %}
|
||||
<span class="text-xs font-medium text-purple-600 dark:text-purple-400">Timeout</span>
|
||||
{% else %}
|
||||
<span class="text-xs font-medium text-slate-600 dark:text-slate-400">{{ mod_event.type }}</span>
|
||||
{% endif %}
|
||||
|
||||
Reference in New Issue
Block a user