> ## Documentation Index
> Fetch the complete documentation index at: https://www.chapterjs.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Commandes

> Écrire une commande slash en un fichier, choisir où elle fonctionne et qui peut l’utiliser, et la voir apparaître sur votre serveur de test

Une commande slash, c’est ce que les gens tapent après `/` dans Discord. Pour en créer une, déclarez-la avec `command()` dans n’importe quel fichier de `src/`, et exportez-la :

```ts src/commands/ping.ts theme={"theme":{"light":"github-light","dark":"vesper"}}
import { command } from 'chapterjs';

export default command({
  name: 'ping',
  description: 'Répond Pong !',
  async run({ interaction }) {
    await interaction.reply('Pong !');
  },
});
```

C’est tout : `/ping` apparaît sur votre serveur de test dès que vous enregistrez, et votre fonction `run` tourne quand quelqu’un l’utilise. Rien à enregistrer, aucune liste à tenir à jour.

> [!NOTE]
>
> Chaque champ que prend une commande et chaque type qu’elle utilise sont dans la [référence](https://www.chapterjs.org/fr/reference/command.md).

## Le nom

`name` est ce que les gens tapent après le `/`. Une sous-commande s’écrit avec ses parents, séparés par des espaces :

| `name` | Commande |
| - | - |
| `'ping'` | `/ping` |
| `'mod ban'` | `/mod ban` |
| `'mod kick'` | `/mod kick` |
| `'mod roles add'` | `/mod roles add` |

* Un mot est une commande.
* Deux mots font une sous-commande de la commande nommée par le premier.
* Trois font un groupe. Discord n’autorise rien de plus profond : un quatrième mot est signalé.

```text theme={"theme":{"light":"github-light","dark":"vesper"}}
✗ src/commands/add.ts The name "mod roles admin add" has 4 words: Discord allows a command, a group and a subcommand, so 3 at most ('mod roles add' is /mod roles add).
```

Les noms suivent les règles de Discord : lettres minuscules, chiffres, `-` et `_`, 32 caractères au plus. Une commande qui les enfreint est signalée quand son fichier se charge :

```text theme={"theme":{"light":"github-light","dark":"vesper"}}
✗ src/commands/ping.ts "Ping" can't be in the name of a command: use lowercase letters, digits, - and _ only, 32 characters at most.
```

Une commande avec des sous-commandes (`/mod`) n’a besoin d’aucune déclaration à elle : Discord demande sa description mais ne l’affiche jamais, alors ChapterJS en génère une.

> [!WARNING]
>
> Une commande avec des sous-commandes ne peut pas être utilisée seule : avec `'mod ban'`, il n’y a pas de `/mod`. Une commande nommée `'mod'` à côté est signalée et mise de côté :
>
> ```text theme={"theme":{"light":"github-light","dark":"vesper"}}
> ✗ src/commands/mod.ts /mod can't be a command and have subcommands (src/commands/ban.ts is /mod ban): Discord only lets people use the subcommands. Make this one a subcommand too, for example name: 'mod run'.
> ```

### Organiser vos fichiers

L’endroit d’un fichier et son nom ne veulent rien dire pour la commande : `src/commands/ban.ts`, `src/moderation/ban.ts` ou un fichier qui déclare `/ban` à côté du bouton qu’elle affiche sont tous le même `/ban`. Un fichier peut déclarer plusieurs commandes, chacune exportée sous son propre nom. Deux déclarations de la même commande sont signalées, et la seconde est mise de côté :

```text theme={"theme":{"light":"github-light","dark":"vesper"}}
✗ src/moderation/ban.ts (again) /ban is already declared in src/moderation/ban.ts: two commands can't have the same name.
```

### Une commande ou une sous-commande ?

Préférez des **commandes** (`/ban`, `/kick`), rangées dans les dossiers que vous voulez, et gardez les **sous-commandes** pour les variantes d’une même action (`/timeout add`, `/timeout remove`).

La raison est la façon dont Discord cache les commandes : il affiche ou cache une commande entière, jamais une seule sous-commande. Avec `/mod ban` et `/mod kick`, quelqu’un qui a seulement le droit d’expulser voit quand même `/mod ban` ; ChapterJS le refuse quand il l’utilise, mais avec `/ban` et `/kick`, il ne la verrait pas du tout.

## La description

`description` est le texte que Discord affiche sous le nom de la commande, de 1 à 100 caractères. C’est le seul champ dont une commande a besoin en plus de `run` :

```text theme={"theme":{"light":"github-light","dark":"vesper"}}
✗ src/commands/ping.ts This command has no description: write it in src/messages/en-US.ts (commands: { "ping": { description: '...' } }), or in the file (description: '...').
```

Un bot en plusieurs langues peut la laisser hors du fichier et l’écrire, avec ses traductions, dans les [fichiers de langue](https://www.chapterjs.org/fr/translated-messages.md#les-noms-et-descriptions-des-commandes) à la place : un endroit ou l’autre.

## Ce que reçoit run

`run` reçoit un objet. Prenez-y ce dont vous avez besoin :

```ts src/commands/whoami.ts theme={"theme":{"light":"github-light","dark":"vesper"}}
import { command } from 'chapterjs';

export default command({
  name: 'whoami',
  description: 'Dit qui vous êtes',
  async run({ interaction, user, member, guild, channel }) {
    await interaction.reply(
      `Vous êtes ${user.username}, connu comme ${member.displayName} sur ${guild.name}, dans #${channel.name}.`
    );
  },
});
```

| Nom | Ce que c’est |
| - | - |
| `interaction` | L’utilisation de la commande : de quoi répondre. Voir [Répondre](https://www.chapterjs.org/fr/commands/answering.md). |
| `options` | Ce que la personne a rempli, typé d’après ce que vous avez déclaré. Voir [Options](https://www.chapterjs.org/fr/commands/options.md). |
| `user` | Qui a utilisé la commande, en tant qu’[utilisateur](https://www.chapterjs.org/fr/reference/user.md). |
| `member` | Qui a utilisé la commande, en tant que [membre](https://www.chapterjs.org/fr/reference/member.md) du serveur. |
| `guild` | Le [serveur](https://www.chapterjs.org/fr/reference/guild.md) où la commande a été utilisée. |
| `channel` | Le [salon](https://www.chapterjs.org/fr/reference/channels) où la commande a été utilisée : toujours là, sans requête, donc vous pouvez faire `channel.send()` tout de suite. |
| `t` | Les textes de votre bot dans la langue de qui lira la réponse, quand le projet déclare une [langue](https://www.chapterjs.org/fr/translated-messages.md). |

Sur un serveur, `member`, `guild` et `channel` sont toujours là : aucun `?.` à écrire. L’`interaction` les connaît aussi (`interaction.guild`, `interaction.member`, `interaction.channel`), ainsi que la langue de la personne (`interaction.locale`).

## Serveurs et messages privés

Une commande fonctionne sur les serveurs. `where` change cela, et ce que reçoit `run` suit :

| `where` | La commande est proposée | `guild` et `member` | `channel` |
| - | - | - | - |
| `'guild'` (par défaut) | Sur les serveurs | Toujours là | Un salon du serveur |
| `'dm'` | En messages privés avec votre bot | N’existent pas : votre éditeur ne les propose même pas | La conversation privée |
| `'both'` | Les deux | Là ou `null` : un seul `if (guild)` vous le dit, pour tout à la fois | L’un ou l’autre |

```ts src/commands/hello.ts theme={"theme":{"light":"github-light","dark":"vesper"}}
import { command } from 'chapterjs';

