mirror of
https://github.com/tiramisulabs/seyfert.git
synced 2025-07-02 21:16:09 +00:00
feat: experimental custom handlers
This commit is contained in:
parent
168aab508a
commit
9b40239b55
@ -4,7 +4,7 @@ import type { Adapter } from '../cache';
|
|||||||
import { Cache, MemoryAdapter } from '../cache';
|
import { Cache, MemoryAdapter } from '../cache';
|
||||||
import type { RegisteredMiddlewares } from '../commands';
|
import type { RegisteredMiddlewares } from '../commands';
|
||||||
import type { InferWithPrefix, MiddlewareContext } from '../commands/applications/shared';
|
import type { InferWithPrefix, MiddlewareContext } from '../commands/applications/shared';
|
||||||
import { CommandHandler } from '../commands/handler';
|
import { CommandHandler, type CommandHandlerLike } from '../commands/handler';
|
||||||
import {
|
import {
|
||||||
ChannelShorter,
|
ChannelShorter,
|
||||||
EmojiShorter,
|
EmojiShorter,
|
||||||
@ -25,8 +25,8 @@ import {
|
|||||||
} from '../common';
|
} from '../common';
|
||||||
|
|
||||||
import type { DeepPartial, IntentStrings, OmitInsert, When } from '../common/types/util';
|
import type { DeepPartial, IntentStrings, OmitInsert, When } from '../common/types/util';
|
||||||
import { ComponentHandler } from '../components/handler';
|
import { ComponentHandler, type ComponentHandlerLike } from '../components/handler';
|
||||||
import { LangsHandler } from '../langs/handler';
|
import { LangsHandler, type LangsHandlerLike } from '../langs/handler';
|
||||||
import type {
|
import type {
|
||||||
ChatInputCommandInteraction,
|
ChatInputCommandInteraction,
|
||||||
Message,
|
Message,
|
||||||
@ -55,9 +55,9 @@ export class BaseClient {
|
|||||||
name: '[Seyfert]',
|
name: '[Seyfert]',
|
||||||
});
|
});
|
||||||
|
|
||||||
langs = new LangsHandler(this.logger);
|
langs?: LangsHandlerLike = new LangsHandler(this.logger);
|
||||||
commands = new CommandHandler(this.logger, this);
|
commands?: CommandHandlerLike = new CommandHandler(this.logger, this);
|
||||||
components = new ComponentHandler(this.logger, this);
|
components?: ComponentHandlerLike = new ComponentHandler(this.logger, this);
|
||||||
|
|
||||||
private _applicationId?: string;
|
private _applicationId?: string;
|
||||||
private _botId?: string;
|
private _botId?: string;
|
||||||
@ -99,7 +99,7 @@ export class BaseClient {
|
|||||||
return new Router(this.rest).createProxy();
|
return new Router(this.rest).createProxy();
|
||||||
}
|
}
|
||||||
|
|
||||||
setServices({ rest, cache, langs, middlewares }: ServicesOptions) {
|
setServices({ rest, cache, langs, middlewares, handlers }: ServicesOptions) {
|
||||||
if (rest) {
|
if (rest) {
|
||||||
this.rest = rest;
|
this.rest = rest;
|
||||||
}
|
}
|
||||||
@ -111,13 +111,24 @@ export class BaseClient {
|
|||||||
this,
|
this,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (langs) {
|
|
||||||
if (langs.default) this.langs.defaultLang = langs.default;
|
|
||||||
if (langs.aliases) this.langs.aliases = Object.entries(langs.aliases);
|
|
||||||
}
|
|
||||||
if (middlewares) {
|
if (middlewares) {
|
||||||
this.middlewares = middlewares;
|
this.middlewares = middlewares;
|
||||||
}
|
}
|
||||||
|
if (handlers) {
|
||||||
|
if ('components' in handlers) {
|
||||||
|
this.components = handlers.components;
|
||||||
|
}
|
||||||
|
if ('commands' in handlers) {
|
||||||
|
this.commands = handlers.commands;
|
||||||
|
}
|
||||||
|
if ('langs' in handlers) {
|
||||||
|
this.langs = handlers.langs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (langs) {
|
||||||
|
if (langs.default) this.langs!.defaultLang = langs.default;
|
||||||
|
if (langs.aliases) this.langs!.aliases = Object.entries(langs.aliases);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async execute(..._options: unknown[]) {
|
protected async execute(..._options: unknown[]) {
|
||||||
@ -170,7 +181,7 @@ export class BaseClient {
|
|||||||
applicationId ??= await this.getRC().then(x => x.applicationId ?? this.applicationId);
|
applicationId ??= await this.getRC().then(x => x.applicationId ?? this.applicationId);
|
||||||
BaseClient.assertString(applicationId, 'applicationId is not a string');
|
BaseClient.assertString(applicationId, 'applicationId is not a string');
|
||||||
|
|
||||||
const commands = this.commands.values.map(x => x.toJSON());
|
const commands = this.commands!.values.map(x => x.toJSON());
|
||||||
const filter = filterSplit(commands, command => !command.guild_id);
|
const filter = filterSplit(commands, command => !command.guild_id);
|
||||||
|
|
||||||
await this.proxy.applications(applicationId).commands.put({
|
await this.proxy.applications(applicationId).commands.put({
|
||||||
@ -197,7 +208,7 @@ export class BaseClient {
|
|||||||
|
|
||||||
async loadCommands(dir?: string) {
|
async loadCommands(dir?: string) {
|
||||||
dir ??= await this.getRC().then(x => x.commands);
|
dir ??= await this.getRC().then(x => x.commands);
|
||||||
if (dir) {
|
if (dir && this.commands) {
|
||||||
await this.commands.load(dir, this);
|
await this.commands.load(dir, this);
|
||||||
this.logger.info('CommandHandler loaded');
|
this.logger.info('CommandHandler loaded');
|
||||||
}
|
}
|
||||||
@ -205,7 +216,7 @@ export class BaseClient {
|
|||||||
|
|
||||||
async loadComponents(dir?: string) {
|
async loadComponents(dir?: string) {
|
||||||
dir ??= await this.getRC().then(x => x.components);
|
dir ??= await this.getRC().then(x => x.components);
|
||||||
if (dir) {
|
if (dir && this.components) {
|
||||||
await this.components.load(dir);
|
await this.components.load(dir);
|
||||||
this.logger.info('ComponentHandler loaded');
|
this.logger.info('ComponentHandler loaded');
|
||||||
}
|
}
|
||||||
@ -213,14 +224,14 @@ export class BaseClient {
|
|||||||
|
|
||||||
async loadLangs(dir?: string) {
|
async loadLangs(dir?: string) {
|
||||||
dir ??= await this.getRC().then(x => x.langs);
|
dir ??= await this.getRC().then(x => x.langs);
|
||||||
if (dir) {
|
if (dir && this.langs) {
|
||||||
await this.langs.load(dir);
|
await this.langs.load(dir);
|
||||||
this.logger.info('LangsHandler loaded');
|
this.logger.info('LangsHandler loaded');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
t(locale: string) {
|
t(locale: string) {
|
||||||
return this.langs.get(locale);
|
return this.langs!.get(locale);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getRC<
|
async getRC<
|
||||||
@ -310,4 +321,9 @@ export interface ServicesOptions {
|
|||||||
aliases?: Record<string, LocaleString[]>;
|
aliases?: Record<string, LocaleString[]>;
|
||||||
};
|
};
|
||||||
middlewares?: Record<string, MiddlewareContext>;
|
middlewares?: Record<string, MiddlewareContext>;
|
||||||
|
handlers?: {
|
||||||
|
components?: ComponentHandlerLike;
|
||||||
|
commands?: CommandHandlerLike;
|
||||||
|
langs?: LangsHandlerLike;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { parentPort, workerData } from 'node:worker_threads';
|
import { parentPort, workerData } from 'node:worker_threads';
|
||||||
import type { Command, CommandContext, Message, SubCommand } from '..';
|
import type { Command, CommandContext, EventHandlerLike, Message, SubCommand } from '..';
|
||||||
import {
|
import {
|
||||||
GatewayIntentBits,
|
GatewayIntentBits,
|
||||||
type DeepPartial,
|
type DeepPartial,
|
||||||
@ -22,7 +22,7 @@ import { onMessageCreate } from './onmessagecreate';
|
|||||||
export class Client<Ready extends boolean = boolean> extends BaseClient {
|
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;
|
||||||
events = new EventHandler(this.logger);
|
events?: EventHandlerLike = new EventHandler(this.logger);
|
||||||
me!: If<Ready, ClientUser>;
|
me!: If<Ready, ClientUser>;
|
||||||
declare options: ClientOptions | undefined;
|
declare options: ClientOptions | undefined;
|
||||||
memberUpdateHandler = new MemberUpdateHandler();
|
memberUpdateHandler = new MemberUpdateHandler();
|
||||||
@ -37,6 +37,9 @@ export class Client<Ready extends boolean = boolean> extends BaseClient {
|
|||||||
...rest
|
...rest
|
||||||
}: ServicesOptions & {
|
}: ServicesOptions & {
|
||||||
gateway?: ShardManager;
|
gateway?: ShardManager;
|
||||||
|
handlers?: ServicesOptions['handlers'] & {
|
||||||
|
events?: EventHandlerLike;
|
||||||
|
};
|
||||||
}) {
|
}) {
|
||||||
super.setServices(rest);
|
super.setServices(rest);
|
||||||
if (gateway) {
|
if (gateway) {
|
||||||
@ -48,11 +51,14 @@ export class Client<Ready extends boolean = boolean> extends BaseClient {
|
|||||||
};
|
};
|
||||||
this.gateway = gateway;
|
this.gateway = gateway;
|
||||||
}
|
}
|
||||||
|
if (rest.handlers && 'events' in rest.handlers) {
|
||||||
|
this.events = rest.handlers.events;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async loadEvents(dir?: string) {
|
async loadEvents(dir?: string) {
|
||||||
dir ??= await this.getRC().then(x => x.events);
|
dir ??= await this.getRC().then(x => x.events);
|
||||||
if (dir) {
|
if (dir && this.events) {
|
||||||
await this.events.load(dir);
|
await this.events.load(dir);
|
||||||
this.logger.info('EventHandler loaded');
|
this.logger.info('EventHandler loaded');
|
||||||
}
|
}
|
||||||
@ -114,21 +120,21 @@ export class Client<Ready extends boolean = boolean> extends BaseClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected async onPacket(shardId: number, packet: GatewayDispatchPayload) {
|
protected async onPacket(shardId: number, packet: GatewayDispatchPayload) {
|
||||||
await this.events.runEvent('RAW', this, packet, shardId);
|
await this.events?.runEvent('RAW', this, packet, shardId);
|
||||||
switch (packet.t) {
|
switch (packet.t) {
|
||||||
//// Cases where we must obtain the old data before updating
|
//// Cases where we must obtain the old data before updating
|
||||||
case 'GUILD_MEMBER_UPDATE':
|
case 'GUILD_MEMBER_UPDATE':
|
||||||
if (!this.memberUpdateHandler.check(packet.d)) {
|
if (!this.memberUpdateHandler.check(packet.d)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await this.events.execute(packet.t, packet, this as Client<true>, shardId);
|
await this.events?.execute(packet.t, packet, this as Client<true>, shardId);
|
||||||
await this.cache.onPacket(packet);
|
await this.cache.onPacket(packet);
|
||||||
break;
|
break;
|
||||||
case 'PRESENCE_UPDATE':
|
case 'PRESENCE_UPDATE':
|
||||||
if (!this.presenceUpdateHandler.check(packet.d as any)) {
|
if (!this.presenceUpdateHandler.check(packet.d as any)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await this.events.execute(packet.t, packet, this as Client<true>, shardId);
|
await this.events?.execute(packet.t, packet, this as Client<true>, shardId);
|
||||||
await this.cache.onPacket(packet);
|
await this.cache.onPacket(packet);
|
||||||
break;
|
break;
|
||||||
//rest of the events
|
//rest of the events
|
||||||
@ -153,7 +159,7 @@ export class Client<Ready extends boolean = boolean> extends BaseClient {
|
|||||||
!((this.gateway.options.intents & GatewayIntentBits.Guilds) === GatewayIntentBits.Guilds)
|
!((this.gateway.options.intents & GatewayIntentBits.Guilds) === GatewayIntentBits.Guilds)
|
||||||
) {
|
) {
|
||||||
if ([...this.gateway.values()].every(shard => shard.data.session_id)) {
|
if ([...this.gateway.values()].every(shard => shard.data.session_id)) {
|
||||||
await this.events.runEvent('BOT_READY', this, this.me, -1);
|
await this.events?.runEvent('BOT_READY', this, this.me, -1);
|
||||||
}
|
}
|
||||||
delete this.__handleGuilds;
|
delete this.__handleGuilds;
|
||||||
}
|
}
|
||||||
@ -163,7 +169,7 @@ export class Client<Ready extends boolean = boolean> extends BaseClient {
|
|||||||
if (this.__handleGuilds?.has(packet.d.id)) {
|
if (this.__handleGuilds?.has(packet.d.id)) {
|
||||||
this.__handleGuilds.delete(packet.d.id);
|
this.__handleGuilds.delete(packet.d.id);
|
||||||
if (!this.__handleGuilds.size && [...this.gateway.values()].every(shard => shard.data.session_id)) {
|
if (!this.__handleGuilds.size && [...this.gateway.values()].every(shard => shard.data.session_id)) {
|
||||||
await this.events.runEvent('BOT_READY', this, this.me, -1);
|
await this.events?.runEvent('BOT_READY', this, this.me, -1);
|
||||||
}
|
}
|
||||||
if (!this.__handleGuilds.size) delete this.__handleGuilds;
|
if (!this.__handleGuilds.size) delete this.__handleGuilds;
|
||||||
return;
|
return;
|
||||||
@ -171,7 +177,7 @@ export class Client<Ready extends boolean = boolean> extends BaseClient {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await this.events.execute(packet.t, packet, this as Client<true>, shardId);
|
await this.events?.execute(packet.t, packet, this as Client<true>, shardId);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import { ApplicationCommandType, InteractionType, type APIInteraction } from 'discord-api-types/v10';
|
import { ApplicationCommandType, InteractionType, type APIInteraction } from 'discord-api-types/v10';
|
||||||
import {
|
import {
|
||||||
CommandContext,
|
CommandContext,
|
||||||
type ContextOptionsResolved,
|
|
||||||
MenuCommandContext,
|
MenuCommandContext,
|
||||||
OptionResolver,
|
OptionResolver,
|
||||||
type Command,
|
type Command,
|
||||||
type ContextMenuCommand,
|
type ContextMenuCommand,
|
||||||
|
type ContextOptionsResolved,
|
||||||
} from '../commands';
|
} from '../commands';
|
||||||
import type {
|
import type {
|
||||||
ChatInputCommandInteraction,
|
ChatInputCommandInteraction,
|
||||||
@ -28,7 +28,7 @@ export async function onInteractionCreate(
|
|||||||
switch (body.type) {
|
switch (body.type) {
|
||||||
case InteractionType.ApplicationCommandAutocomplete:
|
case InteractionType.ApplicationCommandAutocomplete:
|
||||||
{
|
{
|
||||||
const parentCommand = self.commands.values.find(x => {
|
const parentCommand = self.commands?.values.find(x => {
|
||||||
if (x.guild_id && !x.guild_id.includes(body.data.guild_id ?? '')) {
|
if (x.guild_id && !x.guild_id.includes(body.data.guild_id ?? '')) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -76,7 +76,7 @@ export async function onInteractionCreate(
|
|||||||
case ApplicationCommandType.Message:
|
case ApplicationCommandType.Message:
|
||||||
case ApplicationCommandType.User:
|
case ApplicationCommandType.User:
|
||||||
{
|
{
|
||||||
const command = self.commands.values.find(x => {
|
const command = self.commands?.values.find(x => {
|
||||||
if (x.guild_id && !x.guild_id.includes(body.data.guild_id ?? '')) {
|
if (x.guild_id && !x.guild_id.includes(body.data.guild_id ?? '')) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -135,7 +135,7 @@ export async function onInteractionCreate(
|
|||||||
case ApplicationCommandType.ChatInput:
|
case ApplicationCommandType.ChatInput:
|
||||||
{
|
{
|
||||||
const packetData = body.data;
|
const packetData = body.data;
|
||||||
const parentCommand = self.commands.values.find(x => {
|
const parentCommand = self.commands?.values.find(x => {
|
||||||
if (x.guild_id && !x.guild_id.includes(packetData.guild_id ?? '')) {
|
if (x.guild_id && !x.guild_id.includes(packetData.guild_id ?? '')) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -206,20 +206,20 @@ export async function onInteractionCreate(
|
|||||||
case InteractionType.ModalSubmit:
|
case InteractionType.ModalSubmit:
|
||||||
{
|
{
|
||||||
const interaction = BaseInteraction.from(self, body, __reply) as ModalSubmitInteraction;
|
const interaction = BaseInteraction.from(self, body, __reply) as ModalSubmitInteraction;
|
||||||
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(interaction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case InteractionType.MessageComponent:
|
case InteractionType.MessageComponent:
|
||||||
{
|
{
|
||||||
const interaction = BaseInteraction.from(self, body, __reply) as ComponentInteraction;
|
const interaction = BaseInteraction.from(self, body, __reply) as ComponentInteraction;
|
||||||
if (self.components.hasComponent(body.message.id, interaction.customId)) {
|
if (self.components?.hasComponent(body.message.id, interaction.customId)) {
|
||||||
await self.components.onComponent(body.message.id, interaction);
|
await self.components.onComponent(body.message.id, interaction);
|
||||||
} else {
|
} else {
|
||||||
await self.components.executeComponent(interaction);
|
await self.components?.executeComponent(interaction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -34,7 +34,7 @@ function getCommandFromContent(
|
|||||||
const parentName = commandRaw[0];
|
const parentName = commandRaw[0];
|
||||||
const groupName = commandRaw.length === 3 ? commandRaw[1] : undefined;
|
const groupName = commandRaw.length === 3 ? commandRaw[1] : undefined;
|
||||||
const subcommandName = groupName ? commandRaw[2] : commandRaw[1];
|
const subcommandName = groupName ? commandRaw[2] : commandRaw[1];
|
||||||
const parent = self.commands.values.find(x => x.name === parentName);
|
const parent = self.commands!.values.find(x => x.name === parentName);
|
||||||
const fullCommandName = `${parentName}${
|
const fullCommandName = `${parentName}${
|
||||||
groupName ? ` ${groupName} ${subcommandName}` : `${subcommandName ? ` ${subcommandName}` : ''}`
|
groupName ? ` ${groupName} ${subcommandName}` : `${subcommandName ? ` ${subcommandName}` : ''}`
|
||||||
}`;
|
}`;
|
||||||
@ -80,7 +80,10 @@ export async function onMessageCreate(
|
|||||||
|
|
||||||
const content = message.content.slice(prefix.length).trimStart();
|
const content = message.content.slice(prefix.length).trimStart();
|
||||||
const { fullCommandName, command, parent } = getCommandFromContent(
|
const { fullCommandName, command, parent } = getCommandFromContent(
|
||||||
content.split(' ').filter(x => x).slice(0, 3),
|
content
|
||||||
|
.split(' ')
|
||||||
|
.filter(x => x)
|
||||||
|
.slice(0, 3),
|
||||||
self,
|
self,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ import type { Cache } from '../cache';
|
|||||||
import { WorkerAdapter } from '../cache';
|
import { WorkerAdapter } from '../cache';
|
||||||
import type { GatewayDispatchPayload, GatewaySendPayload, When } from '../common';
|
import type { GatewayDispatchPayload, GatewaySendPayload, When } from '../common';
|
||||||
import { GatewayIntentBits, LogLevels, Logger, type DeepPartial } from '../common';
|
import { GatewayIntentBits, LogLevels, Logger, type DeepPartial } from '../common';
|
||||||
import { EventHandler } from '../events';
|
import { EventHandler, type EventHandlerLike } from '../events';
|
||||||
import { ClientUser } from '../structures';
|
import { ClientUser } from '../structures';
|
||||||
import { Shard, type ShardManagerOptions, type WorkerData } from '../websocket';
|
import { Shard, type ShardManagerOptions, type WorkerData } from '../websocket';
|
||||||
import type {
|
import type {
|
||||||
@ -21,7 +21,7 @@ import type {
|
|||||||
WorkerStart,
|
WorkerStart,
|
||||||
} from '../websocket/discord/worker';
|
} from '../websocket/discord/worker';
|
||||||
import type { ManagerMessages } from '../websocket/discord/workermanager';
|
import type { ManagerMessages } from '../websocket/discord/workermanager';
|
||||||
import type { BaseClientOptions, StartOptions } from './base';
|
import type { BaseClientOptions, ServicesOptions, StartOptions } from './base';
|
||||||
import { BaseClient } from './base';
|
import { BaseClient } from './base';
|
||||||
import type { Client } from './client';
|
import type { Client } from './client';
|
||||||
import { onInteractionCreate } from './oninteractioncreate';
|
import { onInteractionCreate } from './oninteractioncreate';
|
||||||
@ -46,7 +46,7 @@ export class WorkerClient<Ready extends boolean = boolean> extends BaseClient {
|
|||||||
name: `[Worker #${workerData.workerId}]`,
|
name: `[Worker #${workerData.workerId}]`,
|
||||||
});
|
});
|
||||||
|
|
||||||
events = new EventHandler(this.logger);
|
events?: EventHandlerLike = new EventHandler(this.logger);
|
||||||
me!: When<Ready, ClientUser>;
|
me!: When<Ready, ClientUser>;
|
||||||
promises = new Map<string, { resolve: (value: any) => void; timeout: NodeJS.Timeout }>();
|
promises = new Map<string, { resolve: (value: any) => void; timeout: NodeJS.Timeout }>();
|
||||||
|
|
||||||
@ -98,6 +98,19 @@ export class WorkerClient<Ready extends boolean = boolean> extends BaseClient {
|
|||||||
return acc / this.shards.size;
|
return acc / this.shards.size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setServices({
|
||||||
|
...rest
|
||||||
|
}: ServicesOptions & {
|
||||||
|
handlers?: ServicesOptions['handlers'] & {
|
||||||
|
events?: EventHandlerLike;
|
||||||
|
};
|
||||||
|
}) {
|
||||||
|
super.setServices(rest);
|
||||||
|
if (rest.handlers && 'events' in rest.handlers) {
|
||||||
|
this.events = rest.handlers.events;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async start(options: Omit<DeepPartial<StartOptions>, 'httpConnection' | 'token' | 'connection'> = {}) {
|
async start(options: Omit<DeepPartial<StartOptions>, 'httpConnection' | 'token' | 'connection'> = {}) {
|
||||||
await super.start(options);
|
await super.start(options);
|
||||||
await this.loadEvents(options.eventsDir);
|
await this.loadEvents(options.eventsDir);
|
||||||
@ -106,7 +119,7 @@ export class WorkerClient<Ready extends boolean = boolean> extends BaseClient {
|
|||||||
|
|
||||||
async loadEvents(dir?: string) {
|
async loadEvents(dir?: string) {
|
||||||
dir ??= await this.getRC().then(x => x.events);
|
dir ??= await this.getRC().then(x => x.events);
|
||||||
if (dir) {
|
if (dir && this.events) {
|
||||||
await this.events.load(dir);
|
await this.events.load(dir);
|
||||||
this.logger.info('EventHandler loaded');
|
this.logger.info('EventHandler loaded');
|
||||||
}
|
}
|
||||||
@ -221,7 +234,7 @@ export class WorkerClient<Ready extends boolean = boolean> extends BaseClient {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'BOT_READY':
|
case 'BOT_READY':
|
||||||
await this.events.runEvent('BOT_READY', this, this.me, -1);
|
await this.events?.runEvent('BOT_READY', this, this.me, -1);
|
||||||
break;
|
break;
|
||||||
case 'API_RESPONSE':
|
case 'API_RESPONSE':
|
||||||
{
|
{
|
||||||
@ -302,14 +315,14 @@ export class WorkerClient<Ready extends boolean = boolean> extends BaseClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected async onPacket(packet: GatewayDispatchPayload, shardId: number) {
|
protected async onPacket(packet: GatewayDispatchPayload, shardId: number) {
|
||||||
await this.events.execute('RAW', packet, this as WorkerClient<true>, shardId);
|
await this.events?.execute('RAW', packet, this as WorkerClient<true>, shardId);
|
||||||
switch (packet.t) {
|
switch (packet.t) {
|
||||||
case 'GUILD_MEMBER_UPDATE':
|
case 'GUILD_MEMBER_UPDATE':
|
||||||
await this.events.execute(packet.t, packet, this as WorkerClient<true>, shardId);
|
await this.events?.execute(packet.t, packet, this as WorkerClient<true>, shardId);
|
||||||
await this.cache.onPacket(packet);
|
await this.cache.onPacket(packet);
|
||||||
break;
|
break;
|
||||||
case 'PRESENCE_UPDATE':
|
case 'PRESENCE_UPDATE':
|
||||||
await this.events.execute(packet.t, packet, this as WorkerClient<true>, shardId);
|
await this.events?.execute(packet.t, packet, this as WorkerClient<true>, shardId);
|
||||||
await this.cache.onPacket(packet);
|
await this.cache.onPacket(packet);
|
||||||
break;
|
break;
|
||||||
//rest of the events
|
//rest of the events
|
||||||
@ -332,7 +345,7 @@ export class WorkerClient<Ready extends boolean = boolean> extends BaseClient {
|
|||||||
type: 'WORKER_READY',
|
type: 'WORKER_READY',
|
||||||
workerId: this.workerId,
|
workerId: this.workerId,
|
||||||
} as WorkerReady);
|
} as WorkerReady);
|
||||||
await this.events.runEvent('WORKER_READY', this, this.me, -1);
|
await this.events?.runEvent('WORKER_READY', this, this.me, -1);
|
||||||
}
|
}
|
||||||
delete this.__handleGuilds;
|
delete this.__handleGuilds;
|
||||||
}
|
}
|
||||||
@ -352,14 +365,14 @@ export class WorkerClient<Ready extends boolean = boolean> extends BaseClient {
|
|||||||
type: 'WORKER_READY',
|
type: 'WORKER_READY',
|
||||||
workerId: this.workerId,
|
workerId: this.workerId,
|
||||||
} as WorkerReady);
|
} as WorkerReady);
|
||||||
await this.events.runEvent('WORKER_READY', this, this.me, -1);
|
await this.events?.runEvent('WORKER_READY', this, this.me, -1);
|
||||||
}
|
}
|
||||||
if (!this.__handleGuilds.size) delete this.__handleGuilds;
|
if (!this.__handleGuilds.size) delete this.__handleGuilds;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await this.events.execute(packet.t, packet, this, shardId);
|
await this.events?.execute(packet.t, packet, this, shardId);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,7 @@ export class CommandContext<T extends OptionsRecord = {}, M extends keyof Regist
|
|||||||
}
|
}
|
||||||
|
|
||||||
get t() {
|
get t() {
|
||||||
return this.client.langs.get(this.interaction?.locale ?? this.client.langs.defaultLang ?? 'en-US');
|
return this.client.langs!.get(this.interaction?.locale ?? this.client.langs!.defaultLang ?? 'en-US');
|
||||||
}
|
}
|
||||||
|
|
||||||
get fullCommandName() {
|
get fullCommandName() {
|
||||||
|
@ -60,7 +60,7 @@ export class MenuCommandContext<
|
|||||||
}
|
}
|
||||||
|
|
||||||
get t() {
|
get t() {
|
||||||
return this.client.langs.get(this.interaction.locale);
|
return this.client.langs!.get(this.interaction.locale ?? this.client.langs!.defaultLang ?? 'en-US');
|
||||||
}
|
}
|
||||||
|
|
||||||
get fullCommandName() {
|
get fullCommandName() {
|
||||||
|
@ -5,6 +5,11 @@ import { Command, SubCommand } from './applications/chat';
|
|||||||
import { ContextMenuCommand } from './applications/menu';
|
import { ContextMenuCommand } from './applications/menu';
|
||||||
import type { UsingClient } from './applications/shared';
|
import type { UsingClient } from './applications/shared';
|
||||||
|
|
||||||
|
export interface CommandHandlerLike {
|
||||||
|
values: CommandHandler['values'];
|
||||||
|
load: CommandHandler['load'];
|
||||||
|
}
|
||||||
|
|
||||||
export class CommandHandler extends BaseHandler {
|
export class CommandHandler extends BaseHandler {
|
||||||
values: (Command | ContextMenuCommand)[] = [];
|
values: (Command | ContextMenuCommand)[] = [];
|
||||||
protected filter = (path: string) => path.endsWith('.js') || (!path.endsWith('.d.ts') && path.endsWith('.ts'));
|
protected filter = (path: string) => path.endsWith('.js') || (!path.endsWith('.d.ts') && path.endsWith('.ts'));
|
||||||
@ -122,20 +127,20 @@ export class CommandHandler extends BaseHandler {
|
|||||||
if (command.__t) {
|
if (command.__t) {
|
||||||
command.name_localizations = {};
|
command.name_localizations = {};
|
||||||
command.description_localizations = {};
|
command.description_localizations = {};
|
||||||
for (const locale of Object.keys(client.langs.values)) {
|
for (const locale of Object.keys(client.langs!.values)) {
|
||||||
const locales = this.client.langs.aliases.find(x => x[0] === locale)?.[1] ?? [];
|
const locales = this.client.langs!.aliases.find(x => x[0] === locale)?.[1] ?? [];
|
||||||
if (Object.values<string>(Locale).includes(locale)) locales.push(locale as LocaleString);
|
if (Object.values<string>(Locale).includes(locale)) locales.push(locale as LocaleString);
|
||||||
|
|
||||||
if (command.__t.name) {
|
if (command.__t.name) {
|
||||||
for (const i of locales) {
|
for (const i of locales) {
|
||||||
const valueName = client.langs.getKey(locale, command.__t.name!);
|
const valueName = client.langs!.getKey(locale, command.__t.name!);
|
||||||
if (valueName) command.name_localizations[i] = valueName;
|
if (valueName) command.name_localizations[i] = valueName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (command.__t.description) {
|
if (command.__t.description) {
|
||||||
for (const i of locales) {
|
for (const i of locales) {
|
||||||
const valueKey = client.langs.getKey(locale, command.__t.description!);
|
const valueKey = client.langs!.getKey(locale, command.__t.description!);
|
||||||
if (valueKey) command.description_localizations[i] = valueKey;
|
if (valueKey) command.description_localizations[i] = valueKey;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -146,20 +151,20 @@ export class CommandHandler extends BaseHandler {
|
|||||||
if (options instanceof SubCommand || !options.locales) continue;
|
if (options instanceof SubCommand || !options.locales) continue;
|
||||||
options.name_localizations = {};
|
options.name_localizations = {};
|
||||||
options.description_localizations = {};
|
options.description_localizations = {};
|
||||||
for (const locale of Object.keys(client.langs.values)) {
|
for (const locale of Object.keys(client.langs!.values)) {
|
||||||
const locales = this.client.langs.aliases.find(x => x[0] === locale)?.[1] ?? [];
|
const locales = this.client.langs!.aliases.find(x => x[0] === locale)?.[1] ?? [];
|
||||||
if (Object.values<string>(Locale).includes(locale)) locales.push(locale as LocaleString);
|
if (Object.values<string>(Locale).includes(locale)) locales.push(locale as LocaleString);
|
||||||
|
|
||||||
if (options.locales.name) {
|
if (options.locales.name) {
|
||||||
for (const i of locales) {
|
for (const i of locales) {
|
||||||
const valueName = client.langs.getKey(locale, options.locales.name!);
|
const valueName = client.langs!.getKey(locale, options.locales.name!);
|
||||||
if (valueName) options.name_localizations[i] = valueName;
|
if (valueName) options.name_localizations[i] = valueName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.locales.description) {
|
if (options.locales.description) {
|
||||||
for (const i of locales) {
|
for (const i of locales) {
|
||||||
const valueKey = client.langs.getKey(locale, options.locales.description!);
|
const valueKey = client.langs!.getKey(locale, options.locales.description!);
|
||||||
if (valueKey) options.description_localizations[i] = valueKey;
|
if (valueKey) options.description_localizations[i] = valueKey;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -168,8 +173,8 @@ export class CommandHandler extends BaseHandler {
|
|||||||
|
|
||||||
if (command instanceof Command && command.__tGroups) {
|
if (command instanceof Command && command.__tGroups) {
|
||||||
command.groups = {};
|
command.groups = {};
|
||||||
for (const locale of Object.keys(client.langs.values)) {
|
for (const locale of Object.keys(client.langs!.values)) {
|
||||||
const locales = this.client.langs.aliases.find(x => x[0] === locale)?.[1] ?? [];
|
const locales = this.client.langs!.aliases.find(x => x[0] === locale)?.[1] ?? [];
|
||||||
if (Object.values<string>(Locale).includes(locale)) locales.push(locale as LocaleString);
|
if (Object.values<string>(Locale).includes(locale)) locales.push(locale as LocaleString);
|
||||||
for (const group in command.__tGroups) {
|
for (const group in command.__tGroups) {
|
||||||
command.groups[group] ??= {
|
command.groups[group] ??= {
|
||||||
@ -180,7 +185,7 @@ export class CommandHandler extends BaseHandler {
|
|||||||
|
|
||||||
if (command.__tGroups[group].name) {
|
if (command.__tGroups[group].name) {
|
||||||
for (const i of locales) {
|
for (const i of locales) {
|
||||||
const valueName = client.langs.getKey(locale, command.__tGroups[group].name!);
|
const valueName = client.langs!.getKey(locale, command.__tGroups[group].name!);
|
||||||
if (valueName) {
|
if (valueName) {
|
||||||
command.groups[group].name!.push([i, valueName]);
|
command.groups[group].name!.push([i, valueName]);
|
||||||
}
|
}
|
||||||
@ -189,7 +194,7 @@ export class CommandHandler extends BaseHandler {
|
|||||||
|
|
||||||
if (command.__tGroups[group].description) {
|
if (command.__tGroups[group].description) {
|
||||||
for (const i of locales) {
|
for (const i of locales) {
|
||||||
const valueKey = client.langs.getKey(locale, command.__tGroups[group].description!);
|
const valueKey = client.langs!.getKey(locale, command.__tGroups[group].description!);
|
||||||
if (valueKey) {
|
if (valueKey) {
|
||||||
command.groups[group].description!.push([i, valueKey]);
|
command.groups[group].description!.push([i, valueKey]);
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ export class MessageShorter extends BaseShorter {
|
|||||||
.messages(messageId)
|
.messages(messageId)
|
||||||
.delete({ reason })
|
.delete({ reason })
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return this.client.components.onMessageDelete(messageId);
|
return this.client.components?.onMessageDelete(messageId);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
fetch(messageId: string, channelId: string) {
|
fetch(messageId: string, channelId: string) {
|
||||||
|
@ -14,8 +14,28 @@ type COMPONENTS = {
|
|||||||
__run: (customId: string | string[] | RegExp, callback: ComponentCallback) => any;
|
__run: (customId: string | string[] | RegExp, callback: ComponentCallback) => any;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export interface ComponentHandlerLike {
|
||||||
|
readonly values: Map<string, COMPONENTS>;
|
||||||
|
readonly commands: (ComponentCommand | ModalCommand)[];
|
||||||
|
readonly modals: Map<string, ModalSubmitCallback> | LimitedCollection<string, ModalSubmitCallback>;
|
||||||
|
|
||||||
|
createComponentCollector: ComponentHandler['createComponentCollector'];
|
||||||
|
|
||||||
|
hasModal: ComponentHandler['hasModal'];
|
||||||
|
onModalSubmit: ComponentHandler['onModalSubmit'];
|
||||||
|
executeModal: ComponentHandler['executeModal'];
|
||||||
|
|
||||||
|
hasComponent: ComponentHandler['hasComponent'];
|
||||||
|
executeComponent: ComponentHandler['executeComponent'];
|
||||||
|
onComponent: ComponentHandler['onComponent'];
|
||||||
|
|
||||||
|
load: ComponentHandler['load'];
|
||||||
|
|
||||||
|
onMessageDelete: ComponentHandler['onMessageDelete'];
|
||||||
|
}
|
||||||
|
|
||||||
export class ComponentHandler extends BaseHandler {
|
export class ComponentHandler extends BaseHandler {
|
||||||
protected onFail?: OnFailCallback;
|
onFail?: OnFailCallback;
|
||||||
readonly values = new Map<string, COMPONENTS>();
|
readonly values = new Map<string, COMPONENTS>();
|
||||||
// 10 minutes timeout, because discord dont send an event when the user cancel the modal
|
// 10 minutes timeout, because discord dont send an event when the user cancel the modal
|
||||||
readonly modals = new LimitedCollection<string, ModalSubmitCallback>({ expire: 60e3 * 10 });
|
readonly modals = new LimitedCollection<string, ModalSubmitCallback>({ expire: 60e3 * 10 });
|
||||||
@ -99,11 +119,13 @@ export class ComponentHandler extends BaseHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
hasComponent(id: string, customId: string) {
|
hasComponent(id: string, customId: string) {
|
||||||
return this.values.get(id)?.components?.some(x => {
|
return (
|
||||||
|
this.values.get(id)?.components?.some(x => {
|
||||||
if (typeof x.match === 'string') return x.match === customId;
|
if (typeof x.match === 'string') return x.match === customId;
|
||||||
if (Array.isArray(x.match)) return x.match.includes(customId);
|
if (Array.isArray(x.match)) return x.match.includes(customId);
|
||||||
return customId.match(x.match);
|
return customId.match(x.match);
|
||||||
});
|
}) ?? false
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
resetTimeouts(id: string) {
|
resetTimeouts(id: string) {
|
||||||
@ -164,6 +186,7 @@ export class ComponentHandler extends BaseHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async reload(path: string) {
|
async reload(path: string) {
|
||||||
|
if (!this.client.components) return;
|
||||||
const component = this.client.components.commands.find(
|
const component = this.client.components.commands.find(
|
||||||
x =>
|
x =>
|
||||||
x.__filePath?.endsWith(`${path}.js`) ||
|
x.__filePath?.endsWith(`${path}.js`) ||
|
||||||
@ -184,6 +207,7 @@ export class ComponentHandler extends BaseHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async reloadAll() {
|
async reloadAll() {
|
||||||
|
if (!this.client.components) return;
|
||||||
for (const i of this.client.components.commands) {
|
for (const i of this.client.components.commands) {
|
||||||
if (!i.__filePath) return this.logger.warn('Unknown command dont have __filePath property', i);
|
if (!i.__filePath) return this.logger.warn('Unknown command dont have __filePath property', i);
|
||||||
await this.reload(i.__filePath);
|
await this.reload(i.__filePath);
|
||||||
|
@ -19,6 +19,13 @@ type EventValue = MakeRequired<ClientEvent, '__filePath'> & { fired?: boolean };
|
|||||||
|
|
||||||
type GatewayEvents = Uppercase<SnakeCase<keyof ClientEvents>>;
|
type GatewayEvents = Uppercase<SnakeCase<keyof ClientEvents>>;
|
||||||
|
|
||||||
|
export interface EventHandlerLike {
|
||||||
|
runEvent: EventHandler['runEvent'];
|
||||||
|
execute: EventHandler['execute'];
|
||||||
|
load: EventHandler['load'];
|
||||||
|
values: EventHandler['values'];
|
||||||
|
}
|
||||||
|
|
||||||
export class EventHandler extends BaseHandler {
|
export class EventHandler extends BaseHandler {
|
||||||
protected onFail: OnFailCallback = err => this.logger.warn('<Client>.events.OnFail', err);
|
protected onFail: OnFailCallback = err => this.logger.warn('<Client>.events.OnFail', err);
|
||||||
protected filter = (path: string) => path.endsWith('.js') || (!path.endsWith('.d.ts') && path.endsWith('.ts'));
|
protected filter = (path: string) => path.endsWith('.js') || (!path.endsWith('.d.ts') && path.endsWith('.ts'));
|
||||||
@ -54,7 +61,7 @@ export class EventHandler extends BaseHandler {
|
|||||||
case 'MESSAGE_CREATE':
|
case 'MESSAGE_CREATE':
|
||||||
{
|
{
|
||||||
const { d: data } = args[0] as GatewayMessageCreateDispatch;
|
const { d: data } = args[0] as GatewayMessageCreateDispatch;
|
||||||
if (args[1].components.values.has(data.interaction?.id ?? data.id)) {
|
if (args[1].components?.values.has(data.interaction?.id ?? data.id)) {
|
||||||
args[1].components.values.get(data.interaction?.id ?? data.id)!.messageId = data.id;
|
args[1].components.values.get(data.interaction?.id ?? data.id)!.messageId = data.id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -62,20 +69,20 @@ export class EventHandler extends BaseHandler {
|
|||||||
case 'MESSAGE_DELETE':
|
case 'MESSAGE_DELETE':
|
||||||
{
|
{
|
||||||
const { d: data } = args[0] as GatewayMessageDeleteDispatch;
|
const { d: data } = args[0] as GatewayMessageDeleteDispatch;
|
||||||
const value = [...args[1].components.values].find(x => x[1].messageId === data.id);
|
const value = [...(args[1].components?.values ?? [])].find(x => x[1].messageId === data.id);
|
||||||
if (value) {
|
if (value) {
|
||||||
args[1].components.onMessageDelete(value[0]);
|
args[1].components!.onMessageDelete(value[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'MESSAGE_DELETE_BULK':
|
case 'MESSAGE_DELETE_BULK':
|
||||||
{
|
{
|
||||||
const { d: data } = args[0] as GatewayMessageDeleteBulkDispatch;
|
const { d: data } = args[0] as GatewayMessageDeleteBulkDispatch;
|
||||||
const values = [...args[1].components.values];
|
const values = [...(args[1].components?.values ?? [])];
|
||||||
data.ids.forEach(id => {
|
data.ids.forEach(id => {
|
||||||
const value = values.find(x => x[1].messageId === id);
|
const value = values.find(x => x[1].messageId === id);
|
||||||
if (value) {
|
if (value) {
|
||||||
args[1].components.onMessageDelete(value[0]);
|
args[1].components!.onMessageDelete(value[0]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,15 @@
|
|||||||
import { BaseHandler, type Locale, type LocaleString } from '../common';
|
import { BaseHandler, type Locale, type LocaleString } from '../common';
|
||||||
import { LangRouter } from './router';
|
import { LangRouter } from './router';
|
||||||
|
|
||||||
|
export interface LangsHandlerLike {
|
||||||
|
getKey: LangsHandler['getKey'];
|
||||||
|
load: LangsHandler['load'];
|
||||||
|
values: LangsHandler['values'];
|
||||||
|
aliases: LangsHandler['aliases'];
|
||||||
|
get: LangsHandler['get'];
|
||||||
|
defaultLang?: LangsHandler['defaultLang'];
|
||||||
|
}
|
||||||
|
|
||||||
export class LangsHandler extends BaseHandler {
|
export class LangsHandler extends BaseHandler {
|
||||||
values: Partial<Record<string, any>> = {};
|
values: Partial<Record<string, any>> = {};
|
||||||
protected filter = (path: string) =>
|
protected filter = (path: string) =>
|
||||||
|
@ -388,7 +388,7 @@ export class Interaction<
|
|||||||
.webhooks(this.applicationId)(this.token)
|
.webhooks(this.applicationId)(this.token)
|
||||||
.messages(messageId)
|
.messages(messageId)
|
||||||
.delete()
|
.delete()
|
||||||
.then(() => this.client.components.onMessageDelete(messageId === '@original' ? this.id : messageId));
|
.then(() => this.client.components?.onMessageDelete(messageId === '@original' ? this.id : messageId));
|
||||||
}
|
}
|
||||||
|
|
||||||
async createResponse({ files, ...body }: MessageWebhookCreateBodyRequest) {
|
async createResponse({ files, ...body }: MessageWebhookCreateBodyRequest) {
|
||||||
|
@ -51,7 +51,7 @@ export class BaseMessage extends DiscordBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
createComponentCollector(options?: ListenerOptions) {
|
createComponentCollector(options?: ListenerOptions) {
|
||||||
return this.client.components.createComponentCollector(this.id, options);
|
return this.client.components!.createComponentCollector(this.id, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
get url() {
|
get url() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user