A declaration per reaction
To react to an event, declare it withevent() and export it: name is the event, and the rest is one reaction. The file is yours to place and to name; this tutorial keeps its events in src/events/. Create src/events/hello.ts:
src/events/hello.ts
name and run. And the function receives what the event is about: here a member (who joined) and a guild (where). Hover member in your editor: it is a GuildMember, with everything the previous pages showed. The same import { event } from 'chapterjs' line, with name: 'roleDelete', would give your function a role. Every event works this way: what it is about, and the server, guild. Nothing else, so you never search for where something is.
guild.systemChannelId is the channel where Discord itself posts “X joined the server”, when the server has one: a sensible default for a welcome. guild.channels.get() reads it from what the bot knows, and isTextBased() makes sure a message can go there.
The first privileged intent
Save the file. The terminal does not say “Reloaded”. It says:GUILDS) when it connected. Knowing about members joining is another intent, GUILD_MEMBERS, and that one is privileged: Discord wants you to enable it by hand, because the list of members of a server is personal data.
Open the link (it goes straight to the Bot page of your dev application), turn on Server Members Intent, click Save Changes. The terminal goes on by itself:
You never wrote an intent. The framework reads the events your files
declare, works out what they need, asks Discord for exactly that, and tells
you when one needs a switch in the Developer Portal. When you delete the
declaration, the intent is not asked for any more. That is what “intents are computed from your files” means
on the first line of every start.
Several files for one event
Declare as many reactions to one event as you want, and all of them run when it happens, at the same time, in no particular order. Addsrc/events/role.ts, which gives newcomers a role:
src/events/role.ts
role.ts throws (the role was deleted, the bot’s role is too low), hello.ts still welcomes. And each one stays short enough to read. When two steps must happen in order, keep them in the same function.
The ready event
ready is special: it is not something that happens on Discord, but the moment your bot is connected and knows every server it is in. It runs once per start, never on a reload. Create src/events/ready.ts:
src/events/ready.ts
buddy is online in 1 server(s), once. user is the bot itself, guilds the servers it is in. Use it for things that must happen once at startup. Do not use it for things that must happen regularly: that is what tasks are for, a few chapters from here.
The events you can react to
A
name that is not an event is underlined in the editor, then reported when it loads, with the closest event name when there is one. The exact contents of each are in the Reference.
What was deleted
For something that no longer exists, the event gives it to you as it was:roleDelete gives the role, channelDelete the channel, guildLeave the server. The bot remembered them all, so they are there. memberLeave gives the account of who left, user: a server can have more members than the bot remembers, so the member they were may be long forgotten, but the account is always there.
src/events/bye.ts
Points of attention
- Everything your function receives is read-only. Assigning to it throws; it is shared by every reaction to the event.
- What must exist is there.
member.guild,channel.guild,guild.me: no?.. What may really be missing is nullable, likeguild.memberCount, which Discord does not always send. - In dev, only your test server.
chapterjs devignores what happens in other servers and in private messages. That is why you can run the dev bot and the production bot with one token without them answering twice;chapterjs starthears everything. - A failing file is reported with the file and the line, and nothing else stops:
Recap
event({ name, run })is one reaction to the eventname; declare as many as you like, and all run.- What
runreceives followsname, with no type to write. - Intents are computed from the events you declare; a privileged one is a switch in the Developer Portal, and the terminal waits for you.
readyruns once per start; deleted things come as they were.
Messages as events
React to what people write, where, and from whom.
Guide: Events
The same, in short.