Name | Modified | Size | Downloads / Week |
---|---|---|---|
Parent folder | |||
8.0.0 source code.tar.gz | 2020-03-03 | 74.4 kB | |
8.0.0 source code.zip | 2020-03-03 | 114.2 kB | |
README.md | 2020-03-03 | 21.4 kB | |
Totals: 3 Items | 210.1 kB | 0 |
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!
Summary
Structural Rework of Handlers
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:
:::js
class CoolClient extends Client {
constructor() {
super({ <options> });
this.commandHandler = new CommandHandler(this, { <options> });
// etc.
}
start() {
this.commandHandler.loadAll();
// etc.
}
}
Command Locks
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.
:::js
class SpecialCommand extends Command {
constructor() {
super('special', {
<options>
lock: 'channel'
// or perhaps, returning a string:
// lock: msg => something(msg.author)
});
}
// etc.
}
Generator Arguments
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:
:::js
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:
:::js
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>
.
Cancelling Arguments
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
:
:::js
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 };
}
Expressing Failure
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:
:::js
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>
.
Otherwise
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!
:::js
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.
Continuing Parsing
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.
:::js
*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.
Unordered Arguments
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!
:::js
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
).
Composing Types
So that you do not have to use type functions as much, there are new static Argument
functions to help you out!
:::js
// 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')
Better Prompts
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!
:::js
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.
And More!
Other important features include:
- Filtering files for handlers to load.
- Promise support in more places, e.g. prefixes and permissions.
- More information passed to events.
- More
CommandUtil
parse properties. - Better handling and choosing of prefixes.
- More built-in argument types.
- Argument match
separate
for handling phrases one by one. - Breaking out of prompts by using another command.
- Default text and text modifications for prompts.
- Consistency in callback parameter ordering.
- Consistency in callback return types.
There are even more features and also a lot of breaking changes.
Read the full changelog below for more.
Changelog
General
- Added many previously private/protected methods to the public interface.
- Added
AkairoClient#isOwner
for owner check. - Added an
extensions
option for AkairoHandler to load only files with those extensions. - Added a
loadFilter
option for AkairoHandler to filter files. - Added parameter
directory
toAkairoHandler#loadAll
in order to load from a specified directory. - Added parameter
filter
toAkairoHandler#loadAll
to filter files to load. - Added
ClientUtil#attachment
. - Added support for Promise values in more places.
- Permissions checks in commands.
- Argument default value function.
- Prefix and allow mention functions.
- Prompt content functions.
- Changed errors thrown by Akairo to instances of AkairoError (extends Error).
- Changed structure of AkairoClient.
- It no longer takes the options meant for other handlers.
- It no longer automatically create the handlers.
- You must now create and build the handlers manually, see the updating guide for an example.
- Changed all handlers' constructors to
(client, options)
. - Changed all modules' constructors to
(id, options)
. - Changed methods into properties (this means you may have to check if they are a function before using them):
Argument#default
Command#regex
(previouslyCommand#trigger
)CommandHandler#prefix
CommandHandler#allowMention
- Changed
AkairoClient#load
event to pass anisReload
param. - Changed type checks for Promise and EventEmitter, polyfilled items (e.g. Bluebird, EventEmitter 2/3/4) will now work.
- Renamed
ClientUtil#fetchMemberFrom
toClientUtil#fetchMember
. - Renamed typedefs in typings.
- Removed support for selfbots.
- Removed support for instance exports.
- This means
module.exports = new Command(...)
, for example, will no longer be loaded. - This also means
AkairoHandler#load
no longer takes a module instance. - Removed
AkairoModule#exec
, should be implemented as needed in child classes now.
- This means
- Removed
AkairoHandler#add
method. - Removed
AkairoHandler#add
andAkairoHandler#reload
events. - Removed anything related to enabling/disabling modules.
AkairoHandler#enable
andAkairoHandler#disable
events.AkairoModule#enabled
property.Command#protected
property.AkairoModule#enable
andAkairoModule#disable
methods.Category#enableAll
andCategory#disableAll
methods.
- Removed
ClientUtil#prompt
andClientUtil#promptIn
. - Removed deprecated AkairoClient members.
- Removed deprecated CommandUtil methods.
- Removed deprecated ClientUtil methods.
- Removed deprecated SQLiteHandler class.
- Fixed many typings.
- Fixed invalid modules in typings.
Commands
- Added command locks feature (thanks to xdimgg).
- Added command handler option
ignoreCooldownID
for user(s) to ignore cooldown, defaults to the owner(s). - Added command handler option
aliasReplacement
to automatically make command aliases. - Added ways to manually run commands in CommandHandler.
handleDirectCommand
to use post inhibitors then run a command on a message.handleRegexCommands
, andhandleConditionalCommands
to trigger those commands manually on a message.runCommand
to run a command with specified arguments.
- Added ways to manually run inhibitors in CommandHandler.
runAllTypeInhibitors
,runPreTypeInhibitors
,runPostTypeInhibitors
, andrunCooldowns
- Note these return true/false, actual details are emitted in the corresponding events.
- Added ways to manually parse in CommandHandler.
parseCommand
andparseCommandWithOverwrittenPrefixes
.
- Added
Command#before
that runs before argument parsing. - Added
CommandUtil#handler
. - Added
CommandUtil#sendNew
to force a new message to be sent. - Added
CommandUtil#setEditable
for setting theshouldEdit
property. - Added
CommandUtil#parsed
which contains various parsed components of the message. - Added
CommandUtil#messages
and the command handler optionstoreMessages
for storing prompt and prompt replies. - Added
CommandHandler#missingPermissions
event for permissions checks. - Added
CommandHandler#commandCancelled
event for when commands are cancelled. - Added
CommandHandler#ignorePermissions
and addedCommandHandler#ignoreCooldown
as functions. - Changed CommandHandler and Command option
defaultPrompt
toargumentDefaults
, to allow for more default options.defaultPrompt
is just nowargumentDefaults.prompt
, for example.- Also includes
otherwise
andmodifyOtherwise
.
- Changed
Command#parse
from(content, message)
to(message, content)
to be consistent. - Changed regex command arguments, it is now
(message, args)
where args has propertiesmatch
andmatches
. - Changed conditional command arguments, it is now
(message, args)
where args is an empty object. - Changed CommandUtil related options to need the
commandUtil
option to be explicitly set. - Changed CommandUtil constructor to
(handler, message)
. - Changed the parsed things in CommandUtil to a
parsed
object property. - Changed the structure of stored prefixes in
CommandHandler#prefixes
. - Changed the structure of stored ongoing prompts in
CommandHandler#prompts
. - Changed ongoing prompt methods' parameters to
(channel, user)
. - Changed permission check functions' return type to be the reason rather than a boolean.
- The reason will be then passed as the
missing
parameter in the event below.
- The reason will be then passed as the
- Changed CommandHandler events to be more useful.
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)
.
- Changed the default of
commandUtilLifetime
to 5 minutes. - Changed cooldown and throttling to not affect the bot owner(s).
- Changed prefix overwrite parsing, it will now allow empty strings and choose prefixes better.
- Renamed
CommandHandler#ignoreCooldownID
toCommandHandler#ignoreCooldown
. - Renamed
CommandHandler#onCooldown
toCommandHandler#cooldown
. - Renamed
Command#channelRestriction
toCommand#channel
. - Renamed
Command#trigger
toCommand#regex
. - Removed
args
property. - Removed
edited
parameters in command-related functions and events. - Removed the ability to change the split type with
Command#split
.- There is now the
quoted
option, either true or false. - For custom separators, there is now the
separator
option.
- There is now the
- Removed
Command#protected
. - Removed
Command#options
. - Removed
CommandUtil#client
. - Fixed prefixes not being case-insensitive.
Arguments
- Added support for these quotation marks:
“”
. - Added argument option
limit
which limits how many phrases to match. - Added argument option
unordered
to allow for matching phrases throughout the command rather than by index. - Added argument match
separate
which works likerest
but processes each phrase separately.- Will also work with
infinite
prompts by enabling infinite matching only when no input was provided. - When there was already input, the prompt will work on each incorrect input separately.
- Will also work with
- Added argument match
restContent
which works likerest
but also matches flags. - Added argument option
multipleFlags
to allow for matching aflag
or anoption
multiple times. - Added argument option
otherwise
andmodifyOtherwise
for a message when argument parsing fails. - Added argument type
userMention
for mentions that refer to any user. - Added argument type
guildMessage
for a message within any of the channels in the guild. - Added argument type
relevantMessage
for a message within any of the channels in the guild or in DMs. - Added prompt option
breakout
, to allow a command to be used to break out of the prompt and run that command instead. - Added prompt modification functions in prompt options for modifying prompts.
modifyStart
,modifyRetry
,modifyTimeout
,modifyEnded
, andmodifyCancel
.- Also supports promises.
- Added new Argument methods for casting and prompting.
- Methods
cast
(taking place of the renamedcast
toprocess
method) casts text andcollect
prompts a user. - With static equivalent
Argument.cast
.
- Methods
- Added static Argument methods to create types from existing types.
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
andArgument.composeWithFailure
to compose types.Argument.withInput
,Argument.tagged
, andArgument.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.
- Added Flag, a way to signal special changes during parsing.
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).
- Added new parameter to
default
for miscellaneous data, including the failed value. - Added
TypeResolver#inhibitorHandler
andTypeResolver#listenerHandler
. - Changed internals of argument handling to a generator-based implementation.
- The
args
option on commands can now be a generator function.
- The
- Changed
this
context of all functions in ArgumentOption to the Argument instance. - Changed
this
context of types added using TypeResolver to the Argument instance. - Changed argument matching to count LF as whitespace rather than as part of a phrase.
- Changed Promise rejection as the way to signify argument type cast failure to
Promise<null>
orPromise<undefined>
. - Changed a type function returning
true
causing the phrase to be used to now literally usetrue
. - Changed the default value of the
default
option from empty string tonull
. - Changed argument prompt functions' third parameter to a data object with properties:
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 newFlag.fail
).
- Changed
invite
type to fetch an invite instead of matching an invite. - Changed argument and type functions
message
parameter to the front and removed previous args parameter.- e.g.
type
is now(message, phrase)
instead of(phrase, message, args)
- e.g.
- Changed TypeResolver to store types in a collection instead of on the instance.
- Changed mentions-related matching to only match valid snowflakes (Clyde prevented).
- Changed the behavior of arguments matching with respect to whitespace.
- Changed interaction of prompts and CommandUtil to be more user-friendly.
- Messages sent by prompts will no longer be editable anywhere.
- Changed prompts to start at retry count of 2 and retry text instead of start text if there was input but was invalid.
- Changed phrase index to not increase when using unordered arguments or when the
index
option is set. - Renamed
Argument#prefix
toArgument#flag
. - Renamed
Argument#cast
toArgument#process
. - Renamed
TypeResolver#handler
toTypeResolver#commandHandler
. - Renamed
groups
tomatches
in context of regex commands and regex types. - Renamed
word
tophrase
in context of argument matching and parsing. - Renamed
prefix
tooption
in terms of the match type. - Renamed
prefix
toflag
in terms of the preceeding string. - Removed the
match
option being a function. - Removed the
dynamic
anddynamicInt
types.- Use
Argument.union
instead.
- Use
- Removed argument description.
- Fixed argument default inversing flag not working.
Inhibitors
- Added
Inhibitor#priority
option for when more than one inhibitor blocks a message. - Changed Promise rejection as the way to block in inhibitors to
Promise<true>
. - Renamed the block reason
notSelf
toothers
.
Listeners
- Added
ListenerHandler#setEmitters
for adding new emitters. - Renamed
Listener#eventName
toListener#event
. - Removed
emitters
options from ListenerHandler. - Removed the defaults for the
emitter
andevent
options of listener options.