> ## 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.

# Options

> Déclarer ce que les gens remplissent après le nom d’une commande, et le recevoir typé dans votre fonction

Les options sont ce que les gens remplissent après le nom d’une commande. Déclarez-les sous forme d’objet, et `run` reçoit leurs valeurs **déjà typées** : vous n’écrivez jamais un type.

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

export default command({
  name: 'mod ban',
  description: 'Bannit un membre',
  permissions: ['BanMembers'],
  options: {
    target: { type: 'user', description: 'Qui bannir', required: true },
    reason: { type: 'string', description: 'Pourquoi', maxLength: 200 },
    days: { type: 'integer', description: 'Jours de messages à supprimer', min: 0, max: 7 },
  },
  async run({ interaction, options, guild }) {
    // options.target : User
    // options.reason : string | undefined
    // options.days : number | undefined
    await guild.ban(options.target, {
      reason: options.reason,
      deleteMessageSeconds: (options.days ?? 0) * 86_400,
    });
    await interaction.reply(`${options.target.displayName} a été banni.`);
  },
});
```

C’est tout : Discord demande `target`, `reason` et `days` dans cet ordre, et votre éditeur sait que `options.target` est un `User` et que `options.reason` peut manquer.

> [!NOTE]
>
> Chaque champ de chaque sorte d’option est dans la [référence](https://www.chapterjs.org/fr/reference/command.md#les-options).

## Déclarer une option

La clé est le nom de l’option, la valeur dit ce qu’elle est. Chaque option a un `type` et une `description` (de 1 à 100 caractères, affichée sous son nom) :

| `type` | Ce que la personne remplit | Ce que reçoit `run` |
| - | - | - |
| `'string'` | Un texte | `string` |
| `'integer'` | Un nombre entier | `number` |
| `'number'` | N’importe quel nombre | `number` |
| `'boolean'` | Vrai ou faux | `boolean` |
| `'user'` | Un utilisateur | [`User`](https://www.chapterjs.org/fr/reference/user) |
| `'role'` | Un rôle | [`Role`](https://www.chapterjs.org/fr/reference/role) |
| `'channel'` | Un salon | [`Channel`](https://www.chapterjs.org/fr/reference/channels) |
| `'mentionable'` | Un utilisateur ou un rôle | `User \| Role` |
| `'attachment'` | Un fichier | [`Attachment`](https://www.chapterjs.org/fr/reference/data#attachment) |

Les noms suivent les règles de Discord : lettres minuscules, chiffres, `-` et `_`, 32 caractères au plus. Une commande a 25 options au plus.

## Obligatoire ou facultative

Une option est **facultative** sauf si elle dit `required: true`. Dans `run`, une option obligatoire est toujours là ; une facultative peut être `undefined`, et votre éditeur vous le rappelle :

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

export default command({
  name: 'greet',
  description: 'Salue quelqu’un',
  options: {
    who: { type: 'user', description: 'Qui saluer', required: true },
    message: { type: 'string', description: 'Quoi dire' },
  },
  async run({ interaction, options }) {
    // options.who : User
    // options.message : string | undefined
    await interaction.reply(`${options.message ?? 'Bonjour'}, ${options.who.displayName} !`);
  },
});
```

Discord veut les options obligatoires en premier. Vous pouvez les déclarer dans n’importe quel ordre : ChapterJS met les obligatoires en premier pour vous, et garde l’ordre que vous avez écrit pour le reste.

## Les choix

Avec `choices`, la personne choisit dans une liste au lieu de taper, et la valeur est typée comme l’un des choix. Une option `string`, `integer` ou `number` peut avoir entre 1 et 25 choix :

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

