messageCreate, messageUpdate and messageDelete. They are the most frequent events a bot receives, and the ones where a careless bot does the most damage: answering itself forever, or pinging everyone. This page writes a small reaction, and shows the safety nets the framework puts under it.
Reacting to a word
Createsrc/events/thanks.ts:
src/events/thanks.ts
message.content is empty for everyone but itself. Enable it, save, and the bot reconnects. Then write “thanks” in your test server: the bot reacts.
Why did
/dice not need this? Because a slash command is sent to the bot by
Discord as a command, with its options, and not as a message. That is one more
reason to prefer slash commands for anything that is an order to the bot, and
keep message events for reactions to what people say.Safe by default
Look at what the file does not do. It does not checkif (message.author.bot) return;. It does not check that the message is in a server. Both are the default:
- Messages of bots and webhooks are ignored, yours included. A bot that reacts to messages and answers with a message will see its own answer, react to it, and so on forever; a server with two such bots has them talking to each other all night. So by default your file only runs for messages written by people. When you really want the messages of bots, say it:
bots: true, written next toname. - Only the messages of servers. Private messages are a different place, with no server, no member and no channel of a server; a file that handles both has to tell them apart. So by default your file listens in servers, where
message.guild,message.channelandmessage.memberare always there.
name change it, and what they change in what your function receives:
The types follow the options: in a
'dm' file, the editor does not even offer message.guild; in a 'both' file, one if (message.guild) narrows everything inside it to a message of a server. Each file decides for itself: two files of the same folder can listen in different places.
chapterjs dev only runs your bot in your test server, so a file with where: 'dm' can’t be tried there, and the terminal tells you once. Private messages
reach your bot with chapterjs start.Answering a message
message.reply() answers in the channel, with the original shown above the answer. Here is a file that answers a question about the rules:
src/events/rules.ts
message.guild is used without a check: this file listens in servers only, so it is always there. allowedMentions: { repliedUser: false } answers without pinging the author: a bot that pings people every time it helps gets muted fast.
Deleted and edited messages
messageUpdate gives the message after the edit. messageDelete is different: the message no longer exists, so its message is what is left of it: its id, the channel it was in, and before, the message itself, only when the bot remembered it, which it does not by default (messages are what a bot receives the most, and most bots never read an old one). Always use message.id:
src/events/audit.ts
messageDelete does not need the Message Content Intent.
Points of attention
- Never answer a message with a message without thinking about loops. With the default (no bots), you are safe. With
bots: true, make sure your file can’t react to its own answer. - A reaction to a word runs on every message of every channel. Keep the check cheap and first, and
returnearly. - Private messages are for production. A support bot that listens in private messages is tried with
chapterjs start, on the dev application if you like. - A thread the bot never saw. A message can arrive in a channel the bot does not know yet (a thread created before it connected). The framework asks Discord for it once, before running your files, so
message.channelis always there. When Discord refuses (the bot can’t see that channel), the event is not delivered and the terminal says so with⚠.
Recap
- A
messageCreateevent runs for messages written by people, in servers, by default: noauthor.botcheck to write. - The Message Content Intent is needed to read
message.contentformessageCreateandmessageUpdate. bots: trueandwhere: 'dm'orwhere: 'both'widen what a file hears, and the types follow.messageDeletegives what is left of the message (id,channel) and the server;message.beforeisnull.
Reactions and voice
React to reactions, and to who joins a voice channel.
Guide: Messages
The three events and their options, in short.