A basic and probably over engineered approach to creating a discord bot in haxe. This project depends on aidan's ecs but is easy to swap out should you want to. I also bundle the discord externs, they were created with dts2hx and I made some very basic modifications to types here and there. If you want to upgrade the discord externs follow the process outlined in the dts2hx repo linked below.
The new update to this library moves the framework completely to the new discord commands API. Take note of the changed code base and command instantiation. DOCS ARE UPDATED TO INCLUDE NEW WORKFLOW
THINGS MAY CHANGE
Will be experimenting with some stuff but this is just to get a preliminary release of the new API done and dusted.
Requires:
Optional:
Example Project:
- clone the repo
- cd into the repo and then run the following:
haxelib install hxnodejs
haxelib git aidan-ecs https://github.com/Aidan63/ecs
Note: hxnodejs
is not mandatory, it is just used to access sys stuff. For this example it is required but easily removed should you not need it
- cd into the
bin
directory and then run:
npm install
- Create a file in the
bin
directory calledconfig.json
and put the following in it:
{
"project_name": "Hi Bot",
"discord_token": "TOKEN_HERE",
"client_id": "CLIENT ID",
"server_id": "DEVELOPER SERVER ID",
"commands": []
}
Note: You can use this file to store other config settings by modifying the typedef found in the Main.hx
file
- Get your
API token
and read here for further bot setup instructions - Add the bot to a server
- Compile!
- Run the bot using:
node main.js
or hit the debug button in vscode - In your discord server send the command
/hi
or/boop
and the bot should reply :)
Usage is simple, a system represents a command and most of the initial parsing work is done in CommandBase
all you need to do is just implement your commands.
First go to src/components/Command.hx
and you should see an enum called CommandOptions
. This is what handles the typing for the discord parameters and filtering the commands, simply add an enum to the list based on the config spec.
enum CommandOptions {
Hi; //A basic command, has no parameters
Boop(user:User); //Expects the user to pass a discord user object as a parameter
Test(category:Float, data:String); //Takes 2 parameters from the user, a number and a string
}
With the new system to make the bot making experience more focused on developing the bot, I have opted to trial setting up the command spec via the config.json
file. This lets me automate the majority of the command setup process for the bot maker and keep code tidy. If you happen to forget the structure to define, you can find the definition of the json structure in Main.hx
named TCommands
.
Complete config.json
example:
{
"project_name": "Hi Bot",
"discord_token": "TOKEN_HERE",
"client_id": "CLIENT ID",
"server_id": "DEVELOPER SERVER ID"
"commands": [
{
"name": "hi",
"description": "Say hi to the bot"
},
{
"name": "boop",
"description": "boops a user",
"params": [
{
"name": "user",
"type": "user",
"description": "The user to boop",
"required": true
}
]
},
{
"name": "test",
"description": "tests user input",
"params": [
{
"name": "type",
"type": "number",
"description": "Category of test",
"required": true
},
{
"name": "topic",
"type": "string",
"description": "additional condition",
"required": false
}
]
}
]
}
This sets up 3 commands and should be fairly self explanatory with the enum definitions above.
name
: The parent objectname
is what comes directly after the slash./hi
,/boop
, or/test
description
: This will show a brief description in the command list within discord about the commandparams
: It has the same structure, except nowname
anddescription
describe the parameter definition
Then head to the Main.hx
and you should see a line that says:
universe.setSystems(Hi);
To add more commands, simply append it to the universe. When adding the component to the file, directly import it and make sure to not use wildcard imports.
universe.setSystems(Hi, Help, Test); //All these commands extend CommandBase
package systems.commands;
import components.Command;
class Hi extends CommandBase {
function run(command:Command, interaction:BaseCommandInteraction) {
message.reply("Hey there");
}
function get_name():String {
return 'hi';
}
}
package systems.commands;
import discord_builder.BaseCommandInteraction;
import components.Command;
class Boop extends CommandBase {
function run(command:Command, interaction:BaseCommandInteraction) {
switch (command.content) {
case Boop(user):
interaction.reply('BOOP <@${user.id}>');
default:
}
}
function get_name():String {
return 'boop';
}
}
get_name()
Is where you define your command name, this is what your users will type in discord to trigger the command - it is required.
function run(command:Command, interaction:BaseCommandInteraction)
Is what will be called when a message that matches the commands has been sent, treat this as the init point of the command.
Click Message
to see the official API, documentation and usage.
Command
is just an object with 2 fields:
name
: The command name (/hi
)content
: Content encapsulates any parameters parsed to the bot, it will be organised into an enum constructor
{
name: "hi",
content: Hi //represented by a haxe enum
}
If you need to add some code to the update loop, just override it but remember to call super
otherwise the base logic wont run
override function update(_) {
// code checks here
super.update(_);
// ... or here
}