mirror of
https://github.com/tiramisulabs/seyfert.git
synced 2025-07-04 14:06:07 +00:00
feat: componentcommand and modalcommand now can use middlewares
This commit is contained in:
parent
3a780ea347
commit
23422cadfa
@ -17,6 +17,7 @@ import type {
|
|||||||
} from '../structures';
|
} from '../structures';
|
||||||
import { AutocompleteInteraction, BaseInteraction } from '../structures';
|
import { AutocompleteInteraction, BaseInteraction } from '../structures';
|
||||||
import type { BaseClient } from './base';
|
import type { BaseClient } from './base';
|
||||||
|
import { ModalContext } from '../components';
|
||||||
|
|
||||||
export async function onInteractionCreate(
|
export async function onInteractionCreate(
|
||||||
self: BaseClient,
|
self: BaseClient,
|
||||||
@ -97,7 +98,7 @@ export async function onInteractionCreate(
|
|||||||
...interaction.appPermissions.values([command.botPermissions]),
|
...interaction.appPermissions.values([command.botPermissions]),
|
||||||
);
|
);
|
||||||
if (!interaction.appPermissions.has('Administrator') && permissions.length) {
|
if (!interaction.appPermissions.has('Administrator') && permissions.length) {
|
||||||
return command.onBotPermissionsFail?.(context, interaction.appPermissions.keys(permissions));
|
return command.onBotPermissionsFail(context, interaction.appPermissions.keys(permissions));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const resultRunGlobalMiddlewares = await command.__runGlobalMiddlewares(context);
|
const resultRunGlobalMiddlewares = await command.__runGlobalMiddlewares(context);
|
||||||
@ -120,7 +121,7 @@ export async function onInteractionCreate(
|
|||||||
await command.run(context);
|
await command.run(context);
|
||||||
await command.onAfterRun?.(context, undefined);
|
await command.onAfterRun?.(context, undefined);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
await command.onRunError?.(context, error);
|
await command.onRunError(context, error);
|
||||||
await command.onAfterRun?.(context, error);
|
await command.onAfterRun?.(context, error);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -208,7 +209,7 @@ export async function onInteractionCreate(
|
|||||||
if (self.components?.hasModal(interaction)) {
|
if (self.components?.hasModal(interaction)) {
|
||||||
await self.components.onModalSubmit(interaction);
|
await self.components.onModalSubmit(interaction);
|
||||||
} else {
|
} else {
|
||||||
await self.components?.executeModal(interaction);
|
await self.components?.executeModal(new ModalContext(self, interaction));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -60,7 +60,7 @@ export class MenuCommandContext<
|
|||||||
}
|
}
|
||||||
|
|
||||||
get t() {
|
get t() {
|
||||||
return this.client.langs!.get(this.interaction.locale ?? this.client.langs!.defaultLang ?? 'en-US');
|
return this.client.t(this.interaction.locale ?? this.client.langs!.defaultLang ?? 'en-US');
|
||||||
}
|
}
|
||||||
|
|
||||||
get fullCommandName() {
|
get fullCommandName() {
|
||||||
|
@ -13,6 +13,8 @@ import type {
|
|||||||
import type { MessageCommandInteraction, UserCommandInteraction } from '../../structures';
|
import type { MessageCommandInteraction, UserCommandInteraction } from '../../structures';
|
||||||
import type { CommandContext } from './chatcontext';
|
import type { CommandContext } from './chatcontext';
|
||||||
import type { MiddlewareContext } from './shared';
|
import type { MiddlewareContext } from './shared';
|
||||||
|
import type { ModalContext } from '../../components';
|
||||||
|
import type { ComponentContext } from '../../components/componentcontext';
|
||||||
|
|
||||||
export type SeyfertBasicOption<T extends keyof __TypesWrapper, D = {}> = __TypesWrapper[T] & D;
|
export type SeyfertBasicOption<T extends keyof __TypesWrapper, D = {}> = __TypesWrapper[T] & D;
|
||||||
|
|
||||||
@ -86,9 +88,15 @@ export function createAttachmentOption<T extends SeyfertAttachmentOption = Seyfe
|
|||||||
|
|
||||||
export function createMiddleware<
|
export function createMiddleware<
|
||||||
T = any,
|
T = any,
|
||||||
C extends CommandContext | MenuCommandContext<MessageCommandInteraction<boolean> | UserCommandInteraction<boolean>> =
|
C extends
|
||||||
| CommandContext
|
| CommandContext
|
||||||
| MenuCommandContext<MessageCommandInteraction<boolean> | UserCommandInteraction<boolean>>,
|
| MenuCommandContext<MessageCommandInteraction<boolean> | UserCommandInteraction<boolean>>
|
||||||
|
| ComponentContext
|
||||||
|
| ModalContext =
|
||||||
|
| CommandContext
|
||||||
|
| MenuCommandContext<MessageCommandInteraction<boolean> | UserCommandInteraction<boolean>>
|
||||||
|
| ComponentContext
|
||||||
|
| ModalContext,
|
||||||
>(data: MiddlewareContext<T, C>) {
|
>(data: MiddlewareContext<T, C>) {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import type { ModalContext } from '../components';
|
||||||
import type { ContextComponentCommandInteractionMap, ComponentContext } from '../components/componentcontext';
|
import type { ContextComponentCommandInteractionMap, ComponentContext } from '../components/componentcontext';
|
||||||
import type { MessageCommandInteraction, UserCommandInteraction } from '../structures';
|
import type { MessageCommandInteraction, UserCommandInteraction } from '../structures';
|
||||||
import type { CommandContext } from './applications/chatcontext';
|
import type { CommandContext } from './applications/chatcontext';
|
||||||
@ -7,6 +8,9 @@ import type { UsingClient } from './applications/shared';
|
|||||||
export class BaseContext {
|
export class BaseContext {
|
||||||
constructor(readonly client: UsingClient) {}
|
constructor(readonly client: UsingClient) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the proxy object.
|
||||||
|
*/
|
||||||
get proxy() {
|
get proxy() {
|
||||||
return this.client.proxy;
|
return this.client.proxy;
|
||||||
}
|
}
|
||||||
@ -30,4 +34,8 @@ export class BaseContext {
|
|||||||
isComponent(): this is ComponentContext<keyof ContextComponentCommandInteractionMap> {
|
isComponent(): this is ComponentContext<keyof ContextComponentCommandInteractionMap> {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isModal(): this is ModalContext {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,33 +0,0 @@
|
|||||||
import { ComponentType } from 'discord-api-types/v10';
|
|
||||||
import type { ModalSubmitInteraction } from '../structures';
|
|
||||||
import type { ContextComponentCommandInteractionMap, ComponentContext } from './componentcontext';
|
|
||||||
|
|
||||||
export const InteractionCommandType = {
|
|
||||||
COMPONENT: 0,
|
|
||||||
MODAL: 1,
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export interface ComponentCommand {
|
|
||||||
__filePath?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export abstract class ComponentCommand {
|
|
||||||
type = InteractionCommandType.COMPONENT;
|
|
||||||
abstract componentType: keyof ContextComponentCommandInteractionMap;
|
|
||||||
abstract filter(interaction: ComponentContext<typeof this.componentType>): Promise<boolean> | boolean;
|
|
||||||
abstract run(interaction: ComponentContext<typeof this.componentType>): any;
|
|
||||||
|
|
||||||
get cType(): number {
|
|
||||||
return ComponentType[this.componentType];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ModalCommand {
|
|
||||||
__filePath?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export abstract class ModalCommand {
|
|
||||||
type = InteractionCommandType.MODAL;
|
|
||||||
abstract filter(interaction: ModalSubmitInteraction): Promise<boolean> | boolean;
|
|
||||||
abstract run(interaction: ModalSubmitInteraction): any;
|
|
||||||
}
|
|
95
src/components/componentcommand.ts
Normal file
95
src/components/componentcommand.ts
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
import { ComponentType } from 'discord-api-types/v10';
|
||||||
|
import type { ContextComponentCommandInteractionMap, ComponentContext } from './componentcontext';
|
||||||
|
import type { PassFunction, RegisteredMiddlewares, StopFunction, UsingClient } from '../commands';
|
||||||
|
|
||||||
|
export const InteractionCommandType = {
|
||||||
|
COMPONENT: 0,
|
||||||
|
MODAL: 1,
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export interface ComponentCommand {
|
||||||
|
__filePath?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export abstract class ComponentCommand {
|
||||||
|
type = InteractionCommandType.COMPONENT;
|
||||||
|
abstract componentType: keyof ContextComponentCommandInteractionMap;
|
||||||
|
abstract filter(context: ComponentContext<typeof this.componentType>): Promise<boolean> | boolean;
|
||||||
|
abstract run(context: ComponentContext<typeof this.componentType>): any;
|
||||||
|
|
||||||
|
get cType(): number {
|
||||||
|
return ComponentType[this.componentType];
|
||||||
|
}
|
||||||
|
|
||||||
|
onAfterRun?(context: ComponentContext, error: unknown | undefined): any;
|
||||||
|
onRunError(context: ComponentContext, error: unknown): any {
|
||||||
|
context.client.logger.fatal('ComponentCommand.<onRunError>', context.author.id, error);
|
||||||
|
}
|
||||||
|
onMiddlewaresError(context: ComponentContext, error: string): any {
|
||||||
|
context.client.logger.fatal('ComponentCommand.<onMiddlewaresError>', context.author.id, error);
|
||||||
|
}
|
||||||
|
onInternalError(client: UsingClient, error?: unknown): any {
|
||||||
|
client.logger.fatal(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
middlewares: (keyof RegisteredMiddlewares)[] = [];
|
||||||
|
/** @internal */
|
||||||
|
static __runMiddlewares(
|
||||||
|
context: ComponentContext,
|
||||||
|
middlewares: (keyof RegisteredMiddlewares)[],
|
||||||
|
global: boolean,
|
||||||
|
): Promise<{ error?: string; pass?: boolean }> {
|
||||||
|
if (!middlewares.length) {
|
||||||
|
return Promise.resolve({});
|
||||||
|
}
|
||||||
|
let index = 0;
|
||||||
|
|
||||||
|
return new Promise(res => {
|
||||||
|
let running = true;
|
||||||
|
const pass: PassFunction = () => {
|
||||||
|
if (!running) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
running = false;
|
||||||
|
return res({ pass: true });
|
||||||
|
};
|
||||||
|
function next(obj: any) {
|
||||||
|
if (!running) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// biome-ignore lint/style/noArguments: yes
|
||||||
|
if (arguments.length) {
|
||||||
|
// @ts-expect-error
|
||||||
|
context[global ? 'globalMetadata' : 'metadata'][middlewares[index]] = obj;
|
||||||
|
}
|
||||||
|
if (++index >= middlewares.length) {
|
||||||
|
running = false;
|
||||||
|
return res({});
|
||||||
|
}
|
||||||
|
context.client.middlewares![middlewares[index]]({ context, next, stop, pass });
|
||||||
|
}
|
||||||
|
const stop: StopFunction = err => {
|
||||||
|
if (!running) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
running = false;
|
||||||
|
return res({ error: err });
|
||||||
|
};
|
||||||
|
context.client.middlewares![middlewares[0]]({ context, next, stop, pass });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @internal */
|
||||||
|
__runMiddlewares(context: ComponentContext) {
|
||||||
|
return ComponentCommand.__runMiddlewares(context, this.middlewares as (keyof RegisteredMiddlewares)[], false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @internal */
|
||||||
|
__runGlobalMiddlewares(context: ComponentContext) {
|
||||||
|
return ComponentCommand.__runMiddlewares(
|
||||||
|
context,
|
||||||
|
(context.client.options?.globalMiddlewares ?? []) as (keyof RegisteredMiddlewares)[],
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -13,13 +13,14 @@ import type {
|
|||||||
UserSelectMenuInteraction,
|
UserSelectMenuInteraction,
|
||||||
WebhookMessage,
|
WebhookMessage,
|
||||||
} from '..';
|
} from '..';
|
||||||
import type { ExtendContext, UsingClient } from '../commands';
|
import type { CommandMetadata, ExtendContext, GlobalMetadata, RegisteredMiddlewares, UsingClient } from '../commands';
|
||||||
import { BaseContext } from '../commands/basecontext';
|
import { BaseContext } from '../commands/basecontext';
|
||||||
import type {
|
import type {
|
||||||
ComponentInteractionMessageUpdate,
|
ComponentInteractionMessageUpdate,
|
||||||
InteractionCreateBodyRequest,
|
InteractionCreateBodyRequest,
|
||||||
InteractionMessageUpdateBodyRequest,
|
InteractionMessageUpdateBodyRequest,
|
||||||
ModalCreateBodyRequest,
|
ModalCreateBodyRequest,
|
||||||
|
UnionToTuple,
|
||||||
When,
|
When,
|
||||||
} from '../common';
|
} from '../common';
|
||||||
|
|
||||||
@ -32,7 +33,10 @@ export interface ComponentContext<
|
|||||||
* Represents a context for interacting with components in a Discord bot.
|
* Represents a context for interacting with components in a Discord bot.
|
||||||
* @template Type - The type of component interaction.
|
* @template Type - The type of component interaction.
|
||||||
*/
|
*/
|
||||||
export class ComponentContext<Type extends keyof ContextComponentCommandInteractionMap> extends BaseContext {
|
export class ComponentContext<
|
||||||
|
Type extends keyof ContextComponentCommandInteractionMap,
|
||||||
|
M extends keyof RegisteredMiddlewares = never,
|
||||||
|
> extends BaseContext {
|
||||||
/**
|
/**
|
||||||
* Creates a new instance of the ComponentContext class.
|
* Creates a new instance of the ComponentContext class.
|
||||||
* @param client - The UsingClient instance.
|
* @param client - The UsingClient instance.
|
||||||
@ -45,18 +49,14 @@ export class ComponentContext<Type extends keyof ContextComponentCommandInteract
|
|||||||
super(client);
|
super(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
metadata: CommandMetadata<UnionToTuple<M>> = {} as never;
|
||||||
* Gets the proxy object.
|
globalMetadata: GlobalMetadata = {};
|
||||||
*/
|
|
||||||
get proxy() {
|
|
||||||
return this.client.proxy;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the language object for the interaction's locale.
|
* Gets the language object for the interaction's locale.
|
||||||
*/
|
*/
|
||||||
get t() {
|
get t() {
|
||||||
return this.client.langs!.get(this.interaction?.locale ?? this.client.langs?.defaultLang ?? 'en-US');
|
return this.client.t(this.interaction?.locale ?? this.client.langs?.defaultLang ?? 'en-US');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -3,8 +3,10 @@ import { LimitedCollection } from '../collection';
|
|||||||
import type { UsingClient } from '../commands';
|
import type { UsingClient } from '../commands';
|
||||||
import { BaseHandler, magicImport, type Logger, type OnFailCallback } from '../common';
|
import { BaseHandler, magicImport, type Logger, type OnFailCallback } from '../common';
|
||||||
import type { ComponentInteraction, ModalSubmitInteraction, StringSelectMenuInteraction } from '../structures';
|
import type { ComponentInteraction, ModalSubmitInteraction, StringSelectMenuInteraction } from '../structures';
|
||||||
import { ComponentCommand, InteractionCommandType, ModalCommand } from './command';
|
import { ComponentCommand, InteractionCommandType } from './componentcommand';
|
||||||
import { ComponentContext } from './componentcontext';
|
import { ComponentContext } from './componentcontext';
|
||||||
|
import { ModalCommand } from './modalcommand';
|
||||||
|
import type { ModalContext } from './modalcontext';
|
||||||
|
|
||||||
type COMPONENTS = {
|
type COMPONENTS = {
|
||||||
components: { match: string | string[] | RegExp; callback: ComponentCallback }[];
|
components: { match: string | string[] | RegExp; callback: ComponentCallback }[];
|
||||||
@ -212,7 +214,37 @@ export class ComponentHandler extends BaseHandler {
|
|||||||
const extended = this.client.options?.context?.(interaction) ?? {};
|
const extended = this.client.options?.context?.(interaction) ?? {};
|
||||||
Object.assign(context, extended);
|
Object.assign(context, extended);
|
||||||
if (!(await i.filter(context))) continue;
|
if (!(await i.filter(context))) continue;
|
||||||
|
try {
|
||||||
|
const resultRunGlobalMiddlewares = await i.__runGlobalMiddlewares(context);
|
||||||
|
if (resultRunGlobalMiddlewares.pass) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ('error' in resultRunGlobalMiddlewares) {
|
||||||
|
return i.onMiddlewaresError(context, resultRunGlobalMiddlewares.error ?? 'Unknown error');
|
||||||
|
}
|
||||||
|
|
||||||
|
const resultRunMiddlewares = await i.__runMiddlewares(context);
|
||||||
|
if (resultRunMiddlewares.pass) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ('error' in resultRunMiddlewares) {
|
||||||
|
return i.onMiddlewaresError(context, resultRunMiddlewares.error ?? 'Unknown error');
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
await i.run(context);
|
await i.run(context);
|
||||||
|
await i.onAfterRun?.(context, undefined);
|
||||||
|
} catch (error) {
|
||||||
|
await i.onRunError(context, error);
|
||||||
|
await i.onAfterRun?.(context, error);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
try {
|
||||||
|
await i.onInternalError(this.client, error);
|
||||||
|
} catch {
|
||||||
|
// supress error
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -221,11 +253,41 @@ export class ComponentHandler extends BaseHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async executeModal(interaction: ModalSubmitInteraction) {
|
async executeModal(context: ModalContext) {
|
||||||
for (const i of this.commands) {
|
for (const i of this.commands) {
|
||||||
try {
|
try {
|
||||||
if (i.type === InteractionCommandType.MODAL && (await i.filter(interaction))) {
|
if (i.type === InteractionCommandType.MODAL && (await i.filter(context))) {
|
||||||
await i.run(interaction);
|
try {
|
||||||
|
const resultRunGlobalMiddlewares = await i.__runGlobalMiddlewares(context);
|
||||||
|
if (resultRunGlobalMiddlewares.pass) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ('error' in resultRunGlobalMiddlewares) {
|
||||||
|
return i.onMiddlewaresError(context, resultRunGlobalMiddlewares.error ?? 'Unknown error');
|
||||||
|
}
|
||||||
|
|
||||||
|
const resultRunMiddlewares = await i.__runMiddlewares(context);
|
||||||
|
if (resultRunMiddlewares.pass) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ('error' in resultRunMiddlewares) {
|
||||||
|
return i.onMiddlewaresError(context, resultRunMiddlewares.error ?? 'Unknown error');
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await i.run(context);
|
||||||
|
await i.onAfterRun?.(context, undefined);
|
||||||
|
} catch (error) {
|
||||||
|
await i.onRunError(context, error);
|
||||||
|
await i.onAfterRun?.(context, error);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
try {
|
||||||
|
await i.onInternalError(this.client, error);
|
||||||
|
} catch {
|
||||||
|
// supress error
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -20,8 +20,10 @@ export type MessageComponents =
|
|||||||
|
|
||||||
export type ActionRowMessageComponents = Exclude<MessageComponents, TextInputComponent>;
|
export type ActionRowMessageComponents = Exclude<MessageComponents, TextInputComponent>;
|
||||||
|
|
||||||
export * from './command';
|
export * from './componentcommand';
|
||||||
export * from './componentcontext';
|
export * from './componentcommand';
|
||||||
|
export * from './modalcommand';
|
||||||
|
export * from './modalcontext';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a new component instance based on the component type.
|
* Return a new component instance based on the component type.
|
||||||
|
86
src/components/modalcommand.ts
Normal file
86
src/components/modalcommand.ts
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
import type { RegisteredMiddlewares, PassFunction, StopFunction, UsingClient } from '../commands';
|
||||||
|
import { InteractionCommandType } from './componentcommand';
|
||||||
|
import type { ModalContext } from './modalcontext';
|
||||||
|
|
||||||
|
export interface ModalCommand {
|
||||||
|
__filePath?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export abstract class ModalCommand {
|
||||||
|
type = InteractionCommandType.MODAL;
|
||||||
|
abstract filter(context: ModalContext): Promise<boolean> | boolean;
|
||||||
|
abstract run(context: ModalContext): any;
|
||||||
|
|
||||||
|
middlewares: (keyof RegisteredMiddlewares)[] = [];
|
||||||
|
|
||||||
|
onAfterRun?(context: ModalContext, error: unknown | undefined): any;
|
||||||
|
onRunError(context: ModalContext, error: unknown): any {
|
||||||
|
context.client.logger.fatal('ComponentCommand.<onRunError>', context.author.id, error);
|
||||||
|
}
|
||||||
|
onMiddlewaresError(context: ModalContext, error: string): any {
|
||||||
|
context.client.logger.fatal('ComponentCommand.<onMiddlewaresError>', context.author.id, error);
|
||||||
|
}
|
||||||
|
onInternalError(client: UsingClient, error?: unknown): any {
|
||||||
|
client.logger.fatal(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @internal */
|
||||||
|
static __runMiddlewares(
|
||||||
|
context: ModalContext,
|
||||||
|
middlewares: (keyof RegisteredMiddlewares)[],
|
||||||
|
global: boolean,
|
||||||
|
): Promise<{ error?: string; pass?: boolean }> {
|
||||||
|
if (!middlewares.length) {
|
||||||
|
return Promise.resolve({});
|
||||||
|
}
|
||||||
|
let index = 0;
|
||||||
|
|
||||||
|
return new Promise(res => {
|
||||||
|
let running = true;
|
||||||
|
const pass: PassFunction = () => {
|
||||||
|
if (!running) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
running = false;
|
||||||
|
return res({ pass: true });
|
||||||
|
};
|
||||||
|
function next(obj: any) {
|
||||||
|
if (!running) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// biome-ignore lint/style/noArguments: yes
|
||||||
|
if (arguments.length) {
|
||||||
|
// @ts-expect-error
|
||||||
|
context[global ? 'globalMetadata' : 'metadata'][middlewares[index]] = obj;
|
||||||
|
}
|
||||||
|
if (++index >= middlewares.length) {
|
||||||
|
running = false;
|
||||||
|
return res({});
|
||||||
|
}
|
||||||
|
context.client.middlewares![middlewares[index]]({ context, next, stop, pass });
|
||||||
|
}
|
||||||
|
const stop: StopFunction = err => {
|
||||||
|
if (!running) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
running = false;
|
||||||
|
return res({ error: err });
|
||||||
|
};
|
||||||
|
context.client.middlewares![middlewares[0]]({ context, next, stop, pass });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @internal */
|
||||||
|
__runMiddlewares(context: ModalContext) {
|
||||||
|
return ModalCommand.__runMiddlewares(context, this.middlewares as (keyof RegisteredMiddlewares)[], false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @internal */
|
||||||
|
__runGlobalMiddlewares(context: ModalContext) {
|
||||||
|
return ModalCommand.__runMiddlewares(
|
||||||
|
context,
|
||||||
|
(context.client.options?.globalMiddlewares ?? []) as (keyof RegisteredMiddlewares)[],
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
178
src/components/modalcontext.ts
Normal file
178
src/components/modalcontext.ts
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
import { MessageFlags } from 'discord-api-types/v10';
|
||||||
|
import type { AllChannels, Guild, GuildMember, Message, ModalSubmitInteraction, ReturnCache, WebhookMessage } from '..';
|
||||||
|
import type { CommandMetadata, ExtendContext, GlobalMetadata, RegisteredMiddlewares, UsingClient } from '../commands';
|
||||||
|
import { BaseContext } from '../commands/basecontext';
|
||||||
|
import type {
|
||||||
|
InteractionCreateBodyRequest,
|
||||||
|
InteractionMessageUpdateBodyRequest,
|
||||||
|
ModalCreateBodyRequest,
|
||||||
|
UnionToTuple,
|
||||||
|
When,
|
||||||
|
} from '../common';
|
||||||
|
|
||||||
|
export interface ModalContext extends BaseContext, ExtendContext {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a context for interacting with components in a Discord bot.
|
||||||
|
* @template Type - The type of component interaction.
|
||||||
|
*/
|
||||||
|
export class ModalContext<M extends keyof RegisteredMiddlewares = never> extends BaseContext {
|
||||||
|
/**
|
||||||
|
* Creates a new instance of the ComponentContext class.
|
||||||
|
* @param client - The UsingClient instance.
|
||||||
|
* @param interaction - The component interaction object.
|
||||||
|
*/
|
||||||
|
constructor(
|
||||||
|
readonly client: UsingClient,
|
||||||
|
public interaction: ModalSubmitInteraction,
|
||||||
|
) {
|
||||||
|
super(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
metadata: CommandMetadata<UnionToTuple<M>> = {} as never;
|
||||||
|
globalMetadata: GlobalMetadata = {};
|
||||||
|
|
||||||
|
get components() {
|
||||||
|
return this.interaction.components;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the language object for the interaction's locale.
|
||||||
|
*/
|
||||||
|
get t() {
|
||||||
|
return this.client.t(this.interaction?.locale ?? this.client.langs?.defaultLang ?? 'en-US');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes a response to the interaction.
|
||||||
|
* @param body - The body of the response.
|
||||||
|
* @param fetchReply - Whether to fetch the reply or not.
|
||||||
|
*/
|
||||||
|
write<FR extends boolean = false>(body: InteractionCreateBodyRequest, fetchReply?: FR) {
|
||||||
|
return this.interaction.write(body, fetchReply);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defers the reply to the interaction.
|
||||||
|
* @param ephemeral - Whether the reply should be ephemeral or not.
|
||||||
|
*/
|
||||||
|
deferReply(ephemeral = false) {
|
||||||
|
return this.interaction.deferReply(ephemeral ? MessageFlags.Ephemeral : undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Edits the response of the interaction.
|
||||||
|
* @param body - The updated body of the response.
|
||||||
|
*/
|
||||||
|
editResponse(body: InteractionMessageUpdateBodyRequest) {
|
||||||
|
return this.interaction.editResponse(body);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Edits the response or replies to the interaction.
|
||||||
|
* @param body - The body of the response or updated body of the interaction.
|
||||||
|
* @param fetchReply - Whether to fetch the reply or not.
|
||||||
|
*/
|
||||||
|
editOrReply<FR extends boolean = false>(
|
||||||
|
body: InteractionCreateBodyRequest | InteractionMessageUpdateBodyRequest,
|
||||||
|
fetchReply?: FR,
|
||||||
|
): Promise<When<FR, WebhookMessage | Message, void | WebhookMessage | Message>> {
|
||||||
|
return this.interaction.editOrReply(body as InteractionCreateBodyRequest, fetchReply);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes the response of the interaction.
|
||||||
|
* @returns A promise that resolves when the response is deleted.
|
||||||
|
*/
|
||||||
|
deleteResponse() {
|
||||||
|
return this.interaction.deleteResponse();
|
||||||
|
}
|
||||||
|
|
||||||
|
modal(body: ModalCreateBodyRequest) {
|
||||||
|
//@ts-expect-error
|
||||||
|
return this.interaction.modal(body);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the channel of the interaction.
|
||||||
|
* @param mode - The mode to fetch the channel.
|
||||||
|
* @returns A promise that resolves to the channel.
|
||||||
|
*/
|
||||||
|
channel(mode?: 'rest' | 'flow'): Promise<AllChannels>;
|
||||||
|
channel(mode?: 'cache'): ReturnCache<AllChannels>;
|
||||||
|
channel(mode: 'cache' | 'rest' | 'flow' = 'cache') {
|
||||||
|
if (this.interaction?.channel && mode === 'cache')
|
||||||
|
return this.client.cache.adapter.isAsync ? Promise.resolve(this.interaction.channel) : this.interaction.channel;
|
||||||
|
return this.client.channels.fetch(this.channelId, mode === 'rest');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the bot member in the guild of the interaction.
|
||||||
|
* @param mode - The mode to fetch the member.
|
||||||
|
* @returns A promise that resolves to the bot member.
|
||||||
|
*/
|
||||||
|
me(mode?: 'rest' | 'flow'): Promise<GuildMember>;
|
||||||
|
me(mode?: 'cache'): ReturnCache<GuildMember | undefined>;
|
||||||
|
me(mode: 'cache' | 'rest' | 'flow' = 'cache') {
|
||||||
|
if (!this.guildId)
|
||||||
|
return mode === 'cache' ? (this.client.cache.adapter.isAsync ? Promise.resolve() : undefined) : Promise.resolve();
|
||||||
|
switch (mode) {
|
||||||
|
case 'cache':
|
||||||
|
return this.client.cache.members?.get(this.client.botId, this.guildId);
|
||||||
|
default:
|
||||||
|
return this.client.members.fetch(this.guildId, this.client.botId, mode === 'rest');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the guild of the interaction.
|
||||||
|
* @param mode - The mode to fetch the guild.
|
||||||
|
* @returns A promise that resolves to the guild.
|
||||||
|
*/
|
||||||
|
guild(mode?: 'rest' | 'flow'): Promise<Guild<'cached' | 'api'> | undefined>;
|
||||||
|
guild(mode?: 'cache'): ReturnCache<Guild<'cached'> | undefined>;
|
||||||
|
guild(mode: 'cache' | 'rest' | 'flow' = 'cache') {
|
||||||
|
if (!this.guildId)
|
||||||
|
return (
|
||||||
|
mode === 'cache' ? (this.client.cache.adapter.isAsync ? Promise.resolve() : undefined) : Promise.resolve()
|
||||||
|
) as any;
|
||||||
|
switch (mode) {
|
||||||
|
case 'cache':
|
||||||
|
return this.client.cache.guilds?.get(this.guildId);
|
||||||
|
default:
|
||||||
|
return this.client.guilds.fetch(this.guildId, mode === 'rest');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the ID of the guild of the interaction.
|
||||||
|
*/
|
||||||
|
get guildId() {
|
||||||
|
return this.interaction.guildId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the ID of the channel of the interaction.
|
||||||
|
*/
|
||||||
|
get channelId() {
|
||||||
|
return this.interaction.channelId!;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the author of the interaction.
|
||||||
|
*/
|
||||||
|
get author() {
|
||||||
|
return this.interaction.user;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the member of the interaction.
|
||||||
|
*/
|
||||||
|
get member() {
|
||||||
|
return this.interaction.member;
|
||||||
|
}
|
||||||
|
|
||||||
|
isModal(): this is ModalContext {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user