export default command({
  name: 'color',
  description: 'Choisit une couleur',
  options: {
    // Une liste : ce que voit la personne est ce que reçoit votre code.
    color: { type: 'string', description: 'Votre couleur', choices: ['red', 'green'], required: true },
    // Un objet : la clé est affichée, la valeur est reçue.
    size: { type: 'integer', description: 'Quelle taille', choices: { Petit: 1, Grand: 2 } },
  },
  async run({ interaction, options }) {
    // options.color : 'red' | 'green'
    // options.size : 1 | 2 | undefined
    await interaction.reply(`Vous avez choisi ${options.color}.`);
  },
});
```

Les choix d’une option `string` sont des textes, ceux d’une option `integer` ou `number` sont des nombres ; ce qui est affiché fait de 1 à 100 caractères. Le même choix ne peut pas apparaître deux fois.

## Autocomplétion

Quand les valeurs ne sont pas connues à l’avance, ou changent (une chanson, un joueur, un ticket), `autocomplete` les suggère **pendant que la personne tape** : Discord interroge votre bot toutes les quelques frappes, et affiche ce que renvoie votre fonction sous l’option. La personne peut quand même taper autre chose.

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

const SONGS = [
  { id: '1', title: 'Daylight' },
  { id: '2', title: 'Dark Horse' },
  { id: '3', title: 'Darkside' },
];

export default command({
  name: 'play',
  description: 'Joue une chanson',
  options: {
    song: { type: 'string', description: 'Quelle chanson', required: true },
  },
  autocomplete: {
    // Appelée pendant que la personne tape dans « song », avec ce qu’elle a tapé jusque-là.
    song: ({ value }) =>
      SONGS.filter(song => song.title.toLowerCase().startsWith(value.toLowerCase()))
        // Affichée comme le titre, reçue comme l’identifiant.
        .map(song => ({ name: song.title, value: song.id })),
  },
  async run({ interaction, options }) {
    // options.song : string, l’identifiant de la chanson, ou ce qui a été tapé
    const song = SONGS.find(song => song.id === options.song);
    await interaction.reply(song ? `Je joue ${song.title}.` : 'Je ne connais pas cette chanson.');
  },
});
```

`autocomplete` a une fonction par option, par son nom, pour une option `string`, `integer` ou `number` sans `choices`. Elle reçoit :

