Prerequisites and installation
Yuuko will use whatever version of Eris you install alongside it. This allows you to use pretty much whatever version of Eris you want, though sticking with the latest release or an actively-developed dev build is recommended. You can install yuuko
and eris
together with one command:
npm install yuuko eris
The bare minimum
This code will get you a basic call-response bot up and running. Fill in your token, set it running, and send “!ping” in a channel you share with it. It’ll respond “Pong!” as any good bot should.
const {Client, Command} = require('yuuko');
const mybot = new Client({
token: 'feed_me_credentials',
prefix: '!',
});
const pingCommand = new Command('ping', message => {
message.channel.createMessage('Pong!');
});
mybot.addCommand(pingCommand).connect();
import {Client, Command} from 'yuuko';
const mybot = new Client({
token: 'feed_me_credentials',
prefix: '!',
});
const pingCommand = new Command('ping', message => {
message.channel.createMessage('Pong!');
});
mybot.addCommand(pingCommand).connect();
Splitting off your commands
When you have lots of commands, it becomes impractical to store them all in one file. Luckily, Yuuko makes it easy to work with commands stored in other files. Here’s an example:
// index.js
const {Client} = require('yuuko');
const mybot = new Client({
token: 'feed_me_credentials',
prefix: '!',
});
mybot
.addDir(path.join(__dirname, 'commands'))
.connect();
// commands/ping.js
const {Command} = require('yuuko');
module.exports = new Command('ping', message => {
message.channel.createMessage('Pong!');
});
// index.js
import {Client} from 'yuuko';
const mybot = new Client({
token: 'feed_me_credentials',
prefix: '!',
});
mybot
.addDir(path.join(__dirname, 'commands'))
.connect();
// commands/ping.js
import {Command} from 'yuuko';
export default new Command('ping', message => {
message.channel.createMessage('Pong!');
});
Command arguments
The function run when a command is executed takes a second parameter which contains an array of space-separated arguments to the command. You can use it like so:
const addCommand = new Command('add', (message, args) => {
// Convert the arguments to numbers
args = args.map(number => parseInt(number, 10));
// Add them all up!
let sum = 0;
for (const number of args) {
sum += number;
}
msg.channel.createMessage(`The sum is ${sum}!`);
});
const addCommand = new Command('add', (message, args) => {
// Convert the arguments to numbers
args = args.map(number => parseInt(number, 10));
// Add them all up!
let sum = 0;
for (const number of args) {
sum += number;
}
msg.channel.createMessage(`The sum is ${sum}!`);
});
The context argument
Additionally, commands take a third parameter, a context object. By default, this object contains the name of the command being called and a reference to the client object, but you can add custom properties to it through Client#extendContext()
to easily share objects (database connections, etc.) among all your files.
// index.js
const {Client} = require('yuuko');
const mybot = new Client({...});
mybot.extendContext({
myCustomThing: 'This is neat!',
});
mybot.addDir(path.join(__dirname, 'commands')).run();
// commands/test.js
const {Command} = require('yuuko');
module.exports = new Command('test', (message, args, context) => {
context.client // The same as mybot in the first file
context.commandName // The name or alias used to call the command
context.myCustomThing // The string 'This is neat!' that was set above
});
// index.ts
import {Client} from 'yuuko';
const mybot = new Client({...});
mybot.extendContext({
myCustomThing: 'This is neat!',
});
mybot.addDir(path.join(__dirname, 'commands')).run();
// commands/test.ts
import {Command} from 'yuuko';
export default new Command('test', (message, args, context) => {
context.client // The same as mybot in the first file
context.commandName // The name or alias used to call the command
context.myCustomThing // The string 'This is neat!' that was set above
});
Subcommands
Subcommands allow you to create structure and heirarchy in your commands, grouping related features together under a parent command in an intuitive way. Subcommands inherit the requirements of the parent command, but can also include their own requirements. The context object’s commandName
property will also include parent command names, so you can know exactly how the command was called.
// commands/test.js
const {Command} = require('yuuko');
module.exports = new Command('foo', (message, args, context) => {
message.channel.createMessage('Foo!');
context.commandName // The string 'foo'
}, {
guildOnly: true,
})
.addSubcommand(new Command('bar', (message, args, context => {
message.channel.createMessage('Bar!');
context.commandName
}, {
owner: true,
})));
// commands/test.js
import {Command} from 'yuuko';
export default new Command('test', (message, args, context) => {
message.channel.createMessage('Test!');
context.commandName // The string 'foo'
}, {
guildOnly: true,
})
.addSubcommand(new Command('something', (message, args, context) => {
message.channel.createMessage('Secret command!');
context.commandName
}, {
owner: true,
}));
With the command shown in this example, users of your bot can use the .test
command as long as they’re in a server, and only you can use the .test something
command in server. Nesting subcommands is supported, and commands will receive arguments starting with the first word of the message that doesn’t name a subcommand.
Custom prefixes
You can set a function that’s used to set a custom prefix on a per-message basis. This can be used to set per-guild prefixes. This function also receives a context object (minus the prefix
and commandName
properties) as its second argument.
mybot.prefixes(message => {
// If we're not in a guild, just use the default
if (!message.channel.guild) return;
// In guilds, allow two prefixes, "!" and "!!"
return ['! ', '!!'];
});
mybot.prefixes(message => {
// If we're not in a guild, just use the default
if (!message.channel instanceof Eris.GuildChannel) return;
// In guilds, allow two prefixes, "!" and "!!"
return ['! ', '!!'];
});
Listening on events
Yuuko also includes an EventListener
class, which you can use to split up your event logic with a similar interface to commands. The handler you provide will receive a Yuuko context object, including all your additions (but without the prefix
and commandName
entries used with commands).
const {EventListener} = require('yuuko');
module.exports = new EventListener('messageCreate', (message, context) => {
// Reference properties of the client directly while handling an event
console.log(message.author.id === context.client.user.id);
});
import {EventListener} from 'yuuko';
export default new EventListener('messageCreate', (message, context) => {
// Reference properties of the client directly while handling an event
console.log(message.author.id === context.client.user.id);
});
These listeners can be loaded similarly to commands - they’ll be picked up by the addFile
and addDir
methods automatically, and you can also use addEvent
the same way as addCommand
if you need to load an instance directly.
Everything Eris
Yuuko’s client class extends Eris’s, so you can use all the client methods directly.
mybot.once('ready', () => {
console.log('Ready! Logged in as', mybot.user.username);
})
mybot.once('ready', () => {
console.log('Ready! Logged in as', mybot.user.username);
})
More information
For more info about the methods you can use with Yuuko, check out the full API documentation.