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

# Les messages comme événements

> Réagir aux messages que les gens écrivent, choisir où votre fichier écoute et si les bots comptent, et lire le Message Content Intent

Trois événements concernent les messages : `messageCreate`, `messageUpdate` et `messageDelete`. Ce sont les événements les plus fréquents qu’un bot reçoit, et ceux où un bot imprudent fait le plus de dégâts : se répondre à lui-même indéfiniment, ou notifier tout le monde. Cette page écrit une petite réaction, et montre les filets de sécurité que le framework place en dessous.

## Réagir à un mot

Créez `src/events/thanks.ts` :

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

export default event({
  name: 'messageCreate',
  async run({ message }) {
    if (!/\bmerci\b/i.test(message.content)) return;
    await message.react('💜');
  },
});
```

Enregistrez-le. Comme l’intent des membres, il faut un interrupteur :

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

Lire ce que les gens écrivent est la chose la plus personnelle qu’un bot puisse faire, alors Discord en fait un intent privilégié : **Message Content Intent**. Sans lui, un bot reçoit toujours les messages, mais `message.content` est vide pour tout le monde sauf lui-même. Activez-le, enregistrez, et le bot se reconnecte. Puis écrivez « merci » sur votre serveur de test : le bot réagit.

> [!NOTE]
>
> Pourquoi `/dice` n’en avait-il pas besoin ? Parce qu’une commande slash est envoyée au bot par Discord en tant que commande, avec ses options, et non en tant que message. Raison de plus pour préférer les commandes slash pour tout ce qui est un ordre donné au bot, et garder les événements de messages pour réagir à ce que disent les gens.

## Sûr par défaut

Regardez ce que le fichier ne fait **pas**. Il ne vérifie pas `if (message.author.bot) return;`. Il ne vérifie pas que le message est sur un serveur. Les deux sont le comportement par défaut :

* **Les messages des bots et des webhooks sont ignorés**, y compris les vôtres. Un bot qui réagit aux messages et répond par un message verra sa propre réponse, y réagira, et ainsi de suite indéfiniment ; un serveur avec deux bots de ce genre les voit discuter toute la nuit. Alors par défaut, votre fichier ne tourne que pour les messages écrits par des personnes. Quand vous voulez vraiment les messages des bots, dites-le : `bots: true`, écrit à côté de `name`.
* **Seulement les messages des serveurs.** Les messages privés sont un autre endroit, sans serveur, sans membre et sans salon de serveur ; un fichier qui gère les deux doit les distinguer. Alors par défaut, votre fichier écoute sur les serveurs, où `message.guild`, `message.channel` et `message.member` sont toujours là.

Le comportement sûr est le comportement par défaut, et en sortir est explicite. Voici comment les options écrites à côté de `name` le changent, et ce qu’elles changent dans ce que reçoit votre fonction :

| Options | Tourne pour | `message.member` | `message.guild` |
| - | - | - | - |
| aucune | Des personnes, sur les serveurs | Toujours là | Toujours là |
| `bots: true` | Des personnes, des bots et des webhooks, sur les serveurs | Peut être `null` (un webhook n’est pas un membre) | Toujours là |
| `where: 'dm'` | Des personnes, en messages privés | N’existe pas | N’existe pas |
| `where: 'both'` | Des personnes, partout | Là quand `message.guild` l’est | `Guild` ou `null` |

Les types suivent les options : dans un fichier `'dm'`, l’éditeur ne propose même pas `message.guild` ; dans un fichier `'both'`, un seul `if (message.guild)` restreint tout ce qu’il contient à un message de serveur. Chaque fichier décide pour lui-même : deux fichiers du même dossier peuvent écouter à des endroits différents.

> [!NOTE]
>
> `chapterjs dev` ne fait tourner votre bot que sur votre serveur de test, donc un fichier avec `where: 'dm'` ne peut pas y être essayé, et le terminal vous le dit une fois. Les messages privés atteignent votre bot avec `chapterjs start`.

## Répondre à un message

`message.reply()` répond dans le salon, avec l’original affiché au-dessus de la réponse. Voici un fichier qui répond à une question sur le règlement :

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

export default event({
  name: 'messageCreate',
  async run({ message }) {
    if (!message.content.toLowerCase().includes('où est le règlement')) return;
    const rules = message.guild.rulesChannelId
      ? message.guild.channels.get(message.guild.rulesChannelId)
      : undefined;
    await message.reply({
      content: rules ? `Il est dans ${rules}.` : 'Ce serveur n’a pas encore de salon de règlement.',
      allowedMentions: { repliedUser: false },
    });
  },
});
```

`message.guild` est utilisé sans vérification : ce fichier n’écoute que sur les serveurs, donc il est toujours là. `allowedMentions: { repliedUser: false }` répond sans notifier l’auteur : un bot qui notifie les gens chaque fois qu’il aide se fait vite rendre muet.

## Messages supprimés et modifiés

`messageUpdate` donne le message après la modification. `messageDelete` est différent : le message n’existe plus, donc son `message` est ce qu’il en reste : son `id`, le `channel` où il était, et `before`, le message lui-même, seulement quand le bot s’en souvenait, ce qui n’est pas le cas par défaut (les messages sont ce qu’un bot reçoit le plus, et la plupart des bots ne relisent jamais un vieux message). Utilisez toujours `message.id` :

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

export default event({
  name: 'messageDelete',
  run({ message, guild }) {
    console.log(`Message ${message.id} supprimé dans #${message.channel.name} de ${guild.name}`);
  },
});
```

`messageDelete` n’a pas besoin du Message Content Intent.

## Points d’attention

* **Ne répondez jamais à un message par un message sans penser aux boucles.** Avec le comportement par défaut (pas de bots), vous êtes en sécurité. Avec `bots: true`, assurez-vous que votre fichier ne peut pas réagir à sa propre réponse.
* **Une réaction à un mot tourne sur chaque message de chaque salon.** Gardez la vérification légère et en premier, et faites `return` tôt.
* **Les messages privés, c’est pour la production.** Un bot de support qui écoute en messages privés s’essaie avec `chapterjs start`, sur l’application de dev si vous voulez.
* **Un fil que le bot n’a jamais vu.** Un message peut arriver dans un salon que le bot ne connaît pas encore (un fil créé avant sa connexion). Le framework le demande une fois à Discord, avant de lancer vos fichiers, donc `message.channel` est toujours là. Quand Discord refuse (le bot ne peut pas voir ce salon), l’événement n’est pas transmis et le terminal le dit avec `⚠`.

## Récapitulatif

* Un événement `messageCreate` tourne pour les messages écrits par des personnes, sur les serveurs, par défaut : aucune vérification `author.bot` à écrire.
* Le Message Content Intent est nécessaire pour lire `message.content` dans `messageCreate` et `messageUpdate`.
* `bots: true` et `where: 'dm'` ou `where: 'both'` élargissent ce qu’un fichier entend, et les types suivent.
* `messageDelete` donne ce qui reste du message (`id`, `channel`) et le serveur ; `message.before` est `null`.

> [card] [Réactions et vocal](https://www.chapterjs.org/fr/tutorial/reactions-and-voice.md)
>
> Réagir aux réactions, et à qui rejoint un salon vocal.

> [card] [Guide : Messages](https://www.chapterjs.org/fr/events/messages.md)
>
> Les trois événements et leurs options, en bref.


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