| Champ | Ce que c’est |
| - | - |
| `value` | Ce que la personne a tapé jusque-là : un texte (peut-être vide) pour une option `string` ; pour une option `integer` ou `number`, un nombre, ou `undefined` tant que ce n’en est pas encore un |
| `options` | Ce que la personne a rempli jusque-là, chaque option facultative ; une option `user`, `role`, `channel`, `mentionable` ou `attachment` est son identifiant |
| `user`, `locale` | Qui tape, et sa langue |
| `guild`, `member`, `channel` | Où, selon `where` comme pour `run` |
| `t` | Les textes du projet, dans la langue de la personne (voir [messages traduits](https://www.chapterjs.org/fr/translated-messages.md)) |

Elle renvoie les suggestions (ou une promesse de celles-ci) : une valeur, affichée telle quelle, ou `{ name, value }` pour afficher un texte et recevoir une autre valeur. Une option `string` suggère des textes, une option `integer` ou `number` des nombres. Discord en affiche 25 au plus, dans l’ordre où vous les renvoyez, et attend 3 secondes : répondez vite, vos meilleures correspondances d’abord.

> [!WARNING]
>
> Une suggestion est une aide, pas une limite : Discord envoie à votre `run` ce que la personne a tapé, choisi dans la liste ou non. Vérifiez la valeur, comme dans l’exemple.

Ce que renvoie la fonction est vérifié à l’envoi. Trop de suggestions sont coupées à 25, et un nom de plus de 100 caractères est raccourci, dit une fois avec `⚠`. Ce qui ne peut pas être corrigé est une erreur, et rien n’est suggéré :

```text theme={"theme":{"light":"github-light","dark":"vesper"}}
✗ src/commands/play.ts A suggestion of /play song has the value 1: the option is a text, so its suggestions must be texts.
```

## Limiter ce qui est tapé

Un texte peut recevoir une longueur, un nombre un intervalle :

| Champ | Pour | Signification |
| - | - | - |
| `minLength` | `string` | Le texte le plus court accepté, en caractères (0 à 6000) |
| `maxLength` | `string` | Le texte le plus long accepté, en caractères (1 à 6000) |
| `min` | `integer`, `number` | La plus petite valeur acceptée |
| `max` | `integer`, `number` | La plus grande valeur acceptée |

Discord refuse ce qui est en dehors avant même que la commande n’atteigne votre bot. Pour une option `integer`, `min`, `max` et les choix sont des nombres entiers.

## Seulement certaines sortes de salons

`channelTypes` dit quelles sortes de salons peuvent être choisies. Par défaut, toutes :

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

export default command({
  name: 'announce',
  description: 'Annonce quelque chose dans un salon',
  permissions: ['ManageGuild'],
  options: {
    channel: { type: 'channel', description: 'Où', channelTypes: [ChannelType.GuildText], required: true },
    text: { type: 'string', description: 'Quoi dire', required: true, maxLength: 2000 },
  },
  async run({ interaction, options }) {
    if (!options.channel.isTextBased()) return interaction.reply('Choisissez un salon textuel.');
    await options.channel.send(options.text);
    await interaction.reply({ content: 'Fait.', ephemeral: true });
  },
});
```

Les valeurs sont celles de [`ChannelType`](https://www.chapterjs.org/fr/reference/enums#channeltype). Ce que reçoit `run` est toujours un [`Channel`](https://www.chapterjs.org/fr/reference/channels) : vérifiez sa sorte avec `isTextBased()` ou `isVoice()` avant d’utiliser ce que seule cette sorte possède.

## Ce qui est vérifié

Tout ce que déclare une option est vérifié au chargement du fichier, par rapport aux limites de Discord. Une erreur est expliquée dans votre terminal avant que Discord ne la refuse, avec le fichier devant :

> [accordion] Un nom que Discord refuse
>
> ```text theme={"theme":{"light":"github-light","dark":"vesper"}}
> ✗ src/commands/ban.ts "Target" can't be the name of an option: use lowercase letters, digits, - and _ only, 32 characters at most.
> ```

> [accordion] Un type qui n’existe pas
>
> ```text theme={"theme":{"light":"github-light","dark":"vesper"}}
> ✗ src/commands/ban.ts The type of the option "target" is "member", which does not exist. Types are: string, integer, number, boolean, user, role, channel, mentionable, attachment.
> ```

> [accordion] Un champ que le type n’a pas
>
> ```text theme={"theme":{"light":"github-light","dark":"vesper"}}
> ✗ src/commands/ban.ts "min" is not something the option "reason" has. It can have: type, description, required, choices, minLength, maxLength.
> ```

> [accordion] Une description manquante ou trop longue
>
> ```text theme={"theme":{"light":"github-light","dark":"vesper"}}
> ✗ src/commands/ban.ts the option "target" needs a description: a short text that says what it is for, like description: 'Bans a member'.
> ```
>
> ```text theme={"theme":{"light":"github-light","dark":"vesper"}}
> ✗ src/commands/ban.ts The description of the option "target" is 120 characters long: Discord accepts 100 at most.
> ```

> [accordion] Trop d’options
>
> ```text theme={"theme":{"light":"github-light","dark":"vesper"}}
> ✗ src/commands/big.ts This command has 26 options: Discord accepts 25 at most.
> ```

> [accordion] Les choix
>
> ```text theme={"theme":{"light":"github-light","dark":"vesper"}}
> ✗ src/commands/color.ts the option "color" has 26 choices: Discord accepts between 1 and 25.
> ```
>
> ```text theme={"theme":{"light":"github-light","dark":"vesper"}}
> ✗ src/commands/color.ts The choices of the option "size" must be numbers, since its type is integer: got "big".
> ```
>
> ```text theme={"theme":{"light":"github-light","dark":"vesper"}}
> ✗ src/commands/color.ts The choice 1.5 of the option "size" is not a whole number.
> ```
>
> ```text theme={"theme":{"light":"github-light","dark":"vesper"}}
> ✗ src/commands/color.ts the option "color" has the same choice twice.
> ```

> [accordion] Un intervalle impossible à remplir
>
> ```text theme={"theme":{"light":"github-light","dark":"vesper"}}
> ✗ src/commands/ban.ts the option "days" can never be filled in: its "min" (8) is greater than its "max" (7).
> ```
>
> ```text theme={"theme":{"light":"github-light","dark":"vesper"}}
> ✗ src/commands/ban.ts "maxLength" of the option "reason" is between 0 and 6000, got 9000.
> ```

> [accordion] Les sortes de salons
>
> ```text theme={"theme":{"light":"github-light","dark":"vesper"}}
> ✗ src/commands/announce.ts "channelTypes" of the option "channel" is a list of ChannelType values, like [ChannelType.GuildText].
> ```

> [accordion] L’autocomplétion
>
> ```text theme={"theme":{"light":"github-light","dark":"vesper"}}
> ✗ src/commands/play.ts "title" of "autocomplete" is not an option of this command. Its options are: song.
> ```
>
> ```text theme={"theme":{"light":"github-light","dark":"vesper"}}
> ✗ src/commands/play.ts "who" of "autocomplete" can't have suggestions: the option "who" is a user. Only a string, integer, number option can.
> ```
>
> ```text theme={"theme":{"light":"github-light","dark":"vesper"}}
> ✗ src/commands/play.ts "song" of "autocomplete" can't have suggestions: the option "song" has "choices", and Discord takes one or the other. Remove its choices to suggest them from here, or take it out of "autocomplete".
> ```

Votre éditeur souligne la plupart de ces erreurs avant même que vous n’enregistriez : les types de `command()` n’acceptent que ce qui existe.

> [card] [Répondre](https://www.chapterjs.org/fr/commands/answering.md)
>
> Répondre, différer, modifier, envoyer une suite.

> [card] [Traductions](https://www.chapterjs.org/fr/commands/translations.md)
>
> Options et choix dans la langue de chaque personne.


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