export default command({
  name: 'hello',
  description: 'Dit bonjour',
  where: 'both',
  async run({ interaction, guild, member, channel }) {
    if (guild) {
      // Sur un serveur : le membre et le salon sont ceux d’un serveur.
      await interaction.reply(`Bonjour ${member.displayName}, dans #${channel.name} !`);
    } else {
      await interaction.reply('Bonjour ! Nous sommes en privé ici.');
    }
  },
});
```

Il en va de même pour `interaction.guild`, `interaction.member` et `interaction.channel`. ChapterJS s’en assure quand la commande est utilisée : une commande de serveur utilisée en privé, ou l’inverse, est refusée par une réponse privée (« This command can only be used in a server. » ou « This command can only be used in a private message with me. »), et votre fonction ne tourne pas.

> [!NOTE]
>
> Avec `chapterjs dev`, votre bot ne tourne que sur votre serveur de test. Une commande avec `where: 'dm'` ne peut pas y être essayée, et `chapterjs dev` vous le dit une fois par fichier :
>
> ```text theme={"theme":{"light":"github-light","dark":"vesper"}}
> ℹ src/commands/settings.ts /settings only works in private messages, and chapterjs dev only runs your bot in My Server. Try it with chapterjs start.
> ```
>
> Une commande avec `where: 'both'` ne peut être essayée que sur le serveur. Pour les essayer en messages privés, lancez [`chapterjs start`](https://www.chapterjs.org/fr/run/start).

## Qui peut utiliser une commande

`permissions` liste ce dont un membre a besoin pour utiliser la commande :

```ts src/commands/purge.ts theme={"theme":{"light":"github-light","dark":"vesper"}}
import { command } from 'chapterjs';

