Useful packages
Day.js
TIP
Official documentation: https://day.js.org/open in new window
Day.js is a powerful package that parses, validates, manipulates, and displays dates and times in JavaScript. It allows you to quickly and easily format dates in any way you want or parse strings back into JavaScript Date objects. There are many plugins for it that allow you to work with durations and more.
For example if you wanted to ask your users to give you a date,
you can use Day.js to turn it into a Date object you can use in your code:
const input = await interaction.channel.awaitMessages({
filter: m => m.author.id === interaction.user.id,
max: 1,
time: 10e3,
errors: ['time'],
});
const date = dayjs(input.first().content).toDate();
2
3
4
5
6
7
Using the duration pluginopen in new window, you could tell the user if the date is in the future or the past:
if (date.isValid()) {
const now = dayjs();
const duration = date - now;
const formatted = dayjs.duration(duration, 'ms').format();
if (duration > 0) {
interaction.reply(`The date you gave me is ${formatted} into the future.`);
} else {
interaction.reply(`The date you gave me is ${formatted} into the past.`);
}
} else {
interaction.reply('You didn\'t give me a valid date.');
}
2
3
4
5
6
7
8
9
10
11
12
13
ms
TIP
Official documentation: https://github.com/vercel/msopen in new window
Ms is another tool for working with times in JavaScript. However, ms specializes on durations. It allows you to convert times in milliseconds into human-readable formats and vice versa.
Example:
await interaction.reply('Send two messages and I\'ll tell you how far apart you sent them.');
const messages = await interaction.channel.awaitMessages({
filter: m => m.author.id === interaction.user.id,
max: 2,
time: 30e3,
errors: ['time'],
});
const difference = messages.last().createdTimestamp - messages.first().createdTimestamp;
const formatted = ms(difference);
await interaction.followUp(`You sent the two messages ${formatted} apart.`);
2
3
4
5
6
7
8
9
10
11
12
common-tags
TIP
Official documentation: https://github.com/zspecza/common-tagsopen in new window
Common-tags is a library all about working with template literals.
So far, you have probably only used them for interpolating variables into your strings, but they can do a whole lot more. If you got time, you should check out the MDN's documentation about tagged literals.open in new window.
Ever got annoyed your multi-line strings had nasty bits of indentation in them, but you did not want to remove the indentation in your source code?
common-tags got you covered:
const packageName = 'common-tags';
if (someCondition) {
const poem = stripIndents`
I like ${packageName}.
It makes my strings so pretty,
you should use it too.
`;
console.log(poem);
}
2
3
4
5
6
7
8
9
10
11
This will print your little poem like expected, but it will not have any tabs or other whitespace on the left.
But this is just the start! Another set of useful functions are the list-related functions: inlineLists
, commaLists
, etc.
With those, you can easily interpolate arrays into your strings without them looking ugly:
const options = ['add', 'delete', 'edit'];
// -> Do you want me to add, delete or edit the channel?
interaction.reply(oneLineCommaListsOr`
Do you want me to ${options} the channel?
`);
2
3
4
5
6
Check the the documentation to find more useful functions.
chalk
TIP
Official documentation: https://www.npmjs.com/package/chalkopen in new window
Chalk is not exactly useful for Discord bots themselves, but it will make your terminal output a lot prettier and organized. This package lets you color and style your console.log
s in many different ways; No more simple white on black.
Let's say you want your error messages to be easily visible; Let us give them a nice red color:
console.error(chalk.redBright('FATAL ERROR'), 'Something really bad happened!');
You can also chain multiple different multipliers.
If you wanted to have green text, a grey background, and have it all underlined, that is possible:
console.log(chalk.green.bgBrightBlack.underline('This is so pretty.'));
winston
TIP
Official documentation: https://github.com/winstonjs/winstonopen in new window
Winston is "a logger for just about everything". You can log to the terminal, you can log to a file, etc.
"But wait," I hear you cry, "what's wrong with console.log
?".
Well, the answer is simple: console.log
is slow and not quite versatile. Whenever you call console.log
, your program halts; it cannot do anything until console.log
finishes, which does not sound good. Well, that is precisely what winston is for.
Winston is fast and highly configurable. It has different log levels for all your needs; it can log to files, the terminal, etc. Like moment.js, it also has extension packages. So if there is something you feel is missing, you can probably find one that fits your needs.
Now, there are a lot of options, so it is recommended you take a look at the docs yourself. But let us get a quick overview of what it can do:
const client = new Client({ intents: [Intents.FLAGS.GUILDS] });
const logger = winston.createLogger({
transports: [
new winston.transports.Console(),
new winston.transports.File({ filename: 'log' }),
],
format: winston.format.printf(log => `[${log.level.toUpperCase()}] - ${log.message}`),
});
client.on('ready', () => logger.log('info', 'The bot is online!'));
client.on('debug', m => logger.log('debug', m));
client.on('warn', m => logger.log('warn', m));
client.on('error', m => logger.log('error', m));
process.on('uncaughtException', error => logger.log('error', error));
client.login('your-token-goes-here');
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
The above code creates a simple logger that will log to both the console and a file called "log" (defined by the transports
options).
The format
option tells the logger which format to use for the messages; by default, it outputs JSON objects. While useful, JSON is not very readable, so we define a custom format that displays the log level in all caps alongside the message. If you wanted to, you could also use the chalk module to make the logger's format a bit prettier by applying colors, etc.
Winston is not the only logging library out there, though, so if you are not convinced, you should google around a bit and you should find something you will like.
i18next
TIP
Official documentation: https://www.i18next.comopen in new window
i18next is an internationalization-framework for JavaScript. It is beneficial to translate your bot's user-facing messages into various languages based on the server it is used in.
Covering an entire use case example for internationalization would be out of this guide's scope and requires some more explanation as to how the system operates. Please refer to the official documentation linked above for an in-depth usage guide.