diff --git a/src/Parser.ts b/src/Parser.ts index 14eddfd..7430e88 100644 --- a/src/Parser.ts +++ b/src/Parser.ts @@ -52,7 +52,7 @@ class Parser extends EventEmitter { return command || null; } - async parseMessage(message: string, prefix = this.prefix) { + async parseMessage(message: string, prefix = this.prefix, guild?: unknown) { if (!message.startsWith(prefix) || !message.length) return null; let params: string[] = message.replace(prefix, '').split(' ').filter((str) => str.length); @@ -143,7 +143,7 @@ class Parser extends EventEmitter { // Clean up params for option parsing for (const flag of Object.values(args)) { this.debug(`Running parser for ${flag.name}`); - const result = await flag.parse(); + const result = await flag.parse(guild); if (result.error) { if (flag.choices.length) { throw new Error(`Invalid choice for ${flag.name}, Valid choices are ${flag.choices.join(', ')}.`); @@ -173,14 +173,14 @@ class Parser extends EventEmitter { error = false; if (cloned.plural) { // E.g. if the type is CHANNEL**S**, parse out any potential channels from the message cloned.rawValue = params; - ({ removed } = await cloned.parse()); + ({ removed } = await cloned.parse(guild)); } else for (let index = 0; index < params.length;) { // Attempt to parse out a value from each param if (params[index] === null) { index++; continue; } cloned.rawValue = [params[index]]; - ({ removed, error } = await cloned.parse()); + ({ removed, error } = await cloned.parse(guild)); if (!error) break; index++; } @@ -220,7 +220,7 @@ class Parser extends EventEmitter { const val = strings.shift(); if (!val) break; const cloned = strOpt.clone([val]); - await cloned.parse(); + await cloned.parse(guild); args[cloned.name] = cloned; } diff --git a/src/classes/Command.ts b/src/classes/Command.ts index 77d8ce4..bd960e4 100644 --- a/src/classes/Command.ts +++ b/src/classes/Command.ts @@ -18,7 +18,11 @@ class Command implements ICommand { this.aliases = def.aliases || []; - this.options = def.options || []; + this.options = []; + for (const opt of def.options || []) { + if (opt instanceof CommandOption) this.options.push(opt); + else this.options.push(new CommandOption(opt)); + } } diff --git a/src/classes/CommandOption.ts b/src/classes/CommandOption.ts index b9dc5d6..4b41022 100644 --- a/src/classes/CommandOption.ts +++ b/src/classes/CommandOption.ts @@ -40,6 +40,8 @@ class CommandOption implements ICommandOption { aliased = false; + strict: boolean; + private resolver?: IResolver|undefined = undefined; constructor(def: CommandOptionDefinition|ICommandOption) { @@ -50,6 +52,7 @@ class CommandOption implements ICommandOption { this.options = def.options || []; this.choices = def.choices || []; + this.strict = def.strict || false; this.type = def.type || OptionType.STRING; this.flag = def.flag || false; @@ -71,9 +74,13 @@ class CommandOption implements ICommandOption { return opt; } - async parse(): Promise { - if(!this[OptionType[this.type]]) throw new Error(`Missing parsing function for ${this.type}`); - const result = await this[OptionType[this.type]]; + async parse(guild?: unknown): Promise { + if (!this[OptionType[this.type]]) throw new Error(`Missing parsing function for ${this.type}`); + if (typeof this[OptionType[this.type]] !== 'function') throw new Error(`Expected function type for memberr ${OptionType[this.type]}`); + this.guild = guild; + // eslint-disable-next-line @typescript-eslint/ban-types + const func = this[OptionType[this.type]] as Function; + const result = await func(); return result as ParseResult; } @@ -84,7 +91,7 @@ class CommandOption implements ICommandOption { protected async MEMBER() { if (!this.resolver) throw new Error('Missing resolver'); if(!this.rawValue) throw new Error('Missing raw value'); - const member = await this.resolver?.resolveMember(this.rawValue[0]); + const member = await this.resolver?.resolveMember(this.rawValue[0], this.strict, this.guild); if (!member) return { error: true }; return { value: member, removed: this.rawValue }; } diff --git a/src/interfaces/Command.ts b/src/interfaces/Command.ts index 57f43c0..0c0cd9a 100644 --- a/src/interfaces/Command.ts +++ b/src/interfaces/Command.ts @@ -1,6 +1,7 @@ import CommandOption from '../classes/CommandOption'; import SubcommandGroupOption from '../classes/SubcommandGroupOption'; import SubcommandOption from '../classes/SubcommandOption'; +import { CommandOptionDefinition } from './CommandOption'; interface ICommand { @@ -22,7 +23,7 @@ interface ICommand { type CommandDefinition = { name: string; aliases?: string[]; - options?: CommandOption[]; + options?: (CommandOption|CommandOptionDefinition)[]; } export { ICommand, CommandDefinition }; diff --git a/src/interfaces/CommandOption.ts b/src/interfaces/CommandOption.ts index 8867c71..cd40806 100644 --- a/src/interfaces/CommandOption.ts +++ b/src/interfaces/CommandOption.ts @@ -74,6 +74,7 @@ type CommandOptionDefinition = { // eslint-disable-next-line no-use-before-define options?: CommandOption[]; type?: OptionType; + strict?: boolean required?: boolean; choices?: Choice[]; @@ -102,6 +103,7 @@ interface ICommandOption { options: CommandOption[]; choices: Choice[] type: OptionType; + strict: boolean; required: boolean; @@ -127,7 +129,7 @@ interface ICommandOption { clone(rawValue?: string[], resolver?: IResolver): CommandOption - parse(): Promise + parse(guild: unknown): Promise get plural(): boolean diff --git a/src/interfaces/Resolver.ts b/src/interfaces/Resolver.ts index ead53fb..06c5106 100644 --- a/src/interfaces/Resolver.ts +++ b/src/interfaces/Resolver.ts @@ -19,7 +19,7 @@ interface IResolver { * @return {Member} {Member} * @memberof IResolver */ - resolveMember(resolveable: string, strict?: boolean, guild?: Guild): Promise + resolveMember(resolveable: string, strict: boolean, guild: Guild): Promise /** * Should resolve to a role abstraction @@ -30,7 +30,7 @@ interface IResolver { * @return {Channel} {Channel} * @memberof IResolver */ - resolveChannel(resolveable: string, strict?: boolean, guild?: Guild): Promise + resolveChannel(resolveable: string, strict: boolean, guild: Guild): Promise /** * Should resolve to a role abstraction @@ -41,7 +41,7 @@ interface IResolver { * @return {Role} {Role} * @memberof IResolver */ - resolveRole(resolveable: string, strict?: boolean, guild?: Guild): Promise + resolveRole(resolveable: string, strict: boolean, guild: Guild): Promise /** * Should resolve to true when a truthy resolveable is passed, i.e. yes, true, on etc