|
| 1 | +# Guide des Interactions Discord |
| 2 | + |
| 3 | +Les interactions Discord permettent à votre module de réagir aux interactions des utilisateurs avec des composants UI comme les boutons, menus déroulants et modales. Ce système complète les commandes slash et les listeners d'événements. |
| 4 | + |
| 5 | +## Types d'Interactions Supportées |
| 6 | + |
| 7 | +AsyncMod supporte deux types d'interactions : |
| 8 | + |
| 9 | +- **Message Component Interactions** : Boutons, menus déroulants, etc. |
| 10 | +- **Modal Submit Interactions** : Soumissions de formulaires modaux |
| 11 | + |
| 12 | +## Structure des Interactions |
| 13 | + |
| 14 | +### Structure de fichier |
| 15 | + |
| 16 | +``` |
| 17 | +src/modules/mon-module/ |
| 18 | +├── module.ts |
| 19 | +├── commands/ |
| 20 | +│ └── ma-commande.command.ts |
| 21 | +└── interactions/ |
| 22 | + ├── mon-bouton.button.ts |
| 23 | + ├── mon-menu.select.ts |
| 24 | + └── ma-modale.modal.ts |
| 25 | +``` |
| 26 | + |
| 27 | +## API des Interactions |
| 28 | + |
| 29 | +### Interface InteractionHandler |
| 30 | + |
| 31 | +```typescript |
| 32 | +export interface InteractionHandler<T extends CompatibleInteraction> { |
| 33 | + customId: string; // Identifiant unique |
| 34 | + check: (interaction: CompatibleInteraction) => interaction is T; // Vérification du type |
| 35 | + execute: (interaction: T, args: string[]) => Promise<void>; // Fonction d'exécution |
| 36 | +} |
| 37 | +``` |
| 38 | + |
| 39 | +## Création d'une Interaction |
| 40 | + |
| 41 | +### Exemple : Bouton |
| 42 | + |
| 43 | +```typescript |
| 44 | +// src/modules/mon-module/interactions/confirm.button.ts |
| 45 | +import { MessageFlags } from "discord.js"; |
| 46 | +import { declareInteractionHandler } from "../../../lib/interaction.js"; |
| 47 | + |
| 48 | +export default declareInteractionHandler({ |
| 49 | + customId: "confirm-action", |
| 50 | + check: (interaction) => interaction.isButton(), |
| 51 | + |
| 52 | + async execute(interaction, [actionId, userId]) { |
| 53 | + await interaction.reply({ |
| 54 | + content: `Action ${actionId} confirmée pour l'utilisateur ${userId}`, |
| 55 | + flags: MessageFlags.Ephemeral, |
| 56 | + }); |
| 57 | + }, |
| 58 | +}); |
| 59 | +``` |
| 60 | + |
| 61 | +### Exemple : Menu Déroulant |
| 62 | + |
| 63 | +```typescript |
| 64 | +// src/modules/mon-module/interactions/role-select.select.ts |
| 65 | +import { declareInteractionHandler } from "../../../lib/interaction.js"; |
| 66 | + |
| 67 | +export default declareInteractionHandler({ |
| 68 | + customId: "role-select", |
| 69 | + check: (interaction) => interaction.isStringSelectMenu(), |
| 70 | + |
| 71 | + async execute(interaction, [targetUserId]) { |
| 72 | + const selectedRoles = interaction.values; |
| 73 | + |
| 74 | + await interaction.reply({ |
| 75 | + content: `Rôles ${selectedRoles.join(", ")} attribués à <@${targetUserId}>`, |
| 76 | + ephemeral: true, |
| 77 | + }); |
| 78 | + }, |
| 79 | +}); |
| 80 | +``` |
| 81 | + |
| 82 | +### Exemple : Modal |
| 83 | + |
| 84 | +```typescript |
| 85 | +// src/modules/mon-module/interactions/feedback.modal.ts |
| 86 | +import { declareInteractionHandler } from "../../../lib/interaction.js"; |
| 87 | + |
| 88 | +export default declareInteractionHandler({ |
| 89 | + customId: "feedback-modal", |
| 90 | + check: (interaction) => interaction.isModalSubmit(), |
| 91 | + |
| 92 | + async execute(interaction, [category]) { |
| 93 | + const feedback = interaction.fields.getTextInputValue("feedback-input"); |
| 94 | + |
| 95 | + // Traitement du feedback |
| 96 | + console.log(`Feedback reçu (${category}): ${feedback}`); |
| 97 | + |
| 98 | + await interaction.reply({ |
| 99 | + content: "Merci pour votre retour !", |
| 100 | + ephemeral: true, |
| 101 | + }); |
| 102 | + }, |
| 103 | +}); |
| 104 | +``` |
| 105 | + |
| 106 | +## Système de Custom ID avec Arguments |
| 107 | + |
| 108 | +Le système AsyncMod permet de passer des arguments via le `customId` : |
| 109 | + |
| 110 | +``` |
| 111 | +customId:arg1:arg2:arg3 |
| 112 | +``` |
| 113 | + |
| 114 | +### Utilisation dans une commande |
| 115 | + |
| 116 | +```typescript |
| 117 | +// Dans une commande qui crée un bouton |
| 118 | +const button = new ButtonBuilder() |
| 119 | + .setCustomId(`confirm-action:delete:${userId}`) |
| 120 | + .setLabel("Confirmer") |
| 121 | + .setStyle(ButtonStyle.Danger); |
| 122 | +``` |
| 123 | + |
| 124 | +## Enregistrement dans le Module |
| 125 | + |
| 126 | +```typescript |
| 127 | +// src/modules/mon-module/mon-module.module.ts |
| 128 | +import confirmButton from "./interactions/confirm.button.js"; |
| 129 | +import roleSelect from "./interactions/role-select.select.js |
| 130 | +"; |
| 131 | + |
| 132 | +export default defineModule({ |
| 133 | + onLoad(client, registry) { |
| 134 | + registry.register(confirmButton); |
| 135 | + registry.register(roleSelect); |
| 136 | + }, |
| 137 | +}); |
| 138 | +``` |
| 139 | + |
| 140 | +## Gestion Automatique de l'Activation |
| 141 | + |
| 142 | +Le système AsyncMod gère automatiquement l'activation/désactivation des interactions : |
| 143 | + |
| 144 | +- ✅ Les interactions ne fonctionnent que si le module est activé sur le serveur |
| 145 | +- ✅ Pas de code supplémentaire nécessaire pour vérifier l'état |
| 146 | +- ✅ Messages d'erreur automatiques si le module est désactivé |
| 147 | + |
| 148 | +## Bonnes Pratiques |
| 149 | + |
| 150 | +### 1. Validation des Arguments |
| 151 | + |
| 152 | +```typescript |
| 153 | +async execute(interaction, [userId, action]) { |
| 154 | + if (!userId || !action) { |
| 155 | + await interaction.reply({ |
| 156 | + content: "Données manquantes. Veuillez réessayer.", |
| 157 | + ephemeral: true, |
| 158 | + }); |
| 159 | + return; |
| 160 | + } |
| 161 | + // Logique principale |
| 162 | +} |
| 163 | +``` |
| 164 | + |
| 165 | +### 2. Gestion des Erreurs |
| 166 | + |
| 167 | +```typescript |
| 168 | +async execute(interaction, [targetId]) { |
| 169 | + try { |
| 170 | + await performRiskyOperation(targetId); |
| 171 | + await interaction.reply({ content: "Opération réussie !", ephemeral: true }); |
| 172 | + } catch (error) { |
| 173 | + console.error("Erreur:", error); |
| 174 | + await interaction.reply({ |
| 175 | + content: "Une erreur s'est produite. Veuillez réessayer.", |
| 176 | + ephemeral: true, |
| 177 | + }); |
| 178 | + } |
| 179 | +} |
| 180 | +``` |
| 181 | + |
| 182 | +### 3. Types de Réponses |
| 183 | + |
| 184 | +```typescript |
| 185 | +// Action instantanée |
| 186 | +await interaction.reply({ content: "Fait !", ephemeral: true }); |
| 187 | + |
| 188 | +// Action longue |
| 189 | +await interaction.deferReply({ ephemeral: true }); |
| 190 | +await longOperation(); |
| 191 | +await interaction.editReply({ content: "Terminé !" }); |
| 192 | + |
| 193 | +// Mise à jour du message (boutons) |
| 194 | +await interaction.update({ content: "Mis à jour", components: [] }); |
| 195 | +``` |
| 196 | + |
| 197 | +## Prochaines Étapes |
| 198 | + |
| 199 | +- [Configuration des Modules](./modules.md) pour gérer les paramètres |
| 200 | +- [Commandes Discord](./commands.md) pour créer des commandes slash |
| 201 | +- [Guide des Listeners](./listeners.md) pour réagir aux événements |
0 commit comments