Compare commits

..

No commits in common. "57313488b4136a83e26f05f0c225f2a8a43e0124" and "aa7fe8643c0f539bf43631067465bd8471565aa8" have entirely different histories.

3 changed files with 21 additions and 63 deletions

View File

@ -1,6 +1,6 @@
{
"name": "@navy.gif/commandparser",
"version": "1.5.0",
"version": "1.4.5",
"description": "Parser meant to parse commands and their options for discord bots",
"author": "Navy.gif",
"license": "MIT",

View File

@ -26,12 +26,6 @@ type ParserOptions = {
resolver?: IResolver<unknown, unknown, unknown, unknown, unknown>
}
type ParseOptions = {
prefix?: string,
commandFilter?: (cmd: Command) => boolean,
guild?: unknown
}
class ParseError extends Error {}
const flagReg = /(?:^| )(?<flag>(?:--[a-z0-9]{3,})|(?:-[a-z]{1,2}))(?:$| )/iu;
@ -81,12 +75,8 @@ class Parser extends EventEmitter {
*/
// eslint-disable-next-line @typescript-eslint/ban-types
async parseMessage (
message: string,
{
prefix = this.prefix,
guild,
commandFilter
}: ParseOptions = {}
message: string, prefix = this.prefix,
guild?: unknown, commandFilter?: (command: Command) => boolean
): Promise<ParseResult | null> {
if (!message.startsWith(prefix) || !message.length)
@ -144,20 +134,11 @@ class Parser extends EventEmitter {
}
const activeCommand = subcommand || command;
const flags = activeCommand.options.filter((opt) => opt.flag);
params = Util.parseQuotes(params.join(' ')).map(([ str ]: (string | boolean)[]): string => str.toString());
this.debug(`Given params: "${params.join('", "')}"`);
parseResult.args = await this.parseOptions(params, activeCommand.options, guild);
return parseResult;
}
async parseOptions (params: string[], options: CommandOption[], guild?: unknown) {
let currentFlag = null;
const flags = options.filter((opt) => opt.flag);
const args: ArgsResult = {};
// Parse flags
for (let index = 0; index < params.length;) {
@ -221,13 +202,12 @@ class Parser extends EventEmitter {
}
this.debug(`Params after parsing "${params.join('", "')}"`);
// Non-string options
const nStrOptions = options.filter((opt) => !opt.flag && (opt.type !== OptionType.STRING || opt.choices.length));
const stringOpts = options.filter((opt) => !opt.flag && !opt.choices.length && opt.type === OptionType.STRING);
const options = activeCommand.options.filter((opt) => !opt.flag && (opt.type !== OptionType.STRING || opt.choices.length));
const stringOpts = activeCommand.options.filter((opt) => !opt.flag && !opt.choices.length && opt.type === OptionType.STRING);
this.debug(`Parsing non-flag options`);
// Parse out non-flag options
for (const option of nStrOptions) { // String options are parsed separately at the end
for (const option of options) { // String options are parsed separately at the end
if (!params.some((param) => param !== null)) {
this.debug(`No potential values left in params`);
break;
@ -299,26 +279,26 @@ class Parser extends EventEmitter {
}
// This part is obsolete now, I think, the string option checks the choice value
// for (const arg of Object.values(args)) {
// if (!arg.choices.length)
// continue;
// if (!arg.choices.some((choice) => {
// if (typeof arg.value === 'string' && typeof choice === 'string')
// return arg.value.toLowerCase() === choice.toLowerCase();
// return arg.value === choice;
// }))
// throw new ParseError(`Invalid choice: ${arg.name} value must be one of ${arg.choices.join(', ')}`); // return { error: true, index: 'O_COMMANDHANDLER_INVALID_CHOICE', params: { option: arg.name, value: arg.value, choices: arg.choices.map((c) => c).join('`, `') } };
// }
for (const arg of Object.values(args)) {
if (!arg.choices.length)
continue;
if (!arg.choices.some((choice) => {
if (typeof arg.value === 'string' && typeof choice === 'string')
return arg.value.toLowerCase() === choice.toLowerCase();
return arg.value === choice;
}))
throw new ParseError(`Invalid choice: ${arg.name} value must be one of ${arg.choices.join(', ')}`); // return { error: true, index: 'O_COMMANDHANDLER_INVALID_CHOICE', params: { option: arg.name, value: arg.value, choices: arg.choices.map((c) => c).join('`, `') } };
}
this.debug(`Making sure required options were given.`);
for (const req of options.filter((opt) => opt.required))
for (const req of activeCommand.options.filter((opt) => opt.required))
if (!args[req.name])
throw new ParseError(`${req.name} is a required option`);
if (strings.length)
throw new ParseError(`Unrecognised option(s): "${strings.join('", "')}"`);
throw new ParseError(`Unrecognised option(s): "${strings.join('", "')}"`);// return { error: true, index: 'O_COMMANDHANDLER_UNRECOGNISED_OPTIONS', params: { opts: strings.join('`, `') } };
return args;
return parseResult;
}

View File

@ -96,25 +96,3 @@ test('Command Parser', async () => {
await expect(parser.parseMessage('create code 1')).resolves.toHaveProperty('args.amount.value', 1);
});
test('Choice option', async () => {
const command = new Command({
name: 'create',
options: [{
name: 'registration-code',
aliases: ['code'],
type: OptionType.SUB_COMMAND,
options: [{
name: 'amount',
type: OptionType.STRING,
choices: ['one', 'two']
}]
}]
});
const parser = new Parser({ commands: [command], prefix: '' });
await expect(parser.parseMessage('create code 1')).rejects.toThrow();
await expect(parser.parseMessage('create code one')).resolves.toHaveProperty('args.amount.value', 'one');
});