export default command({
  name: 'purge',
  description: 'Supprime les derniers messages de ce salon',
  permissions: ['ManageMessages'],
  options: {
    count: { type: 'integer', description: 'Combien', min: 2, max: 100, required: true },
  },
  async run({ interaction, options, channel }) {
    const messages = await channel.fetchMessages({ limit: options.count });
    const deleted = await channel.bulkDelete(messages);
    await interaction.reply({ content: `${deleted} messages supprimés.`, ephemeral: true });
  },
});
```

Discord cache la commande aux membres qui n’ont pas les permissions, et ChapterJS vérifie à nouveau quand elle est utilisée : quelqu’un qui ne les a pas reçoit une réponse privée qui dit lesquelles manquent (« You need the Manage Messages permission to use this command. »), et votre fonction ne tourne pas. Les administrateurs d’un serveur peuvent changer qui voit la commande dans les réglages de leur serveur.

Les noms sont ceux de [Permissions](https://www.chapterjs.org/fr/reference/permissions.md#permissionname) : `['BanMembers']`, `['ManageMessages', 'ManageThreads']`... Un nom qui n’existe pas est signalé au chargement du fichier.

> [!NOTE]
>
> Une commande avec des sous-commandes est affichée aux membres qui ont ce que demande **chaque** sous-commande ; chaque sous-commande vérifie ensuite ses propres permissions quand elle est utilisée.

## Délais entre deux utilisations

`cooldown` est le temps qu’une personne attend avant de pouvoir utiliser à nouveau la commande :

```ts src/commands/daily.ts theme={"theme":{"light":"github-light","dark":"vesper"}}
import { command } from 'chapterjs';

export default command({
  name: 'daily',
  description: 'Récupère votre récompense quotidienne',
  cooldown: '1d',
  async run({ interaction }) {
    await interaction.reply('Voici votre récompense ! 🎁');
  },
});
```

Une durée est un nombre et une unité, `s`, `m`, `h` ou `d`, d’une seconde au moins ; les parties s’additionnent (`'1h30m'`). Quelqu’un qui utilise la commande trop tôt reçoit une réponse privée qui dit quand il pourra (« You can use this command again in 5 minutes. », avec une heure que Discord affiche dans sa langue et décompte), et votre fonction ne tourne pas. La réponse se supprime toute seule quand le délai se termine, donc elle ne dit jamais « il y a 5 minutes ». Un délai de plus de 15 minutes, qui dure plus longtemps que ce que Discord laisse le bot supprimer, affiche la date et l’heure à la place (« again 8 October 2026 17:12 »). Chaque personne a son propre compte, et chaque commande aussi.

Un délai peut aussi valoir pour un salon ou un serveur, quel que soit qui a utilisé la commande ; les trois se combinent :

```ts src/commands/announce.ts theme={"theme":{"light":"github-light","dark":"vesper"}}
import { command } from 'chapterjs';

