Skip to main content

Writing your first bot

Creating project

You can create a simple project using the built-in dart command dart create:

$ dart create -t console-simple your-project-name && cd ./your-project-name

Replace your-project-name with your desired name.

This command will create few files that are needed to start a project. There will be a pubspec.yaml with basic project info and dependency declaration. There will also be a file created with name of your project in bin directory. This is the main file that you would have to run to start the bot.

To add nyxx to your project, run dart pub add nyxx. Your pubspec.yaml file should then look similar to this:

./pubspec.yaml
name: test
description: A simple command-line application.
version: 1.0.0
# homepage: https://www.example.com

environment:
sdk: ">=2.14.2 <3.0.0"

dependencies:
nyxx: ^6.0.0

dev_dependencies:
lints: ^1.0.0

Now, execute the dart pub get command in the project's root directory to fetch all the required dependencies:

$ dart pub get
Resolving dependencies...
+ async 2.8.2
+ charcode 1.3.1
+ collection 1.15.0
+ http 1.0.0
+ http_parser 4.0.0
+ logging 1.0.2
+ meta 1.7.0
+ nyxx 6.0.0
+ path 1.8.0
+ pedantic 1.11.1
+ source_span 1.8.1
+ string_scanner 1.1.0
+ term_glyph 1.2.0
+ typed_data 1.3.0
Changed 14 dependencies!

Creating a bot account

For the next part of this tutorial, you'll need a token for your bot. See Creating a Bot Account for details on how to do this.

First code

With everything set up, we can now start coding our bot, but let's start with something easy. This is simple bot which replies to messages mentioning the bot.

Here's the code for this, which we'll explain line by line:

bin/your_project_name.dart
import 'package:nyxx/nyxx.dart';

void main() async {
final client = await Nyxx.connectGateway(
'TOKEN', // Replace this with your bot's token
GatewayIntents.allUnprivileged,
options: GatewayClientOptions(plugins: [logging, cliIntegration]),
);

final botUser = await client.users.fetchCurrentUser();

client.onMessageCreate.listen((event) async {
if (event.mentions.contains(botUser)) {
await event.message.channel.sendMessage(MessageBuilder(
content: 'Hi There!',
replyId: event.message.id,
));
}
});
}

First, we need to create a client that can connect to Discord's API. To do that, we use the Nyxx.connectGateway method:

final client = await Nyxx.connectGateway(
'TOKEN', // Replace this with your bot's token
GatewayIntents.allUnprivileged,
options: GatewayClientOptions(plugins: [logging, cliIntegration]),
);

The connectGateway method creates a client that can execute actions using the API and receive events from Discord whenever something happens - such as a user sending a message. There are other ways to use the API, but we won't look at those now.

The first parameter is the token that the bot will use to communicate with the API. This is the token that was generated when you created your bot account. Because you shouldn't ever publish your token, we recommend using an environment variable instead of hard-coding the token value.

The second parameter are the intents your client wants to use. Intents are a way of selecting which events you want Discord's API to send you - which can lighten the load on your bot when it gets large. Since this bot isn't going to be handling thousands of users, we can just specify that we want to receive all the unprivileged events.

info

Notice that we use GatewayIntents.allUnprivileged instead of GatewayIntents.all. This is because some intents require authorization from Discord to use as they provide access to potentially sensitive information.

See here to enable and use these.

The last parameter are the options we are using to configure our client. Client options allow you to configure nyxx itself. For now, we just specify that we want to add the logging and cliIntegration plugins to our client.

Next, in order to know whether the bot was mentioned, we need to know who the bot's user is. That's what users.fetchCurrentUser() allows us to do:

final botUser = await client.users.fetchCurrentUser();

The client exposes Managers for running operations on the API. In this case, we use the users manager to fetch the current user (which will be the bot's user). There are other managers for other types of entities: channels, guilds, commands...

Finally, we want to run code every time the bot receives a message to check if it was mentioned. For that, we listen to the onMessageCreate stream:

client.onMessageCreate.listen((event) async {
if (event.mentions.contains(botUser)) {
await event.message.channel.sendMessage(MessageBuilder(
content: 'Hi There!',
replyId: event.message.id,
));
}
});

An event will be added to the onMessageCreate stream whenever a message that the bot can see is created. The MessageCreateEvent event will contain the created Message as well as some extra fields, like mentions.

In our case, we first check if the users mentioned in the event include our user:

if (event.mentions.contains(botUser)) {
...
}

If it does, then we want to send a message to the same channel the message was sent in:

await event.message.channel.sendMessage(MessageBuilder(
content: 'Hi There!',
replyId: event.message.id,
));

The sendMessage method takes a MessageBuilder that describes the message that will be sent. In this case, we specify the content of our message and a replyId.

The replyId parameter allows us to reply to a message (here, the message that mentioned the bot) by giving its ID. Most entities - messages included - have an ID on Discord, which we access with message.id.