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

# Événements

> Réagir à ce qui se passe sur Discord : un nouveau membre, un salon supprimé, un message

Un événement est quelque chose qui se passe sur Discord. Pour réagir à l’un d’eux, déclarez-le avec `event()` dans n’importe quel fichier de `src/`, et exportez-le :

```ts src/events/welcome.ts theme={"theme":{"light":"github-light","dark":"vesper"}}
import { event } from 'chapterjs';

export default event({
  name: 'memberJoin',
  async run({ member, guild }) {
    await member.send(`Bienvenue sur ${guild.name}, ${member.displayName} !`);
  },
});
```

C’est tout. `chapterjs dev` trouve la déclaration et lance votre fonction chaque fois que quelqu’un rejoint votre serveur de test. Rien à enregistrer, aucune liste à tenir à jour, et aucun type à écrire : votre éditeur sait déjà que `member` est un [`GuildMember`](https://www.chapterjs.org/fr/reference/member) et `guild` un [`Guild`](https://www.chapterjs.org/fr/reference/guild).

Chaque événement donne les deux mêmes choses : **ce dont il parle** (`member` ici, `message`, `role`, `reaction`, `voice`...) et **le serveur** où il s’est produit, `guild`. Rien d’autre, plus `t` quand votre projet a des [langues](https://www.chapterjs.org/fr/translated-messages.md). Ce que donne chaque événement est listé dans un seul tableau de la [référence](https://www.chapterjs.org/fr/reference/events.md#ce-que-donne-chaque-événement).

## Le nom est l’événement

* **`name` est l’événement.** C’est l’un des [événements](https://www.chapterjs.org/fr/reference/events.md), et votre éditeur les propose pendant que vous tapez ; un autre mot est souligné, et signalé avec le nom d’événement le plus proche quand le fichier se charge.
* **Une déclaration est une réaction.** L’endroit du fichier et son nom sont à vous : `src/events/welcome.ts`, ou `src/welcome/welcome.ts`, ou `src/welcome.ts`, ou à côté de la commande qu’il accompagne, comme le fait le modèle `tickets`. Déclarez-en autant que vous voulez, dans un fichier ou plusieurs : elles tournent toutes.
* **L’import est le même partout.** `name` est ce qui dit à `event` ce que reçoit votre fonction : un membre pour `'memberJoin'`, un rôle pour `'roleDelete'`. La même ligne, `import { event } from 'chapterjs'`, fonctionne dans chaque fichier.

## Plusieurs réactions à un événement

Quand un événement se produit, chaque déclaration de cet événement tourne, **en même temps et sans ordre particulier**. L’une n’attend jamais l’autre, et une qui échoue n’arrête jamais les autres.

Utilisez une déclaration par chose que fait votre bot : `welcome`, `log`, `roles`... Quand deux étapes doivent se faire l’une après l’autre, gardez-les dans la même fonction :

```ts src/events/roles.ts theme={"theme":{"light":"github-light","dark":"vesper"}}
import { event } from 'chapterjs';

export default event({
  name: 'memberJoin',
  async run({ member, guild }) {
    const role = [...guild.roles.values()].find(role => role.name === 'Newcomer');
    if (!role) return;
    await member.addRole(role, 'Vient d’arriver');
    await member.send(`Vous avez maintenant le rôle ${role.name}.`);
  },
});
```

Chaque déclaration d’un événement reçoit la même chose, et peut la lire mais pas la modifier : y affecter une valeur (`context.role = ...`) lève une erreur, signalée comme n’importe quelle autre.

## Ce qui ne manque jamais

Votre fonction reçoit des [structures](https://www.chapterjs.org/fr/reference.md) que vous pouvez lire et utiliser. Sur un serveur, ce qui doit exister est toujours là, sans `?.` à écrire :

* `member.guild`, `role.guild`, `channel.guild` pour un salon de serveur, `member.highestRole` ;
* `guild.me` (votre bot en tant que membre du serveur), `guild.everyoneRole` ;
* `message.guild`, `message.member` et `message.channel` dans les [événements sur les messages](https://www.chapterjs.org/fr/events/messages.md).

Ils restent là pendant que votre fonction tourne, même si la personne part ou que le salon est supprimé entre-temps : votre fonction les garde tels qu’ils étaient. Le bot garde aussi `guild.me` à part de [ce dont il se souvient](https://www.chapterjs.org/fr/memory.md), donc il est là dans un serveur de n’importe quelle taille.

Ce qui peut être `null` est ce qui peut vraiment ne pas exister : un salon sans catégorie (`channel.parent`), un message jamais modifié (`message.editedAt`), un nombre de membres que Discord n’a jamais envoyé (`guild.memberCount`), un message supprimé dont le bot ne se souvenait pas (`message.before` dans `messageDelete`).

### Ce qui a été supprimé

Les événements sur quelque chose qui n’existe plus donnent la chose elle-même **telle qu’elle était** :

* `roleDelete` : `role` est toujours là, le bot connaît chaque rôle de ses serveurs.
* `channelDelete` : `channel` est le salon ou le fil tel qu’il était.
* `guildLeave` : `guild` est le serveur tel qu’il était.
* `memberLeave` : `user` est le compte de la personne partie, toujours là.

```ts src/events/goodbye.ts theme={"theme":{"light":"github-light","dark":"vesper"}}
import { event } from 'chapterjs';

export default event({
  name: 'memberLeave',
  async run({ user, guild }) {
    const channel = guild.systemChannelId ? guild.channels.get(guild.systemChannelId) : undefined;
    if (!channel || !channel.isTextBased()) return;
    const name = user.displayName;
    await channel.send(`${name} a quitté ${guild.name}.`);
  },
});
```

## L’événement `ready`

`ready` tourne **une fois par démarrage**, quand le bot est connecté et connaît chaque serveur où il se trouve. Ce n’est pas un événement de Discord : rien ne peut le relancer, et enregistrer un fichier dans `chapterjs dev` ne le lance jamais une seconde fois.

```ts src/events/online.ts theme={"theme":{"light":"github-light","dark":"vesper"}}
import { event } from 'chapterjs';

export default event({
  name: 'ready',
  run({ user, guilds }) {
    console.log(`${user.username} est en ligne sur ${guilds.size} serveur(s)`);
  },
});
```

## Options

Certains événements prennent des options, écrites à côté de `name`. Chaque déclaration décide pour elle-même : deux réactions au même événement peuvent avoir des options différentes, et ce que reçoit votre fonction les suit.

```ts src/events/relay.ts theme={"theme":{"light":"github-light","dark":"vesper"}}
import { event } from 'chapterjs';

export default event({
  name: 'messageCreate',
  bots: true,
  run({ message }) {
    console.log(`${message.author.username}: ${message.content}`);
  },
});
```

Une option vaut `true` ou `false`, ou un mot d’une liste. Votre éditeur ne propose que les options de l’événement nommé, et une option qui n’existe pas, ou une mauvaise valeur, est soulignée, puis signalée au chargement du fichier, avant que le bot ne le lance. Les événements qui ont des options sont les [événements sur les messages](https://www.chapterjs.org/fr/events/messages.md) et les [réactions, sondages et saisie](https://www.chapterjs.org/fr/events/reactions.md).

## Intents : rien à lister

Discord n’envoie à un bot que les événements qu’il a demandés, par les *intents*. Vous ne les écrivez jamais : ChapterJS les déduit des événements que vos fichiers déclarent, et vous le dit à la connexion :

```text theme={"theme":{"light":"github-light","dark":"vesper"}}
ℹ Intents computed from your files: GUILDS, GUILD_MEMBERS
```

Quand vous enregistrez un fichier qui en demande davantage, `chapterjs dev` se reconnecte tout seul :

```text theme={"theme":{"light":"github-light","dark":"vesper"}}
↻ Your files now need more from Discord (GUILD_MESSAGES, MESSAGE_CONTENT): reconnecting...
```

Trois des intents dont vos fichiers peuvent avoir besoin sont **privilégiés** : Discord vous demande de les activer vous-même, dans le [Developer Portal](https://www.chapterjs.org/fr/setup/discord-application.md).

| Événements | Option à activer |
| - | - |
| `memberJoin`, `memberUpdate`, `memberLeave`, `threadMemberJoin`, `threadMemberLeave` | **Server Members Intent** |
| `messageCreate`, `messageUpdate` | **Message Content Intent** : sans lui, les messages des autres arrivent sans leur texte |
| `presenceUpdate` | **Presence Intent** |

Quand l’un manque, `chapterjs dev` nomme les fichiers qui en ont besoin et vous donne le lien, puis attend :

```text theme={"theme":{"light":"github-light","dark":"vesper"}}
⚠ Your files need an option that is not enabled for your bot:
  - Server Members Intent, needed by src/events/welcome.ts
  Enable it under "Privileged Gateway Intents", then save:
  https://discord.com/developers/applications/123456789012345678/bot
  Waiting for you to enable it...
✓ Privileged intents enabled
```

> [!NOTE]
>
> La commande n’attend que lorsqu’elle tourne dans un terminal. Lancée par un autre programme, elle s’arrête avec la même explication.

## Quand votre fonction échoue

Une erreur dans une de vos fonctions n’arrête jamais le bot, ni les autres fichiers. Elle est affichée dans votre terminal avec le fichier et la ligne, que ce soit un bug de votre part ou Discord qui refuse ce que vous avez demandé :

```text theme={"theme":{"light":"github-light","dark":"vesper"}}
✗ src/events/welcome.ts:4 Discord refused POST /channels/{channel.id}/messages: Cannot send messages to this user (50007)
```

Pour gérer un échec vous-même, utilisez `try` / `catch` : voir [Erreurs](https://www.chapterjs.org/fr/reference/errors.md).

## En dev, seulement votre serveur de test

`chapterjs dev` fait tourner votre bot [sur votre serveur de test uniquement](https://www.chapterjs.org/fr/run/dev.md#seulement-votre-serveur-de-test) : ce qui se passe dans les autres serveurs et en messages privés est ignoré, et les intents qui ne servent qu’aux messages privés ne sont pas demandés. Avec `chapterjs start`, votre bot entend chaque serveur où il se trouve et les messages privés aussi.

> [!NOTE]
>
> Chaque événement, avec ce que reçoit votre fonction, est dans la [référence](https://www.chapterjs.org/fr/reference/events.md). Les types de `event()` sont dans [event()](https://www.chapterjs.org/fr/reference/event.md).

## Toutes les sortes d’événements

Au-delà des membres, des rôles, des salons et des serveurs eux-mêmes, vos fichiers peuvent réagir :

* **Aux messages** : envoyés, modifiés, supprimés. Voir [Messages](https://www.chapterjs.org/fr/events/messages.md).
* **Aux réactions, aux sondages et à la saisie** : une réaction ajoutée ou retirée, un vote, quelqu’un qui écrit. Voir [Réactions, sondages et saisie](https://www.chapterjs.org/fr/events/reactions.md).
* **Au vocal** : quelqu’un qui rejoint, quitte, change de salon, coupe son micro ou lance un stream. Voir [Vocal](https://www.chapterjs.org/fr/events/voice.md).
* **À la modération et au serveur** : bannissements, journal d’audit, invitations, emojis, événements programmés, qui est dans un fil, présences. Voir [Modération et serveur](https://www.chapterjs.org/fr/events/server.md).

> [card] [Messages](https://www.chapterjs.org/fr/events/messages.md)
>
> Serveurs ou messages privés, bots ou personnes : les événements sur les messages et leurs options.

> [card] [Ce dont votre bot se souvient](https://www.chapterjs.org/fr/memory.md)
>
> Pourquoi lire un serveur ou un membre ne coûte rien, et comment la mémoire reste sous contrôle.


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