Enhance moderation commands and ProtonDB integration in Discord bot
- Introduced a new slash command `/say` for sending messages in specific channels, improving moderation capabilities. - Updated the ProtonDB command to include an alias `/pdb`, streamlining user interaction. - Refactored command descriptions and improved error handling for better user experience.
This commit is contained in:
@@ -27,12 +27,13 @@ from discordbot.moderation import (
|
|||||||
moderation_ctx_ban_author,
|
moderation_ctx_ban_author,
|
||||||
moderation_ctx_kick_author,
|
moderation_ctx_kick_author,
|
||||||
moderation_ctx_timeout_author,
|
moderation_ctx_timeout_author,
|
||||||
|
moderation_slash_say,
|
||||||
)
|
)
|
||||||
from discordbot.welcome import sendWelcomeMessage, sendLeaveMessage, updateInviteCache
|
from discordbot.welcome import sendWelcomeMessage, sendLeaveMessage, updateInviteCache
|
||||||
from discordbot.patreon import checkPatreonPosts
|
from discordbot.patreon import checkPatreonPosts
|
||||||
from discordbot.youtube import checkYouTubeVideos
|
from discordbot.youtube import checkYouTubeVideos
|
||||||
from discordbot.auto_rooms import on_voice_state_update_auto_rooms, on_raw_reaction_add_auto_rooms, on_message_auto_rooms, cleanup_orphaned_auto_rooms
|
from discordbot.auto_rooms import on_voice_state_update_auto_rooms, on_raw_reaction_add_auto_rooms, on_message_auto_rooms, cleanup_orphaned_auto_rooms
|
||||||
from discordbot.protondb_discord import protondb_slash_command, protondb_message_context_menu
|
from discordbot.protondb_discord import protondb_slash_command, pdb_slash_command
|
||||||
|
|
||||||
class DiscordBot(discord.Client):
|
class DiscordBot(discord.Client):
|
||||||
def __init__(self, *, intents: discord.Intents):
|
def __init__(self, *, intents: discord.Intents):
|
||||||
@@ -49,8 +50,9 @@ class DiscordBot(discord.Client):
|
|||||||
moderation_ctx_ban_author,
|
moderation_ctx_ban_author,
|
||||||
moderation_ctx_kick_author,
|
moderation_ctx_kick_author,
|
||||||
moderation_ctx_timeout_author,
|
moderation_ctx_timeout_author,
|
||||||
|
moderation_slash_say,
|
||||||
protondb_slash_command,
|
protondb_slash_command,
|
||||||
protondb_message_context_menu,
|
pdb_slash_command,
|
||||||
):
|
):
|
||||||
self.tree.add_command(cmd)
|
self.tree.add_command(cmd)
|
||||||
logging.info("Commandes d'application (transfert, modération, ProtonDB) ajoutées au CommandTree")
|
logging.info("Commandes d'application (transfert, modération, ProtonDB) ajoutées au CommandTree")
|
||||||
|
|||||||
@@ -910,9 +910,8 @@ async def handle_staff_help_command(message: Message, bot):
|
|||||||
if ConfigurationHelper().getValue('proton_db_enable_enable'):
|
if ConfigurationHelper().getValue('proton_db_enable_enable'):
|
||||||
public_commands.append(
|
public_commands.append(
|
||||||
"**🎮 ProtonDB**\n"
|
"**🎮 ProtonDB**\n"
|
||||||
"• `/protondb` — recherche par nom de jeu\n"
|
"• `/protondb` ou `/pdb` — recherche par nom de jeu\n"
|
||||||
"• Clic droit sur un message → Applications → **Rechercher sur ProtonDB**\n"
|
"Ex. `/pdb` avec le paramètre *jeu* : Elden Ring"
|
||||||
"Ex. `/protondb` avec le paramètre *jeu* : Elden Ring"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
from database.models import Commande
|
from database.models import Commande
|
||||||
@@ -998,6 +997,7 @@ async def handle_staff_help_command(message: Message, bot):
|
|||||||
embed.add_field(
|
embed.add_field(
|
||||||
name="💬 Autres",
|
name="💬 Autres",
|
||||||
value=(
|
value=(
|
||||||
|
"• `/say` — salon + message (équivalent de `!say`)\n"
|
||||||
"• `!say #channel message`\n"
|
"• `!say #channel message`\n"
|
||||||
" Envoie un message en tant que bot\n"
|
" Envoie un message en tant que bot\n"
|
||||||
" Ex: `!say #annonces Nouvelle fonctionnalité !`\n\n"
|
" Ex: `!say #annonces Nouvelle fonctionnalité !`\n\n"
|
||||||
@@ -1979,6 +1979,58 @@ async def moderation_slash_timeout(
|
|||||||
ephemeral=True,
|
ephemeral=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@app_commands.command(name="say", description="Envoie un message dans un salon ou un fil (équivalent de !say).")
|
||||||
|
@app_commands.guild_only()
|
||||||
|
@app_commands.default_permissions(manage_messages=True)
|
||||||
|
@app_commands.describe(canal="Salon ou fil cible", message="Contenu du message à envoyer")
|
||||||
|
async def moderation_slash_say(
|
||||||
|
interaction: discord.Interaction,
|
||||||
|
canal: discord.TextChannel | discord.Thread,
|
||||||
|
message: str,
|
||||||
|
):
|
||||||
|
if not _interaction_must_be_staff_member(interaction):
|
||||||
|
await interaction.response.send_message(
|
||||||
|
"❌ Vous n'avez pas les permissions nécessaires pour utiliser cette commande.",
|
||||||
|
ephemeral=True,
|
||||||
|
)
|
||||||
|
return
|
||||||
|
if interaction.guild and getattr(canal, "guild", None) and canal.guild.id != interaction.guild.id:
|
||||||
|
await interaction.response.send_message(
|
||||||
|
"❌ Vous ne pouvez cibler qu'un salon de ce serveur.",
|
||||||
|
ephemeral=True,
|
||||||
|
)
|
||||||
|
return
|
||||||
|
text = message.strip()
|
||||||
|
if not text:
|
||||||
|
await interaction.response.send_message("❌ Le message ne peut pas être vide.", ephemeral=True)
|
||||||
|
return
|
||||||
|
if len(text) > 2000:
|
||||||
|
await interaction.response.send_message(
|
||||||
|
"❌ Le message dépasse la limite de 2000 caractères.",
|
||||||
|
ephemeral=True,
|
||||||
|
)
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
await canal.send(text)
|
||||||
|
except discord.Forbidden:
|
||||||
|
await interaction.response.send_message(
|
||||||
|
"❌ Je n'ai pas les permissions pour écrire dans ce canal.",
|
||||||
|
ephemeral=True,
|
||||||
|
)
|
||||||
|
return
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"Slash say : {e}")
|
||||||
|
await interaction.response.send_message(
|
||||||
|
f"❌ Impossible d'envoyer le message : {e}",
|
||||||
|
ephemeral=True,
|
||||||
|
)
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
mention = canal.mention
|
||||||
|
except Exception:
|
||||||
|
mention = f"#{canal.name}"
|
||||||
|
await interaction.response.send_message(f"✅ Message envoyé dans {mention}.", ephemeral=True)
|
||||||
|
|
||||||
@app_commands.context_menu(name="Bannir l'auteur")
|
@app_commands.context_menu(name="Bannir l'auteur")
|
||||||
@app_commands.guild_only()
|
@app_commands.guild_only()
|
||||||
@app_commands.default_permissions(ban_members=True)
|
@app_commands.default_permissions(ban_members=True)
|
||||||
|
|||||||
@@ -61,42 +61,40 @@ def _build_protondb_embed(games: List[Any]) -> discord.Embed:
|
|||||||
|
|
||||||
|
|
||||||
async def _protondb_search_followup(interaction: discord.Interaction, query: str) -> None:
|
async def _protondb_search_followup(interaction: discord.Interaction, query: str) -> None:
|
||||||
|
# Une seule réponse éditée (pas de followups en chaîne) : évite les fils « message introuvable »
|
||||||
|
# et supprime le besoin d’un message séparé « Recherche en cours… ».
|
||||||
await interaction.response.defer()
|
await interaction.response.defer()
|
||||||
search_msg = None
|
|
||||||
try:
|
|
||||||
search_msg = await interaction.followup.send(f"🔍 Recherche en cours pour **{query}**...", wait=True)
|
|
||||||
except Exception as e:
|
|
||||||
logging.error(f"ProtonDB : message de recherche : {e}")
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
games = searhProtonDb(query)
|
games = searhProtonDb(query)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(f"ProtonDB : searhProtonDb : {e}")
|
logging.error(f"ProtonDB : searhProtonDb : {e}")
|
||||||
games = []
|
games = []
|
||||||
|
|
||||||
if search_msg:
|
|
||||||
try:
|
|
||||||
await search_msg.delete()
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
|
|
||||||
if len(games) == 0:
|
if len(games) == 0:
|
||||||
await interaction.followup.send(
|
try:
|
||||||
f"{interaction.user.mention} Je n'ai pas trouvé de jeux correspondant à **{query}**. Es-tu sûr que le jeu est disponible sur Steam ?",
|
await interaction.edit_original_response(
|
||||||
suppress_embeds=True,
|
content=(
|
||||||
|
f"{interaction.user.mention} Je n'ai pas trouvé de jeux correspondant à **{query}**. "
|
||||||
|
"Es-tu sûr que le jeu est disponible sur Steam ?"
|
||||||
|
),
|
||||||
|
embed=None,
|
||||||
)
|
)
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"ProtonDB : edit_original_response (vide) : {e}")
|
||||||
return
|
return
|
||||||
|
|
||||||
embed = _build_protondb_embed(games)
|
embed = _build_protondb_embed(games)
|
||||||
try:
|
try:
|
||||||
await interaction.followup.send(embed=embed)
|
await interaction.edit_original_response(content=None, embed=embed)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(f"ProtonDB : envoi embed : {e}")
|
logging.error(f"ProtonDB : edit_original_response (embed) : {e}")
|
||||||
|
try:
|
||||||
|
await interaction.followup.send(embed=embed)
|
||||||
|
except Exception as e2:
|
||||||
|
logging.error(f"ProtonDB : followup de secours : {e2}")
|
||||||
|
|
||||||
|
|
||||||
@app_commands.command(name="protondb", description="Recherche un jeu sur ProtonDB (compatibilité Linux / Steam).")
|
async def _protondb_slash_impl(interaction: discord.Interaction, jeu: str, exemple: str) -> None:
|
||||||
@app_commands.describe(jeu="Nom du jeu (ex. Elden Ring)")
|
|
||||||
async def protondb_slash_command(interaction: discord.Interaction, jeu: str):
|
|
||||||
if not ConfigurationHelper().getValue('proton_db_enable_enable'):
|
if not ConfigurationHelper().getValue('proton_db_enable_enable'):
|
||||||
await interaction.response.send_message(
|
await interaction.response.send_message(
|
||||||
"❌ La commande ProtonDB n'est pas activée.",
|
"❌ La commande ProtonDB n'est pas activée.",
|
||||||
@@ -106,26 +104,20 @@ async def protondb_slash_command(interaction: discord.Interaction, jeu: str):
|
|||||||
query = jeu.strip()
|
query = jeu.strip()
|
||||||
if not query:
|
if not query:
|
||||||
await interaction.response.send_message(
|
await interaction.response.send_message(
|
||||||
"⚠️ Indique le nom d'un jeu.\nExemple : `/protondb jeu:Elden Ring`",
|
f"⚠️ Indique le nom d'un jeu.\nExemple : `{exemple}`",
|
||||||
ephemeral=True,
|
ephemeral=True,
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
await _protondb_search_followup(interaction, query)
|
await _protondb_search_followup(interaction, query)
|
||||||
|
|
||||||
|
|
||||||
@app_commands.context_menu(name="Rechercher sur ProtonDB")
|
@app_commands.command(name="protondb", description="Recherche un jeu sur ProtonDB (compatibilité Linux / Steam).")
|
||||||
async def protondb_message_context_menu(interaction: discord.Interaction, message: discord.Message):
|
@app_commands.describe(jeu="Nom du jeu (ex. Elden Ring)")
|
||||||
if not ConfigurationHelper().getValue('proton_db_enable_enable'):
|
async def protondb_slash_command(interaction: discord.Interaction, jeu: str):
|
||||||
await interaction.response.send_message(
|
await _protondb_slash_impl(interaction, jeu, "/protondb jeu:Elden Ring")
|
||||||
"❌ La commande ProtonDB n'est pas activée.",
|
|
||||||
ephemeral=True,
|
|
||||||
)
|
@app_commands.command(name="pdb", description="Alias de /protondb — recherche un jeu sur ProtonDB.")
|
||||||
return
|
@app_commands.describe(jeu="Nom du jeu (ex. Elden Ring)")
|
||||||
query = (message.clean_content or "").strip()
|
async def pdb_slash_command(interaction: discord.Interaction, jeu: str):
|
||||||
if not query:
|
await _protondb_slash_impl(interaction, jeu, "/pdb jeu:Elden Ring")
|
||||||
await interaction.response.send_message(
|
|
||||||
"❌ Ce message n'a pas de texte exploitable pour une recherche (ou seulement des pièces jointes / mentions vides).",
|
|
||||||
ephemeral=True,
|
|
||||||
)
|
|
||||||
return
|
|
||||||
await _protondb_search_followup(interaction, query)
|
|
||||||
|
|||||||
Reference in New Issue
Block a user