mirror of
https://github.com/tiramisulabs/seyfert.git
synced 2025-07-04 22:16:08 +00:00
feat: optionsParser option
This commit is contained in:
parent
5f61e8e66b
commit
2737b8f426
@ -1,6 +1,29 @@
|
|||||||
import { GatewayIntentBits, type GatewayDispatchPayload, type GatewayPresenceUpdateData } from 'discord-api-types/v10';
|
import {
|
||||||
import type { Command, CommandContext, Message, SubCommand } from '..';
|
type APIApplicationCommandInteractionDataOption,
|
||||||
import { lazyLoadPackage, type DeepPartial, type If, type WatcherPayload, type WatcherSendToShard } from '../common';
|
GatewayIntentBits,
|
||||||
|
type GatewayMessageCreateDispatchData,
|
||||||
|
type GatewayDispatchPayload,
|
||||||
|
type GatewayPresenceUpdateData,
|
||||||
|
} from 'discord-api-types/v10';
|
||||||
|
import type {
|
||||||
|
Command,
|
||||||
|
CommandContext,
|
||||||
|
ContextOptionsResolved,
|
||||||
|
Message,
|
||||||
|
MessageCommandOptionErrors,
|
||||||
|
SubCommand,
|
||||||
|
UsingClient,
|
||||||
|
} from '..';
|
||||||
|
import {
|
||||||
|
type Awaitable,
|
||||||
|
type MakeRequired,
|
||||||
|
MergeOptions,
|
||||||
|
lazyLoadPackage,
|
||||||
|
type DeepPartial,
|
||||||
|
type If,
|
||||||
|
type WatcherPayload,
|
||||||
|
type WatcherSendToShard,
|
||||||
|
} from '../common';
|
||||||
import { EventHandler } from '../events';
|
import { EventHandler } from '../events';
|
||||||
import { ClientUser } from '../structures';
|
import { ClientUser } from '../structures';
|
||||||
import { ShardManager, properties, type ShardManagerOptions } from '../websocket';
|
import { ShardManager, properties, type ShardManagerOptions } from '../websocket';
|
||||||
@ -9,7 +32,7 @@ import { PresenceUpdateHandler } from '../websocket/discord/events/presenceUpdat
|
|||||||
import type { BaseClientOptions, InternalRuntimeConfig, ServicesOptions, StartOptions } from './base';
|
import type { BaseClientOptions, InternalRuntimeConfig, ServicesOptions, StartOptions } from './base';
|
||||||
import { BaseClient } from './base';
|
import { BaseClient } from './base';
|
||||||
import { onInteractionCreate } from './oninteractioncreate';
|
import { onInteractionCreate } from './oninteractioncreate';
|
||||||
import { onMessageCreate } from './onmessagecreate';
|
import { defaultArgsParser, defaultParseOptions, onMessageCreate } from './onmessagecreate';
|
||||||
import { Collectors } from './collectors';
|
import { Collectors } from './collectors';
|
||||||
|
|
||||||
let parentPort: import('node:worker_threads').MessagePort;
|
let parentPort: import('node:worker_threads').MessagePort;
|
||||||
@ -18,7 +41,9 @@ export class Client<Ready extends boolean = boolean> extends BaseClient {
|
|||||||
private __handleGuilds?: Set<string> = new Set();
|
private __handleGuilds?: Set<string> = new Set();
|
||||||
gateway!: ShardManager;
|
gateway!: ShardManager;
|
||||||
me!: If<Ready, ClientUser>;
|
me!: If<Ready, ClientUser>;
|
||||||
declare options: ClientOptions;
|
declare options: Omit<ClientOptions, 'commands'> & {
|
||||||
|
commands: MakeRequired<NonNullable<ClientOptions['commands']>, 'argsParser' | 'optionsParser'>;
|
||||||
|
};
|
||||||
memberUpdateHandler = new MemberUpdateHandler();
|
memberUpdateHandler = new MemberUpdateHandler();
|
||||||
presenceUpdateHandler = new PresenceUpdateHandler();
|
presenceUpdateHandler = new PresenceUpdateHandler();
|
||||||
collectors = new Collectors();
|
collectors = new Collectors();
|
||||||
@ -26,6 +51,12 @@ export class Client<Ready extends boolean = boolean> extends BaseClient {
|
|||||||
|
|
||||||
constructor(options?: ClientOptions) {
|
constructor(options?: ClientOptions) {
|
||||||
super(options);
|
super(options);
|
||||||
|
this.options = MergeOptions(this.options, {
|
||||||
|
commands: {
|
||||||
|
argsParser: defaultArgsParser,
|
||||||
|
optionsParser: defaultParseOptions,
|
||||||
|
},
|
||||||
|
} satisfies ClientOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
setServices({
|
setServices({
|
||||||
@ -212,6 +243,20 @@ export interface ClientOptions extends BaseClientOptions {
|
|||||||
deferReplyResponse?: (ctx: CommandContext) => Parameters<Message['write']>[0];
|
deferReplyResponse?: (ctx: CommandContext) => Parameters<Message['write']>[0];
|
||||||
reply?: (ctx: CommandContext) => boolean;
|
reply?: (ctx: CommandContext) => boolean;
|
||||||
argsParser?: (content: string, command: SubCommand | Command, message: Message) => Record<string, string>;
|
argsParser?: (content: string, command: SubCommand | Command, message: Message) => Record<string, string>;
|
||||||
|
optionsParser?: (
|
||||||
|
self: UsingClient,
|
||||||
|
command: Command | SubCommand,
|
||||||
|
message: GatewayMessageCreateDispatchData,
|
||||||
|
args: Partial<Record<string, string>>,
|
||||||
|
resolved: MakeRequired<ContextOptionsResolved>,
|
||||||
|
) => Awaitable<{
|
||||||
|
errors: {
|
||||||
|
name: string;
|
||||||
|
error: string;
|
||||||
|
fullError: MessageCommandOptionErrors;
|
||||||
|
}[];
|
||||||
|
options: APIApplicationCommandInteractionDataOption[];
|
||||||
|
}>;
|
||||||
};
|
};
|
||||||
handlePayload?: ShardManagerOptions['handlePayload'];
|
handlePayload?: ShardManagerOptions['handlePayload'];
|
||||||
}
|
}
|
||||||
|
@ -1,457 +1,469 @@
|
|||||||
import {
|
import {
|
||||||
ApplicationCommandOptionType,
|
ApplicationCommandOptionType,
|
||||||
ChannelType,
|
ChannelType,
|
||||||
InteractionContextType,
|
InteractionContextType,
|
||||||
type APIApplicationCommandInteractionDataOption,
|
type APIApplicationCommandInteractionDataOption,
|
||||||
type GatewayMessageCreateDispatchData,
|
type GatewayMessageCreateDispatchData,
|
||||||
} from 'discord-api-types/v10';
|
} from 'discord-api-types/v10';
|
||||||
import {
|
import {
|
||||||
Command,
|
Command,
|
||||||
CommandContext,
|
CommandContext,
|
||||||
IgnoreCommand,
|
IgnoreCommand,
|
||||||
OptionResolver,
|
type MessageCommandOptionErrors,
|
||||||
SubCommand,
|
OptionResolver,
|
||||||
User,
|
SubCommand,
|
||||||
type Client,
|
User,
|
||||||
type CommandOption,
|
type UsingClient,
|
||||||
type ContextOptionsResolved,
|
type Client,
|
||||||
type SeyfertChannelOption,
|
type CommandOption,
|
||||||
type SeyfertIntegerOption,
|
type ContextOptionsResolved,
|
||||||
type SeyfertNumberOption,
|
type SeyfertChannelOption,
|
||||||
type SeyfertStringOption,
|
type SeyfertIntegerOption,
|
||||||
type WorkerClient,
|
type SeyfertNumberOption,
|
||||||
} from '..';
|
type SeyfertStringOption,
|
||||||
import type { MakeRequired } from '../common';
|
type WorkerClient,
|
||||||
import { Message } from '../structures';
|
} from '..';
|
||||||
|
import type { MakeRequired } from '../common';
|
||||||
function getCommandFromContent(
|
import { Message } from '../structures';
|
||||||
commandRaw: string[],
|
|
||||||
self: Client | WorkerClient,
|
function getCommandFromContent(
|
||||||
): {
|
commandRaw: string[],
|
||||||
command?: Command | SubCommand;
|
self: Client | WorkerClient,
|
||||||
parent?: Command;
|
): {
|
||||||
fullCommandName: string;
|
command?: Command | SubCommand;
|
||||||
} {
|
parent?: Command;
|
||||||
const rawParentName = commandRaw[0];
|
fullCommandName: string;
|
||||||
const rawGroupName = commandRaw.length === 3 ? commandRaw[1] : undefined;
|
} {
|
||||||
const rawSubcommandName = rawGroupName ? commandRaw[2] : commandRaw[1];
|
const rawParentName = commandRaw[0];
|
||||||
const parent = self.commands!.values.find(
|
const rawGroupName = commandRaw.length === 3 ? commandRaw[1] : undefined;
|
||||||
x =>
|
const rawSubcommandName = rawGroupName ? commandRaw[2] : commandRaw[1];
|
||||||
(!('ignore' in x) || x.ignore !== IgnoreCommand.Message) &&
|
const parent = self.commands!.values.find(
|
||||||
(x.name === rawParentName || ('aliases' in x ? x.aliases?.includes(rawParentName) : false)),
|
x =>
|
||||||
);
|
(!('ignore' in x) || x.ignore !== IgnoreCommand.Message) &&
|
||||||
const fullCommandName = `${rawParentName}${
|
(x.name === rawParentName || ('aliases' in x ? x.aliases?.includes(rawParentName) : false)),
|
||||||
rawGroupName ? ` ${rawGroupName} ${rawSubcommandName}` : `${rawSubcommandName ? ` ${rawSubcommandName}` : ''}`
|
);
|
||||||
}`;
|
const fullCommandName = `${rawParentName}${
|
||||||
|
rawGroupName ? ` ${rawGroupName} ${rawSubcommandName}` : `${rawSubcommandName ? ` ${rawSubcommandName}` : ''}`
|
||||||
if (!(parent instanceof Command)) return { fullCommandName };
|
}`;
|
||||||
|
|
||||||
if (rawGroupName && !parent.groups?.[rawGroupName] && !parent.groupsAliases?.[rawGroupName])
|
if (!(parent instanceof Command)) return { fullCommandName };
|
||||||
return getCommandFromContent([rawParentName, rawGroupName], self);
|
|
||||||
if (
|
if (rawGroupName && !parent.groups?.[rawGroupName] && !parent.groupsAliases?.[rawGroupName])
|
||||||
rawSubcommandName &&
|
return getCommandFromContent([rawParentName, rawGroupName], self);
|
||||||
!parent.options?.some(
|
if (
|
||||||
x => x instanceof SubCommand && (x.name === rawSubcommandName || x.aliases?.includes(rawSubcommandName)),
|
rawSubcommandName &&
|
||||||
)
|
!parent.options?.some(
|
||||||
)
|
x => x instanceof SubCommand && (x.name === rawSubcommandName || x.aliases?.includes(rawSubcommandName)),
|
||||||
return getCommandFromContent([rawParentName], self);
|
)
|
||||||
|
)
|
||||||
const groupName = rawGroupName ? parent.groupsAliases?.[rawGroupName] || rawGroupName : undefined;
|
return getCommandFromContent([rawParentName], self);
|
||||||
|
|
||||||
const command =
|
const groupName = rawGroupName ? parent.groupsAliases?.[rawGroupName] || rawGroupName : undefined;
|
||||||
groupName || rawSubcommandName
|
|
||||||
? (parent.options?.find(opt => {
|
const command =
|
||||||
if (opt instanceof SubCommand) {
|
groupName || rawSubcommandName
|
||||||
if (groupName) {
|
? (parent.options?.find(opt => {
|
||||||
if (opt.group !== groupName) return false;
|
if (opt instanceof SubCommand) {
|
||||||
}
|
if (groupName) {
|
||||||
if (opt.group && !groupName) return false;
|
if (opt.group !== groupName) return false;
|
||||||
return rawSubcommandName === opt.name || opt.aliases?.includes(rawSubcommandName);
|
}
|
||||||
}
|
if (opt.group && !groupName) return false;
|
||||||
return false;
|
return rawSubcommandName === opt.name || opt.aliases?.includes(rawSubcommandName);
|
||||||
}) as SubCommand)
|
}
|
||||||
: parent;
|
return false;
|
||||||
|
}) as SubCommand)
|
||||||
return {
|
: parent;
|
||||||
command,
|
|
||||||
fullCommandName,
|
return {
|
||||||
parent,
|
command,
|
||||||
};
|
fullCommandName,
|
||||||
}
|
parent,
|
||||||
|
};
|
||||||
export async function onMessageCreate(
|
}
|
||||||
self: Client | WorkerClient,
|
|
||||||
rawMessage: GatewayMessageCreateDispatchData,
|
export async function onMessageCreate(
|
||||||
shardId: number,
|
self: Client | WorkerClient,
|
||||||
) {
|
rawMessage: GatewayMessageCreateDispatchData,
|
||||||
if (!self.options?.commands?.prefix) return;
|
shardId: number,
|
||||||
const message = new Message(self, rawMessage);
|
) {
|
||||||
const prefixes = (await self.options.commands.prefix(message)).sort((a, b) => b.length - a.length);
|
if (!self.options?.commands?.prefix) return;
|
||||||
const prefix = prefixes.find(x => message.content.startsWith(x));
|
const message = new Message(self, rawMessage);
|
||||||
|
const prefixes = (await self.options.commands.prefix(message)).sort((a, b) => b.length - a.length);
|
||||||
if (!(prefix && message.content.startsWith(prefix))) return;
|
const prefix = prefixes.find(x => message.content.startsWith(x));
|
||||||
|
|
||||||
const content = message.content.slice(prefix.length).trimStart();
|
if (!(prefix && message.content.startsWith(prefix))) return;
|
||||||
const { fullCommandName, command, parent } = getCommandFromContent(
|
|
||||||
content
|
const content = message.content.slice(prefix.length).trimStart();
|
||||||
.split(' ')
|
const { fullCommandName, command, parent } = getCommandFromContent(
|
||||||
.filter(x => x)
|
content
|
||||||
.slice(0, 3),
|
.split(' ')
|
||||||
self,
|
.filter(x => x)
|
||||||
);
|
.slice(0, 3),
|
||||||
|
self,
|
||||||
if (!command) return;
|
);
|
||||||
if (!command.run) return self.logger.warn(`${fullCommandName} command does not have 'run' callback`);
|
|
||||||
|
if (!command) return;
|
||||||
if (!(command.contexts?.includes(InteractionContextType.BotDM) || message.guildId)) return;
|
if (!command.run) return self.logger.warn(`${fullCommandName} command does not have 'run' callback`);
|
||||||
if (command.guildId && !command.guildId?.includes(message.guildId!)) return;
|
|
||||||
|
if (!(command.contexts?.includes(InteractionContextType.BotDM) || message.guildId)) return;
|
||||||
const resolved: MakeRequired<ContextOptionsResolved> = {
|
if (command.guildId && !command.guildId?.includes(message.guildId!)) return;
|
||||||
channels: {},
|
|
||||||
roles: {},
|
const resolved: MakeRequired<ContextOptionsResolved> = {
|
||||||
users: {},
|
channels: {},
|
||||||
members: {},
|
roles: {},
|
||||||
attachments: {},
|
users: {},
|
||||||
};
|
members: {},
|
||||||
|
attachments: {},
|
||||||
let newContent = content;
|
};
|
||||||
for (const i of fullCommandName.split(' ')) {
|
|
||||||
newContent = newContent.slice(newContent.indexOf(i) + i.length);
|
let newContent = content;
|
||||||
}
|
for (const i of fullCommandName.split(' ')) {
|
||||||
|
newContent = newContent.slice(newContent.indexOf(i) + i.length);
|
||||||
const args = (self.options?.commands?.argsParser ?? defaultArgsParser)(newContent.slice(1), command, message);
|
}
|
||||||
const { options, errors } = await parseOptions(self, command, rawMessage, args, resolved);
|
|
||||||
const optionsResolver = new OptionResolver(self, options, parent as Command, message.guildId, resolved);
|
const args = self.options.commands.argsParser(newContent.slice(1), command, message);
|
||||||
const context = new CommandContext(self, message, optionsResolver, shardId, command);
|
const { options, errors } = await self.options.commands.optionsParser(self, command, rawMessage, args, resolved);
|
||||||
//@ts-expect-error
|
const optionsResolver = new OptionResolver(self, options, parent as Command, message.guildId, resolved);
|
||||||
const extendContext = self.options?.context?.(message) ?? {};
|
const context = new CommandContext(self, message, optionsResolver, shardId, command);
|
||||||
Object.assign(context, extendContext);
|
//@ts-expect-error
|
||||||
try {
|
const extendContext = self.options?.context?.(message) ?? {};
|
||||||
if (command.defaultMemberPermissions && message.guildId) {
|
Object.assign(context, extendContext);
|
||||||
const memberPermissions = await self.members.permissions(message.guildId, message.author.id);
|
try {
|
||||||
const permissions = memberPermissions.missings(...memberPermissions.values([command.defaultMemberPermissions]));
|
if (errors.length) {
|
||||||
if (
|
return command.onOptionsError?.(
|
||||||
!memberPermissions.has('Administrator') &&
|
context,
|
||||||
permissions.length &&
|
Object.fromEntries(
|
||||||
(await message.guild())!.ownerId !== message.author.id
|
errors.map(x => {
|
||||||
) {
|
return [
|
||||||
return command.onPermissionsFail?.(context, memberPermissions.keys(permissions));
|
x.name,
|
||||||
}
|
{
|
||||||
}
|
failed: true,
|
||||||
if (command.botPermissions && message.guildId) {
|
value: x.error,
|
||||||
const meMember = await self.cache.members?.get(self.botId, message.guildId);
|
},
|
||||||
if (!meMember) return; //enable member cache and "Guilds" intent, lol
|
];
|
||||||
const appPermissions = await meMember.fetchPermissions();
|
}),
|
||||||
const permissions = appPermissions.missings(...appPermissions.values([command.botPermissions]));
|
),
|
||||||
if (!appPermissions.has('Administrator') && permissions.length) {
|
);
|
||||||
return command.onBotPermissionsFail?.(context, appPermissions.keys(permissions));
|
}
|
||||||
}
|
if (command.defaultMemberPermissions && message.guildId) {
|
||||||
}
|
const memberPermissions = await self.members.permissions(message.guildId, message.author.id);
|
||||||
if (errors.length) {
|
const permissions = memberPermissions.missings(...memberPermissions.values([command.defaultMemberPermissions]));
|
||||||
return command.onOptionsError?.(
|
if (
|
||||||
context,
|
!memberPermissions.has('Administrator') &&
|
||||||
Object.fromEntries(
|
permissions.length &&
|
||||||
errors.map(x => {
|
(await message.guild())!.ownerId !== message.author.id
|
||||||
return [
|
) {
|
||||||
x.name,
|
return command.onPermissionsFail?.(context, memberPermissions.keys(permissions));
|
||||||
{
|
}
|
||||||
failed: true,
|
}
|
||||||
value: x.error,
|
if (command.botPermissions && message.guildId) {
|
||||||
},
|
const meMember = await self.cache.members?.get(self.botId, message.guildId);
|
||||||
];
|
if (!meMember) return; //enable member cache and "Guilds" intent, lol
|
||||||
}),
|
const appPermissions = await meMember.fetchPermissions();
|
||||||
),
|
const permissions = appPermissions.missings(...appPermissions.values([command.botPermissions]));
|
||||||
);
|
if (!appPermissions.has('Administrator') && permissions.length) {
|
||||||
}
|
return command.onBotPermissionsFail?.(context, appPermissions.keys(permissions));
|
||||||
const [erroredOptions, result] = await command.__runOptions(context, optionsResolver);
|
}
|
||||||
if (erroredOptions) {
|
}
|
||||||
return command.onOptionsError?.(context, result);
|
const [erroredOptions, result] = await command.__runOptions(context, optionsResolver);
|
||||||
}
|
if (erroredOptions) {
|
||||||
const resultRunGlobalMiddlewares = await command.__runGlobalMiddlewares(context);
|
return command.onOptionsError?.(context, result);
|
||||||
if (resultRunGlobalMiddlewares.pass) {
|
}
|
||||||
return;
|
const resultRunGlobalMiddlewares = await command.__runGlobalMiddlewares(context);
|
||||||
}
|
if (resultRunGlobalMiddlewares.pass) {
|
||||||
if ('error' in resultRunGlobalMiddlewares) {
|
return;
|
||||||
return command.onMiddlewaresError?.(context, resultRunGlobalMiddlewares.error ?? 'Unknown error');
|
}
|
||||||
}
|
if ('error' in resultRunGlobalMiddlewares) {
|
||||||
const resultRunMiddlewares = await command.__runMiddlewares(context);
|
return command.onMiddlewaresError?.(context, resultRunGlobalMiddlewares.error ?? 'Unknown error');
|
||||||
if (resultRunMiddlewares.pass) {
|
}
|
||||||
return;
|
const resultRunMiddlewares = await command.__runMiddlewares(context);
|
||||||
}
|
if (resultRunMiddlewares.pass) {
|
||||||
if ('error' in resultRunMiddlewares) {
|
return;
|
||||||
return command.onMiddlewaresError?.(context, resultRunMiddlewares.error ?? 'Unknown error');
|
}
|
||||||
}
|
if ('error' in resultRunMiddlewares) {
|
||||||
|
return command.onMiddlewaresError?.(context, resultRunMiddlewares.error ?? 'Unknown error');
|
||||||
try {
|
}
|
||||||
await command.run?.(context);
|
|
||||||
await command.onAfterRun?.(context, undefined);
|
try {
|
||||||
} catch (error) {
|
await command.run?.(context);
|
||||||
await command.onRunError?.(context, error);
|
await command.onAfterRun?.(context, undefined);
|
||||||
await command.onAfterRun?.(context, error);
|
} catch (error) {
|
||||||
}
|
await command.onRunError?.(context, error);
|
||||||
} catch (error) {
|
await command.onAfterRun?.(context, error);
|
||||||
try {
|
}
|
||||||
await command.onInternalError?.(self, context.command, error);
|
} catch (error) {
|
||||||
} catch {
|
try {
|
||||||
// supress error
|
await command.onInternalError?.(self, context.command, error);
|
||||||
}
|
} catch {
|
||||||
}
|
// supress error
|
||||||
}
|
}
|
||||||
|
}
|
||||||
async function parseOptions(
|
}
|
||||||
self: Client | WorkerClient,
|
|
||||||
command: Command | SubCommand,
|
export async function defaultParseOptions(
|
||||||
message: GatewayMessageCreateDispatchData,
|
self: UsingClient,
|
||||||
args: Partial<Record<string, string>>,
|
command: Command | SubCommand,
|
||||||
resolved: MakeRequired<ContextOptionsResolved>,
|
message: GatewayMessageCreateDispatchData,
|
||||||
) {
|
args: Partial<Record<string, string>>,
|
||||||
const options: APIApplicationCommandInteractionDataOption[] = [];
|
resolved: MakeRequired<ContextOptionsResolved>,
|
||||||
const errors: { name: string; error: string }[] = [];
|
) {
|
||||||
for (const i of (command.options ?? []) as (CommandOption & { type: ApplicationCommandOptionType })[]) {
|
const options: APIApplicationCommandInteractionDataOption[] = [];
|
||||||
try {
|
const errors: { name: string; error: string; fullError: MessageCommandOptionErrors }[] = [];
|
||||||
let value: string | boolean | number | undefined;
|
for (const i of (command.options ?? []) as (CommandOption & { type: ApplicationCommandOptionType })[]) {
|
||||||
let indexAttachment = -1;
|
try {
|
||||||
switch (i.type) {
|
let value: string | boolean | number | undefined;
|
||||||
case ApplicationCommandOptionType.Attachment:
|
let indexAttachment = -1;
|
||||||
if (message.attachments[++indexAttachment]) {
|
switch (i.type) {
|
||||||
value = message.attachments[indexAttachment].id;
|
case ApplicationCommandOptionType.Attachment:
|
||||||
resolved.attachments[value] = message.attachments[indexAttachment];
|
if (message.attachments[++indexAttachment]) {
|
||||||
}
|
value = message.attachments[indexAttachment].id;
|
||||||
break;
|
resolved.attachments[value] = message.attachments[indexAttachment];
|
||||||
case ApplicationCommandOptionType.Boolean:
|
}
|
||||||
if (args[i.name]) {
|
break;
|
||||||
value = ['yes', 'y', 'true', 'treu'].includes(args[i.name]!.toLowerCase());
|
case ApplicationCommandOptionType.Boolean:
|
||||||
}
|
if (args[i.name]) {
|
||||||
break;
|
value = ['yes', 'y', 'true', 'treu'].includes(args[i.name]!.toLowerCase());
|
||||||
case ApplicationCommandOptionType.Channel:
|
}
|
||||||
{
|
break;
|
||||||
const rawId =
|
case ApplicationCommandOptionType.Channel:
|
||||||
message.content.match(/(?<=<#)[0-9]{17,19}(?=>)/g)?.find(x => args[i.name]?.includes(x)) ||
|
{
|
||||||
args[i.name]?.match(/[0-9]{17,19}/g)?.[0];
|
const rawId =
|
||||||
if (rawId) {
|
message.content.match(/(?<=<#)[0-9]{17,19}(?=>)/g)?.find(x => args[i.name]?.includes(x)) ||
|
||||||
const channel =
|
args[i.name]?.match(/[0-9]{17,19}/g)?.[0];
|
||||||
(await self.cache.channels?.get(rawId)) ?? (i.required ? await self.channels.fetch(rawId) : undefined);
|
if (rawId) {
|
||||||
if (channel) {
|
const channel =
|
||||||
if ('channel_types' in i) {
|
(await self.cache.channels?.get(rawId)) ?? (i.required ? await self.channels.fetch(rawId) : undefined);
|
||||||
if (!(i as SeyfertChannelOption).channel_types!.includes(channel.type)) {
|
if (channel) {
|
||||||
errors.push({
|
if ('channel_types' in i) {
|
||||||
name: i.name,
|
if (!(i as SeyfertChannelOption).channel_types!.includes(channel.type)) {
|
||||||
error: `The entered channel type is not one of ${(i as SeyfertChannelOption)
|
errors.push({
|
||||||
.channel_types!.map(t => ChannelType[t])
|
name: i.name,
|
||||||
.join(', ')}`,
|
error: `The entered channel type is not one of ${(i as SeyfertChannelOption)
|
||||||
});
|
.channel_types!.map(t => ChannelType[t])
|
||||||
break;
|
.join(', ')}`,
|
||||||
}
|
fullError: ['CHANNEL_TYPES', (i as SeyfertChannelOption).channel_types!],
|
||||||
}
|
});
|
||||||
value = rawId;
|
break;
|
||||||
resolved.channels[rawId] = channel;
|
}
|
||||||
}
|
}
|
||||||
}
|
value = rawId;
|
||||||
}
|
resolved.channels[rawId] = channel;
|
||||||
break;
|
}
|
||||||
case ApplicationCommandOptionType.Mentionable:
|
}
|
||||||
{
|
}
|
||||||
const matches = message.content.match(/<@[0-9]{17,19}(?=>)|<@&[0-9]{17,19}(?=>)/g) ?? [];
|
break;
|
||||||
for (const match of matches) {
|
case ApplicationCommandOptionType.Mentionable:
|
||||||
if (match.includes('&')) {
|
{
|
||||||
const rawId = match.slice(3);
|
const matches = message.content.match(/<@[0-9]{17,19}(?=>)|<@&[0-9]{17,19}(?=>)/g) ?? [];
|
||||||
if (rawId) {
|
for (const match of matches) {
|
||||||
const role =
|
if (match.includes('&')) {
|
||||||
(await self.cache.roles?.get(rawId)) ??
|
const rawId = match.slice(3);
|
||||||
(i.required ? (await self.roles.list(message.guild_id!)).find(x => x.id === rawId) : undefined);
|
if (rawId) {
|
||||||
if (role) {
|
const role =
|
||||||
value = rawId;
|
(await self.cache.roles?.get(rawId)) ??
|
||||||
resolved.roles[rawId] = role;
|
(i.required ? (await self.roles.list(message.guild_id!)).find(x => x.id === rawId) : undefined);
|
||||||
break;
|
if (role) {
|
||||||
}
|
value = rawId;
|
||||||
}
|
resolved.roles[rawId] = role;
|
||||||
} else {
|
break;
|
||||||
const rawId = match.slice(2);
|
}
|
||||||
const raw = message.mentions.find(x => rawId === x.id);
|
}
|
||||||
if (raw) {
|
} else {
|
||||||
const { member, ...user } = raw;
|
const rawId = match.slice(2);
|
||||||
value = raw.id;
|
const raw = message.mentions.find(x => rawId === x.id);
|
||||||
resolved.users[raw.id] = user;
|
if (raw) {
|
||||||
if (member) resolved.members[raw.id] = member;
|
const { member, ...user } = raw;
|
||||||
break;
|
value = raw.id;
|
||||||
}
|
resolved.users[raw.id] = user;
|
||||||
}
|
if (member) resolved.members[raw.id] = member;
|
||||||
}
|
break;
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
case ApplicationCommandOptionType.Role:
|
}
|
||||||
{
|
}
|
||||||
const rawId =
|
break;
|
||||||
message.mention_roles.find(x => args[i.name]?.includes(x)) || args[i.name]?.match(/[0-9]{17,19}/g)?.[0];
|
case ApplicationCommandOptionType.Role:
|
||||||
if (rawId) {
|
{
|
||||||
const role =
|
const rawId =
|
||||||
(await self.cache.roles?.get(rawId)) ??
|
message.mention_roles.find(x => args[i.name]?.includes(x)) || args[i.name]?.match(/[0-9]{17,19}/g)?.[0];
|
||||||
(i.required ? (await self.roles.list(message.guild_id!)).find(x => x.id === rawId) : undefined);
|
if (rawId) {
|
||||||
|
const role =
|
||||||
if (role) {
|
(await self.cache.roles?.get(rawId)) ??
|
||||||
value = rawId;
|
(i.required ? (await self.roles.list(message.guild_id!)).find(x => x.id === rawId) : undefined);
|
||||||
resolved.roles[rawId] = role;
|
|
||||||
}
|
if (role) {
|
||||||
}
|
value = rawId;
|
||||||
}
|
resolved.roles[rawId] = role;
|
||||||
break;
|
}
|
||||||
case ApplicationCommandOptionType.User:
|
}
|
||||||
{
|
}
|
||||||
const rawId =
|
break;
|
||||||
message.mentions.find(x => args[i.name]?.includes(x.id))?.id || args[i.name]?.match(/[0-9]{17,19}/g)?.[0];
|
case ApplicationCommandOptionType.User:
|
||||||
if (rawId) {
|
{
|
||||||
const raw =
|
const rawId =
|
||||||
message.mentions.find(x => args[i.name]?.includes(x.id)) ??
|
message.mentions.find(x => args[i.name]?.includes(x.id))?.id || args[i.name]?.match(/[0-9]{17,19}/g)?.[0];
|
||||||
(await self.cache.users?.get(rawId)) ??
|
if (rawId) {
|
||||||
(i.required ? await self.users.fetch(rawId) : undefined);
|
const raw =
|
||||||
if (raw) {
|
message.mentions.find(x => args[i.name]?.includes(x.id)) ??
|
||||||
value = raw.id;
|
(await self.cache.users?.get(rawId)) ??
|
||||||
if (raw instanceof User) {
|
(i.required ? await self.users.fetch(rawId) : undefined);
|
||||||
resolved.users[raw.id] = raw;
|
if (raw) {
|
||||||
if (message.guild_id) {
|
value = raw.id;
|
||||||
const member =
|
if (raw instanceof User) {
|
||||||
message.mentions.find(x => args[i.name]?.includes(x.id))?.member ??
|
resolved.users[raw.id] = raw;
|
||||||
(await self.cache.members?.get(rawId, message.guild_id)) ??
|
if (message.guild_id) {
|
||||||
(i.required ? await self.members.fetch(rawId, message.guild_id) : undefined);
|
const member =
|
||||||
if (member) resolved.members[raw.id] = member;
|
message.mentions.find(x => args[i.name]?.includes(x.id))?.member ??
|
||||||
}
|
(await self.cache.members?.get(rawId, message.guild_id)) ??
|
||||||
} else {
|
(i.required ? await self.members.fetch(rawId, message.guild_id) : undefined);
|
||||||
const { member, ...user } = raw;
|
if (member) resolved.members[raw.id] = member;
|
||||||
resolved.users[user.id] = user;
|
}
|
||||||
if (member) resolved.members[user.id] = member;
|
} else {
|
||||||
}
|
const { member, ...user } = raw;
|
||||||
}
|
resolved.users[user.id] = user;
|
||||||
}
|
if (member) resolved.members[user.id] = member;
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
case ApplicationCommandOptionType.String:
|
}
|
||||||
{
|
}
|
||||||
value = args[i.name];
|
break;
|
||||||
const option = i as SeyfertStringOption;
|
case ApplicationCommandOptionType.String:
|
||||||
if (!value) break;
|
{
|
||||||
if (option.min_length) {
|
value = args[i.name];
|
||||||
if (value.length < option.min_length) {
|
const option = i as SeyfertStringOption;
|
||||||
value = undefined;
|
if (!value) break;
|
||||||
errors.push({
|
if (option.min_length) {
|
||||||
name: i.name,
|
if (value.length < option.min_length) {
|
||||||
error: `The entered string has less than ${option.min_length} characters. The minimum required is ${option.min_length} characters.`,
|
value = undefined;
|
||||||
});
|
errors.push({
|
||||||
break;
|
name: i.name,
|
||||||
}
|
error: `The entered string has less than ${option.min_length} characters. The minimum required is ${option.min_length} characters.`,
|
||||||
}
|
fullError: ['STRING_MIN_LENGTH', option.min_length],
|
||||||
if (option.max_length) {
|
});
|
||||||
if (value.length > option.max_length) {
|
break;
|
||||||
value = undefined;
|
}
|
||||||
errors.push({
|
}
|
||||||
name: i.name,
|
if (option.max_length) {
|
||||||
error: `The entered string has more than ${option.max_length} characters. The maximum required is ${option.max_length} characters.`,
|
if (value.length > option.max_length) {
|
||||||
});
|
value = undefined;
|
||||||
break;
|
errors.push({
|
||||||
}
|
name: i.name,
|
||||||
}
|
error: `The entered string has more than ${option.max_length} characters. The maximum required is ${option.max_length} characters.`,
|
||||||
if (option.choices?.length) {
|
fullError: ['STRING_MAX_LENGTH', option.max_length],
|
||||||
const choice = option.choices.find(x => x.name === value);
|
});
|
||||||
if (!choice) {
|
break;
|
||||||
value = undefined;
|
}
|
||||||
errors.push({
|
}
|
||||||
name: i.name,
|
if (option.choices?.length) {
|
||||||
error: `The entered choice is invalid. Please choose one of the following options: ${option.choices
|
const choice = option.choices.find(x => x.name === value);
|
||||||
.map(x => x.name)
|
if (!choice) {
|
||||||
.join(', ')}.`,
|
value = undefined;
|
||||||
});
|
errors.push({
|
||||||
break;
|
name: i.name,
|
||||||
}
|
error: `The entered choice is invalid. Please choose one of the following options: ${option.choices
|
||||||
value = choice.value;
|
.map(x => x.name)
|
||||||
}
|
.join(', ')}.`,
|
||||||
}
|
fullError: ['STRING_INVALID_CHOICE', option.choices],
|
||||||
break;
|
});
|
||||||
case ApplicationCommandOptionType.Number:
|
break;
|
||||||
case ApplicationCommandOptionType.Integer:
|
}
|
||||||
{
|
value = choice.value;
|
||||||
const option = i as SeyfertNumberOption | SeyfertIntegerOption;
|
}
|
||||||
if (!option.choices?.length) {
|
}
|
||||||
value = Number(args[i.name]);
|
break;
|
||||||
if (args[i.name] === undefined) {
|
case ApplicationCommandOptionType.Number:
|
||||||
value = undefined;
|
case ApplicationCommandOptionType.Integer:
|
||||||
break;
|
{
|
||||||
}
|
const option = i as SeyfertNumberOption | SeyfertIntegerOption;
|
||||||
if (Number.isNaN(value)) {
|
if (!option.choices?.length) {
|
||||||
value = undefined;
|
value = Number(args[i.name]);
|
||||||
errors.push({
|
if (args[i.name] === undefined) {
|
||||||
name: i.name,
|
value = undefined;
|
||||||
error: 'The entered choice is an invalid number.',
|
break;
|
||||||
});
|
}
|
||||||
break;
|
if (Number.isNaN(value)) {
|
||||||
}
|
value = undefined;
|
||||||
if (option.min_value) {
|
errors.push({
|
||||||
if (value < option.min_value) {
|
name: i.name,
|
||||||
value = undefined;
|
error: 'The entered choice is an invalid number.',
|
||||||
errors.push({
|
fullError: ['NUMBER_NAN', args[i.name]],
|
||||||
name: i.name,
|
});
|
||||||
error: `The entered number is less than ${option.min_value}. The minimum allowed is ${option.min_value}`,
|
break;
|
||||||
});
|
}
|
||||||
break;
|
if (option.min_value) {
|
||||||
}
|
if (value < option.min_value) {
|
||||||
}
|
value = undefined;
|
||||||
if (option.max_value) {
|
errors.push({
|
||||||
if (value > option.max_value) {
|
name: i.name,
|
||||||
value = undefined;
|
error: `The entered number is less than ${option.min_value}. The minimum allowed is ${option.min_value}`,
|
||||||
errors.push({
|
fullError: ['NUMBER_MIN_VALUE', option.min_value],
|
||||||
name: i.name,
|
});
|
||||||
error: `The entered number is greater than ${option.max_value}. The maximum allowed is ${option.max_value}`,
|
break;
|
||||||
});
|
}
|
||||||
break;
|
}
|
||||||
}
|
if (option.max_value) {
|
||||||
}
|
if (value > option.max_value) {
|
||||||
break;
|
value = undefined;
|
||||||
}
|
errors.push({
|
||||||
const choice = option.choices.find(x => x.name === args[i.name]);
|
name: i.name,
|
||||||
if (!choice) {
|
error: `The entered number is greater than ${option.max_value}. The maximum allowed is ${option.max_value}`,
|
||||||
value = undefined;
|
fullError: ['NUMBER_MAX_VALUE', option.max_value],
|
||||||
errors.push({
|
});
|
||||||
name: i.name,
|
break;
|
||||||
error: `The entered choice is invalid. Please choose one of the following options: ${option.choices
|
}
|
||||||
.map(x => x.name)
|
}
|
||||||
.join(', ')}.`,
|
break;
|
||||||
});
|
}
|
||||||
break;
|
const choice = option.choices.find(x => x.name === args[i.name]);
|
||||||
}
|
if (!choice) {
|
||||||
value = choice.value;
|
value = undefined;
|
||||||
}
|
errors.push({
|
||||||
break;
|
name: i.name,
|
||||||
default:
|
error: `The entered choice is invalid. Please choose one of the following options: ${option.choices
|
||||||
break;
|
.map(x => x.name)
|
||||||
}
|
.join(', ')}.`,
|
||||||
if (value !== undefined) {
|
fullError: ['NUMBER_INVALID_CHOICE', option.choices],
|
||||||
options.push({
|
});
|
||||||
name: i.name,
|
break;
|
||||||
type: i.type,
|
}
|
||||||
value,
|
value = choice.value;
|
||||||
} as APIApplicationCommandInteractionDataOption);
|
}
|
||||||
} else if (i.required)
|
break;
|
||||||
if (!errors.some(x => x.name === i.name))
|
default:
|
||||||
errors.push({
|
break;
|
||||||
error: 'Option is required but returned undefined',
|
}
|
||||||
name: i.name,
|
if (value !== undefined) {
|
||||||
});
|
options.push({
|
||||||
} catch (e) {
|
name: i.name,
|
||||||
errors.push({
|
type: i.type,
|
||||||
error: e && typeof e === 'object' && 'message' in e ? (e.message as string) : `${e}`,
|
value,
|
||||||
name: i.name,
|
} as APIApplicationCommandInteractionDataOption);
|
||||||
});
|
} else if (i.required)
|
||||||
}
|
if (!errors.some(x => x.name === i.name))
|
||||||
}
|
errors.push({
|
||||||
|
error: 'Option is required but returned undefined',
|
||||||
return { errors, options };
|
name: i.name,
|
||||||
}
|
fullError: ['OPTION_REQUIRED'],
|
||||||
|
});
|
||||||
function defaultArgsParser(content: string) {
|
} catch (e) {
|
||||||
const args: Record<string, string> = {};
|
errors.push({
|
||||||
for (const i of content.match(/-(.*?)(?=\s-|$)/gs) ?? []) {
|
error: e && typeof e === 'object' && 'message' in e ? (e.message as string) : `${e}`,
|
||||||
args[i.slice(1).split(' ')[0]] = i.split(' ').slice(1).join(' ');
|
name: i.name,
|
||||||
}
|
fullError: ['UNKNOWN', e],
|
||||||
return args;
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
//-(.*?)(?=\s-|$)/gs
|
|
||||||
//-(?<text>[^-]*)/gm
|
return { errors, options };
|
||||||
|
}
|
||||||
|
|
||||||
|
export function defaultArgsParser(content: string) {
|
||||||
|
const args: Record<string, string> = {};
|
||||||
|
for (const i of content.match(/-(.*?)(?=\s-|$)/gs) ?? []) {
|
||||||
|
args[i.slice(1).split(' ')[0]] = i.split(' ').slice(1).join(' ');
|
||||||
|
}
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-(.*?)(?=\s-|$)/gs
|
||||||
|
//-(?<text>[^-]*)/gm
|
||||||
|
@ -31,6 +31,7 @@ import type {
|
|||||||
StopFunction,
|
StopFunction,
|
||||||
UsingClient,
|
UsingClient,
|
||||||
} from './shared';
|
} from './shared';
|
||||||
|
import { inspect } from 'node:util';
|
||||||
|
|
||||||
export interface ReturnOptionsTypes {
|
export interface ReturnOptionsTypes {
|
||||||
1: never; // subcommand
|
1: never; // subcommand
|
||||||
@ -153,9 +154,15 @@ export class BaseCommand {
|
|||||||
const value =
|
const value =
|
||||||
resolver.getHoisted(i.name)?.value !== undefined
|
resolver.getHoisted(i.name)?.value !== undefined
|
||||||
? await new Promise(
|
? await new Promise(
|
||||||
(res, rej) =>
|
// biome-ignore lint/suspicious/noAsyncPromiseExecutor: yes
|
||||||
option.value?.({ context: ctx, value: resolver.getValue(i.name) } as never, res, rej) ||
|
async (res, rej) => {
|
||||||
res(resolver.getValue(i.name)),
|
try {
|
||||||
|
(await option.value?.({ context: ctx, value: resolver.getValue(i.name) } as never, res, rej)) ||
|
||||||
|
res(resolver.getValue(i.name));
|
||||||
|
} catch (e) {
|
||||||
|
rej(e);
|
||||||
|
}
|
||||||
|
},
|
||||||
)
|
)
|
||||||
: undefined;
|
: undefined;
|
||||||
if (value === undefined) {
|
if (value === undefined) {
|
||||||
@ -178,7 +185,7 @@ export class BaseCommand {
|
|||||||
errored = true;
|
errored = true;
|
||||||
data[i.name] = {
|
data[i.name] = {
|
||||||
failed: true,
|
failed: true,
|
||||||
value: e instanceof Error ? e.message : `${e}`,
|
value: e instanceof Error ? e.message : typeof e === 'string' ? e : inspect(e),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,59 +1,74 @@
|
|||||||
import type { BaseClient } from '../../client/base';
|
import type { ChannelType } from 'discord-api-types/v10';
|
||||||
import type { IsStrictlyUndefined } from '../../common';
|
import type { BaseClient } from '../../client/base';
|
||||||
import type { RegisteredMiddlewares } from '../decorators';
|
import type { IsStrictlyUndefined } from '../../common';
|
||||||
|
import type { RegisteredMiddlewares } from '../decorators';
|
||||||
export type OKFunction<T> = (value: T) => void;
|
|
||||||
export type StopFunction = (error: string) => void;
|
export type OKFunction<T> = (value: T) => void;
|
||||||
export type NextFunction<T = unknown> = IsStrictlyUndefined<T> extends true ? () => void : (data: T) => void;
|
export type StopFunction = (error: string) => void;
|
||||||
export type PassFunction = () => void;
|
export type NextFunction<T = unknown> = IsStrictlyUndefined<T> extends true ? () => void : (data: T) => void;
|
||||||
|
export type PassFunction = () => void;
|
||||||
export type InferWithPrefix = InternalOptions extends { withPrefix: infer P } ? P : false;
|
|
||||||
|
export type InferWithPrefix = InternalOptions extends { withPrefix: infer P } ? P : false;
|
||||||
export interface GlobalMetadata {}
|
|
||||||
export interface DefaultLocale {}
|
export interface GlobalMetadata {}
|
||||||
export interface ExtendContext {}
|
export interface DefaultLocale {}
|
||||||
export interface UsingClient extends BaseClient {}
|
export interface ExtendContext {}
|
||||||
export type ParseClient<T extends BaseClient> = T;
|
export interface UsingClient extends BaseClient {}
|
||||||
export interface InternalOptions {}
|
export type ParseClient<T extends BaseClient> = T;
|
||||||
|
export interface InternalOptions {}
|
||||||
export type MiddlewareContext<T = any, C = any> = (context: {
|
|
||||||
context: C;
|
export type MiddlewareContext<T = any, C = any> = (context: {
|
||||||
next: NextFunction<T>;
|
context: C;
|
||||||
stop: StopFunction;
|
next: NextFunction<T>;
|
||||||
pass: PassFunction;
|
stop: StopFunction;
|
||||||
}) => any;
|
pass: PassFunction;
|
||||||
export type MetadataMiddleware<T extends MiddlewareContext> = IsStrictlyUndefined<
|
}) => any;
|
||||||
Parameters<Parameters<T>[0]['next']>[0]
|
export type MetadataMiddleware<T extends MiddlewareContext> = IsStrictlyUndefined<
|
||||||
> extends true
|
Parameters<Parameters<T>[0]['next']>[0]
|
||||||
? never
|
> extends true
|
||||||
: Parameters<Parameters<T>[0]['next']>[0];
|
? never
|
||||||
export type CommandMetadata<T extends readonly (keyof RegisteredMiddlewares)[]> = T extends readonly [
|
: Parameters<Parameters<T>[0]['next']>[0];
|
||||||
infer first,
|
export type CommandMetadata<T extends readonly (keyof RegisteredMiddlewares)[]> = T extends readonly [
|
||||||
...infer rest,
|
infer first,
|
||||||
]
|
...infer rest,
|
||||||
? first extends keyof RegisteredMiddlewares
|
]
|
||||||
? (MetadataMiddleware<RegisteredMiddlewares[first]> extends never
|
? first extends keyof RegisteredMiddlewares
|
||||||
? {}
|
? (MetadataMiddleware<RegisteredMiddlewares[first]> extends never
|
||||||
: {
|
? {}
|
||||||
[key in first]: MetadataMiddleware<RegisteredMiddlewares[first]>;
|
: {
|
||||||
}) &
|
[key in first]: MetadataMiddleware<RegisteredMiddlewares[first]>;
|
||||||
(rest extends readonly (keyof RegisteredMiddlewares)[] ? CommandMetadata<rest> : {})
|
}) &
|
||||||
: {}
|
(rest extends readonly (keyof RegisteredMiddlewares)[] ? CommandMetadata<rest> : {})
|
||||||
: {};
|
: {}
|
||||||
|
: {};
|
||||||
export type OnOptionsReturnObject = Record<
|
|
||||||
string,
|
export type MessageCommandOptionErrors =
|
||||||
| {
|
| ['CHANNEL_TYPES', type: ChannelType[]]
|
||||||
failed: false;
|
| ['STRING_MIN_LENGTH', min: number]
|
||||||
value: unknown;
|
| ['STRING_MAX_LENGTH', max: number]
|
||||||
}
|
| ['STRING_INVALID_CHOICE', choices: readonly { name: string; value: string }[]]
|
||||||
| {
|
| ['NUMBER_NAN', value: string | undefined]
|
||||||
failed: true;
|
| ['NUMBER_MIN_VALUE', min: number]
|
||||||
value: string;
|
| ['NUMBER_MAX_VALUE', max: number]
|
||||||
}
|
| ['NUMBER_INVALID_CHOICE', choices: readonly { name: string; value: number }[]]
|
||||||
>;
|
| ['OPTION_REQUIRED']
|
||||||
|
| ['UNKNOWN', error: unknown];
|
||||||
export enum IgnoreCommand {
|
|
||||||
Slash = 0,
|
export type OnOptionsReturnObject = Record<
|
||||||
Message = 1,
|
string,
|
||||||
}
|
| {
|
||||||
|
failed: false;
|
||||||
|
value: unknown;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
failed: true;
|
||||||
|
value: string;
|
||||||
|
parseError?: //only for text command
|
||||||
|
MessageCommandOptionErrors;
|
||||||
|
}
|
||||||
|
>;
|
||||||
|
|
||||||
|
export enum IgnoreCommand {
|
||||||
|
Slash = 0,
|
||||||
|
Message = 1,
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user