Bot releases are visible (Hide)
mongoose
library. Thanks to @Zerefdev.Command#condition
. Thanks to @Papaia.Argument.union
and Argument.product
not binding this
. Thanks to @perilstar.separate
match not returning short circuit flags. Thanks to @Norviah.CommandHandler#cooldowns
. Thanks to @Papaia.Constants
. Thanks to @Papaia.Published by 1Computer1 over 4 years ago
Akairo has been updated to Node 10 and Discord.js v12, now taking advantage of async/await!
Many breaking changes come in this version in order to make the framework better and more consistent.
For help with updating from v7 to v8, see the guide here.
Also, join the official Akairo Discord server and ask questions!
Before, the client and the handlers were intertwined and this made it hard for customization.
With this rework, it is easier to do things like your own command handler and such.
Your custom client class will now look something like this:
class CoolClient extends Client {
constructor() {
super({ <options> });
this.commandHandler = new CommandHandler(this, { <options> });
// etc.
}
start() {
this.commandHandler.loadAll();
// etc.
}
}
The command locks system allow you to lock down a command while it is in use.
For example, a command can only be used one at a time in a guild, in a channel, by a user, or by your own metric.
class SpecialCommand extends Command {
constructor() {
super('special', {
<options>
lock: 'channel'
// or perhaps, returning a string:
// lock: msg => something(msg.author)
});
}
// etc.
}
A large rework into how commands and arguments are parsed and processed have been done.
The main thing is that arguments are now processed via generators, which will allow you to put JavaScript into your argument handling:
class NumbersCommand extends Command {
constructor() {
super('numbers', { <options> });
}
*args() {
const x = yield { type: 'integer', default: 0 };
const y = yield { type: x > 10 ? 'integer' : 'string' };
console.log('debug', x, y);
return { x, y };
}
}
This method supports async and also allows you to implement your own parsing if you wish, with the hard part taken care of:
async *args(message, parsed, state) {
await message.util.send('Hold on I\'m working on it...');
console.log(parsed.phrases);
// ['a', 'bunch', 'of', 'input']
}
The old method still works if you do not use arguments that depend on previous arguments, so you can still have args: [{ <options> }, <more args>]
.
If you do, note that the ability to access previous arguments has been removed, e.g. type: (phrase, message, args) => <code>
has been changed to type: (message, phrase) => <code>
.
A utility known as Flag
has been added, which allow you to signify special operations.
For example, to cancel a command during argument handling, use Flag.cancel
:
async *args(message) {
const x = yield { type: 'integer' };
if (x == null) {
await message.util.send('No integer found!');
return Flag.cancel();
}
const y = yield { type: x > 10 ? 'integer' : 'string' };
return { x, y };
}
To express failure inside argument parsing, normally you would return null
.
However, sometimes more data needs to be given, e.g. why the failure happened or what caused the failure.
Here, the new Flag.fail
can be used:
type: (msg, phrase) => {
const toMembers = this.handler.resolver.type('members');
const members = toMembers(phrase);
if (members.size !== 1) {
return Flag.fail(member.size);
}
return members;
}
You can also use it when choosing a default, e.g. default: (message, { failure }) => <code>
.
To cancel the command early in argument parsing, you can use Flag.cancel
as in above, but you can also do it a bit more automatically with the otherwise
option.
It will send some message when the argument fails parsing.
Combine it with Flag.fail
for some good user-facing error messages!
type: (msg, phrase) => {
const toMembers = this.handler.resolver.type('members');
const members = toMembers(phrase);
if (members.size !== 1) {
return Flag.fail(member.size);
}
return members;
},
otherwise: (msg, { failure }) => `Bad input, that gave me ${failure.value} members instead of one!`
// Or just `otherwise: 'Bad input!'` if you want.
To facilitate subcommands, there is also Flag.continue
.
Using it, you can run another command with the rest of the phrases that are not yet parsed.
*args() {
const sub = yield {
type: ['cmd1', 'cmd2', 'cmd3'],
default: 'cmd1'
};
// Will run the command with ID `cmd1`, `cmd2`, or `cmd3`.
return Flag.continue(sub);
}
So now, if a user is to type !command cmd1 1 2 3
, the input 1 2 3
will be passed on to cmd1
to parse and run.
A new argument match type is unordered
which allows for more natural user input.
That is, the user can enter their arguments in any order as they want and Akairo will pick up the right ones!
args: [
{
id: 'member',
type: 'member',
match: 'unordered'
},
{
id: 'number',
type: 'number',
match: 'unordered'
}
]
Now, !command person 5
works as expected, but also !command 5 person
.
Of course, if there is ambiguity, the thing that comes first gets priority (e.g. someone might be named 5
).
So that you do not have to use type functions as much, there are new static Argument
functions to help you out!
// Either a user or an integer or a string .
type: Argument.union('user', 'integer', 'string')
// Everything at once, will give back [integer, number, string].
type: Argument.product('integer', 'number', 'string')
// Check that some property of the parsed value is correct.
type: Argument.validate('string', (msg, value) => value.length === 100)
// Shortcut for number ranges:
type: Argument.range('integer', 1, 100)
// Attach the input with the result or failure using `Flag.fail`.
type: Argument.withInput('integer')
For prompts, some extra data has been added so that you can customize your prompts to your heart's content.
In conjuction with Flag.fail
, it is very powerful!
const members = yield {
type: (msg, phrase) => {
const toMembers = this.handler.resolver.type('members');
const members = toMembers(phrase);
if (members.size !== 1) {
return Flag.fail(member.size);
}
return members;
},
prompt: {
start: 'Please give me a member!',
retry: (msg, { failure }) => `Please refine your search, ${failure.data} members were found.`
}
};
The second parameter also contains information like how many retries there has been, the message that caused the prompt, etc.
Other important features include:
CommandUtil
parse properties.separate
for handling phrases one by one.There are even more features and also a lot of breaking changes.
Read the full changelog below for more.
AkairoClient#isOwner
for owner check.extensions
option for AkairoHandler to load only files with those extensions.loadFilter
option for AkairoHandler to filter files.directory
to AkairoHandler#loadAll
in order to load from a specified directory.filter
to AkairoHandler#loadAll
to filter files to load.ClientUtil#attachment
.(client, options)
.(id, options)
.Argument#default
Command#regex
(previously Command#trigger
)CommandHandler#prefix
CommandHandler#allowMention
AkairoClient#load
event to pass an isReload
param.ClientUtil#fetchMemberFrom
to ClientUtil#fetchMember
.module.exports = new Command(...)
, for example, will no longer be loaded.AkairoHandler#load
no longer takes a module instance.AkairoModule#exec
, should be implemented as needed in child classes now.AkairoHandler#add
method.AkairoHandler#add
and AkairoHandler#reload
events.AkairoHandler#enable
and AkairoHandler#disable
events.AkairoModule#enabled
property.Command#protected
property.AkairoModule#enable
and AkairoModule#disable
methods.Category#enableAll
and Category#disableAll
methods.ClientUtil#prompt
and ClientUtil#promptIn
.ignoreCooldownID
for user(s) to ignore cooldown, defaults to the owner(s).aliasReplacement
to automatically make command aliases.handleDirectCommand
to use post inhibitors then run a command on a message.handleRegexCommands
, and handleConditionalCommands
to trigger those commands manually on a message.runCommand
to run a command with specified arguments.runAllTypeInhibitors
, runPreTypeInhibitors
, runPostTypeInhibitors
, and runCooldowns
parseCommand
and parseCommandWithOverwrittenPrefixes
.Command#before
that runs before argument parsing.CommandUtil#handler
.CommandUtil#sendNew
to force a new message to be sent.CommandUtil#setEditable
for setting the shouldEdit
property.CommandUtil#parsed
which contains various parsed components of the message.CommandUtil#messages
and the command handler option storeMessages
for storing prompt and prompt replies.CommandHandler#missingPermissions
event for permissions checks.CommandHandler#commandCancelled
event for when commands are cancelled.CommandHandler#ignorePermissions
and added CommandHandler#ignoreCooldown
as functions.defaultPrompt
to argumentDefaults
, to allow for more default options.
defaultPrompt
is just now argumentDefaults.prompt
, for example.otherwise
and modifyOtherwise
.Command#parse
from (content, message)
to (message, content)
to be consistent.(message, args)
where args has properties match
and matches
.(message, args)
where args is an empty object.commandUtil
option to be explicitly set.(handler, message)
.parsed
object property.CommandHandler#prefixes
.CommandHandler#prompts
.(channel, user)
.missing
parameter in the event below.commandStarted
now passes (message, command, args)
.commandFinished
now passes (message, command, args, returnValue)
.commandBlocked
will no longer be emitted permission checks, instead:missingPermissions
will now be emitted for permissions checks, passing (message, command, type, missing)
.commandUtilLifetime
to 5 minutes.CommandHandler#ignoreCooldownID
to CommandHandler#ignoreCooldown
.CommandHandler#onCooldown
to CommandHandler#cooldown
.Command#channelRestriction
to Command#channel
.Command#trigger
to Command#regex
.args
property.edited
parameters in command-related functions and events.Command#split
.
quoted
option, either true or false.separator
option.Command#protected
.Command#options
.CommandUtil#client
.“”
.limit
which limits how many phrases to match.unordered
to allow for matching phrases throughout the command rather than by index.separate
which works like rest
but processes each phrase separately.
infinite
prompts by enabling infinite matching only when no input was provided.restContent
which works like rest
but also matches flags.multipleFlags
to allow for matching a flag
or an option
multiple times.otherwise
and modifyOtherwise
for a message when argument parsing fails.userMention
for mentions that refer to any user.guildMessage
for a message within any of the channels in the guild.relevantMessage
for a message within any of the channels in the guild or in DMs.breakout
, to allow a command to be used to break out of the prompt and run that command instead.modifyStart
, modifyRetry
, modifyTimeout
, modifyEnded
, and modifyCancel
.cast
(taking place of the renamed cast
to process
method) casts text and collect
prompts a user.Argument.cast
.Argument.union
to create a union type.Argument.product
to create a product type.Argument.validate
for a type with extra validation.Argument.range
for a type in a range, works with numbers, arrays, etc.Argument.compose
and Argument.composeWithFailure
to compose types.Argument.withInput
, Argument.tagged
, and Argument.taggedWithInput
for a type that attaches the original input and/or some arbitrary tag.Argument.taggedUnion
, for a union that is also tagged by each type.Argument.isFailure
to check for failure.Flag.cancel
to cancel a command.Flag.retry
to retry another command.Flag.fail
to specify a failed parse with extra data.Flag.continue
to continue the parsing and running with another command (for subcommands).default
for miscellaneous data, including the failed value.TypeResolver#inhibitorHandler
and TypeResolver#listenerHandler
.args
option on commands can now be a generator function.this
context of all functions in ArgumentOption to the Argument instance.this
context of types added using TypeResolver to the Argument instance.Promise<null>
or Promise<undefined>
.true
causing the phrase to be used to now literally use true
.default
option from empty string to null
.retries
, for amount of retries.infinite
, whether or not the prompt is infinite.message
, the message that caused the prompt.phrase
, the phrase that caused the prompt if there was one.failure
, the failed value that caused the prompt if there was one (used in conjuction with new Flag.fail
).invite
type to fetch an invite instead of matching an invite.message
parameter to the front and removed previous args parameter.
type
is now (message, phrase)
instead of (phrase, message, args)
index
option is set.Argument#prefix
to Argument#flag
.Argument#cast
to Argument#process
.TypeResolver#handler
to TypeResolver#commandHandler
.groups
to matches
in context of regex commands and regex types.word
to phrase
in context of argument matching and parsing.prefix
to option
in terms of the match type.prefix
to flag
in terms of the preceeding string.match
option being a function.dynamic
and dynamicInt
types.
Argument.union
instead.Inhibitor#priority
option for when more than one inhibitor blocks a message.Promise<true>
.notSelf
to others
.ListenerHandler#setEmitters
for adding new emitters.Listener#eventName
to Listener#event
.emitters
options from ListenerHandler.emitter
and event
options of listener options.Published by 1Computer1 over 5 years ago
This update fixes the NPM release.
Published by 1Computer1 over 5 years ago
compose
and composeWithFailure
.Published by 1Computer1 over 5 years ago
Argument.tagged
and Argument.taggedWithInput
.Argument.taggedUnion
.Argument.composeWithFailure
, splits off the last option of Argument.compose
.otherwise
and modifyOtherwise
to allow an empty string, which will do nothing, like propmts.Argument.compose
(and therefore Argument.composeWithFailure
) to work with variable arguments.Argument.range
to work on things with a length
or size
property.Argument.tuple
to Argument.product
.argumentDefaults
.otherwise
being used when an argument doesn't have it specified.Published by 1Computer1 over 5 years ago
This release is last known to work with discord.js commit 04fa56d
.
modifyOtherwise
.defaultPrompt
with argumentDefaults
which include prompt
, otherwise
, and modifyOtherwise
.this
context of *args
functions.Published by 1Computer1 over 5 years ago
This release has no code changes, only documentation changes.
Published by 1Computer1 over 5 years ago
This release has no code changes, only documentation changes.
Published by 1Computer1 over 5 years ago
This release is last known to work with discord.js commit 9b2bf03
.
restContent
match which works like rest
but also matches flags.Flag.continue
to also take the rest of the flags (i.e. it works like restContent
instead of rest
now).
rest
behavior, you can match rest
yourself.text
and content
match behaviors being switched around.content
and rest
match not keeping whitespace and quotes.Published by 1Computer1 over 5 years ago
This release is last known to work with discord.js commit 9b2bf03
.
The focus of this release is a complete rewrite of how arguments are handled internally, which lends itself to some awesome new features!
Of course, there are breaking changes from 8.0.0-beta.1, but if you are reading this, you were prepared anyways.
Command#args
.Command#parser
.ArgumentOptions#description
and Argument#description
.message
parameters by moving them to the front of functions and removed previous arguments from ALL functions.
type
is now (message, phrase)
instead of (phrase, message, args)
.start
is now (message, data)
instead of (message, args, data)
.index
option is set.multipleFlags
to be affected by limit
and also work on flag
match by counting occurences.// Takes `(message, parsed, state)`.
// The latter two are internal data but can be useful.
async *args(message) {
// Get arguments as normal using `yield`.
const x = yield { type: 'integer', default: 0 };
// Use previous arguments by referring to the identifier.
// This replaces `Control.if` and `Control.case`.
const y = yield (x > 10 ? { type: 'integer' } : { type: 'string' });
// `Control.do` is replaced by just doing it:
console.log('debug', x, y);
// If you want to do what `Control.cancel` did, use `Flag.cancel`.
// Before, this would've been a combination of `Control.if`, `Control.do`, and `Control.cancel`. Ew!
if (x > 10 && !y) {
await message.util.send('`y` cannot be empty!');
return Flag.cancel();
}
// When done (equivalent to `Control.end`), return what you need:
return { x, y };
}
flags: ['--f'],
optionFlags: ['--o'],
*args() {
const f = yield {
match: 'flag',
flag: '--f'
};
const o = yield {
match: 'option',
flag: '--o'
};
return { f, o };
}
Flag.fail
for failing argument parsing with more data.
null
or undefined
but will give you extra data in its value
property.failure
property (along with phrase
) in the second parameter of default
functions.failure
in ArgumentPromptData.
type: (msg, phrase) => {
const toMembers = this.handler.resolver.type('members');
const members = toMembers(phrase);
if (members.size !== 1) {
return Flag.fail(member.size);
}
return members;
},
prompt: {
start: 'Please give me a member!',
retry: (msg, { failure }) => `Please refine your search, ${failure.value} members were found.`
}
Flag.continue
for subcommands-like behaviour.
*args() {
const sub = yield {
type: ['cmd1', 'cmd2', 'cmd3'],
default: 'cmd1'
};
return Flag.continue(sub);
}
otherwise
that sends some message when argument parsing fails.
default
.default
and prompts.type: 'integer',
otherwise: 'An integer was expected!'
// Also:
type: 'integer',
otherwise: (msg, { phrase }) => `An integer was expected! You gave ${phrase || 'nothing'}, which is not one.`
Argument.withInput
that attaches the original phrase along with the output.Argument.isFailure
that checks if something is a failure (null
, undefined
, fail flag).Published by 1Computer1 over 5 years ago
This is a beta release! It it last known to work with Discord.js commit fe5563
.
Akairo has been updated to Node 10 and Discord.js v12, now taking advantage of async/await!
Many breaking changes come in this version in order to make the framework better and more consistent.
Some of the main changes are:
For help with updating from v7 to v8, see the GitBooks guide here.
Also, join the official Akairo Discord server and ask questions!
(client, options)
.(id, options)
.Argument#default
Command#regex
(previously Command#trigger
)CommandHandler#prefix
CommandHandler#allowMention
Command#parse
from (content, message)
to (message, content)
to be consistent.(message, args)
where args has properties match
and matches
.(message, args)
where args is an empty object.commandUtil
option to be explicitly set.(handler, message)
.parsed
object property.CommandHandler#prefixes
.CommandHandler#prompts
.(channel, user)
.missing
parameter in the event below.commandStarted
now passes (message, command, args)
.commandFinished
now passes (message, command, args, returnValue)
.commandBlocked
will no longer be emitted permission checks, instead:missingPermissions
will now be emitted for permissions checks, passing (message, command, type, missing)
.Command#args
to store an ArgumentParser rather than Argument instances.this
context of all functions in ArgumentOption to the Argument instance.this
context of types added using TypeResolver to the Argument instance.Promise<null>
or Promise<undefined>
.true
causing the phrase to be used to now literally use true
.default
option from empty string to null
.retries
, for amount of retries.infinite
, whether or not the prompt is infinite.message
, the message that caused the prompt.phrase
, the phrase that caused the prompt if there was one.invite
type to fetch an invite instead of matching an invite.Promise<true>
.ClientUtil#fetchMemberFrom
to ClientUtil#fetchMember
.CommandHandler#ignoreCooldownID
to CommandHandler#ignoreCooldown
.CommandHandler#onCooldown
to CommandHandler#cooldown
.Command#channelRestriction
to Command#channel
.Command#trigger
to Command#regex
.Argument#prefix
to Argument#flag
.Argument#cast
to Argument#process
.TypeResolver#handler
to TypeResolver#commandHandler
.groups
to matches
in context of regex commands and regex types.word
to phrase
in context of argument matching and parsing.prefix
to option
in terms of the match type.prefix
to flag
in terms of the preceeding string.notSelf
to others
.Listener#eventName
to Listener#event
.module.exports = new Command(...)
, for example, will no longer be loaded.AkairoHandler#load
no longer takes a module instance.AkairoModule#exec
, should be implemented as needed in child classes now.AkairoHandler#add
method.AkairoHandler#add
and AkairoHandler#reload
events.AkairoHandler#enable
and AkairoHandler#disable
events.AkairoModule#enabled
property.Command#protected
property.AkairoModule#enable
and AkairoModule#disable
methods.Category#enableAll
and Category#disableAll
methods.ClientUtil#prompt
and ClientUtil#promptIn
.edited
parameters in command-related functions and events.Command#split
.
quoted
option, either true or false.separator
option.Command#protected
.Command#options
.CommandUtil#client
.match
option being a function.dynamic
and dynamicInt
types.
Argument.union
instead.emitters
options from ListenerHandler.emitter
and event
options of listener options.AkairoClient#isOwner
for owner check.extensions
option for AkairoHandler to load only files with those extensions.loadFilter
option for AkairoHandler to filter files.directory
to AkairoHandler#loadAll
in order to load from a specified directory.filter
to AkairoHandler#loadAll
to filter files to load.ClientUtil#attachment
.ignoreCooldownID
for user(s) to ignore cooldown, defaults to the owner(s).aliasReplacement
to automatically make command aliases.handleDirectCommand
to use post inhibitors then run a command on a message.handleRegexCommands
, and handleConditionalCommands
to trigger those commands manually on a message.runCommand
to run a command with specified arguments.runAllTypeInhibitors
, runPreTypeInhibitors
, runPostTypeInhibitors
, and runCooldowns
parseCommand
and parseCommandWithOverwrittenPrefixes
.Command#before
that runs before argument parsing.CommandUtil#handler
.CommandUtil#sendNew
to force a new message to be sent.CommandUtil#setEditable
for setting the shouldEdit
property.CommandUtil#parsed
which contains various parsed components of the message.CommandUtil#messages
and the command handler option storeMessages
for storing prompt and prompt replies.CommandHandler#missingPermissions
event for permissions checks.CommandHandler#commandCancelled
event for when commands are cancelled.CommandHandler#ignorePermissions
and added CommandHandler#ignoreCooldown
as functions.args
option of a command to a function.“”
.
limit
which limits how many phrases to match.unordered
to allow for matching phrases throughout the command rather than by index.separate
which works like rest
but processes each phrase separately.
infinite
prompts by enabling infinite matching only when no input was provided.userMention
for mentions that refer to any user.guildMessage
for a message within any of the channels in the guild.relevantMessage
for a message within any of the channels in the guild or in DMs.breakout
, to allow a command to be used to break out of the prompt and run that command instead.modifyStart
, modifyRetry
, modifyTimeout
, modifyEnded
, and modifyCancel
.cast
(taking place of the renamed cast
to process
method) casts text and collect
prompts a user.Argument.cast
.Argument.union
to create a union type.Argument.tuple
to create a tuple type.Argument.validate
for a type with extra validation.Argument.range
for a type in a range.Argument.compose
to compose types.Control.if
for branching.Control.case
for multiple branches.Control.do
for general actions.Control.end
for ending parsing.Control.cancel
for cancelling the command.TypeResolver#inhibitorHandler
and TypeResolver#listenerHandler
.Inhibitor#priority
option for when more than one inhibitor blocks a message.ListenerHandler#setEmitters
for adding new emitters.AkairoClient#load
event to pass an isReload
param.commandUtilLifetime
to 5 minutes.Published by 1Computer1 about 6 years ago
AkairoHandler
and AkairoClient
typings.Published by 1Computer1 over 6 years ago
new Command(...)
.fetchMembers
option not checking for webhooks.Published by 1Computer1 almost 7 years ago
Published by 1Computer1 almost 7 years ago
!
Published by 1Computer1 almost 7 years ago
index
not affecting text and content match.Published by 1Computer1 about 7 years ago
AkairoHandler#removeAll
, removes all modules.automateCategory
for automatic category names (#7).limit
, used to limit infinite prompts.ClientUtil#embed
, can return a MessageEmbed
.ClientUtil#resolvePermissionOverwrite
.AkairoClient#mem
, no built-in alternatives.SQLiteHandler
, AkairoClient#addDatabase
, and AkairoClient#databases
.SQLiteProvider
.RichEmbed#file
not being checked in CommandUtil#send
.color
type erroring.AkairoHandler#add
not checking .ts
extensions.Published by 1Computer1 over 7 years ago
MessageOptions#files
not being checked in CommandUtil#send
.Published by 1Computer1 over 7 years ago
ClientUtil#prompt
, ClientUtil#promptIn
, and argument prompts.Published by 1Computer1 over 7 years ago
The indev
branch has been deleted, instead master
will be now where all the development takes place.
The current NPM version will instead be on the stable
branch.
Documentation have also been moved to the gh-pages
branch.
The tutorials have been rewritten and moved to GitBooks.
Master documentation is now available here.
Added AkairoClient#loadAll
, meant for extending the client and adding new handlers.
Added TypeResolver#type
, meant for getting types in a cleaner way.
MessageOptions#content
is now allowed for CommandUtil
methods.
Exposed previous input for ongoing infinite prompt args.
Discord.js version ^11.1.0 is now required.
AkairoClient#build()
no longer calls loadAll()
on the handlers.
ClientUtil#promptIn
will now attempt to create a DM channel for users if there was not one.
Changed to has
from hasPermissions
for permission checks.
clientPermissions
and userPermissions
can now be a single permission string or number.Prefix overwrites now cannot be empty strings, this would cause problems before anyways.
Deprecated several ClientUtil
methods now available in Discord.js v11.1.
displayRole
, use GuildMember#colorRole
.displayColor
, use GuildMember#displayColor
.displayHexColor
, use GuildMember#displayHexColor
.hoistRole
, use GuildMember#hoistRole
.fetchMessage
, use TextBasedChannel#fetchMessage
.Deprecated CommandUtil#send
aliases.
CommandUtil#sendMessage
.CommandUtil#sendCode
.CommandUtil#sendEmbed
.Fixed removing commands deleting still-existing prefix overwrites.
Fixed ClientUtil
permissions-related methods for Discord.js 11.1.0.
Fixed missing color
type in docs.
Argument type color
no longer internally creates a RichEmbed each time.
Fixed TypeScript files and default exports not being loaded.
Minor performance improvements.