Adding command groups
Getting started
What if we wanted to prefix all commands with something? We can use a command group for that.
A CommandGroup is the same as a Command except it contains a list of commands and/or command groups. The group will only match if its matcher and any of the children inside of it also match. You should know how this works from the understanding gears guide.
Creating the command group
Let's make our command group and make it match on "!", like this:
const group = new CommandGroup()
.match(matchPrefixes("!"))
.setCommands(sumCommand, multiplyCommand)
And then, let's replace our bot's commands:
const bot = new Bot({ adapter, commands: [group] })
Now, run your bot again and try a command like !sum 8 8
and it should return 16
Using middleware in command groups
We can improve our code even more, by using middleware in the command group. Wouldn't it be nice if we could just return the message instead of logging it manually? Since middleware is async, we can await next()
to wait for the next middleware to be executed. When you do this, you also get the response returned from the promise.
So let's define some middleware that does exactly that:
const loggingMiddleware = async (context, next) => {
const response = await next()
console.log(`Result: ${response}`)
return response
// Always return the response,
// otherwise the response event on the bot
// will not be usable
}
Now let's change the rest of our code to reflect this:
const { matchPrefixes } = require("@enitoni/gears")
const {
Bot,
Adapter,
Command,
CommandGroup,
} = require("@enitoni/gears-readline")
const numberMiddleware = (context, next) => {
const { content, state } = context
const numbers = content.split(" ").map(n => Number(n))
if (numbers.some(n => isNaN(n))) {
console.log("Please specify a list of numbers separated by space.")
return
}
state.numbers = numbers
return next()
}
const loggingMiddleware = async (context, next) => {
const response = await next()
console.log(`Result: ${response}`)
return response
// Always return the response,
// otherwise the response event on the bot
// will not be usable
}
const sumCommand = new Command()
.match(matchPrefixes("sum "))
.use(numberMiddleware)
.use(context => {
const { numbers } = context.state
return numbers.reduce((a, b) => a + b)
})
const multiplyCommand = new Command()
.match(matchPrefixes("multiply "))
.use(numberMiddleware)
.use(context => {
const { numbers } = context.state
return numbers.reduce((a, b) => a * b)
})
const group = new CommandGroup()
.match(matchPrefixes("!"))
.use(loggingMiddleware)
.setCommands(sumCommand, multiplyCommand)
const adapter = new Adapter({})
const bot = new Bot({ adapter, commands: [group] })
bot.start().then(() => {
console.log("Hello world!")
})
Run your code and type !multiply 1 9 2 9
and you should get Result: 162
back in return.