diff --git a/examples/commands/editChannel.ts b/examples/commands/editChannel.ts index be09515..f600606 100644 --- a/examples/commands/editChannel.ts +++ b/examples/commands/editChannel.ts @@ -8,12 +8,9 @@ export default command(() => ({ bot: ['ManageChannels'], }, render({ message, args: [text] }) { - if ( - message.channel.type === ChannelType.GuildText && - text.name === 'string' - ) { + if (message.channel.type === ChannelType.GuildText) { message.channel.edit({ - name: text.value, + name: text, reason: 'Ecstar editChannel test', }); } diff --git a/examples/commands/send.ts b/examples/commands/send.ts index 6ca5f6e..0b75de5 100644 --- a/examples/commands/send.ts +++ b/examples/commands/send.ts @@ -2,8 +2,7 @@ import { command } from 'ecstar'; export default command(() => ({ name: 'send', - render({ send, getArgs }) { - const args = getArgs({ text: 'string' }); - send(args.text); + render({ send, args: [text] }) { + send(text); }, })); diff --git a/examples/commands/sum.ts b/examples/commands/sum.ts index 0f81768..f3da0de 100644 --- a/examples/commands/sum.ts +++ b/examples/commands/sum.ts @@ -2,8 +2,7 @@ import { command } from 'ecstar'; export default command(() => ({ name: 'sum', - render({ send, getArgs }) { - const { a, b } = getArgs({ a: 'number', b: 'number' }); - send(String(a + b)); + render({ send, args: [a, b] }) { + send(String(a + b)); // 今は計算できない }, })); diff --git a/src/core/events/CommandHandler.ts b/src/core/events/CommandHandler.ts index be5682e..9d24436 100644 --- a/src/core/events/CommandHandler.ts +++ b/src/core/events/CommandHandler.ts @@ -1,8 +1,18 @@ -import { event } from 'ecstar'; +import { Client, event } from 'ecstar'; import { Events } from 'discord.js'; -import { getCommandName } from 'ecstar/utils/getCommandName'; import { commandContext } from 'ecstar/context/command'; +export const divideCommandNameContents = (client: Client, content: string) => { + const mention = `<@!${client.user?.id}>`; + const prefix = client.options.prefix; + if (content.startsWith(mention)) { + return content.slice(mention.length).split(' '); + } else if (content.startsWith(prefix)) { + return content.slice(prefix.length).split(' '); + } + return content; +}; + export default event(() => ({ name: Events.MessageCreate, run({ client }, [message]) { @@ -13,13 +23,16 @@ export default event(() => ({ ) return; - const name = getCommandName(client, message.content); + const [name, ...contents] = divideCommandNameContents( + client, + message.content + ); const command = client.commands.get(name); if (!command) return; // command is not found - const ctx = commandContext(client, message); + const ctx = commandContext(client, message, contents, command); if (command.guildOnly && !message.guild) { return message.channel.send('Can only be used with guild'); diff --git a/src/lib/context/command.ts b/src/lib/context/command.ts index e261f4d..8840553 100644 --- a/src/lib/context/command.ts +++ b/src/lib/context/command.ts @@ -1,18 +1,15 @@ -import { Client } from 'ecstar'; +import { Client, commandOptions } from 'ecstar'; import { Message, Snowflake, TextChannel, User } from 'discord.js'; import { ContextBase } from 'ecstar/context/base'; -import { parser, parsed } from 'ecstar/utils/argumentParser'; -import { getArgs, argsType, TypeList } from 'ecstar/utils/getArgs'; +import { parser } from 'ecstar/utils/argumentParser'; export interface CommandContext extends ContextBase { name: string; type: 'command'; message: Message; author: User; - /** @deprecated Use 'args' directly instead */ - getArgs(types: T): argsType; - args: parsed['args']; + args: string[]; send( content: Parameters[0], channelID?: Snowflake @@ -21,17 +18,18 @@ export interface CommandContext extends ContextBase { export const commandContext = ( client: Client, - message: Message + message: Message, + contents: string[], + options: commandOptions ): CommandContext => { - const { commandName, args } = parser(client, message.content); + const args = parser(client, contents, options); return { - name: commandName.toLowerCase(), + name: options.name, type: 'command', client, message, author: message.author, - getArgs: getArgs(args), args, send(content, id) { const channel = id diff --git a/src/lib/utils/argumentParser.ts b/src/lib/utils/argumentParser.ts index ef0f85e..092434b 100644 --- a/src/lib/utils/argumentParser.ts +++ b/src/lib/utils/argumentParser.ts @@ -1,89 +1,10 @@ import { Client } from 'ecstar'; - -import P from 'parsimmon'; - -const stringInSingleQuote = P.string("'") - .then(P.regex(/[^']+/)) - .skip(P.string("'")); -const stringInDoubleQuote = P.string('"') - .then(P.regex(/[^"]+/)) - .skip(P.string('"')); -const stringInBackQuote = P.string('`') - .then(P.regex(/[^`]+/)) - .skip(P.string('`')); - -const stringInQuotes = P.alt( - stringInSingleQuote, - stringInDoubleQuote, - stringInBackQuote -); - -const stringble = P.regexp(/[^\s]+/); - -const Pstring = P.lazy(() => P.alt(stringInQuotes, stringble)); - -const number = P.regexp(/[0-9]+/).map((result) => Number(result)); - -const boolean = P.alt( - P.string('true').result(true), - P.string('false').result(false) -); - -const lessThan = P.string('<'); -const greaterThan = P.string('>'); -const atSign = P.string('@'); -const snowflake = P.regex(/[0-9]{17,19}/); -const mention = lessThan.then(atSign.then(snowflake)).skip(greaterThan); - -type PType = T extends P.Parser - ? P.Node - : never; - -type ParseResult = - ( - | PType - | PType - | PType - | PType - )[] - -const buildParser = (...parsers: [P.Parser, string][]) => { - return P.alt(...parsers.map(([parser, name]) => parser.node(name))).sepBy( - P.whitespace - ) as P.Parser; -}; - -export const parse = buildParser( - [mention, 'mention'], - [boolean, 'boolean'], - [Pstring, 'string'], - [number, 'number'] -) - - -export type parsed = { commandName: string; args: ParseResult }; - -export const parser = (client: Client, content: string): parsed => { - const mentionPrefix = `<@!${client.user?.id}>`; - - const result = parse.parse(content) - - if (result.status) { - const [prefixAndCommandName, ...args] = result.value - - let commandName: string - - if (content.startsWith(mentionPrefix)) { - // Allow @mention Command and @mentionCommand - commandName = [prefixAndCommandName.value, args[0]] - .join('') - .slice(mentionPrefix.length); - } else { - commandName = prefixAndCommandName.name === "string" ? prefixAndCommandName.value.slice(client.options.prefix.length) : "" - } - - return { commandName, args }; - } - - return { commandName: "parse error", args: [] } +import { commandOptions } from 'ecstar/structures/command'; + +export const parser = ( + client: Client, + content: string[], + options: commandOptions +) => { + return content; }; diff --git a/src/lib/utils/getArgs.ts b/src/lib/utils/getArgs.ts deleted file mode 100644 index ba616d8..0000000 --- a/src/lib/utils/getArgs.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { parsed } from 'ecstar/utils/argumentParser'; - -export type TypeList = { - string: string; - number: number; - boolean: boolean; -}; - -export type argsType = { - [K in keyof types]: TypeList[types[K]]; -}; - -export const getArgs = (args: parsed['args']): typeof func => { - const func = (types: T) => { - return Object.fromEntries( - Object.entries(types).map(([key, type], index) => { - const value = args[index]?.value; - const func = () => { - switch (type) { - case 'string': - return value; - case 'number': - return Number(value); - case 'boolean': - return Boolean(value); - default: - return value; - } - }; - return [key, func()]; - }) - ) as argsType; - }; - return func; -}; diff --git a/src/lib/utils/getCommandName.ts b/src/lib/utils/getCommandName.ts deleted file mode 100644 index 99a87ee..0000000 --- a/src/lib/utils/getCommandName.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Client } from 'ecstar'; - -export const getCommandName = (client: Client, content: string) => { - const mention = `<@!${client.user?.id}>`; - const prefix = client.options.prefix; - if (content.startsWith(mention)) { - return content.slice(mention.length).split(' ')[0]; - } else if (content.startsWith(prefix)) { - return content.slice(prefix.length).split(' ')[0]; - } - return content; -};