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",
"changelog": [
"@changesets/changelog-github",
{
"repo": "tiramisulabs/seyfert"
}
],
"commit": false,
"fixed": [],
"linked": [],
"access": "restricted",
"baseBranch": "main",
"updateInternalDependencies": "patch",
"ignore": []
}
{
"$schema": "https://unpkg.com/@changesets/config@2.3.1/schema.json",
"changelog": [
"@changesets/changelog-github",
{
"repo": "tiramisulabs/seyfert"
}
],
"commit": false,
"fixed": [],
"linked": [],
"access": "restricted",
"baseBranch": "main",
"updateInternalDependencies": "patch",
"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": {
"enabled": true,
"rules": {
"recommended": false,
"all": true,
"security": {
"noGlobalEval": "off"
@ -10,92 +32,52 @@
"suspicious": {
"noExplicitAny": "off",
"noAssignInExpressions": "off",
"useAwait": "off",
"noConfusingVoidType": "off",
"noAsyncPromiseExecutor": "off",
"noUnsafeDeclarationMerging": "off",
"noEmptyInterface": "off",
"noConfusingVoidType": "off",
"noImplicitAnyLet": "off",
"noEmptyBlockStatements": "off",
"useAwait": "off",
"noConsoleLog": "off",
"noAsyncPromiseExecutor": "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": {
"noUnusedVariables": "off",
"noNodejsModules": "off"
"noNodejsModules": "off",
"useImportExtensions": "off",
"noUnusedFunctionParameters": "off",
"noUnusedVariables": "off"
},
"nursery": {
"useImportRestrictions": "off"
"style": {
"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": {
"noUselessLoneBlockStatements": "warn",
"noBannedTypes": "off",
"noForEach": "off",
"noUselessConstructor": "off",
"noExcessiveCognitiveComplexity": "off",
"noStaticOnlyClass": "off"
},
"a11y": {
"all": false
"noUselessConstructor": "off"
},
"performance": {
"noDelete": "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": {
"formatter": {
"quoteStyle": "single",
"semicolons": "always",
"arrowParentheses": "asNeeded",
"bracketSameLine": true,
"semicolons": "always"
"bracketSameLine": true
}
},
"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 {
APIThreadChannel,
RESTDeleteAPIAutoModerationRuleResult,
@ -116,7 +117,6 @@ import type {
RESTPutAPIGuildMemberRoleResult,
RESTPutAPIGuildTemplateSyncResult,
} from '../../types';
import type { Identify, OmitInsert } from '../../common';
import type { ProxyRequestMethod } from '../Router';
import type { RestArguments } from '../api';
import type { RawFile } from '../shared';
@ -334,7 +334,7 @@ export interface GuildRoutes {
args: RestArguments<
ProxyRequestMethod.Post,
Omit<RESTPostAPIGuildStickerFormDataBody, 'file'>,
{},
object,
OmitInsert<RawFile, 'key', { key: 'file' }>[]
>,
): Promise<RESTPostAPIGuildStickerResult>;

View File

@ -5,10 +5,10 @@ import type { WorkerSendApiRequest } from '../websocket/discord/worker';
import { CDNRouter, type ProxyRequestMethod } from './Router';
import { Bucket } from './bucket';
import {
DefaultUserAgent,
type ApiHandlerInternalOptions,
type ApiHandlerOptions,
type ApiRequestOptions,
DefaultUserAgent,
type HttpMethods,
type RawFile,
type RequestHeaders,
@ -54,7 +54,7 @@ export class ApiHandler {
globalUnblock() {
this.globalBlock = false;
let cb;
let cb: (() => void) | undefined;
while ((cb = this.readyQueue.shift())) {
cb();
}
@ -105,7 +105,7 @@ export class ApiHandler {
request: { ...request, auth },
});
let response;
let response: Response;
try {
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 { promises } from 'node:fs';
import path from 'node:path';
import type { UsingClient, RawFile } from '..';
import type { RawFile, UsingClient } from '..';
import type { ImageResolvable, ObjectToLower } from '../common';
import { Base } from '../structures/extra/Base';
import { promises } from 'node:fs';
import type { APIAttachment, RESTAPIAttachment } from '../types';
export interface AttachmentResolvableMap {
url: string;
@ -209,7 +209,7 @@ export async function resolveAttachmentData(
if (Buffer.isBuffer(data)) return { data };
// @ts-expect-error
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));
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: true): string[];
scan(query: string, keys = false) {
const values = [];
const values: (string | unknown)[] = [];
const sq = query.split('.');
for (const [key, value] of this.storage.entries()) {
if (key.split('.').every((value, i) => (sq[i] === '*' ? !!value : sq[i] === value))) {

View File

@ -1,5 +1,5 @@
import { LimitedCollection } from '../..';
import { MergeOptions, type MakeRequired } from '../../common';
import { type MakeRequired, MergeOptions } from '../../common';
import type { Adapter } from './types';
//TODO: optimizar esto
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: true): string[];
scan(query: string, keys = false) {
const values = [];
const values: (string | unknown)[] = [];
const sq = query.split('.');
for (const iterator of [...this.storage.values()].flatMap(x => x.entries()))
for (const [key, value] of iterator) {

View File

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

View File

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

View File

@ -1,21 +1,21 @@
import { type GatewayDispatchPayload, type GatewayPresenceUpdateData, GatewayIntentBits } from '../types';
import type { CommandContext, Message } from '..';
import {
type Awaitable,
lazyLoadPackage,
type DeepPartial,
type If,
type WatcherPayload,
type WatcherSendToShard,
lazyLoadPackage,
} from '../common';
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 { PresenceUpdateHandler } from '../websocket/discord/events/presenceUpdate';
import type { BaseClientOptions, InternalRuntimeConfig, ServicesOptions, StartOptions } from './base';
import { BaseClient } from './base';
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;
@ -149,18 +149,22 @@ export class Client<Ready extends boolean = boolean> extends BaseClient {
this.collectors.run('RAW', packet, this),
]); //ignore promise
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':
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;
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;
case 'GUILD_DELETE':
case 'GUILD_CREATE': {
@ -181,12 +185,16 @@ export class Client<Ready extends boolean = boolean> extends BaseClient {
default: {
switch (packet.t) {
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;
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;
case 'READY': {
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 { StructStates } from '../common/';
import {
AnonymousGuild,
AutoModerationRule,
@ -30,8 +30,8 @@ import {
Webhook,
WebhookMessage,
} from '../structures';
import type { StructStates } from '../common/';
import { GuildBan } from '../structures/GuildBan';
import type { ChannelType } from '../types';
export type PollStructure = InferCustomStructure<Poll, 'Poll'>;
export type ClientUserStructure = InferCustomStructure<ClientUser, 'ClientUser'>;
@ -64,130 +64,99 @@ export type VoiceStateStructure = InferCustomStructure<VoiceState, 'VoiceState'>
export type WebhookStructure = InferCustomStructure<Webhook, 'Webhook'>;
export type OptionResolverStructure = InferCustomStructure<OptionResolver, 'OptionResolver'>;
export class Transformers {
static AnonymousGuild(...args: ConstructorParameters<typeof AnonymousGuild>): AnonymousGuildStructure {
export const Transformers = {
AnonymousGuild(...args: ConstructorParameters<typeof AnonymousGuild>): AnonymousGuildStructure {
return new AnonymousGuild(...args);
}
static AutoModerationRule(...args: ConstructorParameters<typeof AutoModerationRule>): AutoModerationRuleStructure {
},
AutoModerationRule(...args: ConstructorParameters<typeof AutoModerationRule>): AutoModerationRuleStructure {
return new AutoModerationRule(...args);
}
static BaseChannel(...args: ConstructorParameters<typeof BaseChannel>): BaseChannelStructure {
},
BaseChannel(...args: ConstructorParameters<typeof BaseChannel>): BaseChannelStructure {
return new BaseChannel(...args);
}
static BaseGuildChannel(...args: ConstructorParameters<typeof BaseGuildChannel>): BaseGuildChannelStructure {
},
BaseGuildChannel(...args: ConstructorParameters<typeof BaseGuildChannel>): BaseGuildChannelStructure {
return new BaseGuildChannel(...args);
}
static TextGuildChannel(...args: ConstructorParameters<typeof TextGuildChannel>): TextGuildChannelStructure {
},
TextGuildChannel(...args: ConstructorParameters<typeof TextGuildChannel>): TextGuildChannelStructure {
return new TextGuildChannel(...args);
}
static DMChannel(...args: ConstructorParameters<typeof DMChannel>): DMChannelStructure {
},
DMChannel(...args: ConstructorParameters<typeof DMChannel>): DMChannelStructure {
return new DMChannel(...args);
}
static VoiceChannel(...args: ConstructorParameters<typeof VoiceChannel>): VoiceChannelStructure {
},
VoiceChannel(...args: ConstructorParameters<typeof VoiceChannel>): VoiceChannelStructure {
return new VoiceChannel(...args);
}
static StageChannel(...args: ConstructorParameters<typeof StageChannel>): StageChannelStructure {
},
StageChannel(...args: ConstructorParameters<typeof StageChannel>): StageChannelStructure {
return new StageChannel(...args);
}
static MediaChannel(...args: ConstructorParameters<typeof MediaChannel>): MediaChannelStructure {
},
MediaChannel(...args: ConstructorParameters<typeof MediaChannel>): MediaChannelStructure {
return new MediaChannel(...args);
}
static ForumChannel(...args: ConstructorParameters<typeof ForumChannel>): ForumChannelStructure {
},
ForumChannel(...args: ConstructorParameters<typeof ForumChannel>): ForumChannelStructure {
return new ForumChannel(...args);
}
static ThreadChannel(...args: ConstructorParameters<typeof ThreadChannel>): ThreadChannelStructure {
},
ThreadChannel(...args: ConstructorParameters<typeof ThreadChannel>): ThreadChannelStructure {
return new ThreadChannel(...args);
}
static CategoryChannel(...args: ConstructorParameters<typeof CategoryChannel>): CategoryChannelStructure {
},
CategoryChannel(...args: ConstructorParameters<typeof CategoryChannel>): CategoryChannelStructure {
return new CategoryChannel(...args);
}
static NewsChannel(...args: ConstructorParameters<typeof NewsChannel>): NewsChannelStructure {
},
NewsChannel(...args: ConstructorParameters<typeof NewsChannel>): NewsChannelStructure {
return new NewsChannel(...args);
}
static DirectoryChannel(...args: ConstructorParameters<typeof DirectoryChannel>): DirectoryChannelStructure {
},
DirectoryChannel(...args: ConstructorParameters<typeof DirectoryChannel>): DirectoryChannelStructure {
return new DirectoryChannel(...args);
}
static ClientUser(...args: ConstructorParameters<typeof ClientUser>): ClientUserStructure {
},
ClientUser(...args: ConstructorParameters<typeof ClientUser>): ClientUserStructure {
return new ClientUser(...args);
}
static Guild<State extends StructStates = 'api'>(
...args: ConstructorParameters<typeof Guild>
): GuildStructure<State> {
},
Guild<State extends StructStates = 'api'>(...args: ConstructorParameters<typeof Guild>): GuildStructure<State> {
return new Guild<State>(...args);
}
static GuildBan(...args: ConstructorParameters<typeof GuildBan>): GuildBanStructure {
},
GuildBan(...args: ConstructorParameters<typeof GuildBan>): GuildBanStructure {
return new GuildBan(...args);
}
static GuildEmoji(...args: ConstructorParameters<typeof GuildEmoji>): GuildEmojiStructure {
},
GuildEmoji(...args: ConstructorParameters<typeof GuildEmoji>): GuildEmojiStructure {
return new GuildEmoji(...args);
}
static GuildMember(...args: ConstructorParameters<typeof GuildMember>): GuildMemberStructure {
},
GuildMember(...args: ConstructorParameters<typeof GuildMember>): GuildMemberStructure {
return new GuildMember(...args);
}
static InteractionGuildMember(
},
InteractionGuildMember(
...args: ConstructorParameters<typeof InteractionGuildMember>
): InteractionGuildMemberStructure {
return new InteractionGuildMember(...args);
}
static GuildRole(...args: ConstructorParameters<typeof GuildRole>): GuildRoleStructure {
},
GuildRole(...args: ConstructorParameters<typeof GuildRole>): GuildRoleStructure {
return new GuildRole(...args);
}
static GuildTemplate(...args: ConstructorParameters<typeof GuildTemplate>): GuildTemplateStructure {
},
GuildTemplate(...args: ConstructorParameters<typeof GuildTemplate>): GuildTemplateStructure {
return new GuildTemplate(...args);
}
static Message(...args: ConstructorParameters<typeof Message>): MessageStructure {
},
Message(...args: ConstructorParameters<typeof Message>): MessageStructure {
return new Message(...args);
}
static WebhookMessage(...args: ConstructorParameters<typeof WebhookMessage>): WebhookMessageStructure {
},
WebhookMessage(...args: ConstructorParameters<typeof WebhookMessage>): WebhookMessageStructure {
return new WebhookMessage(...args);
}
static Poll(...args: ConstructorParameters<typeof Poll>): PollStructure {
},
Poll(...args: ConstructorParameters<typeof Poll>): PollStructure {
return new Poll(...args);
}
static Sticker(...args: ConstructorParameters<typeof Sticker>): StickerStructure {
},
Sticker(...args: ConstructorParameters<typeof Sticker>): StickerStructure {
return new Sticker(...args);
}
static User(...args: ConstructorParameters<typeof User>): UserStructure {
},
User(...args: ConstructorParameters<typeof User>): UserStructure {
return new User(...args);
}
static VoiceState(...args: ConstructorParameters<typeof VoiceState>): VoiceStateStructure {
},
VoiceState(...args: ConstructorParameters<typeof VoiceState>): VoiceStateStructure {
return new VoiceState(...args);
}
static Webhook(...args: ConstructorParameters<typeof Webhook>): WebhookStructure {
},
Webhook(...args: ConstructorParameters<typeof Webhook>): WebhookStructure {
return new Webhook(...args);
}
static OptionResolver(...args: ConstructorParameters<typeof OptionResolver>): OptionResolverStructure {
},
OptionResolver(...args: ConstructorParameters<typeof OptionResolver>): OptionResolverStructure {
return new OptionResolver(...args);
}
}
},
};
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 { ApiHandler, Logger } from '..';
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 { 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 {
WorkerReady,
WorkerReceivePayload,
@ -23,10 +23,10 @@ import type { BaseClientOptions, ServicesOptions, StartOptions } from './base';
import { BaseClient } from './base';
import type { Client, ClientOptions } from './client';
import { Collectors } from './collectors';
import { type ClientUserStructure, Transformers } from './transformers';
import { MemberUpdateHandler } from '../websocket/discord/events/memberUpdate';
import { PresenceUpdateHandler } from '../websocket/discord/events/presenceUpdate';
import { Collectors } from './collectors';
import { type ClientUserStructure, Transformers } from './transformers';
let workerData: WorkerData;
let manager: import('node:worker_threads').MessagePort;
@ -42,7 +42,9 @@ try {
totalShards: Number(process.env.SEYFERT_WORKER_TOTALSHARDS),
mode: process.env.SEYFERT_WORKER_MODE,
} as WorkerData;
} catch {}
} catch {
//
}
export class WorkerClient<Ready extends boolean = boolean> extends BaseClient {
private __handleGuilds?: Set<string> = new Set();
@ -287,7 +289,7 @@ export class WorkerClient<Ready extends boolean = boolean> extends BaseClient {
break;
case 'EXECUTE_EVAL':
{
let result;
let result: unknown;
try {
result = await eval(`
(${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();
this.postMessage({
type: 'EVAL',
@ -389,45 +391,51 @@ export class WorkerClient<Ready extends boolean = boolean> extends BaseClient {
default: {
switch (packet.t) {
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;
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;
case 'READY':
if (!this.__handleGuilds) this.__handleGuilds = new Set();
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.me = Transformers.ClientUser(this, packet.d.user, packet.d.application) as never;
await this.events?.execute(packet.t as never, packet, this, shardId);
if ([...this.shards.values()].every(shard => shard.data.session_id)) {
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.__handleGuilds) this.__handleGuilds = new Set();
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.me = Transformers.ClientUser(this, packet.d.user, packet.d.application) as never;
await this.events?.execute(packet.t as never, packet, this, shardId);
if ([...this.shards.values()].every(shard => shard.data.session_id)) {
this.postMessage({
type: 'WORKER_READY',
type: 'WORKER_SHARDS_CONNECTED',
workerId: this.workerId,
} as WorkerReady);
await this.events?.runEvent('WORKER_READY', this, this.me, -1);
} as WorkerShardsConnected);
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;
default:
await this.events?.execute(packet.t as never, packet, this, shardId);

View File

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

View File

@ -1,4 +1,3 @@
import { ApplicationCommandOptionType, type APIApplicationCommandOptionChoice, type ChannelType } from '../../types';
import type {
AutocompleteCallback,
EntryPointContext,
@ -7,13 +6,14 @@ import type {
ReturnOptionsTypes,
__TypesWrapper,
} from '..';
import type { MessageCommandInteraction, UserCommandInteraction } from '../../structures';
import type { CommandContext } from './chatcontext';
import type { MiddlewareContext } from './shared';
import type { ModalContext } from '../../components';
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'> & {
autocomplete?: AutocompleteCallback;

View File

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

View File

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

View File

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

View File

@ -1,23 +1,23 @@
import {
type APIApplicationCommandOption,
Locale,
type LocaleString,
ApplicationCommandOptionType,
type APIApplicationCommandIntegerOption,
type APIApplicationCommandStringOption,
type APIApplicationCommandSubcommandOption,
type APIApplicationCommandSubcommandGroupOption,
type APIApplicationCommandChannelOption,
type LocalizationMap,
} from '../types';
import { promises } from 'node:fs';
import { basename, dirname } from 'node:path';
import type { EntryPointCommand } from '.';
import type { Logger, MakeRequired, NulleableCoalising, OmitInsert } 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 { ContextMenuCommand } from './applications/menu';
import type { UsingClient } from './applications/shared';
import { promises } from 'node:fs';
import type { EntryPointCommand } from '.';
export class CommandHandler extends BaseHandler {
values: (Command | ContextMenuCommand)[] = [];
@ -97,26 +97,29 @@ export class CommandHandler extends BaseHandler {
return option.channel_types.some(ct => !cached.channel_types!.includes(ct));
}
}
return;
break;
case ApplicationCommandOptionType.Subcommand:
case ApplicationCommandOptionType.SubcommandGroup:
if (
option.options?.length !==
(cached as APIApplicationCommandSubcommandOption | APIApplicationCommandSubcommandGroupOption).options?.length
) {
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;
{
if (
option.options?.length !==
(cached as APIApplicationCommandSubcommandOption | APIApplicationCommandSubcommandGroupOption).options
?.length
) {
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;
case ApplicationCommandOptionType.Integer:
case ApplicationCommandOptionType.Number:
@ -210,7 +213,7 @@ export class CommandHandler extends BaseHandler {
set(commands: SeteableCommand[]) {
this.values ??= [];
for (const command of commands) {
let commandInstance;
let commandInstance: Command | undefined;
try {
commandInstance = this.onCommand(command) as Command;
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 }))) {
if (!commands) continue;
for (const command of commands) {
let commandInstance;
let commandInstance: ReturnType<typeof this.onCommand>;
try {
commandInstance = this.onCommand(command);
if (!commandInstance) continue;
@ -277,7 +280,7 @@ export class CommandHandler extends BaseHandler {
const subCommand = this.onSubCommand(fileSubCommand as HandleableSubCommand);
if (subCommand && subCommand instanceof SubCommand) {
subCommand.__filePath = option;
commandInstance.options.push(subCommand);
commandInstance.options!.push(subCommand);
} else {
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.
*/
export class Formatter {
export const Formatter = {
/**
* Formats a code block.
* @param content The content of the code block.
* @param language The language of the code block. Defaults to 'txt'.
* @returns The formatted code block.
*/
static codeBlock(content: string, language = 'txt'): string {
codeBlock(content: string, language = 'txt'): string {
return `\`\`\`${language}\n${content}\n\`\`\``;
}
},
/**
* Formats content into inline code.
* @param content The content to format.
* @returns The formatted content.
*/
static inlineCode(content: string): `\`${string}\`` {
inlineCode(content: string): `\`${string}\`` {
return `\`${content}\``;
}
},
/**
* Formats content into bold text.
* @param content The content to format.
* @returns The formatted content.
*/
static bold(content: string): `**${string}**` {
bold(content: string): `**${string}**` {
return `**${content}**`;
}
},
/**
* Formats content into italic text.
* @param content The content to format.
* @returns The formatted content.
*/
static italic(content: string): `*${string}*` {
italic(content: string): `*${string}*` {
return `*${content}*`;
}
},
/**
* Formats content into underlined text.
* @param content The content to format.
* @returns The formatted content.
*/
static underline(content: string): `__${string}__` {
underline(content: string): `__${string}__` {
return `__${content}__`;
}
},
/**
* Formats content into strikethrough text.
* @param content The content to format.
* @returns The formatted content.
*/
static strikeThrough(content: string): `~~${string}~~` {
strikeThrough(content: string): `~~${string}~~` {
return `~~${content}~~`;
}
},
/**
* Formats content into a hyperlink.
@ -125,36 +125,36 @@ export class Formatter {
* @param url The URL to hyperlink to.
* @returns The formatted content.
*/
static hyperlink(content: string, url: string): `[${string}](${string})` {
hyperlink(content: string, url: string): `[${string}](${string})` {
return `[${content}](${url})`;
}
},
/**
* Formats content into a spoiler.
* @param content The content to format.
* @returns The formatted content.
*/
static spoiler(content: string): `||${string}||` {
spoiler(content: string): `||${string}||` {
return `||${content}||`;
}
},
/**
* Formats content into a quote.
* @param content The content to format.
* @returns The formatted content.
*/
static blockQuote(content: string): string {
blockQuote(content: string): string {
return `>>> ${content}`;
}
},
/**
* Formats content into a quote.
* @param content The content to format.
* @returns The formatted content.
*/
static quote(content: string): string {
quote(content: string): string {
return `> ${content}`;
}
},
/**
* Formats a message link.
@ -163,9 +163,9 @@ export class Formatter {
* @param messageId The ID of the message.
* @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}`;
}
},
/**
* Formats a header.
@ -173,9 +173,9 @@ export class Formatter {
* @param level The level of the header. Defaults to 1.
* @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}`;
}
},
/**
* Formats a list.
@ -183,13 +183,13 @@ export class Formatter {
* @param ordered Whether the list is ordered. Defaults to false.
* @returns The formatted list.
*/
static list(items: string[], ordered = false): string {
list(items: string[], ordered = false): string {
return items
.map((item, index) => {
return (ordered ? `${index + 1}. ` : '- ') + item;
})
.join('\n');
}
},
/**
* 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'.
* @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}>`;
}
},
/**
* Formats a user mention.
* @param userId The ID of the user to mention.
* @returns The formatted user mention.
*/
static userMention(userId: string): `<@${string}>` {
userMention(userId: string): `<@${string}>` {
return `<@${userId}>`;
}
},
/**
* Formats a role mention.
* @param roleId The ID of the role to mention.
* @returns The formatted role mention.
*/
static roleMention(roleId: string): `<@&${string}>` {
roleMention(roleId: string): `<@&${string}>` {
return `<@&${roleId}>`;
}
},
/**
* Formats a channel mention.
* @param channelId The ID of the channel to mention.
* @returns The formatted channel mention.
*/
static channelMention(channelId: string): `<#${string}>` {
channelMention(channelId: string): `<#${string}>` {
return `<#${channelId}>`;
}
},
/**
* Formats an emoji.
@ -234,9 +234,9 @@ export class Formatter {
* @param animated Whether the emoji is animated. Defaults to false.
* @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}>`;
}
},
/**
* Formats a channel link.
@ -244,7 +244,7 @@ export class Formatter {
* @param guildId The ID of the guild. Defaults to '@me'.
* @returns The formatted channel link.
*/
static channelLink(channelId: string, guildId?: string) {
channelLink(channelId: string, guildId?: string) {
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 { bgBrightWhite, black, bold, brightBlack, cyan, gray, italic, red, stripColor, yellow } from './colors';
import { MergeOptions } from './utils';
@ -53,7 +53,7 @@ export class Logger {
static async clearLogs() {
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));
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];
}
}
@ -126,7 +126,7 @@ export class Logger {
if (!this.active) return;
if (level < this.level) return;
let log;
let log: unknown[] | undefined;
if (Logger.__callback) {
log = Logger.__callback(this, level, args);

View File

@ -1,17 +1,17 @@
import { promises } from 'node:fs';
import { basename, join } from 'node:path';
import {
type ColorResolvable,
DiscordEpoch,
EmbedColors,
type EmojiResolvable,
type TypeArray,
type ColorResolvable,
type Logger,
type ObjectToLower,
type ObjectToSnake,
type TypeArray,
} from '..';
import { type APIPartialEmoji, FormattingPatterns } from '../../types';
import type { Cache } from '../../cache';
import { type APIPartialEmoji, FormattingPatterns } from '../../types';
/**
* 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 {
switch (typeof color) {
case 'string':
case 'string': {
if (color === 'Random') return Math.floor(Math.random() * (0xffffff + 1));
if (color.startsWith('#')) return Number.parseInt(color.slice(1), 16);
if (color in EmbedColors) return EmbedColors[color as keyof typeof EmbedColors];
return EmbedColors.Default;
}
case 'number':
return color;
case 'object':
@ -82,7 +83,7 @@ export function MergeOptions<T>(defaults: any, ...options: any[]): T {
...Object.fromEntries(
Object.entries(defaults).map(([key, value]) => [
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':
result[ReplaceRegex.snake(key)] = value;
break;
case 'object':
case 'object': {
if (Array.isArray(value)) {
result[ReplaceRegex.snake(key)] = value.map(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);
break;
}
}
}
return result as ObjectToSnake<Obj>;
@ -235,7 +237,7 @@ export function toCamelCase<Obj extends Record<string, any>>(target: Obj): Objec
case 'undefined':
result[ReplaceRegex.camel(key)] = value;
break;
case 'object':
case 'object': {
if (Array.isArray(value)) {
result[ReplaceRegex.camel(key)] = value.map(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);
break;
}
}
}
return result as ObjectToLower<Obj>;
@ -291,6 +294,8 @@ export function lazyLoadPackage<T>(mod: string): T | undefined {
try {
return require(mod);
} catch (e) {
// biome-ignore lint/suspicious/noConsoleLog:
// biome-ignore lint/suspicious/noConsole:
console.log(`Cannot import ${mod}`, e);
return;
}

View File

@ -1,3 +1,4 @@
import { type GuildBanStructure, Transformers } from '../../client/transformers';
import type {
APIBan,
RESTGetAPIGuildBansQuery,
@ -5,7 +6,6 @@ import type {
RESTPutAPIGuildBanJSONBody,
} from '../../types';
import { BaseShorter } from './base';
import { Transformers } from '../../client/transformers';
export class BanShorter extends BaseShorter {
/**
@ -50,7 +50,7 @@ export class BanShorter extends BaseShorter {
* @returns A Promise that resolves to the fetched ban.
*/
async fetch(guildId: string, userId: string, force = false) {
let ban;
let ban: APIBan | GuildBanStructure | undefined;
if (!force) {
ban = await this.client.cache.bans?.get(userId, guildId);
if (ban) return ban;
@ -69,7 +69,7 @@ export class BanShorter extends BaseShorter {
* @returns A Promise that resolves to an array of listed bans.
*/
async list(guildId: string, query?: RESTGetAPIGuildBansQuery, force = false) {
let bans;
let bans: APIBan[] | GuildBanStructure[];
if (!force) {
bans = (await this.client.cache.bans?.values(guildId)) ?? [];
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 {
APIChannel,
APIGuildChannel,
RESTGetAPIChannelMessagesQuery,
RESTPatchAPIChannelJSONBody,
RESTPostAPIChannelThreadsJSONBody,
RESTPostAPIGuildForumThreadsJSONBody,
APIGuildChannel,
} 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 { MergeOptions } from '../it/utils';
import type { MakeRequired } from '../types/util';
import { BaseShorter } from './base';
export class ChannelShorter extends BaseShorter {
/**
@ -26,7 +28,7 @@ export class ChannelShorter extends BaseShorter {
}
async raw(id: string, force?: boolean): Promise<APIChannel> {
let channel;
let channel: APIChannel | ReturnType<Channels['raw']>;
if (!force) {
channel = await this.client.cache.channels?.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();
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) {
const roleOverwrites = [];
let memberOverwrites;
let everyoneOverwrites;
const roleOverwrites: ReturnType<Overwrites['get']> = [];
let memberOverwrites: NonNullable<ReturnType<Overwrites['get']>>[number] | undefined;
let everyoneOverwrites: NonNullable<ReturnType<Overwrites['get']>>[number] | undefined;
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 { type GuildEmojiStructure, Transformers } from '../../client/transformers';
import type { APIEmoji, RESTPatchAPIGuildEmojiJSONBody, RESTPostAPIGuildEmojiJSONBody } from '../../types';
import type { ImageResolvable } from '../types/resolvables';
import type { OmitInsert } from '../types/util';
import { BaseShorter } from './base';
import { Transformers } from '../../client/transformers';
export class EmojiShorter extends BaseShorter {
/**
@ -13,7 +13,7 @@ export class EmojiShorter extends BaseShorter {
* @returns A Promise that resolves to an array of emojis.
*/
async list(guildId: string, force = false) {
let emojis;
let emojis: APIEmoji[] | GuildEmojiStructure[];
if (!force) {
emojis = (await this.client.cache.emojis?.values(guildId)) ?? [];
if (emojis.length) {
@ -53,7 +53,7 @@ export class EmojiShorter extends BaseShorter {
* @returns A Promise that resolves to the fetched emoji.
*/
async fetch(guildId: string, emojiId: string, force = false) {
let emoji;
let emoji: APIEmoji | GuildEmojiStructure | undefined;
if (!force) {
emoji = await this.client.cache.emojis?.get(emojiId);
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 {
APIChannel,
APISticker,
GuildWidgetStyle,
RESTGetAPICurrentUserGuildsQuery,
RESTPatchAPIAutoModerationRuleJSONBody,
@ -11,10 +16,7 @@ import type {
RESTPostAPIGuildChannelJSONBody,
RESTPostAPIGuildsJSONBody,
} from '../../types';
import { resolveFiles } from '../../builders';
import { BaseChannel, channelFrom, Guild, GuildMember, type CreateStickerBodyRequest } from '../../structures';
import { BaseShorter } from './base';
import { type GuildStructure, Transformers } from '../../client/transformers';
export class GuildShorter extends BaseShorter {
/**
@ -108,7 +110,7 @@ export class GuildShorter extends BaseShorter {
* @returns A Promise that resolves to an array of channels.
*/
list: async (guildId: string, force = false) => {
let channels;
let channels: ReturnType<Channels['values']> | APIChannel[];
if (!force) {
channels = (await this.client.cache.channels?.values(guildId)) ?? [];
if (channels.length) {
@ -131,7 +133,7 @@ export class GuildShorter extends BaseShorter {
* @returns A Promise that resolves to the fetched channel.
*/
fetch: async (guildId: string, channelId: string, force?: boolean) => {
let channel;
let channel: APIChannel | ReturnType<Channels['get']>;
if (!force) {
channel = await this.client.cache.channels?.get(channelId);
if (channel) return channel;
@ -328,7 +330,7 @@ export class GuildShorter extends BaseShorter {
* @returns A Promise that resolves to the fetched sticker.
*/
fetch: async (guildId: string, stickerId: string, force = false) => {
let sticker;
let sticker: APISticker | StickerStructure | undefined;
if (!force) {
sticker = await this.client.cache.stickers?.get(stickerId);
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 {
type APIGuildMember,
FormattingPatterns,
type RESTGetAPIGuildMembersQuery,
type RESTGetAPIGuildMembersSearchQuery,
type RESTPatchAPIGuildMemberJSONBody,
type RESTPutAPIGuildBanJSONBody,
type RESTPutAPIGuildMemberJSONBody,
FormattingPatterns,
} from '../../types';
import { PermissionsBitField } from '../../structures/extra/Permissions';
import type { GuildMemberResolvable } from '../types/resolvables';
import { BaseShorter } from './base';
import { Transformers, type VoiceStateStructure } from '../../client/transformers';
export class MemberShorter extends BaseShorter {
/**
@ -37,7 +37,7 @@ export class MemberShorter extends BaseShorter {
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;
}
@ -142,7 +142,7 @@ export class MemberShorter extends BaseShorter {
}
async raw(guildId: string, memberId: string, force = false) {
let member;
let member: APIGuildMember | undefined;
if (!force) {
member = await this.client.cache.members?.raw(memberId, guildId);
if (member) return member;
@ -161,7 +161,7 @@ export class MemberShorter extends BaseShorter {
* @returns A Promise that resolves to an array of listed members.
*/
async list(guildId: string, query?: RESTGetAPIGuildMembersQuery, force = false) {
let members;
let members: APIGuildMember[] | GuildMemberStructure[];
if (!force) {
members = (await this.client.cache.members?.values(guildId)) ?? [];
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 {
APIWebhook,
RESTPatchAPIWebhookJSONBody,
RESTPatchAPIWebhookWithTokenJSONBody,
RESTPostAPIChannelWebhookJSONBody,
RESTPostAPIWebhookWithTokenJSONBody,
} from '../../types';
import { resolveFiles } from '../../builders';
import {
MessagesMethods,
type MessageWebhookMethodEditParams,
type MessageWebhookMethodWriteParams,
} from '../../structures';
import { BaseShorter } from './base';
import { Transformers } from '../../client/transformers';
export class WebhookShorter extends BaseShorter {
async create(channelId: string, body: RESTPostAPIChannelWebhookJSONBody) {
@ -64,7 +65,7 @@ export class WebhookShorter extends BaseShorter {
* @returns A Promise that resolves to the fetched webhook.
*/
async fetch(webhookId: string, token?: string) {
let webhook;
let webhook: APIWebhook;
if (token) {
webhook = await this.client.proxy.webhooks(webhookId)(token).get({ auth: false });
} else {

View File

@ -4,6 +4,6 @@ import type { UsingClient } from '../../commands';
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>>;
// eslint-disable-next-line @typescript-eslint/ban-types
//biome-ignore lint/complexity/noBannedTypes:
export type PartialClass<T> = PartialAvoid<Function, T>;
export type AtLeastOne<

View File

@ -2,7 +2,7 @@ import type { ComponentCallback, ListenerOptions, ModalSubmitCallback } from '..
import { LimitedCollection } from '../collection';
import { BaseCommand, type RegisteredMiddlewares, type UsingClient } from '../commands';
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 { ComponentCommand, InteractionCommandType } from './componentcommand';
import type { ComponentContext } from './componentcontext';
@ -165,7 +165,7 @@ export class ComponentHandler extends BaseHandler {
set(instances: (new () => ComponentCommands)[]) {
for (const i of instances) {
let component;
let component: ReturnType<typeof this.callback>;
try {
component = this.callback(i);
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 }))) {
if (!components) continue;
for (const value of components) {
let component;
let component: ReturnType<typeof this.callback>;
try {
component = this.callback(value);
if (!component) continue;

View File

@ -36,7 +36,7 @@ export function componentFactory(
component: APIMessageActionRowComponent,
): ActionRowMessageComponents | BaseComponent<ActionRowMessageComponents['type']> {
switch (component.type) {
case ComponentType.Button:
case ComponentType.Button: {
if (component.style === ButtonStyle.Link) {
return new LinkButtonComponent(component);
}
@ -44,6 +44,7 @@ export function componentFactory(
return new SKUButtonComponent(component);
}
return new ButtonComponent(component);
}
case ComponentType.ChannelSelect:
return new ChannelSelectMenuComponent(component);
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
export type TypeClass<InstanceType = {}, StaticType = {}> = (abstract new (
export type TypeClass<InstanceType = object, StaticType = object> = (abstract new (
...args: any[]
) => InstanceType) &
StaticType;

View File

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

View File

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

View File

@ -6,6 +6,7 @@ import {
type APIChatInputApplicationCommandInteraction,
type APIChatInputApplicationCommandInteractionData,
type APICommandAutocompleteInteractionResponseCallbackData,
type APIEntryPointCommandInteraction,
type APIInteraction,
type APIInteractionResponse,
type APIInteractionResponseChannelMessageWithSource,
@ -31,24 +32,28 @@ import {
ApplicationCommandType,
ComponentType,
type GatewayInteractionCreateDispatchData,
type InteractionCallbackData,
type InteractionCallbackResourceActivity,
InteractionResponseType,
InteractionType,
type MessageFlags,
type RESTPostAPIInteractionCallbackJSONBody,
type RESTAPIAttachment,
type APIEntryPointCommandInteraction,
type InteractionCallbackData,
type InteractionCallbackResourceActivity,
type RESTPostAPIInteractionCallbackJSONBody,
} from '../types';
import type { RawFile } from '../api';
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 ObjectToLower,
type OmitInsert,
type ToClass,
type When,
type ComponentInteractionMessageUpdate,
type InteractionCreateBodyRequest,
type InteractionMessageUpdateBodyRequest,
@ -56,22 +61,17 @@ import {
type MessageUpdateBodyRequest,
type MessageWebhookCreateBodyRequest,
type ModalCreateBodyRequest,
type ObjectToLower,
type OmitInsert,
type ToClass,
type When,
toCamelCase,
} 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 { 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 =
| { 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?: false): string | undefined;
getInputValue(customId: string, required?: boolean): string | undefined {
let value;
let value: string | undefined;
for (const { components } of this.components) {
const get = components.find(x => x.customId === customId);
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 { ActionRow, Embed, PollBuilder, resolveAttachment } from '../builders';
import {
type BaseChannelStructure,
type BaseGuildChannelStructure,
@ -56,7 +16,47 @@ import {
Transformers,
type VoiceChannelStructure,
} 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 {
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>> {
declare type: T;
@ -189,7 +189,7 @@ export class BaseGuildChannel extends BaseChannel<ChannelType> {
permissionOverwrites = {
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) {
@ -333,11 +333,12 @@ export function channelFrom(data: APIChannelBase<ChannelType>, client: UsingClie
return Transformers.CategoryChannel(client, data);
case ChannelType.GuildAnnouncement:
return Transformers.NewsChannel(client, data);
default:
default: {
if ('guild_id' in data) {
return Transformers.BaseGuildChannel(client, data as APIGuildChannel<ChannelType>);
}
return Transformers.BaseChannel(client, data);
}
}
}

View File

@ -60,11 +60,12 @@ export class BitField<T extends object> {
return this.resolve(this.Flags[bits]);
case 'bigint':
return bits;
case 'object':
case 'object': {
if (!Array.isArray(bits)) {
throw new TypeError(`Cannot resolve permission: ${bits}`);
}
return bits.map(x => this.resolve(x)).reduce((acc, cur) => acc | cur, BitField.None);
}
default:
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}
*/
// biome-ignore lint/correctness/noUndeclaredVariables: biome bug lol
Twitter = X,
Xbox = 'xbox',
YouTube = 'youtube',

View File

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

View File

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

View File

@ -1,18 +1,19 @@
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 { DynamicBucket } from '../structures';
import { ConnectTimeout } from '../structures/timeout';
import { BaseSocket } from './basesocket';
import type { ShardData, ShardOptions } from './shared';
import { ShardSocketCloseCodes } from './shared';
import {
type GatewaySendPayload,
type GatewayReceivePayload,
GatewayCloseCodes,
GatewayDispatchEvents,
GatewayOpcodes,
} from '../../types';
export interface ShardHeart {
interval: number;
@ -229,8 +230,10 @@ export class Shard {
}
break;
case GatewayOpcodes.HeartbeatAck:
this.heart.ack = true;
this.heart.lastAck = Date.now();
{
this.heart.ack = true;
this.heart.lastAck = Date.now();
}
break;
case GatewayOpcodes.Heartbeat:
this.heartbeat(true);
@ -254,8 +257,10 @@ export class Shard {
{
switch (packet.t) {
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;
case GatewayDispatchEvents.Ready: {
this.data.resume_gateway_url = packet.d.resume_gateway_url;
@ -288,10 +293,12 @@ export class Shard {
case GatewayCloseCodes.UnknownOpcode:
case GatewayCloseCodes.InvalidSeq:
case GatewayCloseCodes.SessionTimedOut:
this.data.resume_seq = 0;
this.data.session_id = undefined;
this.data.resume_gateway_url = undefined;
await this.reconnect();
{
this.data.resume_seq = 0;
this.data.session_id = undefined;
this.data.resume_gateway_url = undefined;
await this.reconnect();
}
break;
case 1001:
case 1006:
@ -301,8 +308,10 @@ export class Shard {
case GatewayCloseCodes.NotAuthenticated:
case GatewayCloseCodes.AlreadyAuthenticated:
case GatewayCloseCodes.RateLimited:
this.logger.info('Trying to reconnect');
await this.reconnect();
{
this.logger.info('Trying to reconnect');
await this.reconnect();
}
break;
case GatewayCloseCodes.AuthenticationFailed:
@ -315,8 +324,10 @@ export class Shard {
break;
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;
}
}
@ -331,7 +342,7 @@ export class Shard {
}
protected handleMessage(data: string | Buffer) {
let packet;
let packet: GatewayDispatchPayload;
try {
if (data instanceof Buffer) {
data = inflateSync(data);

View File

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

View File

@ -1,10 +1,10 @@
import type { Awaitable, DeepPartial, Logger } from '../../common';
import type {
APIGatewayBotInfo,
GatewayDispatchPayload,
GatewayIntentBits,
GatewayPresenceUpdateData,
} from '../../types';
import type { Awaitable, DeepPartial, Logger } from '../../common';
import type { IdentifyProperties } from '../constants';
export interface ShardManagerOptions extends ShardDetails {
@ -79,7 +79,7 @@ export interface WorkerManagerOptions extends Omit<ShardManagerOptions, 'handleP
path: string;
handlePayload(shardId: number, workerId: number, packet: GatewayDispatchPayload): unknown;
handlePayload?(shardId: number, workerId: number, packet: GatewayDispatchPayload): any;
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 type { Socket } from 'node:net';
@ -179,7 +179,7 @@ export class SeyfertWebSocket {
private _write(buffer: Buffer, opcode: number) {
if (!this.socket?.writable) return;
const length = buffer.length;
let frame;
let frame: Buffer;
// Kinda same logic as above, but client-side
if (length < 126) {
frame = Buffer.allocUnsafe(6 + length);
@ -200,17 +200,29 @@ export class SeyfertWebSocket {
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) {
this.__closeCalled = true;
@ -299,7 +311,7 @@ export class SeyfertWebSocket {
// actual index of the buffer to read
let blockIndex = readable.bufferIndex;
// Buffer to read
let block;
let block: Buffer | undefined;
while ((block = readable.buffer[blockIndex++])) {
for (let i = 0; i < block.length; i++) {
if (++bitIndex > start) {

View File

@ -10,7 +10,7 @@ export interface 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;
workerId: number;
} & D;

View File

@ -1,10 +1,10 @@
import type { GatewayPresenceUpdateData, GatewaySendPayload } from '../../types';
import cluster, { type Worker as ClusterWorker } from 'node:cluster';
import { randomUUID } from 'node:crypto';
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 { 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 { DynamicBucket } from '../structures';
import { ConnectQueue } from '../structures/timeout';
@ -181,11 +181,12 @@ export class WorkerManager extends Map<
worker.on('message', data => this.handleWorkerMessage(data));
return worker;
}
case 'custom':
case 'custom': {
this.options.adapter!.spawn(workerData, env);
return {
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<
'ALLOW_CONNECT',