0.1.0 |
|
---|
#20 in #bots
32KB
663 lines
discord-base
The repo for the crate I use to build my bots on top of, made using Serenity in Rust!
How to set it up
- IDK myself yet..
- Go to the application page, select your bot and set the description. The
info
command will use that and the account that has that application - Then check usage right under here
How to use it
start(config_path: &str)
- Does everything to start up the bot
- Or creates the default config file if it's not there, then you should edit that file
- Use it as the first thing in your
#[tokio::main]
function
use discord_base::start;
start("config.toml").await;
log(ctx: &Context, msg: impl Display + AsRef<[u8]>)
- DMs the owner the message
- Reverts to
print_and_write
if it failed, also telling why it failed
use discord_base::log;
log(&ctx, "Heya owner! How are you?").await;
print_and_write(msg: impl Display)
- Prints and writes the message and the current time in UTC to the log_file set in the config
/*Assume the config file has this in it:
log_file = "logs.txt"
*/
use discord_base::print_and_write;
print_and_write("Magic text appearing in the text file");
/* The file logs.txt is now created and has these in it:
5 February Friday 10:38:20: Magic text appearing in the text file
*/
// Pretend five seconds passed
print_and_write("And even more text here");
/* The file now has these in it:
5 February Friday 10:38:20: Magic text appearing in the text file
5 February Friday 10:38:25: And even more text here
*/
send_embed(ctx: &Context, reply: &Message, is_error: bool, mut embed: CreateEmbed)
- Sends the embed to the channel reply is in, colours it with the colour you gave in your config file
- Unless
is_error
istrue
then it's the error colour (That's all that parameter does) - If it's failed to send though, tries to tell why in the server in plain text (without embeds)
- Or DMs the reply's sender if that also fails
use discord_base::send_embed;
let mut embed = CreateEmbed::default();
embed.title("This is my title");
send_embed(ctx, msg, true, embed).await;
What else it does
Error handling
Everything that's done in this crate follows these principals:
- If the action isn't expected by the user, don't inform them even if it fails
- If anything else, do inform them. Fall back to DMing the user if informing the user failed
- If it's a user error, tell them the error and how to fix it if it's not obvious
- If it's a bot error, tell them how to report it and what they can do and inform the owner of the bot. Fall back to printing and logging in a file
- If we can't be sure, tell them the error and how to report it if it looks like a bot error
These, combined with Rust's safety, ensure the best user experience. Most of these errors could be handled by falling back (Not using embeds, DMing the user etc.) but this overcomplicates the bot and makes it inconsistent, without forcing the user to fix it, so it's not a good practice
Optimisation
- I've tried my best to use statics and avoid
await
s - Also adding buckets and rate limit handling to ensure it isn't abused
- Combined with Rust's and SQLite's performance, the bot should be really lightweight
I can't say fast because we'll be bottlenecked by Discord anyway. It's still definitely fast enough that the user won't notice at all
Presence
- Sets the presence to
Playing a game: @[bot's username] help
(This looks much better than other presences Discord allows)
Commands
All these don't have a prefix so they're run with @bot [command]
. You set your own prefix for the groups you create
(I made it this way because usually only these commands collide with other bots so you can use convenient prefixes for your own commands)
Info command
- An
info
command that gets the desciption and owner from the application page and the GitHub page and invite link from the config file
Prefix command
- A
prefix
command that sets the prefix for the guild, which works for every command in addition to@bot
and the prefixes you set for your groups - This isn't as simple as it seems. It means the bot has to check if the message starts with its prefix in that server for every message that's sent
- To further optimise this, the bot first checks the message's first
max prefix length (10) + longest command's length
characters if it includes any of the commands, if not it doesn't unnecessarily check since there's no way the message includes a command
Help command
(Provided by Serenity's standard framework)
- A nice help command, listing all the other commands and their groups
- Gives more information about a command with
help [command]
- Suggests similar commands if
help [command]
is.. similar to another command
Who I am
Just some (currently) 17 years old girl from Turkey coding
Started with Python, gave a shot to JS but now that I know Rust exists never going back
Basically all I did was Discord bots (at least at the time of writing)
License and stuff I don't care, neither should you but contact me if you want to ask anything
How you can contact me
- Very Fast: Discord: aria#7553
- Slow: GitHub issues or something
- Way slower (or never, if you're unlucky): wentaas@gmail.com
Ideas I had but decided not to implement
Handling permissions
Too expensive, limited, bad for UX, unnecessary and inconsistent. Doing proper error checking and informing the user on an error is just a better option
Localisation
Makes everything more expensive, you now have to check the language for every message you're sending, which means you can't use any static string. Community translation will always be inconsistent, slow and incomplete. Most users wouldn't expect or use it. Having separate bots for each language is just a better option
Customisation
Again makes everything more expensive, since it means you can't use any static string. If someone is hosting the bot, they most likely have enough knowledge to search for a string in the source and replace it then build. It isn't necessary at all and I still tried to include customisation when it didn't mean a performance loss
Dependencies
~59MB
~1M SLoC