export default command({
  name: 'announce',
  description: 'Notifie tout le monde',
  permissions: ['MentionEveryone'],
  cooldown: { user: '10m', guild: '1h' },
  async run({ interaction }) {
    await interaction.reply('@everyone, il se passe quelque chose !');
  },
});
```

| Clé | Qui attend |
| - | - |
| `user` | Chaque personne, où qu’elle utilise la commande. `cooldown: '10s'` équivaut à `cooldown: { user: '10s' }`. |
| `channel` | Chaque salon, quel que soit qui l’utilise. |
| `guild` | Chaque serveur, quel que soit qui l’utilise et où. Pas pour une commande avec `where: 'dm'`. |

Quand plusieurs s’appliquent, la personne est prévenue de celui qui finit le plus tard. Une utilisation refusée ne compte pour rien : c’est la première utilisation qui décide quand la suivante pourra avoir lieu.

Les dernières utilisations sont gardées en mémoire : elles repartent vides au démarrage du bot, et `chapterjs dev` les garde à travers un enregistrement. Une durée illisible est signalée au chargement du fichier :

```text theme={"theme":{"light":"github-light","dark":"vesper"}}
✗ src/commands/daily.ts "cooldown" is "10 minutes", which is not a duration: cooldown: '10s' (a number and a unit: s, m, h or d, like '30s', '2h', '1d' or '1h30m') for each person, or cooldown: { user: '10s', channel: '5s', guild: '1m' } for each place.
```

> [!NOTE]
>
> Un gros bot tourne sur [plusieurs processus](https://www.chapterjs.org/fr/run/start.md#gros-bots), chacun avec sa propre mémoire. Tout ce qui se passe dans un serveur va au même processus, donc les délais d’un salon ou d’un serveur tiennent toujours ; celui d’une personne tient dans chaque processus, donc quelqu’un peut utiliser la commande une fois dans un serveur d’un processus et une fois dans un serveur d’un autre.

## Autres réglages

| Champ | Signification |
| - | - |
| `nsfw: true` | N’afficher la commande que dans les salons soumis à une limite d’âge. |
| `ephemeral: true` | Rendre les réponses de la commande visibles seulement par qui l’a utilisée. Voir [Répondre](https://www.chapterjs.org/fr/commands/answering.md#réponses-que-seule-la-personne-voit). |
| `locales` | La commande dans d’autres langues. Voir [Traductions](https://www.chapterjs.org/fr/commands/translations.md). |

## Là où le bot ne peut pas répondre

Discord peut proposer une commande dans un salon où le bot ne peut pas envoyer de message (un salon qu’il ne voit pas, par exemple). La commande ne tourne alors pas : la personne lit « This command can not be used here. », et votre terminal dit quelle commande et où :

```text theme={"theme":{"light":"github-light","dark":"vesper"}}
⚠ src/commands/where.ts /where was used in a channel the bot can't answer in (type 4): it did not run.
```

Il en va de même sur un serveur où le bot n’est pas. Une commande que Discord propose encore alors que son fichier a disparu ou est cassé répond « This command is not available right now. »

## Comment les commandes arrivent sur Discord

Vous n’enregistrez jamais rien : ChapterJS présente vos commandes à Discord, et seulement quand quelque chose que les gens voient a changé (un nom, une description, une option, une traduction, l’endroit où elle fonctionne). Changer ce que *fait* une commande ne coûte jamais de requête, et relancer votre bot non plus.

### En dev : votre serveur de test uniquement

`chapterjs dev` enregistre vos commandes sur votre **serveur de test uniquement**, où elles apparaissent immédiatement :

```text theme={"theme":{"light":"github-light","dark":"vesper"}}
✓ 3 commands, 2 events loaded
✓ Commands updated on My Server
```

À chaque enregistrement, elles sont enregistrées à nouveau si elles ont changé :

```text theme={"theme":{"light":"github-light","dark":"vesper"}}
↻ Reloaded in 12 ms, 3 commands, 2 events loaded
↻ Commands updated on My Server
```

Si Discord les refuse, le bot continue de tourner avec les commandes que Discord a déjà :

```text theme={"theme":{"light":"github-light","dark":"vesper"}}
✗ Discord refused the commands of your project: Discord refused PUT /applications/{application.id}/guilds/{guild.id}/commands: Invalid Form Body (50035)
```

### En production : tout le monde

`chapterjs start` les enregistre pour tout le monde, dans chaque serveur où se trouve le bot et en messages privés :

```text theme={"theme":{"light":"github-light","dark":"vesper"}}
✓ Commands updated for everyone
```

### Dev et production

Une commande pour tout le monde appartient au bot, pas à un serveur : Discord l’affiche dans chaque serveur où se trouve le bot, votre serveur de test compris, et ne donne aucun moyen de la cacher dans l’un d’eux. Alors utilisez une **seconde application** pour le développement dès le départ, avec son propre token sur votre ordinateur : votre serveur de test n’affiche alors que les commandes de vos fichiers, jamais une en double. Comment la mettre en place est dans [Un second bot pour le développement](https://www.chapterjs.org/fr/run/start.md#un-second-bot-pour-le-développement).

Avec un seul bot pour les deux, `chapterjs dev` fait ce qu’il peut : il n’ajoute à votre serveur de test que les commandes nouvelles ou différentes dans votre projet, et une commande utilisée là-bas fait toujours tourner le code de votre ordinateur. Mais pendant que vous modifiez une commande que la production a déjà, votre serveur de test l’affiche en double (la vôtre, et celle que tout le monde a), et `chapterjs dev` vous le dit une fois :

```text theme={"theme":{"light":"github-light","dark":"vesper"}}
ℹ /poll is not the same here as in production, so My Server shows it twice: yours, and the one everyone has. It is shown once again when production runs your version.
```

> [card] [Options](https://www.chapterjs.org/fr/commands/options.md)
>
> Ce que les gens remplissent, typé pour vous.

> [card] [Répondre](https://www.chapterjs.org/fr/commands/answering.md)
>
> Répondre, différer, modifier, envoyer une suite, et ce qui se passe quand votre fonction échoue.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.