fix: actually using biome

This commit is contained in:
MARCROCK22 2024-09-15 19:02:13 +00:00
parent 23c23156e6
commit 3245291121
49 changed files with 673 additions and 643 deletions

View File

@ -1,16 +1,16 @@
{ {
"$schema": "https://unpkg.com/@changesets/config@2.3.1/schema.json", "$schema": "https://unpkg.com/@changesets/config@2.3.1/schema.json",
"changelog": [ "changelog": [
"@changesets/changelog-github", "@changesets/changelog-github",
{ {
"repo": "tiramisulabs/seyfert" "repo": "tiramisulabs/seyfert"
} }
], ],
"commit": false, "commit": false,
"fixed": [], "fixed": [],
"linked": [], "linked": [],
"access": "restricted", "access": "restricted",
"baseBranch": "main", "baseBranch": "main",
"updateInternalDependencies": "patch", "updateInternalDependencies": "patch",
"ignore": [] "ignore": []
} }

View File

@ -1,8 +1,30 @@
{ {
"$schema": "https://biomejs.dev/schemas/1.8.1/schema.json", "$schema": "https://biomejs.dev/schemas/1.9.0/schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",
"useIgnoreFile": true,
"defaultBranch": "main"
},
"files": {
"ignoreUnknown": true,
"ignore": ["node_modules/", "build", "lib", "__test__", "package.json", "tsconfig.json", ".vscode"]
},
"formatter": {
"enabled": true,
"indentStyle": "tab",
"indentWidth": 2,
"lineWidth": 120,
"lineEnding": "crlf",
"formatWithErrors": true
},
"organizeImports": {
"enabled": true
},
"linter": { "linter": {
"enabled": true, "enabled": true,
"rules": { "rules": {
"recommended": false,
"all": true, "all": true,
"security": { "security": {
"noGlobalEval": "off" "noGlobalEval": "off"
@ -10,92 +32,52 @@
"suspicious": { "suspicious": {
"noExplicitAny": "off", "noExplicitAny": "off",
"noAssignInExpressions": "off", "noAssignInExpressions": "off",
"useAwait": "off",
"noConfusingVoidType": "off",
"noAsyncPromiseExecutor": "off",
"noUnsafeDeclarationMerging": "off", "noUnsafeDeclarationMerging": "off",
"noEmptyInterface": "off", "noEmptyInterface": "off",
"noConfusingVoidType": "off",
"noImplicitAnyLet": "off",
"noEmptyBlockStatements": "off",
"useAwait": "off",
"noConsoleLog": "off",
"noAsyncPromiseExecutor": "off",
"noThenProperty": "off" "noThenProperty": "off"
}, },
"style": {
"noNonNullAssertion": "off",
"noParameterAssign": "off",
"useExportType": "error",
"useImportType": "error",
"useNodejsImportProtocol": "error",
"useNamingConvention": "off",
"noParameterProperties": "off",
"useFilenamingConvention": "off",
"noNamespaceImport": "off",
"useSingleCaseStatement": "off",
"useBlockStatements": "off",
"useEnumInitializers": "off",
"noArguments": "off",
"useForOf": "off"
},
"correctness": { "correctness": {
"noUnusedVariables": "off", "noNodejsModules": "off",
"noNodejsModules": "off" "useImportExtensions": "off",
"noUnusedFunctionParameters": "off",
"noUnusedVariables": "off"
}, },
"nursery": { "style": {
"useImportRestrictions": "off" "noDefaultExport": "off",
"useBlockStatements": "off",
"noParameterProperties": "off",
"useNamingConvention": "off",
"noNonNullAssertion": "off",
"useForOf": "off",
"useDefaultSwitchClause": "off",
"noParameterAssign": "off",
"useFilenamingConvention": "off",
"useEnumInitializers": "off",
"useExplicitLengthCheck": "off",
"noNamespaceImport": "off"
}, },
"complexity": { "complexity": {
"noUselessLoneBlockStatements": "warn",
"noBannedTypes": "off",
"noForEach": "off", "noForEach": "off",
"noUselessConstructor": "off",
"noExcessiveCognitiveComplexity": "off", "noExcessiveCognitiveComplexity": "off",
"noStaticOnlyClass": "off" "noUselessConstructor": "off"
},
"a11y": {
"all": false
}, },
"performance": { "performance": {
"noDelete": "off",
"noBarrelFile": "off", "noBarrelFile": "off",
"noReExportAll": "off" "noDelete": "off",
"noReExportAll": "off",
"useTopLevelRegex": "off"
} }
} }
}, },
"json": {
"formatter": {
"enabled": true,
"indentWidth": 2,
"lineWidth": 80
}
},
"formatter": {
"enabled": true,
"indentWidth": 2,
"indentStyle": "tab",
"lineWidth": 120,
"lineEnding": "crlf",
"formatWithErrors": true
},
"javascript": { "javascript": {
"formatter": { "formatter": {
"quoteStyle": "single", "quoteStyle": "single",
"semicolons": "always",
"arrowParentheses": "asNeeded", "arrowParentheses": "asNeeded",
"bracketSameLine": true, "bracketSameLine": true
"semicolons": "always"
} }
},
"files": {
"ignoreUnknown": true,
"ignore": [
"node_modules/",
"build",
"lib",
"__test__",
"package.json",
"tsconfig.json"
]
},
"organizeImports": {
"enabled": false
} }
} }

View File

@ -1 +1 @@
module.exports = { extends: ['@commitlint/config-conventional'] }; module.exports = { extends: ['@commitlint/config-conventional'] };

View File

@ -1,3 +1,4 @@
import type { Identify, OmitInsert } from '../../common';
import type { import type {
APIThreadChannel, APIThreadChannel,
RESTDeleteAPIAutoModerationRuleResult, RESTDeleteAPIAutoModerationRuleResult,
@ -116,7 +117,6 @@ import type {
RESTPutAPIGuildMemberRoleResult, RESTPutAPIGuildMemberRoleResult,
RESTPutAPIGuildTemplateSyncResult, RESTPutAPIGuildTemplateSyncResult,
} from '../../types'; } from '../../types';
import type { Identify, OmitInsert } from '../../common';
import type { ProxyRequestMethod } from '../Router'; import type { ProxyRequestMethod } from '../Router';
import type { RestArguments } from '../api'; import type { RestArguments } from '../api';
import type { RawFile } from '../shared'; import type { RawFile } from '../shared';
@ -334,7 +334,7 @@ export interface GuildRoutes {
args: RestArguments< args: RestArguments<
ProxyRequestMethod.Post, ProxyRequestMethod.Post,
Omit<RESTPostAPIGuildStickerFormDataBody, 'file'>, Omit<RESTPostAPIGuildStickerFormDataBody, 'file'>,
{}, object,
OmitInsert<RawFile, 'key', { key: 'file' }>[] OmitInsert<RawFile, 'key', { key: 'file' }>[]
>, >,
): Promise<RESTPostAPIGuildStickerResult>; ): Promise<RESTPostAPIGuildStickerResult>;

View File

@ -5,10 +5,10 @@ import type { WorkerSendApiRequest } from '../websocket/discord/worker';
import { CDNRouter, type ProxyRequestMethod } from './Router'; import { CDNRouter, type ProxyRequestMethod } from './Router';
import { Bucket } from './bucket'; import { Bucket } from './bucket';
import { import {
DefaultUserAgent,
type ApiHandlerInternalOptions, type ApiHandlerInternalOptions,
type ApiHandlerOptions, type ApiHandlerOptions,
type ApiRequestOptions, type ApiRequestOptions,
DefaultUserAgent,
type HttpMethods, type HttpMethods,
type RawFile, type RawFile,
type RequestHeaders, type RequestHeaders,
@ -54,7 +54,7 @@ export class ApiHandler {
globalUnblock() { globalUnblock() {
this.globalBlock = false; this.globalBlock = false;
let cb; let cb: (() => void) | undefined;
while ((cb = this.readyQueue.shift())) { while ((cb = this.readyQueue.shift())) {
cb(); cb();
} }
@ -105,7 +105,7 @@ export class ApiHandler {
request: { ...request, auth }, request: { ...request, auth },
}); });
let response; let response: Response;
try { try {
const url = `${this.options.domain}/${this.options.baseUrl}${finalUrl}`; const url = `${this.options.domain}/${this.options.baseUrl}${finalUrl}`;

View File

@ -1,10 +1,10 @@
import type { APIAttachment, RESTAPIAttachment } from '../types';
import { randomBytes } from 'node:crypto'; import { randomBytes } from 'node:crypto';
import { promises } from 'node:fs';
import path from 'node:path'; import path from 'node:path';
import type { UsingClient, RawFile } from '..'; import type { RawFile, UsingClient } from '..';
import type { ImageResolvable, ObjectToLower } from '../common'; import type { ImageResolvable, ObjectToLower } from '../common';
import { Base } from '../structures/extra/Base'; import { Base } from '../structures/extra/Base';
import { promises } from 'node:fs'; import type { APIAttachment, RESTAPIAttachment } from '../types';
export interface AttachmentResolvableMap { export interface AttachmentResolvableMap {
url: string; url: string;
@ -209,7 +209,7 @@ export async function resolveAttachmentData(
if (Buffer.isBuffer(data)) return { data }; if (Buffer.isBuffer(data)) return { data };
// @ts-expect-error // @ts-expect-error
if (typeof data[Symbol.asyncIterator] === 'function') { if (typeof data[Symbol.asyncIterator] === 'function') {
const buffers = []; const buffers: Buffer[] = [];
for await (const resource of data as unknown as AsyncIterable<ArrayBuffer>) buffers.push(Buffer.from(resource)); for await (const resource of data as unknown as AsyncIterable<ArrayBuffer>) buffers.push(Buffer.from(resource));
return { data: Buffer.concat(buffers) }; return { data: Buffer.concat(buffers) };
} }

View File

@ -22,12 +22,14 @@ export class MemoryAdapter<T> implements Adapter {
}, },
) {} ) {}
start() {} start() {
//
}
scan(query: string, keys?: false): any[]; scan(query: string, keys?: false): any[];
scan(query: string, keys: true): string[]; scan(query: string, keys: true): string[];
scan(query: string, keys = false) { scan(query: string, keys = false) {
const values = []; const values: (string | unknown)[] = [];
const sq = query.split('.'); const sq = query.split('.');
for (const [key, value] of this.storage.entries()) { for (const [key, value] of this.storage.entries()) {
if (key.split('.').every((value, i) => (sq[i] === '*' ? !!value : sq[i] === value))) { if (key.split('.').every((value, i) => (sq[i] === '*' ? !!value : sq[i] === value))) {

View File

@ -1,5 +1,5 @@
import { LimitedCollection } from '../..'; import { LimitedCollection } from '../..';
import { MergeOptions, type MakeRequired } from '../../common'; import { type MakeRequired, MergeOptions } from '../../common';
import type { Adapter } from './types'; import type { Adapter } from './types';
//TODO: optimizar esto //TODO: optimizar esto
export interface ResourceLimitedMemoryAdapter { export interface ResourceLimitedMemoryAdapter {
@ -57,12 +57,14 @@ export class LimitedMemoryAdapter<T> implements Adapter {
); );
} }
start() {} start() {
//
}
scan(query: string, keys?: false): any[]; scan(query: string, keys?: false): any[];
scan(query: string, keys: true): string[]; scan(query: string, keys: true): string[];
scan(query: string, keys = false) { scan(query: string, keys = false) {
const values = []; const values: (string | unknown)[] = [];
const sq = query.split('.'); const sq = query.split('.');
for (const iterator of [...this.storage.values()].flatMap(x => x.entries())) for (const iterator of [...this.storage.values()].flatMap(x => x.entries()))
for (const [key, value] of iterator) { for (const [key, value] of iterator) {

View File

@ -1,8 +1,8 @@
import { randomUUID } from 'node:crypto'; import { randomUUID } from 'node:crypto';
import { lazyLoadPackage } from '../../common';
import type { WorkerData } from '../../websocket'; import type { WorkerData } from '../../websocket';
import type { WorkerSendCacheRequest } from '../../websocket/discord/worker'; import type { WorkerSendCacheRequest } from '../../websocket/discord/worker';
import type { Adapter } from './types'; import type { Adapter } from './types';
import { lazyLoadPackage } from '../../common';
let parentPort: import('node:worker_threads').MessagePort; let parentPort: import('node:worker_threads').MessagePort;
@ -15,7 +15,9 @@ export class WorkerAdapter implements Adapter {
if (worker_threads?.parentPort) parentPort = worker_threads.parentPort; if (worker_threads?.parentPort) parentPort = worker_threads.parentPort;
} }
start() {} start() {
//
}
postMessage(body: any): unknown { postMessage(body: any): unknown {
if (parentPort) return parentPort.postMessage(body); if (parentPort) return parentPort.postMessage(body);

80
src/cache/index.ts vendored
View File

@ -1,10 +1,11 @@
import { Logger, type If } from '../common'; import { type If, Logger } from '../common';
import type { Adapter } from './adapters'; import type { Adapter } from './adapters';
import { Guilds } from './resources/guilds'; import { Guilds } from './resources/guilds';
import { Users } from './resources/users'; import { Users } from './resources/users';
import { Bans } from './resources/bans';
import { Channels } from './resources/channels'; import { Channels } from './resources/channels';
import { Emojis } from './resources/emojis'; import { Emojis } from './resources/emojis';
import { Members } from './resources/members'; import { Members } from './resources/members';
@ -14,13 +15,9 @@ import { StageInstances } from './resources/stage-instances';
import { Stickers } from './resources/stickers'; import { Stickers } from './resources/stickers';
import { Threads } from './resources/threads'; import { Threads } from './resources/threads';
import { VoiceStates } from './resources/voice-states'; import { VoiceStates } from './resources/voice-states';
import { Bans } from './resources/bans';
import type { InternalOptions, UsingClient } from '../commands';
import { import {
ChannelType,
GatewayIntentBits,
GuildMemberFlags,
OverwriteType,
type APIChannel, type APIChannel,
type APIEmoji, type APIEmoji,
type APIGuildMember, type APIGuildMember,
@ -28,11 +25,14 @@ import {
type APISticker, type APISticker,
type APITextChannel, type APITextChannel,
type APIUser, type APIUser,
ChannelType,
type GatewayDispatchPayload, type GatewayDispatchPayload,
GatewayIntentBits,
GuildMemberFlags,
OverwriteType,
} from '../types'; } from '../types';
import type { InternalOptions, UsingClient } from '../commands';
import { Overwrites } from './resources/overwrites';
import { Messages } from './resources/messages'; import { Messages } from './resources/messages';
import { Overwrites } from './resources/overwrites';
export { BaseResource } from './resources/default/base'; export { BaseResource } from './resources/default/base';
export { GuildRelatedResource } from './resources/default/guild-related'; export { GuildRelatedResource } from './resources/default/guild-related';
export { GuildBasedResource } from './resources/default/guild-based'; export { GuildBasedResource } from './resources/default/guild-based';
@ -180,7 +180,9 @@ export class Cache {
if (this.disabledCache.onPacket) { if (this.disabledCache.onPacket) {
//@ts-expect-error //@ts-expect-error
this.onPacket = () => {}; this.onPacket = () => {
// disable cache
};
} }
} }
@ -525,15 +527,17 @@ export class Cache {
break; break;
case 'CHANNEL_CREATE': case 'CHANNEL_CREATE':
case 'CHANNEL_UPDATE': case 'CHANNEL_UPDATE':
if ('guild_id' in event.d) { {
await this.channels?.set(event.d.id, event.d.guild_id!, event.d); if ('guild_id' in event.d) {
if (event.d.permission_overwrites?.length) await this.channels?.set(event.d.id, event.d.guild_id!, event.d);
await this.overwrites?.set(event.d.id, event.d.guild_id!, event.d.permission_overwrites); if (event.d.permission_overwrites?.length)
break; await this.overwrites?.set(event.d.id, event.d.guild_id!, event.d.permission_overwrites);
} break;
if (event.d.type === ChannelType.DM) { }
await this.channels?.set(event.d.recipients![0]?.id, '@me', event.d); if (event.d.type === ChannelType.DM) {
break; await this.channels?.set(event.d.recipients![0]?.id, '@me', event.d);
break;
}
} }
break; break;
case 'CHANNEL_DELETE': case 'CHANNEL_DELETE':
@ -553,18 +557,22 @@ export class Cache {
await this.bans?.remove(event.d.user.id, event.d.guild_id); await this.bans?.remove(event.d.user.id, event.d.guild_id);
break; break;
case 'GUILD_EMOJIS_UPDATE': case 'GUILD_EMOJIS_UPDATE':
await this.emojis?.remove(await this.emojis?.keys(event.d.guild_id), event.d.guild_id); {
await this.emojis?.set( await this.emojis?.remove(await this.emojis?.keys(event.d.guild_id), event.d.guild_id);
event.d.emojis.map(x => [x.id!, x] as [string, APIEmoji]), await this.emojis?.set(
event.d.guild_id, event.d.emojis.map(x => [x.id!, x] as [string, APIEmoji]),
); event.d.guild_id,
);
}
break; break;
case 'GUILD_STICKERS_UPDATE': case 'GUILD_STICKERS_UPDATE':
await this.stickers?.remove(await this.stickers?.keys(event.d.guild_id), event.d.guild_id); {
await this.stickers?.set( await this.stickers?.remove(await this.stickers?.keys(event.d.guild_id), event.d.guild_id);
event.d.stickers.map(x => [x.id, x] as [string, APISticker]), await this.stickers?.set(
event.d.guild_id, event.d.stickers.map(x => [x.id, x] as [string, APISticker]),
); event.d.guild_id,
);
}
break; break;
case 'GUILD_MEMBER_ADD': case 'GUILD_MEMBER_ADD':
case 'GUILD_MEMBER_UPDATE': case 'GUILD_MEMBER_UPDATE':
@ -593,14 +601,16 @@ export class Cache {
break; break;
case 'VOICE_STATE_UPDATE': case 'VOICE_STATE_UPDATE':
if (!event.d.guild_id) { {
return; if (!event.d.guild_id) {
} return;
}
if (event.d.channel_id != null) { if (event.d.channel_id != null) {
await this.voiceStates?.set(event.d.user_id, event.d.guild_id, event.d); await this.voiceStates?.set(event.d.user_id, event.d.guild_id, event.d);
} else { } else {
await this.voiceStates?.remove(event.d.user_id, event.d.guild_id); await this.voiceStates?.remove(event.d.user_id, event.d.guild_id);
}
} }
break; break;
case 'STAGE_INSTANCE_CREATE': case 'STAGE_INSTANCE_CREATE':

View File

@ -1,5 +1,5 @@
import { join } from 'node:path'; import { join } from 'node:path';
import { ApiHandler, Router, type APIRoutes } from '../api'; import { type APIRoutes, ApiHandler, Router } from '../api';
import type { Adapter } from '../cache'; import type { Adapter } from '../cache';
import { Cache, MemoryAdapter } from '../cache'; import { Cache, MemoryAdapter } from '../cache';
import type { import type {
@ -23,6 +23,7 @@ import {
InteractionShorter, InteractionShorter,
LogLevels, LogLevels,
Logger, Logger,
type MakeRequired,
MemberShorter, MemberShorter,
MergeOptions, MergeOptions,
MessageShorter, MessageShorter,
@ -34,11 +35,13 @@ import {
WebhookShorter, WebhookShorter,
filterSplit, filterSplit,
magicImport, magicImport,
type MakeRequired,
} from '../common'; } from '../common';
import type { LocaleString, RESTPostAPIChannelMessageJSONBody } from '../types'; import { promises } from 'node:fs';
import { HandleCommand } from '../commands/handle';
import { BanShorter } from '../common/shorters/bans';
import type { Awaitable, DeepPartial, IntentStrings, OmitInsert, PermissionStrings, When } from '../common/types/util'; import type { Awaitable, DeepPartial, IntentStrings, OmitInsert, PermissionStrings, When } from '../common/types/util';
import type { ComponentCommand, ComponentContext, ModalCommand, ModalContext } from '../components';
import { ComponentHandler } from '../components/handler'; import { ComponentHandler } from '../components/handler';
import { LangsHandler } from '../langs/handler'; import { LangsHandler } from '../langs/handler';
import type { import type {
@ -49,10 +52,7 @@ import type {
ModalSubmitInteraction, ModalSubmitInteraction,
UserCommandInteraction, UserCommandInteraction,
} from '../structures'; } from '../structures';
import type { ComponentCommand, ComponentContext, ModalCommand, ModalContext } from '../components'; import type { LocaleString, RESTPostAPIChannelMessageJSONBody } from '../types';
import { promises } from 'node:fs';
import { BanShorter } from '../common/shorters/bans';
import { HandleCommand } from '../commands/handle';
import type { MessageStructure } from './transformers'; import type { MessageStructure } from './transformers';
export class BaseClient { export class BaseClient {
@ -396,18 +396,16 @@ export class BaseClient {
>() { >() {
const seyfertConfig = (BaseClient._seyfertCfWorkerConfig || const seyfertConfig = (BaseClient._seyfertCfWorkerConfig ||
(await this.options?.getRC?.()) || (await this.options?.getRC?.()) ||
( (await Promise.any(
await Promise.any( ['.js', '.mjs', '.cjs', '.ts', '.mts', '.cts'].map(ext =>
['.js', '.mjs', '.cjs', '.ts', '.mts', '.cts'].map(ext => magicImport(join(process.cwd(), `seyfert.config${ext}`)).then(x => x.default ?? x),
magicImport(join(process.cwd(), `seyfert.config${ext}`)).then(x => x.default ?? x), ),
),
)
).catch((e: AggregateError) => { ).catch((e: AggregateError) => {
if (e.errors.every((err: Error) => err.stack?.includes('ERR_MODULE_NOT_FOUND'))) { if (e.errors.every((err: Error) => err.stack?.includes('ERR_MODULE_NOT_FOUND'))) {
throw new Error('No seyfert.config file found'); throw new Error('No seyfert.config file found');
} }
throw e.errors.find((err: Error) => !err.stack?.includes('ERR_MODULE_NOT_FOUND')) ?? e.errors[0]; throw e.errors.find((err: Error) => !err.stack?.includes('ERR_MODULE_NOT_FOUND')) ?? e.errors[0];
})) as T; }))) as T;
const { locations, debug, ...env } = seyfertConfig; const { locations, debug, ...env } = seyfertConfig;
@ -438,7 +436,7 @@ export interface BaseClientOptions {
| ModalSubmitInteraction | ModalSubmitInteraction
| EntryPointInteraction<boolean> | EntryPointInteraction<boolean>
| When<InferWithPrefix, MessageStructure, never>, | When<InferWithPrefix, MessageStructure, never>,
) => {}; ) => object;
globalMiddlewares?: readonly (keyof RegisteredMiddlewares)[]; globalMiddlewares?: readonly (keyof RegisteredMiddlewares)[];
commands?: { commands?: {
defaults?: { defaults?: {

View File

@ -1,21 +1,21 @@
import { type GatewayDispatchPayload, type GatewayPresenceUpdateData, GatewayIntentBits } from '../types';
import type { CommandContext, Message } from '..'; import type { CommandContext, Message } from '..';
import { import {
type Awaitable, type Awaitable,
lazyLoadPackage,
type DeepPartial, type DeepPartial,
type If, type If,
type WatcherPayload, type WatcherPayload,
type WatcherSendToShard, type WatcherSendToShard,
lazyLoadPackage,
} from '../common'; } from '../common';
import { EventHandler } from '../events'; import { EventHandler } from '../events';
import { ShardManager, properties, type ShardManagerOptions } from '../websocket'; import { type GatewayDispatchPayload, GatewayIntentBits, type GatewayPresenceUpdateData } from '../types';
import { ShardManager, type ShardManagerOptions, properties } from '../websocket';
import { MemberUpdateHandler } from '../websocket/discord/events/memberUpdate'; import { MemberUpdateHandler } from '../websocket/discord/events/memberUpdate';
import { PresenceUpdateHandler } from '../websocket/discord/events/presenceUpdate'; import { PresenceUpdateHandler } from '../websocket/discord/events/presenceUpdate';
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 { Collectors } from './collectors'; import { Collectors } from './collectors';
import { type ClientUserStructure, Transformers, type MessageStructure } from './transformers'; import { type ClientUserStructure, type MessageStructure, Transformers } from './transformers';
let parentPort: import('node:worker_threads').MessagePort; let parentPort: import('node:worker_threads').MessagePort;
@ -149,18 +149,22 @@ export class Client<Ready extends boolean = boolean> extends BaseClient {
this.collectors.run('RAW', packet, this), this.collectors.run('RAW', packet, this),
]); //ignore promise ]); //ignore promise
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)) { {
return; if (!this.memberUpdateHandler.check(packet.d)) {
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);
break; break;
case 'PRESENCE_UPDATE': case 'PRESENCE_UPDATE':
if (!this.presenceUpdateHandler.check(packet.d)) { {
return; if (!this.presenceUpdateHandler.check(packet.d)) {
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);
break; break;
case 'GUILD_DELETE': case 'GUILD_DELETE':
case 'GUILD_CREATE': { case 'GUILD_CREATE': {
@ -181,12 +185,16 @@ export class Client<Ready extends boolean = boolean> extends BaseClient {
default: { default: {
switch (packet.t) { switch (packet.t) {
case 'INTERACTION_CREATE': case 'INTERACTION_CREATE':
await this.events?.execute(packet.t as never, packet, this as Client<true>, shardId); {
await this.handleCommand.interaction(packet.d, shardId); await this.events?.execute(packet.t as never, packet, this as Client<true>, shardId);
await this.handleCommand.interaction(packet.d, shardId);
}
break; break;
case 'MESSAGE_CREATE': case 'MESSAGE_CREATE':
await this.events?.execute(packet.t as never, packet, this as Client<true>, shardId); {
await this.handleCommand.message(packet.d, shardId); await this.events?.execute(packet.t as never, packet, this as Client<true>, shardId);
await this.handleCommand.message(packet.d, shardId);
}
break; break;
case 'READY': { case 'READY': {
const ids = packet.d.guilds.map(x => x.id); const ids = packet.d.guilds.map(x => x.id);

View File

@ -1,5 +1,5 @@
import type { ChannelType } from '../types';
import { type CustomStructures, OptionResolver } from '../commands'; import { type CustomStructures, OptionResolver } from '../commands';
import type { StructStates } from '../common/';
import { import {
AnonymousGuild, AnonymousGuild,
AutoModerationRule, AutoModerationRule,
@ -30,8 +30,8 @@ import {
Webhook, Webhook,
WebhookMessage, WebhookMessage,
} from '../structures'; } from '../structures';
import type { StructStates } from '../common/';
import { GuildBan } from '../structures/GuildBan'; import { GuildBan } from '../structures/GuildBan';
import type { ChannelType } from '../types';
export type PollStructure = InferCustomStructure<Poll, 'Poll'>; export type PollStructure = InferCustomStructure<Poll, 'Poll'>;
export type ClientUserStructure = InferCustomStructure<ClientUser, 'ClientUser'>; export type ClientUserStructure = InferCustomStructure<ClientUser, 'ClientUser'>;
@ -64,130 +64,99 @@ export type VoiceStateStructure = InferCustomStructure<VoiceState, 'VoiceState'>
export type WebhookStructure = InferCustomStructure<Webhook, 'Webhook'>; export type WebhookStructure = InferCustomStructure<Webhook, 'Webhook'>;
export type OptionResolverStructure = InferCustomStructure<OptionResolver, 'OptionResolver'>; export type OptionResolverStructure = InferCustomStructure<OptionResolver, 'OptionResolver'>;
export class Transformers { export const Transformers = {
static AnonymousGuild(...args: ConstructorParameters<typeof AnonymousGuild>): AnonymousGuildStructure { AnonymousGuild(...args: ConstructorParameters<typeof AnonymousGuild>): AnonymousGuildStructure {
return new AnonymousGuild(...args); return new AnonymousGuild(...args);
} },
AutoModerationRule(...args: ConstructorParameters<typeof AutoModerationRule>): AutoModerationRuleStructure {
static AutoModerationRule(...args: ConstructorParameters<typeof AutoModerationRule>): AutoModerationRuleStructure {
return new AutoModerationRule(...args); return new AutoModerationRule(...args);
} },
BaseChannel(...args: ConstructorParameters<typeof BaseChannel>): BaseChannelStructure {
static BaseChannel(...args: ConstructorParameters<typeof BaseChannel>): BaseChannelStructure {
return new BaseChannel(...args); return new BaseChannel(...args);
} },
BaseGuildChannel(...args: ConstructorParameters<typeof BaseGuildChannel>): BaseGuildChannelStructure {
static BaseGuildChannel(...args: ConstructorParameters<typeof BaseGuildChannel>): BaseGuildChannelStructure {
return new BaseGuildChannel(...args); return new BaseGuildChannel(...args);
} },
TextGuildChannel(...args: ConstructorParameters<typeof TextGuildChannel>): TextGuildChannelStructure {
static TextGuildChannel(...args: ConstructorParameters<typeof TextGuildChannel>): TextGuildChannelStructure {
return new TextGuildChannel(...args); return new TextGuildChannel(...args);
} },
DMChannel(...args: ConstructorParameters<typeof DMChannel>): DMChannelStructure {
static DMChannel(...args: ConstructorParameters<typeof DMChannel>): DMChannelStructure {
return new DMChannel(...args); return new DMChannel(...args);
} },
VoiceChannel(...args: ConstructorParameters<typeof VoiceChannel>): VoiceChannelStructure {
static VoiceChannel(...args: ConstructorParameters<typeof VoiceChannel>): VoiceChannelStructure {
return new VoiceChannel(...args); return new VoiceChannel(...args);
} },
StageChannel(...args: ConstructorParameters<typeof StageChannel>): StageChannelStructure {
static StageChannel(...args: ConstructorParameters<typeof StageChannel>): StageChannelStructure {
return new StageChannel(...args); return new StageChannel(...args);
} },
MediaChannel(...args: ConstructorParameters<typeof MediaChannel>): MediaChannelStructure {
static MediaChannel(...args: ConstructorParameters<typeof MediaChannel>): MediaChannelStructure {
return new MediaChannel(...args); return new MediaChannel(...args);
} },
ForumChannel(...args: ConstructorParameters<typeof ForumChannel>): ForumChannelStructure {
static ForumChannel(...args: ConstructorParameters<typeof ForumChannel>): ForumChannelStructure {
return new ForumChannel(...args); return new ForumChannel(...args);
} },
ThreadChannel(...args: ConstructorParameters<typeof ThreadChannel>): ThreadChannelStructure {
static ThreadChannel(...args: ConstructorParameters<typeof ThreadChannel>): ThreadChannelStructure {
return new ThreadChannel(...args); return new ThreadChannel(...args);
} },
CategoryChannel(...args: ConstructorParameters<typeof CategoryChannel>): CategoryChannelStructure {
static CategoryChannel(...args: ConstructorParameters<typeof CategoryChannel>): CategoryChannelStructure {
return new CategoryChannel(...args); return new CategoryChannel(...args);
} },
NewsChannel(...args: ConstructorParameters<typeof NewsChannel>): NewsChannelStructure {
static NewsChannel(...args: ConstructorParameters<typeof NewsChannel>): NewsChannelStructure {
return new NewsChannel(...args); return new NewsChannel(...args);
} },
DirectoryChannel(...args: ConstructorParameters<typeof DirectoryChannel>): DirectoryChannelStructure {
static DirectoryChannel(...args: ConstructorParameters<typeof DirectoryChannel>): DirectoryChannelStructure {
return new DirectoryChannel(...args); return new DirectoryChannel(...args);
} },
ClientUser(...args: ConstructorParameters<typeof ClientUser>): ClientUserStructure {
static ClientUser(...args: ConstructorParameters<typeof ClientUser>): ClientUserStructure {
return new ClientUser(...args); return new ClientUser(...args);
} },
Guild<State extends StructStates = 'api'>(...args: ConstructorParameters<typeof Guild>): GuildStructure<State> {
static Guild<State extends StructStates = 'api'>(
...args: ConstructorParameters<typeof Guild>
): GuildStructure<State> {
return new Guild<State>(...args); return new Guild<State>(...args);
} },
GuildBan(...args: ConstructorParameters<typeof GuildBan>): GuildBanStructure {
static GuildBan(...args: ConstructorParameters<typeof GuildBan>): GuildBanStructure {
return new GuildBan(...args); return new GuildBan(...args);
} },
GuildEmoji(...args: ConstructorParameters<typeof GuildEmoji>): GuildEmojiStructure {
static GuildEmoji(...args: ConstructorParameters<typeof GuildEmoji>): GuildEmojiStructure {
return new GuildEmoji(...args); return new GuildEmoji(...args);
} },
GuildMember(...args: ConstructorParameters<typeof GuildMember>): GuildMemberStructure {
static GuildMember(...args: ConstructorParameters<typeof GuildMember>): GuildMemberStructure {
return new GuildMember(...args); return new GuildMember(...args);
} },
InteractionGuildMember(
static InteractionGuildMember(
...args: ConstructorParameters<typeof InteractionGuildMember> ...args: ConstructorParameters<typeof InteractionGuildMember>
): InteractionGuildMemberStructure { ): InteractionGuildMemberStructure {
return new InteractionGuildMember(...args); return new InteractionGuildMember(...args);
} },
GuildRole(...args: ConstructorParameters<typeof GuildRole>): GuildRoleStructure {
static GuildRole(...args: ConstructorParameters<typeof GuildRole>): GuildRoleStructure {
return new GuildRole(...args); return new GuildRole(...args);
} },
GuildTemplate(...args: ConstructorParameters<typeof GuildTemplate>): GuildTemplateStructure {
static GuildTemplate(...args: ConstructorParameters<typeof GuildTemplate>): GuildTemplateStructure {
return new GuildTemplate(...args); return new GuildTemplate(...args);
} },
Message(...args: ConstructorParameters<typeof Message>): MessageStructure {
static Message(...args: ConstructorParameters<typeof Message>): MessageStructure {
return new Message(...args); return new Message(...args);
} },
WebhookMessage(...args: ConstructorParameters<typeof WebhookMessage>): WebhookMessageStructure {
static WebhookMessage(...args: ConstructorParameters<typeof WebhookMessage>): WebhookMessageStructure {
return new WebhookMessage(...args); return new WebhookMessage(...args);
} },
Poll(...args: ConstructorParameters<typeof Poll>): PollStructure {
static Poll(...args: ConstructorParameters<typeof Poll>): PollStructure {
return new Poll(...args); return new Poll(...args);
} },
Sticker(...args: ConstructorParameters<typeof Sticker>): StickerStructure {
static Sticker(...args: ConstructorParameters<typeof Sticker>): StickerStructure {
return new Sticker(...args); return new Sticker(...args);
} },
User(...args: ConstructorParameters<typeof User>): UserStructure {
static User(...args: ConstructorParameters<typeof User>): UserStructure {
return new User(...args); return new User(...args);
} },
VoiceState(...args: ConstructorParameters<typeof VoiceState>): VoiceStateStructure {
static VoiceState(...args: ConstructorParameters<typeof VoiceState>): VoiceStateStructure {
return new VoiceState(...args); return new VoiceState(...args);
} },
Webhook(...args: ConstructorParameters<typeof Webhook>): WebhookStructure {
static Webhook(...args: ConstructorParameters<typeof Webhook>): WebhookStructure {
return new Webhook(...args); return new Webhook(...args);
} },
OptionResolver(...args: ConstructorParameters<typeof OptionResolver>): OptionResolverStructure {
static OptionResolver(...args: ConstructorParameters<typeof OptionResolver>): OptionResolverStructure {
return new OptionResolver(...args); return new OptionResolver(...args);
} },
} };
export type InferCustomStructure<T, N extends string> = CustomStructures extends Record<N, infer P> ? P : T; export type InferCustomStructure<T, N extends string> = CustomStructures extends Record<N, infer P> ? P : T;

View File

@ -1,10 +1,10 @@
import { type GatewayDispatchPayload, type GatewaySendPayload, GatewayIntentBits } from '../types';
import { randomUUID } from 'node:crypto'; import { randomUUID } from 'node:crypto';
import { ApiHandler, Logger } from '..'; import { ApiHandler, Logger } from '..';
import { WorkerAdapter } from '../cache'; import { WorkerAdapter } from '../cache';
import { LogLevels, lazyLoadPackage, type DeepPartial, type When } from '../common'; import { type DeepPartial, LogLevels, type When, lazyLoadPackage } from '../common';
import { EventHandler } from '../events'; import { EventHandler } from '../events';
import { Shard, properties, type ShardManagerOptions, type WorkerData } from '../websocket'; import { type GatewayDispatchPayload, GatewayIntentBits, type GatewaySendPayload } from '../types';
import { Shard, type ShardManagerOptions, type WorkerData, properties } from '../websocket';
import type { import type {
WorkerReady, WorkerReady,
WorkerReceivePayload, WorkerReceivePayload,
@ -23,10 +23,10 @@ import type { BaseClientOptions, ServicesOptions, StartOptions } from './base';
import { BaseClient } from './base'; import { BaseClient } from './base';
import type { Client, ClientOptions } from './client'; import type { Client, ClientOptions } from './client';
import { Collectors } from './collectors';
import { type ClientUserStructure, Transformers } from './transformers';
import { MemberUpdateHandler } from '../websocket/discord/events/memberUpdate'; import { MemberUpdateHandler } from '../websocket/discord/events/memberUpdate';
import { PresenceUpdateHandler } from '../websocket/discord/events/presenceUpdate'; import { PresenceUpdateHandler } from '../websocket/discord/events/presenceUpdate';
import { Collectors } from './collectors';
import { type ClientUserStructure, Transformers } from './transformers';
let workerData: WorkerData; let workerData: WorkerData;
let manager: import('node:worker_threads').MessagePort; let manager: import('node:worker_threads').MessagePort;
@ -42,7 +42,9 @@ try {
totalShards: Number(process.env.SEYFERT_WORKER_TOTALSHARDS), totalShards: Number(process.env.SEYFERT_WORKER_TOTALSHARDS),
mode: process.env.SEYFERT_WORKER_MODE, mode: process.env.SEYFERT_WORKER_MODE,
} as WorkerData; } as WorkerData;
} catch {} } catch {
//
}
export class WorkerClient<Ready extends boolean = boolean> extends BaseClient { export class WorkerClient<Ready extends boolean = boolean> extends BaseClient {
private __handleGuilds?: Set<string> = new Set(); private __handleGuilds?: Set<string> = new Set();
@ -287,7 +289,7 @@ export class WorkerClient<Ready extends boolean = boolean> extends BaseClient {
break; break;
case 'EXECUTE_EVAL': case 'EXECUTE_EVAL':
{ {
let result; let result: unknown;
try { try {
result = await eval(` result = await eval(`
(${data.func})(this) (${data.func})(this)
@ -332,7 +334,7 @@ export class WorkerClient<Ready extends boolean = boolean> extends BaseClient {
}); });
} }
tellWorker(workerId: number, func: (_: this) => {}) { tellWorker(workerId: number, func: (_: this) => any) {
const nonce = this.generateNonce(); const nonce = this.generateNonce();
this.postMessage({ this.postMessage({
type: 'EVAL', type: 'EVAL',
@ -389,45 +391,51 @@ export class WorkerClient<Ready extends boolean = boolean> extends BaseClient {
default: { default: {
switch (packet.t) { switch (packet.t) {
case 'INTERACTION_CREATE': case 'INTERACTION_CREATE':
await this.events?.execute(packet.t as never, packet, this, shardId); {
await this.handleCommand.interaction(packet.d, shardId); await this.events?.execute(packet.t as never, packet, this, shardId);
await this.handleCommand.interaction(packet.d, shardId);
}
break; break;
case 'MESSAGE_CREATE': case 'MESSAGE_CREATE':
await this.events?.execute(packet.t as never, packet, this, shardId); {
await this.handleCommand.message(packet.d, shardId); await this.events?.execute(packet.t as never, packet, this, shardId);
await this.handleCommand.message(packet.d, shardId);
}
break; break;
case 'READY': case 'READY':
if (!this.__handleGuilds) this.__handleGuilds = new Set(); {
for (const g of packet.d.guilds) { if (!this.__handleGuilds) this.__handleGuilds = new Set();
this.__handleGuilds?.add(g.id); for (const g of packet.d.guilds) {
} this.__handleGuilds?.add(g.id);
this.botId = packet.d.user.id; }
this.applicationId = packet.d.application.id; this.botId = packet.d.user.id;
this.me = Transformers.ClientUser(this, packet.d.user, packet.d.application) as never; this.applicationId = packet.d.application.id;
await this.events?.execute(packet.t as never, packet, this, shardId); this.me = Transformers.ClientUser(this, packet.d.user, packet.d.application) as never;
if ([...this.shards.values()].every(shard => shard.data.session_id)) { await this.events?.execute(packet.t as never, packet, this, shardId);
this.postMessage({
type: 'WORKER_SHARDS_CONNECTED',
workerId: this.workerId,
} as WorkerShardsConnected);
await this.events?.runEvent('WORKER_SHARDS_CONNECTED', this, this.me, -1);
}
if (
!(
this.__handleGuilds?.size &&
(workerData.intents & GatewayIntentBits.Guilds) === GatewayIntentBits.Guilds
)
) {
if ([...this.shards.values()].every(shard => shard.data.session_id)) { if ([...this.shards.values()].every(shard => shard.data.session_id)) {
this.postMessage({ this.postMessage({
type: 'WORKER_READY', type: 'WORKER_SHARDS_CONNECTED',
workerId: this.workerId, workerId: this.workerId,
} as WorkerReady); } as WorkerShardsConnected);
await this.events?.runEvent('WORKER_READY', this, this.me, -1); await this.events?.runEvent('WORKER_SHARDS_CONNECTED', this, this.me, -1);
} }
delete this.__handleGuilds; if (
!(
this.__handleGuilds?.size &&
(workerData.intents & GatewayIntentBits.Guilds) === GatewayIntentBits.Guilds
)
) {
if ([...this.shards.values()].every(shard => shard.data.session_id)) {
this.postMessage({
type: 'WORKER_READY',
workerId: this.workerId,
} as WorkerReady);
await this.events?.runEvent('WORKER_READY', this, this.me, -1);
}
delete this.__handleGuilds;
}
this.debugger?.debug(`#${shardId}[${packet.d.user.username}](${this.botId}) is online...`);
} }
this.debugger?.debug(`#${shardId}[${packet.d.user.username}](${this.botId}) is online...`);
break; break;
default: default:
await this.events?.execute(packet.t as never, packet, this, shardId); await this.events?.execute(packet.t as never, packet, this, shardId);

View File

@ -1,13 +1,4 @@
import { import { inspect } from 'node:util';
ApplicationCommandOptionType,
ApplicationCommandType,
type ApplicationIntegrationType,
type InteractionContextType,
type APIApplicationCommandBasicOption,
type APIApplicationCommandOption,
type APIApplicationCommandSubcommandGroupOption,
type LocaleString,
} from '../../types';
import type { import type {
ComponentContext, ComponentContext,
EntryPointContext, EntryPointContext,
@ -18,8 +9,24 @@ import type {
SeyfertStringOption, SeyfertStringOption,
} from '../..'; } from '../..';
import type { Attachment } from '../../builders'; import type { Attachment } from '../../builders';
import { type Awaitable, magicImport, type FlatObjectKeys } from '../../common'; import type {
GuildRoleStructure,
InteractionGuildMemberStructure,
OptionResolverStructure,
UserStructure,
} from '../../client/transformers';
import { type Awaitable, type FlatObjectKeys, magicImport } from '../../common';
import type { AllChannels, AutocompleteInteraction } from '../../structures'; import type { AllChannels, AutocompleteInteraction } from '../../structures';
import {
type APIApplicationCommandBasicOption,
type APIApplicationCommandOption,
type APIApplicationCommandSubcommandGroupOption,
ApplicationCommandOptionType,
ApplicationCommandType,
type ApplicationIntegrationType,
type InteractionContextType,
type LocaleString,
} from '../../types';
import type { Groups, RegisteredMiddlewares } from '../decorators'; import type { Groups, RegisteredMiddlewares } from '../decorators';
import type { CommandContext } from './chatcontext'; import type { CommandContext } from './chatcontext';
import type { import type {
@ -32,13 +39,6 @@ import type {
StopFunction, StopFunction,
UsingClient, UsingClient,
} from './shared'; } from './shared';
import { inspect } from 'node:util';
import type {
GuildRoleStructure,
InteractionGuildMemberStructure,
OptionResolverStructure,
UserStructure,
} from '../../client/transformers';
export interface ReturnOptionsTypes { export interface ReturnOptionsTypes {
1: never; // subcommand 1: never; // subcommand
@ -149,7 +149,7 @@ export class BaseCommand {
/** @internal */ /** @internal */
async __runOptions( async __runOptions(
ctx: CommandContext<{}, never>, ctx: CommandContext<never, never>,
resolver: OptionResolverStructure, resolver: OptionResolverStructure,
): Promise<[boolean, OnOptionsReturnObject]> { ): Promise<[boolean, OnOptionsReturnObject]> {
if (!this?.options?.length) { if (!this?.options?.length) {
@ -202,7 +202,12 @@ export class BaseCommand {
/** @internal */ /** @internal */
static __runMiddlewares( static __runMiddlewares(
context: CommandContext<{}, never> | ComponentContext | MenuCommandContext<any> | ModalContext | EntryPointContext, context:
| CommandContext<never, never>
| ComponentContext
| MenuCommandContext<any>
| ModalContext
| EntryPointContext,
middlewares: (keyof RegisteredMiddlewares)[], middlewares: (keyof RegisteredMiddlewares)[],
global: boolean, global: boolean,
): Promise<{ error?: string; pass?: boolean }> { ): Promise<{ error?: string; pass?: boolean }> {
@ -220,13 +225,12 @@ export class BaseCommand {
running = false; running = false;
return res({ pass: true }); return res({ pass: true });
}; };
function next(obj: any) { function next(...args: unknown[]) {
if (!running) { if (!running) {
return; return;
} }
if (arguments.length) { if (args.length) {
// @ts-expect-error context[global ? 'globalMetadata' : 'metadata'][middlewares[index]] = args[0] as never;
context[global ? 'globalMetadata' : 'metadata'][middlewares[index]] = obj;
} }
if (++index >= middlewares.length) { if (++index >= middlewares.length) {
running = false; running = false;
@ -246,12 +250,12 @@ export class BaseCommand {
} }
/** @internal */ /** @internal */
__runMiddlewares(context: CommandContext<{}, never>) { __runMiddlewares(context: CommandContext<never, never>) {
return BaseCommand.__runMiddlewares(context, this.middlewares as (keyof RegisteredMiddlewares)[], false); return BaseCommand.__runMiddlewares(context, this.middlewares as (keyof RegisteredMiddlewares)[], false);
} }
/** @internal */ /** @internal */
__runGlobalMiddlewares(context: CommandContext<{}, never>) { __runGlobalMiddlewares(context: CommandContext<never, never>) {
return BaseCommand.__runMiddlewares( return BaseCommand.__runMiddlewares(
context, context,
(context.client.options?.globalMiddlewares ?? []) as (keyof RegisteredMiddlewares)[], (context.client.options?.globalMiddlewares ?? []) as (keyof RegisteredMiddlewares)[],

View File

@ -1,13 +1,5 @@
import { MessageFlags } from '../../types';
import type { AllChannels, InferWithPrefix, Message, ReturnCache } from '../..'; import type { AllChannels, InferWithPrefix, Message, ReturnCache } from '../..';
import type { Client, WorkerClient } from '../../client'; import type { Client, WorkerClient } from '../../client';
import type { If, UnionToTuple, When } from '../../common';
import type { InteractionCreateBodyRequest, InteractionMessageUpdateBodyRequest } from '../../common/types/write';
import { ChatInputCommandInteraction } from '../../structures';
import { BaseContext } from '../basecontext';
import type { RegisteredMiddlewares } from '../decorators';
import type { Command, ContextOptions, OptionsRecord, SubCommand } from './chat';
import type { CommandMetadata, ExtendContext, GlobalMetadata, UsingClient } from './shared';
import type { import type {
GuildMemberStructure, GuildMemberStructure,
GuildStructure, GuildStructure,
@ -16,13 +8,21 @@ import type {
OptionResolverStructure, OptionResolverStructure,
WebhookMessageStructure, WebhookMessageStructure,
} from '../../client/transformers'; } from '../../client/transformers';
import type { If, UnionToTuple, When } from '../../common';
import type { InteractionCreateBodyRequest, InteractionMessageUpdateBodyRequest } from '../../common/types/write';
import { ChatInputCommandInteraction } from '../../structures';
import { MessageFlags } from '../../types';
import { BaseContext } from '../basecontext';
import type { RegisteredMiddlewares } from '../decorators';
import type { Command, ContextOptions, OptionsRecord, SubCommand } from './chat';
import type { CommandMetadata, ExtendContext, GlobalMetadata, UsingClient } from './shared';
export interface CommandContext<T extends OptionsRecord = {}, M extends keyof RegisteredMiddlewares = never> export interface CommandContext<T extends OptionsRecord = never, M extends keyof RegisteredMiddlewares = never>
extends BaseContext, extends BaseContext,
ExtendContext {} ExtendContext {}
export class CommandContext< export class CommandContext<
T extends OptionsRecord = {}, T extends OptionsRecord = never,
M extends keyof RegisteredMiddlewares = never, M extends keyof RegisteredMiddlewares = never,
> extends BaseContext { > extends BaseContext {
message!: If<InferWithPrefix, MessageStructure | undefined, undefined>; message!: If<InferWithPrefix, MessageStructure | undefined, undefined>;

View File

@ -1,4 +1,3 @@
import { ApplicationCommandOptionType, type APIApplicationCommandOptionChoice, type ChannelType } from '../../types';
import type { import type {
AutocompleteCallback, AutocompleteCallback,
EntryPointContext, EntryPointContext,
@ -7,13 +6,14 @@ import type {
ReturnOptionsTypes, ReturnOptionsTypes,
__TypesWrapper, __TypesWrapper,
} from '..'; } from '..';
import type { MessageCommandInteraction, UserCommandInteraction } from '../../structures';
import type { CommandContext } from './chatcontext';
import type { MiddlewareContext } from './shared';
import type { ModalContext } from '../../components'; import type { ModalContext } from '../../components';
import type { ComponentContext } from '../../components/componentcontext'; import type { ComponentContext } from '../../components/componentcontext';
import type { MessageCommandInteraction, UserCommandInteraction } from '../../structures';
import { type APIApplicationCommandOptionChoice, ApplicationCommandOptionType, type ChannelType } from '../../types';
import type { CommandContext } from './chatcontext';
import type { MiddlewareContext } from './shared';
export type SeyfertBasicOption<T extends keyof __TypesWrapper, D = {}> = __TypesWrapper[T] & D; export type SeyfertBasicOption<T extends keyof __TypesWrapper, D = object> = __TypesWrapper[T] & D;
export type SeyfertStringOption = SeyfertBasicOption<'String'> & { export type SeyfertStringOption = SeyfertBasicOption<'String'> & {
autocomplete?: AutocompleteCallback; autocomplete?: AutocompleteCallback;

View File

@ -39,13 +39,13 @@ export type CommandMetadata<T extends readonly (keyof RegisteredMiddlewares)[]>
] ]
? first extends keyof RegisteredMiddlewares ? first extends keyof RegisteredMiddlewares
? (MetadataMiddleware<RegisteredMiddlewares[first]> extends never ? (MetadataMiddleware<RegisteredMiddlewares[first]> extends never
? {} ? 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> : never)
: {} : never
: {}; : never;
export type MessageCommandOptionErrors = export type MessageCommandOptionErrors =
| ['CHANNEL_TYPES', type: ChannelType[]] | ['CHANNEL_TYPES', type: ChannelType[]]

View File

@ -1,12 +1,12 @@
import type { FlatObjectKeys, PermissionStrings } from '../common';
import { import {
ApplicationCommandType, ApplicationCommandType,
ApplicationIntegrationType, ApplicationIntegrationType,
type EntryPointCommandHandlerType, type EntryPointCommandHandlerType,
InteractionContextType, InteractionContextType,
PermissionFlagsBits,
type LocaleString, type LocaleString,
PermissionFlagsBits,
} from '../types'; } from '../types';
import type { FlatObjectKeys, PermissionStrings } from '../common';
import type { CommandOption, OptionsRecord, SubCommand } from './applications/chat'; import type { CommandOption, OptionsRecord, SubCommand } from './applications/chat';
import type { DefaultLocale, ExtraProps, IgnoreCommand, MiddlewareContext } from './applications/shared'; import type { DefaultLocale, ExtraProps, IgnoreCommand, MiddlewareContext } from './applications/shared';
@ -42,7 +42,7 @@ export function Locales({
name?: [language: LocaleString, value: string][]; name?: [language: LocaleString, value: string][];
description?: [language: LocaleString, value: string][]; description?: [language: LocaleString, value: string][];
}) { }) {
return <T extends { new (...args: any[]): {} }>(target: T) => return <T extends { new (...args: any[]): object }>(target: T) =>
class extends target { class extends target {
name_localizations = names ? Object.fromEntries(names) : undefined; name_localizations = names ? Object.fromEntries(names) : undefined;
description_localizations = descriptions ? Object.fromEntries(descriptions) : undefined; description_localizations = descriptions ? Object.fromEntries(descriptions) : undefined;
@ -50,7 +50,7 @@ export function Locales({
} }
export function LocalesT(name?: FlatObjectKeys<DefaultLocale>, description?: FlatObjectKeys<DefaultLocale>) { export function LocalesT(name?: FlatObjectKeys<DefaultLocale>, description?: FlatObjectKeys<DefaultLocale>) {
return <T extends { new (...args: any[]): {} }>(target: T) => return <T extends { new (...args: any[]): object }>(target: T) =>
class extends target { class extends target {
__t = { name, description }; __t = { name, description };
}; };
@ -67,7 +67,7 @@ export function GroupsT(
} }
>, >,
) { ) {
return <T extends { new (...args: any[]): {} }>(target: T) => return <T extends { new (...args: any[]): object }>(target: T) =>
class extends target { class extends target {
__tGroups = groups; __tGroups = groups;
groupsAliases: Record<string, string> = {}; groupsAliases: Record<string, string> = {};
@ -93,7 +93,7 @@ export function Groups(
} }
>, >,
) { ) {
return <T extends { new (...args: any[]): {} }>(target: T) => return <T extends { new (...args: any[]): object }>(target: T) =>
class extends target { class extends target {
groups = groups; groups = groups;
groupsAliases: Record<string, string> = {}; groupsAliases: Record<string, string> = {};
@ -109,14 +109,14 @@ export function Groups(
} }
export function Group(groupName: string) { export function Group(groupName: string) {
return <T extends { new (...args: any[]): {} }>(target: T) => return <T extends { new (...args: any[]): object }>(target: T) =>
class extends target { class extends target {
group = groupName; group = groupName;
}; };
} }
export function Options(options: (new () => SubCommand)[] | OptionsRecord) { export function Options(options: (new () => SubCommand)[] | OptionsRecord) {
return <T extends { new (...args: any[]): {} }>(target: T) => return <T extends { new (...args: any[]): object }>(target: T) =>
class extends target { class extends target {
options: SubCommand[] | CommandOption[] = Array.isArray(options) options: SubCommand[] | CommandOption[] = Array.isArray(options)
? options.map(x => new x()) ? options.map(x => new x())
@ -130,7 +130,7 @@ export function Options(options: (new () => SubCommand)[] | OptionsRecord) {
} }
export function AutoLoad() { export function AutoLoad() {
return <T extends { new (...args: any[]): {} }>(target: T) => return <T extends { new (...args: any[]): object }>(target: T) =>
class extends target { class extends target {
__autoload = true; __autoload = true;
}; };
@ -141,14 +141,14 @@ export type ParseMiddlewares<T extends Record<string, MiddlewareContext>> = {
}; };
export function Middlewares(cbs: readonly (keyof RegisteredMiddlewares)[]) { export function Middlewares(cbs: readonly (keyof RegisteredMiddlewares)[]) {
return <T extends { new (...args: any[]): {} }>(target: T) => return <T extends { new (...args: any[]): object }>(target: T) =>
class extends target { class extends target {
middlewares = cbs; middlewares = cbs;
}; };
} }
export function Declare(declare: CommandDeclareOptions) { export function Declare(declare: CommandDeclareOptions) {
return <T extends { new (...args: any[]): {} }>(target: T) => return <T extends { new (...args: any[]): object }>(target: T) =>
class extends target { class extends target {
name = declare.name; name = declare.name;
nsfw = declare.nsfw; nsfw = declare.nsfw;

View File

@ -1,52 +1,52 @@
import { import {
type APIApplicationCommandInteraction,
ApplicationCommandType,
InteractionType,
type APIInteraction,
type GatewayMessageCreateDispatchData,
InteractionContextType,
type APIApplicationCommandInteractionDataOption,
ApplicationCommandOptionType,
type APIInteractionDataResolvedChannel,
ChannelType,
} from '../types';
import {
Command,
type ContextOptionsResolved,
type UsingClient,
type CommandAutocompleteOption,
type ContextMenuCommand,
MenuCommandContext,
BaseCommand, BaseCommand,
Command,
type CommandAutocompleteOption,
CommandContext, CommandContext,
type RegisteredMiddlewares,
SubCommand,
IgnoreCommand,
type CommandOption, type CommandOption,
type ContextMenuCommand,
type ContextOptionsResolved,
type EntryPointCommand,
EntryPointContext,
IgnoreCommand,
MenuCommandContext,
type MessageCommandOptionErrors, type MessageCommandOptionErrors,
type RegisteredMiddlewares,
type SeyfertChannelOption, type SeyfertChannelOption,
type SeyfertIntegerOption, type SeyfertIntegerOption,
type SeyfertNumberOption, type SeyfertNumberOption,
type SeyfertStringOption, type SeyfertStringOption,
EntryPointContext, SubCommand,
type EntryPointCommand, type UsingClient,
} from '.'; } from '.';
import type { Client, WorkerClient } from '../client';
import { type MessageStructure, type OptionResolverStructure, Transformers } from '../client/transformers';
import type { MakeRequired } from '../common';
import { ComponentContext, ModalContext } from '../components';
import { import {
AutocompleteInteraction, AutocompleteInteraction,
BaseInteraction, BaseInteraction,
type ComponentInteraction,
type ModalSubmitInteraction,
type ChatInputCommandInteraction, type ChatInputCommandInteraction,
type ComponentInteraction,
type EntryPointInteraction,
type MessageCommandInteraction, type MessageCommandInteraction,
type ModalSubmitInteraction,
type UserCommandInteraction, type UserCommandInteraction,
type __InternalReplyFunction, type __InternalReplyFunction,
type EntryPointInteraction,
} from '../structures'; } from '../structures';
import type { PermissionsBitField } from '../structures/extra/Permissions'; import type { PermissionsBitField } from '../structures/extra/Permissions';
import { ComponentContext, ModalContext } from '../components'; import {
import type { Client, WorkerClient } from '../client'; type APIApplicationCommandInteraction,
import type { MakeRequired } from '../common'; type APIApplicationCommandInteractionDataOption,
import { type MessageStructure, Transformers, type OptionResolverStructure } from '../client/transformers'; type APIInteraction,
type APIInteractionDataResolvedChannel,
ApplicationCommandOptionType,
ApplicationCommandType,
ChannelType,
type GatewayMessageCreateDispatchData,
InteractionContextType,
InteractionType,
} from '../types';
export type CommandOptionWithType = CommandOption & { export type CommandOptionWithType = CommandOption & {
type: ApplicationCommandOptionType; type: ApplicationCommandOptionType;
@ -390,7 +390,9 @@ export class HandleCommand {
} catch (error) { } catch (error) {
try { try {
await command.onInternalError?.(this.client, command, error); await command.onInternalError?.(this.client, command, error);
} catch {} } catch {
// http 418
}
} }
} }
@ -529,7 +531,7 @@ export class HandleCommand {
async runGlobalMiddlewares( async runGlobalMiddlewares(
command: Command | ContextMenuCommand | SubCommand | EntryPointCommand, command: Command | ContextMenuCommand | SubCommand | EntryPointCommand,
context: CommandContext<{}, never> | MenuCommandContext<any> | EntryPointContext, context: CommandContext<never, never> | MenuCommandContext<any> | EntryPointContext,
) { ) {
try { try {
const resultRunGlobalMiddlewares = await BaseCommand.__runMiddlewares( const resultRunGlobalMiddlewares = await BaseCommand.__runMiddlewares(
@ -548,14 +550,16 @@ export class HandleCommand {
} catch (e) { } catch (e) {
try { try {
await command.onInternalError?.(this.client, command as never, e); await command.onInternalError?.(this.client, command as never, e);
} catch {} } catch {
// http 418
}
} }
return false; return false;
} }
async runMiddlewares( async runMiddlewares(
command: Command | ContextMenuCommand | SubCommand | EntryPointCommand, command: Command | ContextMenuCommand | SubCommand | EntryPointCommand,
context: CommandContext<{}, never> | MenuCommandContext<any> | EntryPointContext, context: CommandContext<never, never> | MenuCommandContext<any> | EntryPointContext,
) { ) {
try { try {
const resultRunMiddlewares = await BaseCommand.__runMiddlewares( const resultRunMiddlewares = await BaseCommand.__runMiddlewares(
@ -574,7 +578,9 @@ export class HandleCommand {
} catch (e) { } catch (e) {
try { try {
await command.onInternalError?.(this.client, command as never, e); await command.onInternalError?.(this.client, command as never, e);
} catch {} } catch {
// http 418
}
} }
return false; return false;
} }
@ -602,7 +608,9 @@ export class HandleCommand {
} catch (e) { } catch (e) {
try { try {
await command.onInternalError?.(this.client, command, e); await command.onInternalError?.(this.client, command, e);
} catch {} } catch {
// http 418
}
} }
return false; return false;
} }

View File

@ -1,23 +1,23 @@
import { import { promises } from 'node:fs';
type APIApplicationCommandOption,
Locale,
type LocaleString,
ApplicationCommandOptionType,
type APIApplicationCommandIntegerOption,
type APIApplicationCommandStringOption,
type APIApplicationCommandSubcommandOption,
type APIApplicationCommandSubcommandGroupOption,
type APIApplicationCommandChannelOption,
type LocalizationMap,
} from '../types';
import { basename, dirname } from 'node:path'; import { basename, dirname } from 'node:path';
import type { EntryPointCommand } from '.';
import type { Logger, MakeRequired, NulleableCoalising, OmitInsert } from '../common'; import type { Logger, MakeRequired, NulleableCoalising, OmitInsert } from '../common';
import { BaseHandler, isCloudfareWorker } from '../common'; import { BaseHandler, isCloudfareWorker } from '../common';
import {
type APIApplicationCommandChannelOption,
type APIApplicationCommandIntegerOption,
type APIApplicationCommandOption,
type APIApplicationCommandStringOption,
type APIApplicationCommandSubcommandGroupOption,
type APIApplicationCommandSubcommandOption,
ApplicationCommandOptionType,
Locale,
type LocaleString,
type LocalizationMap,
} from '../types';
import { Command, type CommandOption, SubCommand } from './applications/chat'; import { Command, type CommandOption, 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';
import { promises } from 'node:fs';
import type { EntryPointCommand } from '.';
export class CommandHandler extends BaseHandler { export class CommandHandler extends BaseHandler {
values: (Command | ContextMenuCommand)[] = []; values: (Command | ContextMenuCommand)[] = [];
@ -97,26 +97,29 @@ export class CommandHandler extends BaseHandler {
return option.channel_types.some(ct => !cached.channel_types!.includes(ct)); return option.channel_types.some(ct => !cached.channel_types!.includes(ct));
} }
} }
return; break;
case ApplicationCommandOptionType.Subcommand: case ApplicationCommandOptionType.Subcommand:
case ApplicationCommandOptionType.SubcommandGroup: case ApplicationCommandOptionType.SubcommandGroup:
if ( {
option.options?.length !== if (
(cached as APIApplicationCommandSubcommandOption | APIApplicationCommandSubcommandGroupOption).options?.length option.options?.length !==
) { (cached as APIApplicationCommandSubcommandOption | APIApplicationCommandSubcommandGroupOption).options
return true; ?.length
} ) {
if ( return true;
option.options &&
(cached as APIApplicationCommandSubcommandOption | APIApplicationCommandSubcommandGroupOption).options
)
for (const i of option.options) {
const cachedOption = (
cached as APIApplicationCommandSubcommandOption | APIApplicationCommandSubcommandGroupOption
).options!.find(x => x.name === i.name);
if (!cachedOption) return true;
if (this.shouldUploadOption(i, cachedOption)) return true;
} }
if (
option.options &&
(cached as APIApplicationCommandSubcommandOption | APIApplicationCommandSubcommandGroupOption).options
)
for (const i of option.options) {
const cachedOption = (
cached as APIApplicationCommandSubcommandOption | APIApplicationCommandSubcommandGroupOption
).options!.find(x => x.name === i.name);
if (!cachedOption) return true;
if (this.shouldUploadOption(i, cachedOption)) return true;
}
}
break; break;
case ApplicationCommandOptionType.Integer: case ApplicationCommandOptionType.Integer:
case ApplicationCommandOptionType.Number: case ApplicationCommandOptionType.Number:
@ -210,7 +213,7 @@ export class CommandHandler extends BaseHandler {
set(commands: SeteableCommand[]) { set(commands: SeteableCommand[]) {
this.values ??= []; this.values ??= [];
for (const command of commands) { for (const command of commands) {
let commandInstance; let commandInstance: Command | undefined;
try { try {
commandInstance = this.onCommand(command) as Command; commandInstance = this.onCommand(command) as Command;
if (!commandInstance) continue; if (!commandInstance) continue;
@ -238,7 +241,7 @@ export class CommandHandler extends BaseHandler {
for (const { commands, file } of result.map(x => ({ commands: this.onFile(x.file), file: x }))) { for (const { commands, file } of result.map(x => ({ commands: this.onFile(x.file), file: x }))) {
if (!commands) continue; if (!commands) continue;
for (const command of commands) { for (const command of commands) {
let commandInstance; let commandInstance: ReturnType<typeof this.onCommand>;
try { try {
commandInstance = this.onCommand(command); commandInstance = this.onCommand(command);
if (!commandInstance) continue; if (!commandInstance) continue;
@ -277,7 +280,7 @@ export class CommandHandler extends BaseHandler {
const subCommand = this.onSubCommand(fileSubCommand as HandleableSubCommand); const subCommand = this.onSubCommand(fileSubCommand as HandleableSubCommand);
if (subCommand && subCommand instanceof SubCommand) { if (subCommand && subCommand instanceof SubCommand) {
subCommand.__filePath = option; subCommand.__filePath = option;
commandInstance.options.push(subCommand); commandInstance.options!.push(subCommand);
} else { } else {
this.logger.warn(subCommand ? 'SubCommand expected' : 'Invalid SubCommand', subCommand); this.logger.warn(subCommand ? 'SubCommand expected' : 'Invalid SubCommand', subCommand);
} }

View File

@ -63,61 +63,61 @@ type Timestamp = `<t:${number}:${TimestampStyle}>`;
/** /**
* Represents a formatter utility for formatting content. * Represents a formatter utility for formatting content.
*/ */
export class Formatter { export const Formatter = {
/** /**
* Formats a code block. * Formats a code block.
* @param content The content of the code block. * @param content The content of the code block.
* @param language The language of the code block. Defaults to 'txt'. * @param language The language of the code block. Defaults to 'txt'.
* @returns The formatted code block. * @returns The formatted code block.
*/ */
static codeBlock(content: string, language = 'txt'): string { codeBlock(content: string, language = 'txt'): string {
return `\`\`\`${language}\n${content}\n\`\`\``; return `\`\`\`${language}\n${content}\n\`\`\``;
} },
/** /**
* Formats content into inline code. * Formats content into inline code.
* @param content The content to format. * @param content The content to format.
* @returns The formatted content. * @returns The formatted content.
*/ */
static inlineCode(content: string): `\`${string}\`` { inlineCode(content: string): `\`${string}\`` {
return `\`${content}\``; return `\`${content}\``;
} },
/** /**
* Formats content into bold text. * Formats content into bold text.
* @param content The content to format. * @param content The content to format.
* @returns The formatted content. * @returns The formatted content.
*/ */
static bold(content: string): `**${string}**` { bold(content: string): `**${string}**` {
return `**${content}**`; return `**${content}**`;
} },
/** /**
* Formats content into italic text. * Formats content into italic text.
* @param content The content to format. * @param content The content to format.
* @returns The formatted content. * @returns The formatted content.
*/ */
static italic(content: string): `*${string}*` { italic(content: string): `*${string}*` {
return `*${content}*`; return `*${content}*`;
} },
/** /**
* Formats content into underlined text. * Formats content into underlined text.
* @param content The content to format. * @param content The content to format.
* @returns The formatted content. * @returns The formatted content.
*/ */
static underline(content: string): `__${string}__` { underline(content: string): `__${string}__` {
return `__${content}__`; return `__${content}__`;
} },
/** /**
* Formats content into strikethrough text. * Formats content into strikethrough text.
* @param content The content to format. * @param content The content to format.
* @returns The formatted content. * @returns The formatted content.
*/ */
static strikeThrough(content: string): `~~${string}~~` { strikeThrough(content: string): `~~${string}~~` {
return `~~${content}~~`; return `~~${content}~~`;
} },
/** /**
* Formats content into a hyperlink. * Formats content into a hyperlink.
@ -125,36 +125,36 @@ export class Formatter {
* @param url The URL to hyperlink to. * @param url The URL to hyperlink to.
* @returns The formatted content. * @returns The formatted content.
*/ */
static hyperlink(content: string, url: string): `[${string}](${string})` { hyperlink(content: string, url: string): `[${string}](${string})` {
return `[${content}](${url})`; return `[${content}](${url})`;
} },
/** /**
* Formats content into a spoiler. * Formats content into a spoiler.
* @param content The content to format. * @param content The content to format.
* @returns The formatted content. * @returns The formatted content.
*/ */
static spoiler(content: string): `||${string}||` { spoiler(content: string): `||${string}||` {
return `||${content}||`; return `||${content}||`;
} },
/** /**
* Formats content into a quote. * Formats content into a quote.
* @param content The content to format. * @param content The content to format.
* @returns The formatted content. * @returns The formatted content.
*/ */
static blockQuote(content: string): string { blockQuote(content: string): string {
return `>>> ${content}`; return `>>> ${content}`;
} },
/** /**
* Formats content into a quote. * Formats content into a quote.
* @param content The content to format. * @param content The content to format.
* @returns The formatted content. * @returns The formatted content.
*/ */
static quote(content: string): string { quote(content: string): string {
return `> ${content}`; return `> ${content}`;
} },
/** /**
* Formats a message link. * Formats a message link.
@ -163,9 +163,9 @@ export class Formatter {
* @param messageId The ID of the message. * @param messageId The ID of the message.
* @returns The formatted message link. * @returns The formatted message link.
*/ */
static messageLink(guildId: string, channelId: string, messageId: string): MessageLink { messageLink(guildId: string, channelId: string, messageId: string): MessageLink {
return `https://discord.com/channels/${guildId}/${channelId}/${messageId}`; return `https://discord.com/channels/${guildId}/${channelId}/${messageId}`;
} },
/** /**
* Formats a header. * Formats a header.
@ -173,9 +173,9 @@ export class Formatter {
* @param level The level of the header. Defaults to 1. * @param level The level of the header. Defaults to 1.
* @returns The formatted header. * @returns The formatted header.
*/ */
static header(content: string, level: HeadingLevel = HeadingLevel.H1): string { header(content: string, level: HeadingLevel = HeadingLevel.H1): string {
return `${'#'.repeat(level)} ${content}`; return `${'#'.repeat(level)} ${content}`;
} },
/** /**
* Formats a list. * Formats a list.
@ -183,13 +183,13 @@ export class Formatter {
* @param ordered Whether the list is ordered. Defaults to false. * @param ordered Whether the list is ordered. Defaults to false.
* @returns The formatted list. * @returns The formatted list.
*/ */
static list(items: string[], ordered = false): string { list(items: string[], ordered = false): string {
return items return items
.map((item, index) => { .map((item, index) => {
return (ordered ? `${index + 1}. ` : '- ') + item; return (ordered ? `${index + 1}. ` : '- ') + item;
}) })
.join('\n'); .join('\n');
} },
/** /**
* Formats the given timestamp into discord unix timestamp format. * Formats the given timestamp into discord unix timestamp format.
@ -197,36 +197,36 @@ export class Formatter {
* @param style The style of the timestamp. Defaults to 't'. * @param style The style of the timestamp. Defaults to 't'.
* @returns The formatted timestamp. * @returns The formatted timestamp.
*/ */
static timestamp(timestamp: Date, style: TimestampStyle = TimestampStyle.RelativeTime): Timestamp { timestamp(timestamp: Date, style: TimestampStyle = TimestampStyle.RelativeTime): Timestamp {
return `<t:${Math.floor(timestamp.getTime() / 1000)}:${style}>`; return `<t:${Math.floor(timestamp.getTime() / 1000)}:${style}>`;
} },
/** /**
* Formats a user mention. * Formats a user mention.
* @param userId The ID of the user to mention. * @param userId The ID of the user to mention.
* @returns The formatted user mention. * @returns The formatted user mention.
*/ */
static userMention(userId: string): `<@${string}>` { userMention(userId: string): `<@${string}>` {
return `<@${userId}>`; return `<@${userId}>`;
} },
/** /**
* Formats a role mention. * Formats a role mention.
* @param roleId The ID of the role to mention. * @param roleId The ID of the role to mention.
* @returns The formatted role mention. * @returns The formatted role mention.
*/ */
static roleMention(roleId: string): `<@&${string}>` { roleMention(roleId: string): `<@&${string}>` {
return `<@&${roleId}>`; return `<@&${roleId}>`;
} },
/** /**
* Formats a channel mention. * Formats a channel mention.
* @param channelId The ID of the channel to mention. * @param channelId The ID of the channel to mention.
* @returns The formatted channel mention. * @returns The formatted channel mention.
*/ */
static channelMention(channelId: string): `<#${string}>` { channelMention(channelId: string): `<#${string}>` {
return `<#${channelId}>`; return `<#${channelId}>`;
} },
/** /**
* Formats an emoji. * Formats an emoji.
@ -234,9 +234,9 @@ export class Formatter {
* @param animated Whether the emoji is animated. Defaults to false. * @param animated Whether the emoji is animated. Defaults to false.
* @returns The formatted emoji. * @returns The formatted emoji.
*/ */
static emojiMention(emojiId: string, name: string | null, animated = false): string { emojiMention(emojiId: string, name: string | null, animated = false): string {
return `<${animated ? 'a' : ''}:${name ?? '_'}:${emojiId}>`; return `<${animated ? 'a' : ''}:${name ?? '_'}:${emojiId}>`;
} },
/** /**
* Formats a channel link. * Formats a channel link.
@ -244,7 +244,7 @@ export class Formatter {
* @param guildId The ID of the guild. Defaults to '@me'. * @param guildId The ID of the guild. Defaults to '@me'.
* @returns The formatted channel link. * @returns The formatted channel link.
*/ */
static channelLink(channelId: string, guildId?: string) { channelLink(channelId: string, guildId?: string) {
return `https://discord.com/channels/${guildId ?? '@me'}/${channelId}`; return `https://discord.com/channels/${guildId ?? '@me'}/${channelId}`;
} },
} };

View File

@ -1,4 +1,4 @@
import { createWriteStream, existsSync, mkdirSync, promises, type WriteStream } from 'node:fs'; import { type WriteStream, createWriteStream, existsSync, mkdirSync, promises } from 'node:fs';
import { join } from 'node:path'; import { join } from 'node:path';
import { bgBrightWhite, black, bold, brightBlack, cyan, gray, italic, red, stripColor, yellow } from './colors'; import { bgBrightWhite, black, bold, brightBlack, cyan, gray, italic, red, stripColor, yellow } from './colors';
import { MergeOptions } from './utils'; import { MergeOptions } from './utils';
@ -53,7 +53,7 @@ export class Logger {
static async clearLogs() { static async clearLogs() {
for (const i of await promises.readdir(join(process.cwd(), Logger.dirname), { withFileTypes: true })) { for (const i of await promises.readdir(join(process.cwd(), Logger.dirname), { withFileTypes: true })) {
if (Logger.streams[i.name]) await new Promise(res => Logger.streams[i.name]!.close(res)); if (Logger.streams[i.name]) await new Promise(res => Logger.streams[i.name]!.close(res));
await promises.unlink(join(process.cwd(), Logger.dirname, i.name)).catch(() => {}); await promises.unlink(join(process.cwd(), Logger.dirname, i.name)).catch(() => undefined);
delete Logger.streams[i.name]; delete Logger.streams[i.name];
} }
} }
@ -126,7 +126,7 @@ export class Logger {
if (!this.active) return; if (!this.active) return;
if (level < this.level) return; if (level < this.level) return;
let log; let log: unknown[] | undefined;
if (Logger.__callback) { if (Logger.__callback) {
log = Logger.__callback(this, level, args); log = Logger.__callback(this, level, args);

View File

@ -1,17 +1,17 @@
import { promises } from 'node:fs'; import { promises } from 'node:fs';
import { basename, join } from 'node:path'; import { basename, join } from 'node:path';
import { import {
type ColorResolvable,
DiscordEpoch, DiscordEpoch,
EmbedColors, EmbedColors,
type EmojiResolvable, type EmojiResolvable,
type TypeArray,
type ColorResolvable,
type Logger, type Logger,
type ObjectToLower, type ObjectToLower,
type ObjectToSnake, type ObjectToSnake,
type TypeArray,
} from '..'; } from '..';
import { type APIPartialEmoji, FormattingPatterns } from '../../types';
import type { Cache } from '../../cache'; import type { Cache } from '../../cache';
import { type APIPartialEmoji, FormattingPatterns } from '../../types';
/** /**
* Calculates the shard ID for a guild based on its ID. * Calculates the shard ID for a guild based on its ID.
@ -29,11 +29,12 @@ export function calculateShardId(guildId: string, shards?: number) {
*/ */
export function resolveColor(color: ColorResolvable): number { export function resolveColor(color: ColorResolvable): number {
switch (typeof color) { switch (typeof color) {
case 'string': case 'string': {
if (color === 'Random') return Math.floor(Math.random() * (0xffffff + 1)); if (color === 'Random') return Math.floor(Math.random() * (0xffffff + 1));
if (color.startsWith('#')) return Number.parseInt(color.slice(1), 16); if (color.startsWith('#')) return Number.parseInt(color.slice(1), 16);
if (color in EmbedColors) return EmbedColors[color as keyof typeof EmbedColors]; if (color in EmbedColors) return EmbedColors[color as keyof typeof EmbedColors];
return EmbedColors.Default; return EmbedColors.Default;
}
case 'number': case 'number':
return color; return color;
case 'object': case 'object':
@ -82,7 +83,7 @@ export function MergeOptions<T>(defaults: any, ...options: any[]): T {
...Object.fromEntries( ...Object.fromEntries(
Object.entries(defaults).map(([key, value]) => [ Object.entries(defaults).map(([key, value]) => [
key, key,
isObject(value) ? MergeOptions(value, option?.[key] || {}) : option?.[key] ?? value, isObject(value) ? MergeOptions(value, option?.[key] || {}) : (option?.[key] ?? value),
]), ]),
), ),
}, },
@ -195,7 +196,7 @@ export function toSnakeCase<Obj extends Record<string, any>>(target: Obj): Objec
case 'undefined': case 'undefined':
result[ReplaceRegex.snake(key)] = value; result[ReplaceRegex.snake(key)] = value;
break; break;
case 'object': case 'object': {
if (Array.isArray(value)) { if (Array.isArray(value)) {
result[ReplaceRegex.snake(key)] = value.map(prop => result[ReplaceRegex.snake(key)] = value.map(prop =>
typeof prop === 'object' && prop ? toSnakeCase(prop) : prop, typeof prop === 'object' && prop ? toSnakeCase(prop) : prop,
@ -212,6 +213,7 @@ export function toSnakeCase<Obj extends Record<string, any>>(target: Obj): Objec
} }
result[ReplaceRegex.snake(key)] = toSnakeCase(value); result[ReplaceRegex.snake(key)] = toSnakeCase(value);
break; break;
}
} }
} }
return result as ObjectToSnake<Obj>; return result as ObjectToSnake<Obj>;
@ -235,7 +237,7 @@ export function toCamelCase<Obj extends Record<string, any>>(target: Obj): Objec
case 'undefined': case 'undefined':
result[ReplaceRegex.camel(key)] = value; result[ReplaceRegex.camel(key)] = value;
break; break;
case 'object': case 'object': {
if (Array.isArray(value)) { if (Array.isArray(value)) {
result[ReplaceRegex.camel(key)] = value.map(prop => result[ReplaceRegex.camel(key)] = value.map(prop =>
typeof prop === 'object' && prop ? toCamelCase(prop) : prop, typeof prop === 'object' && prop ? toCamelCase(prop) : prop,
@ -252,6 +254,7 @@ export function toCamelCase<Obj extends Record<string, any>>(target: Obj): Objec
} }
result[ReplaceRegex.camel(key)] = toCamelCase(value); result[ReplaceRegex.camel(key)] = toCamelCase(value);
break; break;
}
} }
} }
return result as ObjectToLower<Obj>; return result as ObjectToLower<Obj>;
@ -291,6 +294,8 @@ export function lazyLoadPackage<T>(mod: string): T | undefined {
try { try {
return require(mod); return require(mod);
} catch (e) { } catch (e) {
// biome-ignore lint/suspicious/noConsoleLog:
// biome-ignore lint/suspicious/noConsole:
console.log(`Cannot import ${mod}`, e); console.log(`Cannot import ${mod}`, e);
return; return;
} }

View File

@ -1,3 +1,4 @@
import { type GuildBanStructure, Transformers } from '../../client/transformers';
import type { import type {
APIBan, APIBan,
RESTGetAPIGuildBansQuery, RESTGetAPIGuildBansQuery,
@ -5,7 +6,6 @@ import type {
RESTPutAPIGuildBanJSONBody, RESTPutAPIGuildBanJSONBody,
} from '../../types'; } from '../../types';
import { BaseShorter } from './base'; import { BaseShorter } from './base';
import { Transformers } from '../../client/transformers';
export class BanShorter extends BaseShorter { export class BanShorter extends BaseShorter {
/** /**
@ -50,7 +50,7 @@ export class BanShorter extends BaseShorter {
* @returns A Promise that resolves to the fetched ban. * @returns A Promise that resolves to the fetched ban.
*/ */
async fetch(guildId: string, userId: string, force = false) { async fetch(guildId: string, userId: string, force = false) {
let ban; let ban: APIBan | GuildBanStructure | undefined;
if (!force) { if (!force) {
ban = await this.client.cache.bans?.get(userId, guildId); ban = await this.client.cache.bans?.get(userId, guildId);
if (ban) return ban; if (ban) return ban;
@ -69,7 +69,7 @@ export class BanShorter extends BaseShorter {
* @returns A Promise that resolves to an array of listed bans. * @returns A Promise that resolves to an array of listed bans.
*/ */
async list(guildId: string, query?: RESTGetAPIGuildBansQuery, force = false) { async list(guildId: string, query?: RESTGetAPIGuildBansQuery, force = false) {
let bans; let bans: APIBan[] | GuildBanStructure[];
if (!force) { if (!force) {
bans = (await this.client.cache.bans?.values(guildId)) ?? []; bans = (await this.client.cache.bans?.values(guildId)) ?? [];
if (bans.length) return bans; if (bans.length) return bans;

View File

@ -1,18 +1,20 @@
import type { Channels } from '../../cache/resources/channels';
import type { Overwrites } from '../../cache/resources/overwrites';
import { type MessageStructure, Transformers } from '../../client/transformers';
import { type AllChannels, BaseChannel, type GuildMember, type GuildRole, channelFrom } from '../../structures';
import { PermissionsBitField } from '../../structures/extra/Permissions';
import type { import type {
APIChannel, APIChannel,
APIGuildChannel,
RESTGetAPIChannelMessagesQuery, RESTGetAPIChannelMessagesQuery,
RESTPatchAPIChannelJSONBody, RESTPatchAPIChannelJSONBody,
RESTPostAPIChannelThreadsJSONBody, RESTPostAPIChannelThreadsJSONBody,
RESTPostAPIGuildForumThreadsJSONBody, RESTPostAPIGuildForumThreadsJSONBody,
APIGuildChannel,
} from '../../types'; } from '../../types';
import { BaseChannel, type GuildRole, type GuildMember, type AllChannels, channelFrom } from '../../structures';
import { PermissionsBitField } from '../../structures/extra/Permissions';
import { BaseShorter } from './base';
import { MergeOptions } from '../it/utils';
import { type MessageStructure, Transformers } from '../../client/transformers';
import type { MakeRequired } from '../types/util';
import { type ChannelType, PermissionFlagsBits } from '../../types'; import { type ChannelType, PermissionFlagsBits } from '../../types';
import { MergeOptions } from '../it/utils';
import type { MakeRequired } from '../types/util';
import { BaseShorter } from './base';
export class ChannelShorter extends BaseShorter { export class ChannelShorter extends BaseShorter {
/** /**
@ -26,7 +28,7 @@ export class ChannelShorter extends BaseShorter {
} }
async raw(id: string, force?: boolean): Promise<APIChannel> { async raw(id: string, force?: boolean): Promise<APIChannel> {
let channel; let channel: APIChannel | ReturnType<Channels['raw']>;
if (!force) { if (!force) {
channel = await this.client.cache.channels?.raw(id); channel = await this.client.cache.channels?.raw(id);
const overwrites = await this.client.cache.overwrites?.raw(id); const overwrites = await this.client.cache.overwrites?.raw(id);
@ -38,7 +40,7 @@ export class ChannelShorter extends BaseShorter {
channel = await this.client.proxy.channels(id).get(); channel = await this.client.proxy.channels(id).get();
await this.client.cache.channels?.patch(id, undefined, channel); await this.client.cache.channels?.patch(id, undefined, channel);
return channel; return channel as APIChannel;
} }
/** /**
@ -155,9 +157,9 @@ export class ChannelShorter extends BaseShorter {
} }
async overwritesFor(channelId: string, member: GuildMember) { async overwritesFor(channelId: string, member: GuildMember) {
const roleOverwrites = []; const roleOverwrites: ReturnType<Overwrites['get']> = [];
let memberOverwrites; let memberOverwrites: NonNullable<ReturnType<Overwrites['get']>>[number] | undefined;
let everyoneOverwrites; let everyoneOverwrites: NonNullable<ReturnType<Overwrites['get']>>[number] | undefined;
const channelOverwrites = (await this.client.cache.overwrites?.get(channelId)) ?? []; const channelOverwrites = (await this.client.cache.overwrites?.get(channelId)) ?? [];

View File

@ -1,9 +1,9 @@
import type { APIEmoji, RESTPatchAPIGuildEmojiJSONBody, RESTPostAPIGuildEmojiJSONBody } from '../../types';
import { resolveImage } from '../../builders'; import { resolveImage } from '../../builders';
import { type GuildEmojiStructure, Transformers } from '../../client/transformers';
import type { APIEmoji, RESTPatchAPIGuildEmojiJSONBody, RESTPostAPIGuildEmojiJSONBody } from '../../types';
import type { ImageResolvable } from '../types/resolvables'; import type { ImageResolvable } from '../types/resolvables';
import type { OmitInsert } from '../types/util'; import type { OmitInsert } from '../types/util';
import { BaseShorter } from './base'; import { BaseShorter } from './base';
import { Transformers } from '../../client/transformers';
export class EmojiShorter extends BaseShorter { export class EmojiShorter extends BaseShorter {
/** /**
@ -13,7 +13,7 @@ export class EmojiShorter extends BaseShorter {
* @returns A Promise that resolves to an array of emojis. * @returns A Promise that resolves to an array of emojis.
*/ */
async list(guildId: string, force = false) { async list(guildId: string, force = false) {
let emojis; let emojis: APIEmoji[] | GuildEmojiStructure[];
if (!force) { if (!force) {
emojis = (await this.client.cache.emojis?.values(guildId)) ?? []; emojis = (await this.client.cache.emojis?.values(guildId)) ?? [];
if (emojis.length) { if (emojis.length) {
@ -53,7 +53,7 @@ export class EmojiShorter extends BaseShorter {
* @returns A Promise that resolves to the fetched emoji. * @returns A Promise that resolves to the fetched emoji.
*/ */
async fetch(guildId: string, emojiId: string, force = false) { async fetch(guildId: string, emojiId: string, force = false) {
let emoji; let emoji: APIEmoji | GuildEmojiStructure | undefined;
if (!force) { if (!force) {
emoji = await this.client.cache.emojis?.get(emojiId); emoji = await this.client.cache.emojis?.get(emojiId);
if (emoji) return emoji; if (emoji) return emoji;

View File

@ -1,5 +1,10 @@
import { resolveFiles } from '../../builders';
import type { Channels } from '../../cache/resources/channels';
import { type GuildStructure, type StickerStructure, Transformers } from '../../client/transformers';
import { BaseChannel, type CreateStickerBodyRequest, Guild, GuildMember, channelFrom } from '../../structures';
import type { import type {
APIChannel, APIChannel,
APISticker,
GuildWidgetStyle, GuildWidgetStyle,
RESTGetAPICurrentUserGuildsQuery, RESTGetAPICurrentUserGuildsQuery,
RESTPatchAPIAutoModerationRuleJSONBody, RESTPatchAPIAutoModerationRuleJSONBody,
@ -11,10 +16,7 @@ import type {
RESTPostAPIGuildChannelJSONBody, RESTPostAPIGuildChannelJSONBody,
RESTPostAPIGuildsJSONBody, RESTPostAPIGuildsJSONBody,
} from '../../types'; } from '../../types';
import { resolveFiles } from '../../builders';
import { BaseChannel, channelFrom, Guild, GuildMember, type CreateStickerBodyRequest } from '../../structures';
import { BaseShorter } from './base'; import { BaseShorter } from './base';
import { type GuildStructure, Transformers } from '../../client/transformers';
export class GuildShorter extends BaseShorter { export class GuildShorter extends BaseShorter {
/** /**
@ -108,7 +110,7 @@ export class GuildShorter extends BaseShorter {
* @returns A Promise that resolves to an array of channels. * @returns A Promise that resolves to an array of channels.
*/ */
list: async (guildId: string, force = false) => { list: async (guildId: string, force = false) => {
let channels; let channels: ReturnType<Channels['values']> | APIChannel[];
if (!force) { if (!force) {
channels = (await this.client.cache.channels?.values(guildId)) ?? []; channels = (await this.client.cache.channels?.values(guildId)) ?? [];
if (channels.length) { if (channels.length) {
@ -131,7 +133,7 @@ export class GuildShorter extends BaseShorter {
* @returns A Promise that resolves to the fetched channel. * @returns A Promise that resolves to the fetched channel.
*/ */
fetch: async (guildId: string, channelId: string, force?: boolean) => { fetch: async (guildId: string, channelId: string, force?: boolean) => {
let channel; let channel: APIChannel | ReturnType<Channels['get']>;
if (!force) { if (!force) {
channel = await this.client.cache.channels?.get(channelId); channel = await this.client.cache.channels?.get(channelId);
if (channel) return channel; if (channel) return channel;
@ -328,7 +330,7 @@ export class GuildShorter extends BaseShorter {
* @returns A Promise that resolves to the fetched sticker. * @returns A Promise that resolves to the fetched sticker.
*/ */
fetch: async (guildId: string, stickerId: string, force = false) => { fetch: async (guildId: string, stickerId: string, force = false) => {
let sticker; let sticker: APISticker | StickerStructure | undefined;
if (!force) { if (!force) {
sticker = await this.client.cache.stickers?.get(stickerId); sticker = await this.client.cache.stickers?.get(stickerId);
if (sticker) return sticker; if (sticker) return sticker;

View File

@ -1,16 +1,16 @@
import { type GuildMemberStructure, Transformers, type VoiceStateStructure } from '../../client/transformers';
import { PermissionsBitField } from '../../structures/extra/Permissions';
import { import {
type APIGuildMember, type APIGuildMember,
FormattingPatterns,
type RESTGetAPIGuildMembersQuery, type RESTGetAPIGuildMembersQuery,
type RESTGetAPIGuildMembersSearchQuery, type RESTGetAPIGuildMembersSearchQuery,
type RESTPatchAPIGuildMemberJSONBody, type RESTPatchAPIGuildMemberJSONBody,
type RESTPutAPIGuildBanJSONBody, type RESTPutAPIGuildBanJSONBody,
type RESTPutAPIGuildMemberJSONBody, type RESTPutAPIGuildMemberJSONBody,
FormattingPatterns,
} from '../../types'; } from '../../types';
import { PermissionsBitField } from '../../structures/extra/Permissions';
import type { GuildMemberResolvable } from '../types/resolvables'; import type { GuildMemberResolvable } from '../types/resolvables';
import { BaseShorter } from './base'; import { BaseShorter } from './base';
import { Transformers, type VoiceStateStructure } from '../../client/transformers';
export class MemberShorter extends BaseShorter { export class MemberShorter extends BaseShorter {
/** /**
@ -37,7 +37,7 @@ export class MemberShorter extends BaseShorter {
return this.client.members.fetch(guildId, id); return this.client.members.fetch(guildId, id);
} }
const displayName = 'displayName' in resolve ? resolve.displayName : resolve.nick ?? resolve.user?.username; const displayName = 'displayName' in resolve ? resolve.displayName : (resolve.nick ?? resolve.user?.username);
return displayName ? this.search(guildId, { query: displayName, limit: 1 }).then(x => x[0]) : undefined; return displayName ? this.search(guildId, { query: displayName, limit: 1 }).then(x => x[0]) : undefined;
} }
@ -142,7 +142,7 @@ export class MemberShorter extends BaseShorter {
} }
async raw(guildId: string, memberId: string, force = false) { async raw(guildId: string, memberId: string, force = false) {
let member; let member: APIGuildMember | undefined;
if (!force) { if (!force) {
member = await this.client.cache.members?.raw(memberId, guildId); member = await this.client.cache.members?.raw(memberId, guildId);
if (member) return member; if (member) return member;
@ -161,7 +161,7 @@ export class MemberShorter extends BaseShorter {
* @returns A Promise that resolves to an array of listed members. * @returns A Promise that resolves to an array of listed members.
*/ */
async list(guildId: string, query?: RESTGetAPIGuildMembersQuery, force = false) { async list(guildId: string, query?: RESTGetAPIGuildMembersQuery, force = false) {
let members; let members: APIGuildMember[] | GuildMemberStructure[];
if (!force) { if (!force) {
members = (await this.client.cache.members?.values(guildId)) ?? []; members = (await this.client.cache.members?.values(guildId)) ?? [];
if (members.length) return members; if (members.length) return members;

View File

@ -1,17 +1,18 @@
import { resolveFiles } from '../../builders';
import { Transformers } from '../../client/transformers';
import {
type MessageWebhookMethodEditParams,
type MessageWebhookMethodWriteParams,
MessagesMethods,
} from '../../structures';
import type { import type {
APIWebhook,
RESTPatchAPIWebhookJSONBody, RESTPatchAPIWebhookJSONBody,
RESTPatchAPIWebhookWithTokenJSONBody, RESTPatchAPIWebhookWithTokenJSONBody,
RESTPostAPIChannelWebhookJSONBody, RESTPostAPIChannelWebhookJSONBody,
RESTPostAPIWebhookWithTokenJSONBody, RESTPostAPIWebhookWithTokenJSONBody,
} from '../../types'; } from '../../types';
import { resolveFiles } from '../../builders';
import {
MessagesMethods,
type MessageWebhookMethodEditParams,
type MessageWebhookMethodWriteParams,
} from '../../structures';
import { BaseShorter } from './base'; import { BaseShorter } from './base';
import { Transformers } from '../../client/transformers';
export class WebhookShorter extends BaseShorter { export class WebhookShorter extends BaseShorter {
async create(channelId: string, body: RESTPostAPIChannelWebhookJSONBody) { async create(channelId: string, body: RESTPostAPIChannelWebhookJSONBody) {
@ -64,7 +65,7 @@ export class WebhookShorter extends BaseShorter {
* @returns A Promise that resolves to the fetched webhook. * @returns A Promise that resolves to the fetched webhook.
*/ */
async fetch(webhookId: string, token?: string) { async fetch(webhookId: string, token?: string) {
let webhook; let webhook: APIWebhook;
if (token) { if (token) {
webhook = await this.client.proxy.webhooks(webhookId)(token).get({ auth: false }); webhook = await this.client.proxy.webhooks(webhookId)(token).get({ auth: false });
} else { } else {

View File

@ -4,6 +4,6 @@ import type { UsingClient } from '../../commands';
export type ImageOptions = CDNUrlOptions; export type ImageOptions = CDNUrlOptions;
export type MethodContext<T = {}> = Identify<{ client: UsingClient } & T>; export type MethodContext<T = object> = Identify<{ client: UsingClient } & T>;
export type MessageWebhookPayload<Body, Extra = {}> = Identify<{ body: Body } & Extra>; export type MessageWebhookPayload<Body, Extra = object> = Identify<{ body: Body } & Extra>;

View File

@ -211,7 +211,7 @@ export type Clean<T> = DropT<T, never>;
export type PartialAvoid<U, T> = Identify<KeepT<T, U> & Partial<T>>; export type PartialAvoid<U, T> = Identify<KeepT<T, U> & Partial<T>>;
// eslint-disable-next-line @typescript-eslint/ban-types //biome-ignore lint/complexity/noBannedTypes:
export type PartialClass<T> = PartialAvoid<Function, T>; export type PartialClass<T> = PartialAvoid<Function, T>;
export type AtLeastOne< export type AtLeastOne<

View File

@ -2,7 +2,7 @@ import type { ComponentCallback, ListenerOptions, ModalSubmitCallback } from '..
import { LimitedCollection } from '../collection'; import { LimitedCollection } from '../collection';
import { BaseCommand, type RegisteredMiddlewares, type UsingClient } from '../commands'; import { BaseCommand, type RegisteredMiddlewares, type UsingClient } from '../commands';
import type { FileLoaded } from '../commands/handler'; import type { FileLoaded } from '../commands/handler';
import { BaseHandler, isCloudfareWorker, magicImport, type Logger, type OnFailCallback } from '../common'; import { BaseHandler, type Logger, type OnFailCallback, isCloudfareWorker, magicImport } from '../common';
import type { ComponentInteraction, ModalSubmitInteraction, StringSelectMenuInteraction } from '../structures'; import type { ComponentInteraction, ModalSubmitInteraction, StringSelectMenuInteraction } from '../structures';
import { ComponentCommand, InteractionCommandType } from './componentcommand'; import { ComponentCommand, InteractionCommandType } from './componentcommand';
import type { ComponentContext } from './componentcontext'; import type { ComponentContext } from './componentcontext';
@ -165,7 +165,7 @@ export class ComponentHandler extends BaseHandler {
set(instances: (new () => ComponentCommands)[]) { set(instances: (new () => ComponentCommands)[]) {
for (const i of instances) { for (const i of instances) {
let component; let component: ReturnType<typeof this.callback>;
try { try {
component = this.callback(i); component = this.callback(i);
if (!component) continue; if (!component) continue;
@ -185,7 +185,7 @@ export class ComponentHandler extends BaseHandler {
for (const { components, file } of paths.map(x => ({ components: this.onFile(x.file), file: x }))) { for (const { components, file } of paths.map(x => ({ components: this.onFile(x.file), file: x }))) {
if (!components) continue; if (!components) continue;
for (const value of components) { for (const value of components) {
let component; let component: ReturnType<typeof this.callback>;
try { try {
component = this.callback(value); component = this.callback(value);
if (!component) continue; if (!component) continue;

View File

@ -36,7 +36,7 @@ export function componentFactory(
component: APIMessageActionRowComponent, component: APIMessageActionRowComponent,
): ActionRowMessageComponents | BaseComponent<ActionRowMessageComponents['type']> { ): ActionRowMessageComponents | BaseComponent<ActionRowMessageComponents['type']> {
switch (component.type) { switch (component.type) {
case ComponentType.Button: case ComponentType.Button: {
if (component.style === ButtonStyle.Link) { if (component.style === ButtonStyle.Link) {
return new LinkButtonComponent(component); return new LinkButtonComponent(component);
} }
@ -44,6 +44,7 @@ export function componentFactory(
return new SKUButtonComponent(component); return new SKUButtonComponent(component);
} }
return new ButtonComponent(component); return new ButtonComponent(component);
}
case ComponentType.ChannelSelect: case ComponentType.ChannelSelect:
return new ChannelSelectMenuComponent(component); return new ChannelSelectMenuComponent(component);
case ComponentType.RoleSelect: case ComponentType.RoleSelect:

View File

@ -57,7 +57,7 @@ export function Mixin<T, C extends TypeClass[]>(...args: C): C[number] & T {
} }
// https://github.com/tannerntannern/ts-mixer // https://github.com/tannerntannern/ts-mixer
export type TypeClass<InstanceType = {}, StaticType = {}> = (abstract new ( export type TypeClass<InstanceType = object, StaticType = object> = (abstract new (
...args: any[] ...args: any[]
) => InstanceType) & ) => InstanceType) &
StaticType; StaticType;

View File

@ -1,4 +1,3 @@
import { GatewayIntentBits } from './types';
import { import {
BaseClient, BaseClient,
type BaseClientOptions, type BaseClientOptions,
@ -7,8 +6,9 @@ import {
type RuntimeConfig, type RuntimeConfig,
type RuntimeConfigHTTP, type RuntimeConfigHTTP,
} from './client/base'; } from './client/base';
import type { CustomEventsKeys, ClientNameEvents, ResolveEventParams } from './events';
import { isCloudfareWorker } from './common'; import { isCloudfareWorker } from './common';
import type { ClientNameEvents, CustomEventsKeys, ResolveEventParams } from './events';
import { GatewayIntentBits } from './types';
export { Logger, PermissionStrings, Formatter } from './common'; export { Logger, PermissionStrings, Formatter } from './common';
// //
export { Collection, LimitedCollection } from './collection'; export { Collection, LimitedCollection } from './collection';
@ -64,11 +64,11 @@ export const config = {
'intents' in data 'intents' in data
? typeof data.intents === 'number' ? typeof data.intents === 'number'
? data.intents ? data.intents
: data.intents?.reduce<number>( : (data.intents?.reduce<number>(
(pr, acc) => (pr, acc) =>
pr | (typeof acc === 'number' ? acc : GatewayIntentBits[acc as keyof typeof GatewayIntentBits]), pr | (typeof acc === 'number' ? acc : GatewayIntentBits[acc as keyof typeof GatewayIntentBits]),
0, 0,
) ?? 0 ) ?? 0)
: 0, : 0,
} as InternalRuntimeConfig; } as InternalRuntimeConfig;
}, },

View File

@ -18,7 +18,7 @@ export const LangRouter = (userLocale: string, defaultLang: string, langs: Parti
return value; return value;
} }
return (locale?: string) => { return (locale?: string) => {
let result; let result: unknown;
try { try {
result = getValue(locale ?? userLocale); result = getValue(locale ?? userLocale);
} catch { } catch {

View File

@ -6,6 +6,7 @@ import {
type APIChatInputApplicationCommandInteraction, type APIChatInputApplicationCommandInteraction,
type APIChatInputApplicationCommandInteractionData, type APIChatInputApplicationCommandInteractionData,
type APICommandAutocompleteInteractionResponseCallbackData, type APICommandAutocompleteInteractionResponseCallbackData,
type APIEntryPointCommandInteraction,
type APIInteraction, type APIInteraction,
type APIInteractionResponse, type APIInteractionResponse,
type APIInteractionResponseChannelMessageWithSource, type APIInteractionResponseChannelMessageWithSource,
@ -31,24 +32,28 @@ import {
ApplicationCommandType, ApplicationCommandType,
ComponentType, ComponentType,
type GatewayInteractionCreateDispatchData, type GatewayInteractionCreateDispatchData,
type InteractionCallbackData,
type InteractionCallbackResourceActivity,
InteractionResponseType, InteractionResponseType,
InteractionType, InteractionType,
type MessageFlags, type MessageFlags,
type RESTPostAPIInteractionCallbackJSONBody,
type RESTAPIAttachment, type RESTAPIAttachment,
type APIEntryPointCommandInteraction, type RESTPostAPIInteractionCallbackJSONBody,
type InteractionCallbackData,
type InteractionCallbackResourceActivity,
} from '../types'; } from '../types';
import type { RawFile } from '../api'; import type { RawFile } from '../api';
import { ActionRow, Embed, Modal, PollBuilder, resolveAttachment, resolveFiles } from '../builders'; import { ActionRow, Embed, Modal, PollBuilder, resolveAttachment, resolveFiles } from '../builders';
import {
type GuildRoleStructure,
type InteractionGuildMemberStructure,
type MessageStructure,
type OptionResolverStructure,
Transformers,
type UserStructure,
type WebhookMessageStructure,
} from '../client/transformers';
import type { ContextOptionsResolved, UsingClient } from '../commands'; import type { ContextOptionsResolved, UsingClient } from '../commands';
import { import {
type ObjectToLower,
type OmitInsert,
type ToClass,
type When,
type ComponentInteractionMessageUpdate, type ComponentInteractionMessageUpdate,
type InteractionCreateBodyRequest, type InteractionCreateBodyRequest,
type InteractionMessageUpdateBodyRequest, type InteractionMessageUpdateBodyRequest,
@ -56,22 +61,17 @@ import {
type MessageUpdateBodyRequest, type MessageUpdateBodyRequest,
type MessageWebhookCreateBodyRequest, type MessageWebhookCreateBodyRequest,
type ModalCreateBodyRequest, type ModalCreateBodyRequest,
type ObjectToLower,
type OmitInsert,
type ToClass,
type When,
toCamelCase, toCamelCase,
} from '../common'; } from '../common';
import { channelFrom, type AllChannels } from './'; import { mix } from '../deps/mixer';
import { type AllChannels, channelFrom } from './';
import { Entitlement } from './Entitlement';
import { DiscordBase } from './extra/DiscordBase'; import { DiscordBase } from './extra/DiscordBase';
import { PermissionsBitField } from './extra/Permissions'; import { PermissionsBitField } from './extra/Permissions';
import {
type GuildRoleStructure,
type InteractionGuildMemberStructure,
type MessageStructure,
Transformers,
type UserStructure,
type WebhookMessageStructure,
type OptionResolverStructure,
} from '../client/transformers';
import { mix } from '../deps/mixer';
import { Entitlement } from './Entitlement';
export type ReplyInteractionBody = export type ReplyInteractionBody =
| { type: InteractionResponseType.Modal; data: ModalCreateBodyRequest } | { type: InteractionResponseType.Modal; data: ModalCreateBodyRequest }
@ -774,7 +774,7 @@ export class ModalSubmitInteraction<FromGuild extends boolean = boolean> extends
getInputValue(customId: string, required: true): string; getInputValue(customId: string, required: true): string;
getInputValue(customId: string, required?: false): string | undefined; getInputValue(customId: string, required?: false): string | undefined;
getInputValue(customId: string, required?: boolean): string | undefined { getInputValue(customId: string, required?: boolean): string | undefined {
let value; let value: string | undefined;
for (const { components } of this.components) { for (const { components } of this.components) {
const get = components.find(x => x.customId === customId); const get = components.find(x => x.customId === customId);
if (get) { if (get) {

View File

@ -1,45 +1,5 @@
import {
type APIChannelBase,
type RESTPatchAPIChannelJSONBody,
type RESTPostAPIGuildChannelJSONBody,
type RESTPatchAPIGuildChannelPositionsJSONBody,
type APIGuildChannel,
type RESTGetAPIChannelMessageReactionUsersQuery,
type RESTAPIAttachment,
type APITextChannel,
type APIGuildForumTag,
type ThreadAutoArchiveDuration,
type APIGuildForumDefaultReactionEmoji,
type SortOrderType,
type RESTPostAPIGuildForumThreadsJSONBody,
type RESTPostAPIChannelWebhookJSONBody,
type APIDMChannel,
type APIGuildVoiceChannel,
type APIGuildStageVoiceChannel,
type APIGuildMediaChannel,
type APIGuildForumChannel,
type APIThreadChannel,
ChannelFlags,
type APIGuildCategoryChannel,
type APINewsChannel,
ChannelType,
VideoQualityMode,
} from '../types';
import { ActionRow, Embed, PollBuilder, resolveAttachment } from '../builders';
import type { UsingClient } from '../commands';
import type {
EmojiResolvable,
MessageCreateBodyRequest,
MessageUpdateBodyRequest,
MethodContext,
ObjectToLower,
StringToNumber,
ToClass,
} from '../common';
import type { GuildMember } from './GuildMember';
import type { GuildRole } from './GuildRole';
import { DiscordBase } from './extra/DiscordBase';
import { Collection, Formatter, type RawFile } from '..'; import { Collection, Formatter, type RawFile } from '..';
import { ActionRow, Embed, PollBuilder, resolveAttachment } from '../builders';
import { import {
type BaseChannelStructure, type BaseChannelStructure,
type BaseGuildChannelStructure, type BaseGuildChannelStructure,
@ -56,7 +16,47 @@ import {
Transformers, Transformers,
type VoiceChannelStructure, type VoiceChannelStructure,
} from '../client/transformers'; } from '../client/transformers';
import type { UsingClient } from '../commands';
import type {
EmojiResolvable,
MessageCreateBodyRequest,
MessageUpdateBodyRequest,
MethodContext,
ObjectToLower,
StringToNumber,
ToClass,
} from '../common';
import { mix } from '../deps/mixer'; import { mix } from '../deps/mixer';
import {
type APIChannelBase,
type APIDMChannel,
type APIGuildCategoryChannel,
type APIGuildChannel,
type APIGuildForumChannel,
type APIGuildForumDefaultReactionEmoji,
type APIGuildForumTag,
type APIGuildMediaChannel,
type APIGuildStageVoiceChannel,
type APIGuildVoiceChannel,
type APINewsChannel,
type APITextChannel,
type APIThreadChannel,
ChannelFlags,
ChannelType,
type RESTAPIAttachment,
type RESTGetAPIChannelMessageReactionUsersQuery,
type RESTPatchAPIChannelJSONBody,
type RESTPatchAPIGuildChannelPositionsJSONBody,
type RESTPostAPIChannelWebhookJSONBody,
type RESTPostAPIGuildChannelJSONBody,
type RESTPostAPIGuildForumThreadsJSONBody,
type SortOrderType,
type ThreadAutoArchiveDuration,
VideoQualityMode,
} from '../types';
import type { GuildMember } from './GuildMember';
import type { GuildRole } from './GuildRole';
import { DiscordBase } from './extra/DiscordBase';
export class BaseChannel<T extends ChannelType> extends DiscordBase<APIChannelBase<ChannelType>> { export class BaseChannel<T extends ChannelType> extends DiscordBase<APIChannelBase<ChannelType>> {
declare type: T; declare type: T;
@ -189,7 +189,7 @@ export class BaseGuildChannel extends BaseChannel<ChannelType> {
permissionOverwrites = { permissionOverwrites = {
fetch: () => this.client.cache.overwrites?.get(this.id), fetch: () => this.client.cache.overwrites?.get(this.id),
values: () => (this.guildId ? this.client.cache.overwrites?.values(this.guildId) ?? [] : []), values: () => (this.guildId ? (this.client.cache.overwrites?.values(this.guildId) ?? []) : []),
}; };
memberPermissions(member: GuildMember, checkAdmin = true) { memberPermissions(member: GuildMember, checkAdmin = true) {
@ -333,11 +333,12 @@ export function channelFrom(data: APIChannelBase<ChannelType>, client: UsingClie
return Transformers.CategoryChannel(client, data); return Transformers.CategoryChannel(client, data);
case ChannelType.GuildAnnouncement: case ChannelType.GuildAnnouncement:
return Transformers.NewsChannel(client, data); return Transformers.NewsChannel(client, data);
default: default: {
if ('guild_id' in data) { if ('guild_id' in data) {
return Transformers.BaseGuildChannel(client, data as APIGuildChannel<ChannelType>); return Transformers.BaseGuildChannel(client, data as APIGuildChannel<ChannelType>);
} }
return Transformers.BaseChannel(client, data); return Transformers.BaseChannel(client, data);
}
} }
} }

View File

@ -60,11 +60,12 @@ export class BitField<T extends object> {
return this.resolve(this.Flags[bits]); return this.resolve(this.Flags[bits]);
case 'bigint': case 'bigint':
return bits; return bits;
case 'object': case 'object': {
if (!Array.isArray(bits)) { if (!Array.isArray(bits)) {
throw new TypeError(`Cannot resolve permission: ${bits}`); throw new TypeError(`Cannot resolve permission: ${bits}`);
} }
return bits.map(x => this.resolve(x)).reduce((acc, cur) => acc | cur, BitField.None); return bits.map(x => this.resolve(x)).reduce((acc, cur) => acc | cur, BitField.None);
}
default: default:
throw new TypeError(`Cannot resolve permission: ${typeof bits === 'symbol' ? String(bits) : (bits as any)}`); throw new TypeError(`Cannot resolve permission: ${typeof bits === 'symbol' ? String(bits) : (bits as any)}`);
} }

View File

@ -296,7 +296,6 @@ export enum ConnectionService {
* @deprecated This is the old name for {@apilink ConnectionService#X} * @deprecated This is the old name for {@apilink ConnectionService#X}
*/ */
// biome-ignore lint/correctness/noUndeclaredVariables: biome bug lol
Twitter = X, Twitter = X,
Xbox = 'xbox', Xbox = 'xbox',
YouTube = 'youtube', YouTube = 'youtube',

View File

@ -293,7 +293,6 @@ export enum GatewayIntentBits {
* @deprecated This is the old name for {@apilink GatewayIntentBits#GuildModeration} * @deprecated This is the old name for {@apilink GatewayIntentBits#GuildModeration}
*/ */
// biome-ignore lint/correctness/noUndeclaredVariables: no reason lmao
GuildBans = GuildModeration, GuildBans = GuildModeration,
GuildEmojisAndStickers = 1 << 3, GuildEmojisAndStickers = 1 << 3,
GuildIntegrations = 1 << 4, GuildIntegrations = 1 << 4,

View File

@ -1,5 +1,4 @@
import type { DeepPartial } from '../../common'; import type { DeepPartial } from '../../common';
import type { GatewayDispatchPayload } from '../../types';
import type { ShardManagerOptions, WorkerManagerOptions } from '../discord'; import type { ShardManagerOptions, WorkerManagerOptions } from '../discord';
const COMPRESS = false; const COMPRESS = false;
@ -18,9 +17,6 @@ const ShardManagerDefaults: DeepPartial<ShardManagerOptions> = {
properties, properties,
version: 10, version: 10,
shardStart: 0, shardStart: 0,
handlePayload: (shardId: number, packet: GatewayDispatchPayload): void => {
console.info(`Packet ${packet.t} on shard ${shardId}`);
},
resharding: { resharding: {
interval: 8 * 60 * 60 * 1e3, // 8h interval: 8 * 60 * 60 * 1e3, // 8h
percentage: 80, percentage: 80,
@ -36,7 +32,6 @@ const ShardManagerDefaults: DeepPartial<ShardManagerOptions> = {
const WorkerManagerDefaults: DeepPartial<WorkerManagerOptions> = { const WorkerManagerDefaults: DeepPartial<WorkerManagerOptions> = {
...ShardManagerDefaults, ...ShardManagerDefaults,
shardsPerWorker: 16, shardsPerWorker: 16,
handlePayload: (_shardId: number, _workerId: number, _packet: GatewayDispatchPayload): void => {},
}; };
export interface IdentifyProperties { export interface IdentifyProperties {

View File

@ -1,18 +1,19 @@
import { inflateSync } from 'node:zlib'; import { inflateSync } from 'node:zlib';
import { Logger, LogLevels, type MakeRequired, MergeOptions } from '../../common'; import { LogLevels, Logger, type MakeRequired, MergeOptions } from '../../common';
import {
GatewayCloseCodes,
GatewayDispatchEvents,
type GatewayDispatchPayload,
GatewayOpcodes,
type GatewayReceivePayload,
type GatewaySendPayload,
} from '../../types';
import { properties } from '../constants'; import { properties } from '../constants';
import { DynamicBucket } from '../structures'; import { DynamicBucket } from '../structures';
import { ConnectTimeout } from '../structures/timeout'; import { ConnectTimeout } from '../structures/timeout';
import { BaseSocket } from './basesocket'; import { BaseSocket } from './basesocket';
import type { ShardData, ShardOptions } from './shared'; import type { ShardData, ShardOptions } from './shared';
import { ShardSocketCloseCodes } from './shared'; import { ShardSocketCloseCodes } from './shared';
import {
type GatewaySendPayload,
type GatewayReceivePayload,
GatewayCloseCodes,
GatewayDispatchEvents,
GatewayOpcodes,
} from '../../types';
export interface ShardHeart { export interface ShardHeart {
interval: number; interval: number;
@ -229,8 +230,10 @@ export class Shard {
} }
break; break;
case GatewayOpcodes.HeartbeatAck: case GatewayOpcodes.HeartbeatAck:
this.heart.ack = true; {
this.heart.lastAck = Date.now(); this.heart.ack = true;
this.heart.lastAck = Date.now();
}
break; break;
case GatewayOpcodes.Heartbeat: case GatewayOpcodes.Heartbeat:
this.heartbeat(true); this.heartbeat(true);
@ -254,8 +257,10 @@ export class Shard {
{ {
switch (packet.t) { switch (packet.t) {
case GatewayDispatchEvents.Resumed: case GatewayDispatchEvents.Resumed:
this.offlineSendQueue.map((resolve: () => any) => resolve()); {
this.options.handlePayload(this.id, packet); this.offlineSendQueue.map((resolve: () => any) => resolve());
this.options.handlePayload(this.id, packet);
}
break; break;
case GatewayDispatchEvents.Ready: { case GatewayDispatchEvents.Ready: {
this.data.resume_gateway_url = packet.d.resume_gateway_url; this.data.resume_gateway_url = packet.d.resume_gateway_url;
@ -288,10 +293,12 @@ export class Shard {
case GatewayCloseCodes.UnknownOpcode: case GatewayCloseCodes.UnknownOpcode:
case GatewayCloseCodes.InvalidSeq: case GatewayCloseCodes.InvalidSeq:
case GatewayCloseCodes.SessionTimedOut: case GatewayCloseCodes.SessionTimedOut:
this.data.resume_seq = 0; {
this.data.session_id = undefined; this.data.resume_seq = 0;
this.data.resume_gateway_url = undefined; this.data.session_id = undefined;
await this.reconnect(); this.data.resume_gateway_url = undefined;
await this.reconnect();
}
break; break;
case 1001: case 1001:
case 1006: case 1006:
@ -301,8 +308,10 @@ export class Shard {
case GatewayCloseCodes.NotAuthenticated: case GatewayCloseCodes.NotAuthenticated:
case GatewayCloseCodes.AlreadyAuthenticated: case GatewayCloseCodes.AlreadyAuthenticated:
case GatewayCloseCodes.RateLimited: case GatewayCloseCodes.RateLimited:
this.logger.info('Trying to reconnect'); {
await this.reconnect(); this.logger.info('Trying to reconnect');
await this.reconnect();
}
break; break;
case GatewayCloseCodes.AuthenticationFailed: case GatewayCloseCodes.AuthenticationFailed:
@ -315,8 +324,10 @@ export class Shard {
break; break;
default: default:
this.logger.warn('Unknown close code, trying to reconnect anyways'); {
await this.reconnect(); this.logger.warn('Unknown close code, trying to reconnect anyways');
await this.reconnect();
}
break; break;
} }
} }
@ -331,7 +342,7 @@ export class Shard {
} }
protected handleMessage(data: string | Buffer) { protected handleMessage(data: string | Buffer) {
let packet; let packet: GatewayDispatchPayload;
try { try {
if (data instanceof Buffer) { if (data instanceof Buffer) {
data = inflateSync(data); data = inflateSync(data);

View File

@ -3,23 +3,23 @@ import {
Logger, Logger,
type MakeRequired, type MakeRequired,
MergeOptions, MergeOptions,
lazyLoadPackage,
type WatcherSendToShard, type WatcherSendToShard,
calculateShardId, calculateShardId,
lazyLoadPackage,
} from '../../common'; } from '../../common';
import type { MakeDeepPartial } from '../../common/types/util';
import { import {
type GatewayDispatchPayload,
GatewayOpcodes,
type GatewaySendPayload,
type GatewayUpdatePresence, type GatewayUpdatePresence,
type GatewayVoiceStateUpdate, type GatewayVoiceStateUpdate,
type GatewaySendPayload,
GatewayOpcodes,
type GatewayDispatchPayload,
} from '../../types'; } from '../../types';
import { ShardManagerDefaults } from '../constants'; import { ShardManagerDefaults } from '../constants';
import { DynamicBucket } from '../structures'; import { DynamicBucket } from '../structures';
import { ConnectQueue } from '../structures/timeout'; import { ConnectQueue } from '../structures/timeout';
import { Shard } from './shard'; import { Shard } from './shard';
import type { ShardManagerOptions, WorkerData } from './shared'; import type { ShardManagerOptions, WorkerData } from './shared';
import type { MakeDeepPartial } from '../../common/types/util';
let parentPort: import('node:worker_threads').MessagePort; let parentPort: import('node:worker_threads').MessagePort;
let workerData: WorkerData; let workerData: WorkerData;
@ -162,7 +162,9 @@ export class ShardManager extends Map<number, Shard> {
if (++shardsConnected < info.shards) return; //waiting for last shard to connect if (++shardsConnected < info.shards) return; //waiting for last shard to connect
// dont listen more events when all shards are ready // dont listen more events when all shards are ready
handlePayload = async () => {}; handlePayload = async () => {
//
};
await this.disconnectAll(); await this.disconnectAll();
this.clear(); this.clear();
@ -183,7 +185,9 @@ export class ShardManager extends Map<number, Shard> {
getInfo: () => ({}) as any, getInfo: () => ({}) as any,
interval: 0, interval: 0,
percentage: 0, percentage: 0,
reloadGuilds() {}, reloadGuilds() {
//
},
onGuild() { onGuild() {
return true; return true;
}, },

View File

@ -1,10 +1,10 @@
import type { Awaitable, DeepPartial, Logger } from '../../common';
import type { import type {
APIGatewayBotInfo, APIGatewayBotInfo,
GatewayDispatchPayload, GatewayDispatchPayload,
GatewayIntentBits, GatewayIntentBits,
GatewayPresenceUpdateData, GatewayPresenceUpdateData,
} from '../../types'; } from '../../types';
import type { Awaitable, DeepPartial, Logger } from '../../common';
import type { IdentifyProperties } from '../constants'; import type { IdentifyProperties } from '../constants';
export interface ShardManagerOptions extends ShardDetails { export interface ShardManagerOptions extends ShardDetails {
@ -79,7 +79,7 @@ export interface WorkerManagerOptions extends Omit<ShardManagerOptions, 'handleP
path: string; path: string;
handlePayload(shardId: number, workerId: number, packet: GatewayDispatchPayload): unknown; handlePayload?(shardId: number, workerId: number, packet: GatewayDispatchPayload): any;
properties?: DeepPartial<NonNullable<ShardManagerOptions['properties']>>; properties?: DeepPartial<NonNullable<ShardManagerOptions['properties']>>;
} }

View File

@ -1,4 +1,4 @@
import { randomBytes, createHash, randomUUID } from 'node:crypto'; import { createHash, randomBytes, randomUUID } from 'node:crypto';
import { request } from 'node:https'; import { request } from 'node:https';
import type { Socket } from 'node:net'; import type { Socket } from 'node:net';
@ -179,7 +179,7 @@ export class SeyfertWebSocket {
private _write(buffer: Buffer, opcode: number) { private _write(buffer: Buffer, opcode: number) {
if (!this.socket?.writable) return; if (!this.socket?.writable) return;
const length = buffer.length; const length = buffer.length;
let frame; let frame: Buffer;
// Kinda same logic as above, but client-side // Kinda same logic as above, but client-side
if (length < 126) { if (length < 126) {
frame = Buffer.allocUnsafe(6 + length); frame = Buffer.allocUnsafe(6 + length);
@ -200,17 +200,29 @@ export class SeyfertWebSocket {
this.socket?.write(frame); this.socket?.write(frame);
} }
onping(_data: string) {} onping(_data: string) {
//
}
onpong(_data: string) {} onpong(_data: string) {
//
}
onopen() {} onopen() {
//
}
onmessage(_payload: { data: string | Buffer }) {} onmessage(_payload: { data: string | Buffer }) {
//
}
onclose(_close: { code: number; reason: string }) {} onclose(_close: { code: number; reason: string }) {
//
}
onerror(_err: unknown) {} onerror(_err: unknown) {
//
}
close(code: number, reason: string) { close(code: number, reason: string) {
this.__closeCalled = true; this.__closeCalled = true;
@ -299,7 +311,7 @@ export class SeyfertWebSocket {
// actual index of the buffer to read // actual index of the buffer to read
let blockIndex = readable.bufferIndex; let blockIndex = readable.bufferIndex;
// Buffer to read // Buffer to read
let block; let block: Buffer | undefined;
while ((block = readable.buffer[blockIndex++])) { while ((block = readable.buffer[blockIndex++])) {
for (let i = 0; i < block.length; i++) { for (let i = 0; i < block.length; i++) {
if (++bitIndex > start) { if (++bitIndex > start) {

View File

@ -10,7 +10,7 @@ export interface WorkerShardInfo {
export type WorkerInfo = { shards: WorkerShardInfo[] }; export type WorkerInfo = { shards: WorkerShardInfo[] };
type CreateWorkerMessage<T extends string, D extends object = {}> = { type CreateWorkerMessage<T extends string, D extends object = object> = {
type: T; type: T;
workerId: number; workerId: number;
} & D; } & D;

View File

@ -1,10 +1,10 @@
import type { GatewayPresenceUpdateData, GatewaySendPayload } from '../../types';
import cluster, { type Worker as ClusterWorker } from 'node:cluster'; import cluster, { type Worker as ClusterWorker } from 'node:cluster';
import { randomUUID } from 'node:crypto'; import { randomUUID } from 'node:crypto';
import { ApiHandler, Logger, Router } from '../..'; import { ApiHandler, Logger, Router } from '../..';
import { MemoryAdapter, type Adapter } from '../../cache'; import { type Adapter, MemoryAdapter } from '../../cache';
import { BaseClient, type InternalRuntimeConfig } from '../../client/base'; import { BaseClient, type InternalRuntimeConfig } from '../../client/base';
import { MergeOptions, lazyLoadPackage, type MakePartial } from '../../common'; import { type MakePartial, MergeOptions, lazyLoadPackage } from '../../common';
import type { GatewayPresenceUpdateData, GatewaySendPayload } from '../../types';
import { WorkerManagerDefaults, properties } from '../constants'; import { WorkerManagerDefaults, properties } from '../constants';
import { DynamicBucket } from '../structures'; import { DynamicBucket } from '../structures';
import { ConnectQueue } from '../structures/timeout'; import { ConnectQueue } from '../structures/timeout';
@ -181,11 +181,12 @@ export class WorkerManager extends Map<
worker.on('message', data => this.handleWorkerMessage(data)); worker.on('message', data => this.handleWorkerMessage(data));
return worker; return worker;
} }
case 'custom': case 'custom': {
this.options.adapter!.spawn(workerData, env); this.options.adapter!.spawn(workerData, env);
return { return {
ready: false, ready: false,
}; };
}
} }
} }
@ -450,7 +451,7 @@ export class WorkerManager extends Map<
} }
} }
type CreateManagerMessage<T extends string, D extends object = {}> = { type: T } & D; type CreateManagerMessage<T extends string, D extends object = object> = { type: T } & D;
export type ManagerAllowConnect = CreateManagerMessage< export type ManagerAllowConnect = CreateManagerMessage<
'ALLOW_CONNECT', 'ALLOW_CONNECT',