Skip to content

Commit

Permalink
feat(command): remove getArgs and clean args
Browse files Browse the repository at this point in the history
BREAKING CHANGE: remove getArgs in command and args type will change a lot
  • Loading branch information
mouse484 committed Oct 29, 2022
1 parent 6c13bfe commit dcc54c9
Show file tree
Hide file tree
Showing 8 changed files with 39 additions and 159 deletions.
7 changes: 2 additions & 5 deletions examples/commands/editChannel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
});
}
Expand Down
5 changes: 2 additions & 3 deletions examples/commands/send.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
},
}));
5 changes: 2 additions & 3 deletions examples/commands/sum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)); // 今は計算できない
},
}));
21 changes: 17 additions & 4 deletions src/core/events/CommandHandler.ts
Original file line number Diff line number Diff line change
@@ -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]) {
Expand All @@ -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');
Expand Down
18 changes: 8 additions & 10 deletions src/lib/context/command.ts
Original file line number Diff line number Diff line change
@@ -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<T extends { [key: string]: keyof TypeList }>(types: T): argsType<T>;
args: parsed['args'];
args: string[];
send(
content: Parameters<TextChannel['send']>[0],
channelID?: Snowflake
Expand All @@ -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
Expand Down
95 changes: 8 additions & 87 deletions src/lib/utils/argumentParser.ts
Original file line number Diff line number Diff line change
@@ -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, N extends string> = T extends P.Parser<infer U>
? P.Node<N, U>
: never;

type ParseResult =
(
| PType<typeof mention, 'mention'>
| PType<typeof boolean, 'boolen'>
| PType<typeof Pstring, 'string'>
| PType<typeof number, 'number'>
)[]

const buildParser = (...parsers: [P.Parser<unknown>, string][]) => {
return P.alt(...parsers.map(([parser, name]) => parser.node(name))).sepBy(
P.whitespace
) as P.Parser<ParseResult>;
};

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;
};
35 changes: 0 additions & 35 deletions src/lib/utils/getArgs.ts

This file was deleted.

12 changes: 0 additions & 12 deletions src/lib/utils/getCommandName.ts

This file was deleted.

0 comments on commit dcc54c9

Please sign in to comment.