Compare commits

..

No commits in common. "main" and "v3.1.0" have entirely different histories.
main ... v3.1.0

102 changed files with 1295 additions and 1170 deletions

View File

@ -12,10 +12,8 @@ jobs:
permissions: permissions:
id-token: write id-token: write
if: github.repository == 'tiramisulabs/seyfert' if: github.repository == 'tiramisulabs/seyfert'
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
steps: steps:
- name: Check out code - name: check out code
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Install Node - name: Install Node
@ -31,13 +29,12 @@ jobs:
- name: Install dependencies - name: Install dependencies
run: pnpm install --frozen-lockfile run: pnpm install --frozen-lockfile
- name: Verify npm token
run: npm whoami
- name: Publish dev tag - name: Publish dev tag
id: publish id: publish
run: | run: |
new_version=$(npm version prerelease --preid dev-${{github.run_id}} --no-git-tag-version) new_version=$(npm version prerelease --preid dev-${{github.run_id}} --no-git-tag-version)
echo "New version: $new_version" echo "New version: $new_version"
npm config set //registry.npmjs.org/:_authToken ${NODE_AUTH_TOKEN} npm config set //registry.npmjs.org/:_authToken ${NODE_AUTH_TOKEN}
npm publish --provenance --tag=dev npm publish --provenance --tag=dev
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

80
.github/workflows/releases.yml vendored Normal file
View File

@ -0,0 +1,80 @@
name: Create Release
on:
push:
branches:
- build
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: check out code
uses: actions/checkout@v4
with:
ref: ${{ github.ref }}
- name: Install Node
uses: actions/setup-node@v4
with:
node-version: '20.x'
registry-url: 'https://registry.npmjs.org'
- uses: pnpm/action-setup@v4
with:
version: 9
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Build project
run: pnpm run build
- name: Get version from package.json
id: get_version
run: echo "::set-output name=version::$(node -p "require('./package.json').version")"
- name: Set repository variable
run: echo "REPO=${{ github.repository }}" >> $GITHUB_ENV
- name: Get and format commits
run: |
last_tag=$(git tag --sort=-v:refname | head -n 1)
if [ -z "$last_tag" ]; then
git log --pretty=format:"%h - %s" > commits.txt
else
git log ${last_tag}..HEAD --pretty=format:"%h - %s" > commits.txt
fi
sed -e "s|^\([a-f0-9]\+\) - \(.*\)|- [\1](https://github.com/$REPO/commit/\1) - \2|" commits.txt > formatted_commits.txt
echo "Changes in this release:" > release_body.txt
cat formatted_commits.txt >> release_body.txt
- name: Create tag
run: |
git tag v${{ steps.get_version.outputs.version }}
git push origin v${{ steps.get_version.outputs.version }}
- name: Create Release
id: create_release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: v${{ steps.get_version.outputs.version }}
release_name: Release v${{ steps.get_version.outputs.version }}
body_path: release_body.txt
draft: false
prerelease: false
- name: Zip dist folder
run: zip -r dist.zip src
- name: Upload Release Asset
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./dist.zip
asset_name: dist.zip
asset_content_type: application/zip

View File

@ -1 +1 @@
npx biome check --write npx lint-staged

View File

@ -1,5 +1,5 @@
{ {
"$schema": "https://biomejs.dev/schemas/2.0.0/schema.json", "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
"vcs": { "vcs": {
"enabled": true, "enabled": true,
"clientKind": "git", "clientKind": "git",
@ -8,16 +8,7 @@
}, },
"files": { "files": {
"ignoreUnknown": true, "ignoreUnknown": true,
"includes": [ "ignore": ["node_modules/", "build", "lib", "__test__", "package.json", "tsconfig.json", ".vscode"]
"**/src/**",
"!/node_modules/",
"!/build",
"!/lib",
"!/__test__",
"!/package.json",
"!/tsconfig.json",
"!/.vscode"
]
}, },
"formatter": { "formatter": {
"enabled": true, "enabled": true,
@ -27,17 +18,14 @@
"lineEnding": "crlf", "lineEnding": "crlf",
"formatWithErrors": true "formatWithErrors": true
}, },
"assist": { "organizeImports": {
"actions": { "enabled": true
"source": {
"organizeImports": "on"
}
}
}, },
"linter": { "linter": {
"enabled": true, "enabled": true,
"rules": { "rules": {
"recommended": false, "recommended": false,
"all": true,
"security": { "security": {
"noGlobalEval": "off" "noGlobalEval": "off"
}, },
@ -53,7 +41,9 @@
}, },
"correctness": { "correctness": {
"noNodejsModules": "off", "noNodejsModules": "off",
"useImportExtensions": "off" "useImportExtensions": "off",
"noUnusedFunctionParameters": "off",
"noUnusedVariables": "off"
}, },
"style": { "style": {
"noDefaultExport": "off", "noDefaultExport": "off",
@ -66,7 +56,8 @@
"noParameterAssign": "off", "noParameterAssign": "off",
"useFilenamingConvention": "off", "useFilenamingConvention": "off",
"useEnumInitializers": "off", "useEnumInitializers": "off",
"useExplicitLengthCheck": "off" "useExplicitLengthCheck": "off",
"noNamespaceImport": "off"
}, },
"complexity": { "complexity": {
"noForEach": "off", "noForEach": "off",
@ -78,8 +69,7 @@
"noBarrelFile": "off", "noBarrelFile": "off",
"noDelete": "off", "noDelete": "off",
"noReExportAll": "off", "noReExportAll": "off",
"useTopLevelRegex": "off", "useTopLevelRegex": "off"
"noNamespaceImport": "off"
} }
} }
}, },

View File

@ -1,6 +1,6 @@
{ {
"name": "seyfert", "name": "seyfert",
"version": "3.2.4", "version": "3.1.0",
"description": "The most advanced framework for discord bots", "description": "The most advanced framework for discord bots",
"main": "./lib/index.js", "main": "./lib/index.js",
"module": "./lib/index.js", "module": "./lib/index.js",
@ -21,14 +21,15 @@
"author": "MARCROCK22", "author": "MARCROCK22",
"license": "MIT", "license": "MIT",
"devDependencies": { "devDependencies": {
"@biomejs/biome": "2.0.0", "@biomejs/biome": "1.9.4",
"@changesets/cli": "^2.29.4", "@changesets/cli": "^2.28.1",
"@commitlint/cli": "^19.8.1", "@commitlint/cli": "^19.8.0",
"@commitlint/config-conventional": "^19.8.1", "@commitlint/config-conventional": "^19.8.0",
"@types/node": "^24.0.3", "@types/node": "^22.14.0",
"husky": "^9.1.7", "husky": "^9.1.7",
"typescript": "^5.8.3", "lint-staged": "^15.5.0",
"vitest": "^3.2.4" "typescript": "^5.8.2",
"vitest": "^3.1.1"
}, },
"homepage": "https://seyfert.dev", "homepage": "https://seyfert.dev",
"repository": { "repository": {
@ -64,6 +65,11 @@
"url": "https://github.com/Drylozu" "url": "https://github.com/Drylozu"
} }
], ],
"lint-staged": {
"*.ts": [
"biome check --write"
]
},
"pnpm": { "pnpm": {
"onlyBuiltDependencies": [ "onlyBuiltDependencies": [
"@biomejs/biome", "@biomejs/biome",

1311
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -71,7 +71,7 @@ export interface ApplicationRoutes {
patch( patch(
args: RestArguments<RESTPatchAPIApplicationGuildCommandJSONBody>, args: RestArguments<RESTPatchAPIApplicationGuildCommandJSONBody>,
): Promise<RESTPatchAPIApplicationGuildCommandResult>; ): Promise<RESTPatchAPIApplicationGuildCommandResult>;
delete(args?: RestArgumentsNoBody): Promise<undefined>; delete(args?: RestArgumentsNoBody): Promise<never>;
permissions: { permissions: {
get(args?: RestArgumentsNoBody): Promise<RESTGetAPIGuildApplicationCommandsPermissionsResult>; get(args?: RestArgumentsNoBody): Promise<RESTGetAPIGuildApplicationCommandsPermissionsResult>;
put( put(
@ -92,7 +92,7 @@ export interface ApplicationRoutes {
patch( patch(
args: RestArguments<RESTPatchAPIApplicationCommandJSONBody>, args: RestArguments<RESTPatchAPIApplicationCommandJSONBody>,
): Promise<RESTPatchAPIApplicationCommandResult>; ): Promise<RESTPatchAPIApplicationCommandResult>;
delete(args?: RestArgumentsNoBody): Promise<undefined>; delete(args?: RestArgumentsNoBody): Promise<never>;
}; };
}; };
'role-connections': { 'role-connections': {
@ -122,10 +122,10 @@ export interface ApplicationRoutes {
( (
id: string, id: string,
): { ): {
get(args?: RestArgumentsNoBody): Promise<RESTGetAPIEntitlementResult>; get(args?: RestArgumentsNoBody<never>): Promise<RESTGetAPIEntitlementResult>;
delete(args?: RestArgumentsNoBody): Promise<undefined>; delete(args?: RestArgumentsNoBody): Promise<never>;
consume: { consume: {
post(args?: RestArgumentsNoBody): Promise<undefined>; post(args?: RestArgumentsNoBody): Promise<never>;
}; };
}; };
}; };

View File

@ -190,7 +190,7 @@ export interface ChannelRoutes {
post(args: RestArguments<RESTPostAPIChannelWebhookJSONBody>): Promise<RESTPostAPIChannelWebhookResult>; post(args: RestArguments<RESTPostAPIChannelWebhookJSONBody>): Promise<RESTPostAPIChannelWebhookResult>;
}; };
'voice-status': { 'voice-status': {
put(args: RestArguments<{ status: string | null }>): Promise<undefined>; put(args: RestArguments<{ status: string | null }>): Promise<never>;
}; };
polls(messageId: string): { polls(messageId: string): {
answers(id: ValidAnswerId): { answers(id: ValidAnswerId): {
@ -201,7 +201,7 @@ export interface ChannelRoutes {
}; };
}; };
'send-soundboard-sound': { 'send-soundboard-sound': {
post(args: RestArguments<RESTPostAPISendSoundboardSound>): Promise<undefined>; post(args: RestArguments<RESTPostAPISendSoundboardSound>): Promise<never>;
}; };
}; };
} }

View File

@ -39,10 +39,10 @@ import type {
RESTGetAPIGuildRolesResult, RESTGetAPIGuildRolesResult,
RESTGetAPIGuildScheduledEventQuery, RESTGetAPIGuildScheduledEventQuery,
RESTGetAPIGuildScheduledEventResult, RESTGetAPIGuildScheduledEventResult,
RESTGetAPIGuildScheduledEventsQuery,
RESTGetAPIGuildScheduledEventsResult,
RESTGetAPIGuildScheduledEventUsersQuery, RESTGetAPIGuildScheduledEventUsersQuery,
RESTGetAPIGuildScheduledEventUsersResult, RESTGetAPIGuildScheduledEventUsersResult,
RESTGetAPIGuildScheduledEventsQuery,
RESTGetAPIGuildScheduledEventsResult,
RESTGetAPIGuildSoundboardSoundsResult, RESTGetAPIGuildSoundboardSoundsResult,
RESTGetAPIGuildStickerResult, RESTGetAPIGuildStickerResult,
RESTGetAPIGuildStickersResult, RESTGetAPIGuildStickersResult,
@ -107,12 +107,12 @@ import type {
RESTPostAPIGuildSoundboardSoundResult, RESTPostAPIGuildSoundboardSoundResult,
RESTPostAPIGuildStickerFormDataBody, RESTPostAPIGuildStickerFormDataBody,
RESTPostAPIGuildStickerResult, RESTPostAPIGuildStickerResult,
RESTPostAPIGuildTemplatesJSONBody,
RESTPostAPIGuildTemplatesResult,
RESTPostAPIGuildsJSONBody, RESTPostAPIGuildsJSONBody,
RESTPostAPIGuildsMFAJSONBody, RESTPostAPIGuildsMFAJSONBody,
RESTPostAPIGuildsMFAResult, RESTPostAPIGuildsMFAResult,
RESTPostAPIGuildsResult, RESTPostAPIGuildsResult,
RESTPostAPIGuildTemplatesJSONBody,
RESTPostAPIGuildTemplatesResult,
RESTPostAPITemplateCreateGuildJSONBody, RESTPostAPITemplateCreateGuildJSONBody,
RESTPostAPITemplateCreateGuildResult, RESTPostAPITemplateCreateGuildResult,
RESTPutAPIGuildBanJSONBody, RESTPutAPIGuildBanJSONBody,
@ -361,7 +361,7 @@ export interface GuildRoutes {
patch( patch(
args?: RestArguments<RESTPatchAPIGuildSoundboardSound>, args?: RestArguments<RESTPatchAPIGuildSoundboardSound>,
): Promise<RESTPatchAPIGuildSoundboardSoundResult>; ): Promise<RESTPatchAPIGuildSoundboardSoundResult>;
delete(args?: RestArgumentsNoBody): Promise<undefined>; delete(args?: RestArgumentsNoBody): Promise<never>;
}; };
}; };
}; };

View File

@ -1,11 +1,11 @@
import { randomUUID, type UUID } from 'node:crypto'; import { type UUID, randomUUID } from 'node:crypto';
import { type Awaitable, BASE_HOST, delay, Logger, lazyLoadPackage, snowflakeToTimestamp } from '../common'; import { type Awaitable, BASE_HOST, Logger, delay, lazyLoadPackage, snowflakeToTimestamp } from '../common';
import { toArrayBuffer, toBuffer } from '../common/it/utils'; import { toArrayBuffer, toBuffer } from '../common/it/utils';
import type { WorkerData } from '../websocket'; import type { WorkerData } from '../websocket';
import type { WorkerSendApiRequest } from '../websocket/discord/worker'; import type { WorkerSendApiRequest } from '../websocket/discord/worker';
import { Bucket } from './bucket';
import { CDNRouter, Router } from './Router'; import { CDNRouter, Router } from './Router';
import type { APIRoutes } from './Routes'; import type { APIRoutes } from './Routes';
import { Bucket } from './bucket';
import { import {
type ApiHandlerInternalOptions, type ApiHandlerInternalOptions,
type ApiHandlerOptions, type ApiHandlerOptions,
@ -291,19 +291,17 @@ export class ApiHandler {
await this.onRatelimit?.(response, request); await this.onRatelimit?.(response, request);
const content = `${JSON.stringify(request)} `; const content = `${JSON.stringify(request)} `;
let retryAfter: number | undefined; let retryAfter =
const data = JSON.parse(result);
if (data.retry_after) retryAfter = Math.ceil(data.retry_after * 1000);
retryAfter ??=
Number(response.headers.get('x-ratelimit-reset-after') || response.headers.get('retry-after')) * 1000; Number(response.headers.get('x-ratelimit-reset-after') || response.headers.get('retry-after')) * 1000;
if (Number.isNaN(retryAfter)) { if (Number.isNaN(retryAfter)) {
this.debugger?.warn(`${route} Could not extract retry_after from 429 response. ${result}`); try {
next(); retryAfter = JSON.parse(result).retry_after * 1000;
reject(new Error('Could not extract retry_after from 429 response.')); } catch (err) {
return false; this.debugger?.warn(`Unexpected error: ${err}`);
reject(err);
return false;
}
} }
this.debugger?.info( this.debugger?.info(
@ -386,7 +384,11 @@ export class ApiHandler {
} }
} }
parseRequest(options: { url: string; headers: RequestHeaders; request: ApiRequestOptions }) { parseRequest(options: {
url: string;
headers: RequestHeaders;
request: ApiRequestOptions;
}) {
let finalUrl = options.url; let finalUrl = options.url;
let data: string | FormData | undefined; let data: string | FormData | undefined;
if (options.request.auth) { if (options.request.auth) {

View File

@ -1,4 +1,4 @@
export * from './api';
export * from './Router'; export * from './Router';
export * from './Routes'; export * from './Routes';
export * from './api';
export * from './shared'; export * from './shared';

View File

@ -1,6 +1,6 @@
import { type ActionRow, fromComponent } from '.';
import { type ColorResolvable, type RestOrArray, resolveColor } from '../common'; import { type ColorResolvable, type RestOrArray, resolveColor } from '../common';
import { type APIContainerComponent, ComponentType } from '../types'; import { type APIContainerComponent, ComponentType } from '../types';
import { type ActionRow, fromComponent } from '.';
import { BaseComponentBuilder } from './Base'; import { BaseComponentBuilder } from './Base';
import type { File } from './File'; import type { File } from './File';
import type { MediaGallery } from './MediaGallery'; import type { MediaGallery } from './MediaGallery';

View File

@ -1,6 +1,6 @@
import { type Button, fromComponent } from '.';
import type { RestOrArray } from '../common'; import type { RestOrArray } from '../common';
import { type APISectionComponent, ComponentType } from '../types'; import { type APISectionComponent, ComponentType } from '../types';
import { type Button, fromComponent } from '.';
import { BaseComponentBuilder } from './Base'; import { BaseComponentBuilder } from './Base';
import type { TextDisplay } from './TextDisplay'; import type { TextDisplay } from './TextDisplay';
import type { Thumbnail } from './Thumbnail'; import type { Thumbnail } from './Thumbnail';
@ -9,7 +9,7 @@ export class Section<
Ac extends Button | Thumbnail = Button | Thumbnail, Ac extends Button | Thumbnail = Button | Thumbnail,
> extends BaseComponentBuilder<APISectionComponent> { > extends BaseComponentBuilder<APISectionComponent> {
components: TextDisplay[]; components: TextDisplay[];
accessory?: Ac; accessory!: Ac;
constructor({ components, accessory, ...data }: Partial<APISectionComponent> = {}) { constructor({ components, accessory, ...data }: Partial<APISectionComponent> = {}) {
super({ type: ComponentType.Section, ...data }); super({ type: ComponentType.Section, ...data });
this.components = (components?.map(component => fromComponent(component)) ?? []) as TextDisplay[]; this.components = (components?.map(component => fromComponent(component)) ?? []) as TextDisplay[];
@ -46,7 +46,6 @@ export class Section<
* @returns The JSON representation of this section * @returns The JSON representation of this section
*/ */
toJSON() { toJSON() {
if (!this.accessory) throw new Error('Cannot convert to JSON without an accessory.');
return { return {
...this.data, ...this.data,
components: this.components.map(component => component.toJSON()), components: this.components.map(component => component.toJSON()),

View File

@ -161,7 +161,7 @@ export class RoleSelectMenu extends SelectMenu<APIRoleSelectComponent> {
} }
} }
export type MentionableDefaultElement = { id: string; type: keyof typeof SelectMenuDefaultValueType }; export type MentionableDefaultElement = { id: string; type: keyof Omit<typeof SelectMenuDefaultValueType, 'Channel'> };
/** /**
* Represents a Select Menu for selecting mentionable entities. * Represents a Select Menu for selecting mentionable entities.

View File

@ -1,4 +1,4 @@
import { type APITextDisplayComponent, ComponentType } from '../types'; import { type APITextDispalyComponent, ComponentType } from '../types';
import { BaseComponentBuilder } from './Base'; import { BaseComponentBuilder } from './Base';
/** /**
@ -9,12 +9,12 @@ import { BaseComponentBuilder } from './Base';
* const text = new TextDisplay().content('Hello, world!'); * const text = new TextDisplay().content('Hello, world!');
* ``` * ```
*/ */
export class TextDisplay extends BaseComponentBuilder<APITextDisplayComponent> { export class TextDisplay extends BaseComponentBuilder<APITextDispalyComponent> {
/** /**
* Constructs a new TextDisplay component. * Constructs a new TextDisplay component.
* @param data Optional initial data for the text display component. * @param data Optional initial data for the text display component.
*/ */
constructor(data: Partial<APITextDisplayComponent> = {}) { constructor(data: Partial<APITextDispalyComponent> = {}) {
super({ type: ComponentType.TextDisplay, ...data }); super({ type: ComponentType.TextDisplay, ...data });
} }

View File

@ -94,11 +94,7 @@ export class LimitedMemoryAdapter<T> implements Adapter {
} }
private __set(key: string, data: any) { private __set(key: string, data: any) {
const isArray = Array.isArray(data); const __guildId = Array.isArray(data) ? data[0].guild_id : data.guild_id;
if (isArray && data.length === 0) {
return;
}
const __guildId = isArray ? data[0].guild_id : data.guild_id;
const namespace = `${key.split('.')[0]}${__guildId ? `.${__guildId}` : ''}`; const namespace = `${key.split('.')[0]}${__guildId ? `.${__guildId}` : ''}`;
const self = this; const self = this;
if (!this.storage.has(namespace)) { if (!this.storage.has(namespace)) {

12
src/cache/index.ts vendored
View File

@ -1,5 +1,11 @@
import type { InternalOptions, UsingClient } from '../commands';
import { type If, Logger } from '../common'; import { type If, Logger } from '../common';
import type { Adapter } from './adapters';
import { Guilds } from './resources/guilds';
import { Users } from './resources/users';
import type { InternalOptions, UsingClient } from '../commands';
import { import {
type APIChannel, type APIChannel,
type APIEmoji, type APIEmoji,
@ -14,11 +20,9 @@ import {
GuildMemberFlags, GuildMemberFlags,
OverwriteType, OverwriteType,
} from '../types'; } from '../types';
import type { Adapter } from './adapters';
import { Bans } from './resources/bans'; 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 { Guilds } from './resources/guilds';
import { Members } from './resources/members'; import { Members } from './resources/members';
import { Messages } from './resources/messages'; import { Messages } from './resources/messages';
import { Overwrites } from './resources/overwrites'; import { Overwrites } from './resources/overwrites';
@ -26,9 +30,7 @@ import { Presences } from './resources/presence';
import { Roles } from './resources/roles'; import { Roles } from './resources/roles';
import { StageInstances } from './resources/stage-instances'; import { StageInstances } from './resources/stage-instances';
import { Stickers } from './resources/stickers'; import { Stickers } from './resources/stickers';
import { Users } from './resources/users';
import { VoiceStates } from './resources/voice-states'; import { VoiceStates } from './resources/voice-states';
export { BaseResource } from './resources/default/base'; export { BaseResource } from './resources/default/base';
export { GuildBasedResource } from './resources/default/guild-based'; export { GuildBasedResource } from './resources/default/guild-based';
export { GuildRelatedResource } from './resources/default/guild-related'; export { GuildRelatedResource } from './resources/default/guild-related';

View File

@ -1,7 +1,7 @@
import type { Cache, CacheFrom, ReturnCache } from '..';
import { type GuildStructure, Transformers } from '../../client/transformers'; import { type GuildStructure, Transformers } from '../../client/transformers';
import { fakePromise } from '../../common'; import { fakePromise } from '../../common';
import type { APIGuild, GatewayGuildCreateDispatchData } from '../../types'; import type { APIGuild, GatewayGuildCreateDispatchData } from '../../types';
import type { Cache, CacheFrom, ReturnCache } from '..';
import { BaseResource } from './default/base'; import { BaseResource } from './default/base';
export class Guilds extends BaseResource<any, APIGuild | GatewayGuildCreateDispatchData> { export class Guilds extends BaseResource<any, APIGuild | GatewayGuildCreateDispatchData> {

View File

@ -1,7 +1,5 @@
import { promises } from 'node:fs';
import { join } from 'node:path'; import { join } from 'node:path';
import { ApiHandler } from '../api'; import { ApiHandler } from '../api';
import { isBufferLike } from '../api/utils/utils';
import type { Adapter, DisabledCache } from '../cache'; import type { Adapter, DisabledCache } from '../cache';
import { Cache, MemoryAdapter } from '../cache'; import { Cache, MemoryAdapter } from '../cache';
import type { import type {
@ -18,31 +16,34 @@ import type {
UsingClient, UsingClient,
} from '../commands'; } from '../commands';
import { IgnoreCommand, type InferWithPrefix, type MiddlewareContext } from '../commands/applications/shared'; import { IgnoreCommand, type InferWithPrefix, type MiddlewareContext } from '../commands/applications/shared';
import { HandleCommand } from '../commands/handle';
import { CommandHandler } from '../commands/handler'; import { CommandHandler } from '../commands/handler';
import { import {
ApplicationShorter, ApplicationShorter,
assertString,
ChannelShorter, ChannelShorter,
EmojiShorter, EmojiShorter,
filterSplit,
GuildShorter, GuildShorter,
InteractionShorter, InteractionShorter,
InvitesShorter, InvitesShorter,
Logger,
LogLevels, LogLevels,
Logger,
type MakeRequired, type MakeRequired,
MemberShorter, MemberShorter,
MergeOptions, MergeOptions,
MessageShorter, MessageShorter,
magicImport,
ReactionShorter, ReactionShorter,
RoleShorter, RoleShorter,
TemplateShorter, TemplateShorter,
ThreadShorter, ThreadShorter,
UsersShorter, UsersShorter,
WebhookShorter, WebhookShorter,
assertString,
filterSplit,
magicImport,
} from '../common'; } from '../common';
import { promises } from 'node:fs';
import { isBufferLike } from '../api/utils/utils';
import { HandleCommand } from '../commands/handle';
import { BanShorter } from '../common/shorters/bans'; import { BanShorter } from '../common/shorters/bans';
import { SoundboardShorter } from '../common/shorters/soundboard'; import { SoundboardShorter } from '../common/shorters/soundboard';
import { VoiceStateShorter } from '../common/shorters/voiceStates'; import { VoiceStateShorter } from '../common/shorters/voiceStates';

View File

@ -1,17 +1,17 @@
import type { CommandContext, Message } from '..'; import type { CommandContext, Message } from '..';
import { import {
type Awaitable, type Awaitable,
assertString,
type DeepPartial, type DeepPartial,
type If, type If,
lazyLoadPackage,
type PickPartial, type PickPartial,
type WatcherPayload, type WatcherPayload,
type WatcherSendToShard, type WatcherSendToShard,
assertString,
lazyLoadPackage,
} from '../common'; } from '../common';
import { EventHandler } from '../events'; import { EventHandler } from '../events';
import type { GatewayDispatchPayload, GatewayPresenceUpdateData } from '../types'; import type { GatewayDispatchPayload, GatewayPresenceUpdateData } from '../types';
import { properties, ShardManager, type ShardManagerOptions } from '../websocket'; 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';
@ -219,8 +219,8 @@ export interface ClientOptions extends BaseClientOptions {
}; };
commands?: BaseClientOptions['commands'] & { commands?: BaseClientOptions['commands'] & {
prefix?: (message: MessageStructure) => Awaitable<string[]>; prefix?: (message: MessageStructure) => Awaitable<string[]>;
deferReplyResponse?: (ctx: CommandContext) => Awaitable<Parameters<Message['write']>[0]>; deferReplyResponse?: (ctx: CommandContext) => Parameters<Message['write']>[0];
reply?: (ctx: CommandContext) => Awaitable<boolean>; reply?: (ctx: CommandContext) => boolean;
}; };
handlePayload?: ShardManagerOptions['handlePayload']; handlePayload?: ShardManagerOptions['handlePayload'];
resharding?: PickPartial<NonNullable<ShardManagerOptions['resharding']>, 'getInfo'>; resharding?: PickPartial<NonNullable<ShardManagerOptions['resharding']>, 'getInfo'>;

View File

@ -1,4 +1,4 @@
import { randomUUID, type UUID } from 'node:crypto'; import { type UUID, randomUUID } from 'node:crypto';
import type { UsingClient } from '../commands'; import type { UsingClient } from '../commands';
import type { Awaitable, CamelCase } from '../common'; import type { Awaitable, CamelCase } from '../common';
import type { CallbackEventHandler, CustomEventsKeys, GatewayEvents } from '../events'; import type { CallbackEventHandler, CustomEventsKeys, GatewayEvents } from '../events';

View File

@ -1,5 +1,5 @@
export type { RuntimeConfig, RuntimeConfigHTTP } from './base'; export type { RuntimeConfig, RuntimeConfigHTTP } from './base';
export * from './client'; export * from './client';
export * from './httpclient'; export * from './httpclient';
export * from './transformers';
export * from './workerclient'; export * from './workerclient';
export * from './transformers';

View File

@ -8,8 +8,8 @@ import {
BaseGuildChannel, BaseGuildChannel,
CategoryChannel, CategoryChannel,
ClientUser, ClientUser,
DirectoryChannel,
DMChannel, DMChannel,
DirectoryChannel,
Emoji, Emoji,
Entitlement, Entitlement,
ForumChannel, ForumChannel,

View File

@ -1,24 +1,11 @@
import { randomUUID, type UUID } from 'node:crypto'; import { type UUID, randomUUID } from 'node:crypto';
import { ApiHandler, Logger } from '..'; import { ApiHandler, Logger } from '..';
import { WorkerAdapter } from '../cache'; import { WorkerAdapter } from '../cache';
import { import { type DeepPartial, LogLevels, type MakeRequired, type When, lazyLoadPackage } from '../common';
type Awaitable,
calculateShardId,
type DeepPartial,
LogLevels,
lazyLoadPackage,
type MakeRequired,
type When,
} from '../common';
import { EventHandler } from '../events'; import { EventHandler } from '../events';
import type { GatewayDispatchPayload, GatewaySendPayload } from '../types'; import type { GatewayDispatchPayload, GatewaySendPayload } from '../types';
import { properties, Shard, type ShardManagerOptions, ShardSocketCloseCodes, type WorkerData } from '../websocket'; import { Shard, type ShardManagerOptions, ShardSocketCloseCodes, type WorkerData, properties } from '../websocket';
import { MemberUpdateHandler } from '../websocket/discord/events/memberUpdate';
import { PresenceUpdateHandler } from '../websocket/discord/events/presenceUpdate';
import type { WorkerHeartbeaterMessages } from '../websocket/discord/heartbeater';
import type { ShardData } from '../websocket/discord/shared';
import type { import type {
ClientHeartbeaterMessages,
WorkerDisconnectedAllShardsResharding, WorkerDisconnectedAllShardsResharding,
WorkerMessages, WorkerMessages,
WorkerReady, WorkerReady,
@ -40,6 +27,10 @@ import type { ManagerMessages, ManagerSpawnShards } from '../websocket/discord/w
import type { BaseClientOptions, ServicesOptions, StartOptions } from './base'; 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 { MemberUpdateHandler } from '../websocket/discord/events/memberUpdate';
import { PresenceUpdateHandler } from '../websocket/discord/events/presenceUpdate';
import type { ShardData } from '../websocket/discord/shared';
import { Collectors } from './collectors'; import { Collectors } from './collectors';
import { type ClientUserStructure, Transformers } from './transformers'; import { type ClientUserStructure, Transformers } from './transformers';
@ -175,19 +166,13 @@ export class WorkerClient<Ready extends boolean = boolean> extends BaseClient {
} }
} }
postMessage(body: WorkerMessages | ClientHeartbeaterMessages): unknown { postMessage(body: WorkerMessages): unknown {
if (manager) return manager.postMessage(body); if (manager) return manager.postMessage(body);
return process.send!(body); return process.send!(body);
} }
async handleManagerMessages(data: ManagerMessages | WorkerHeartbeaterMessages) { async handleManagerMessages(data: ManagerMessages) {
switch (data.type) { switch (data.type) {
case 'HEARTBEAT':
this.postMessage({
type: 'ACK_HEARTBEAT',
workerId: workerData.workerId,
});
break;
case 'CACHE_RESULT': case 'CACHE_RESULT':
if (this.cache.adapter instanceof WorkerAdapter && this.cache.adapter.promises.has(data.nonce)) { if (this.cache.adapter instanceof WorkerAdapter && this.cache.adapter.promises.has(data.nonce)) {
const cacheData = this.cache.adapter.promises.get(data.nonce)!; const cacheData = this.cache.adapter.promises.get(data.nonce)!;
@ -392,18 +377,12 @@ export class WorkerClient<Ready extends boolean = boolean> extends BaseClient {
return this.onPacket(packet, shardId); return this.onPacket(packet, shardId);
}; };
} }
workerData.totalShards = data.totalShards;
workerData.shards = [...this.shards.keys()];
this.resharding.clear(); this.resharding.clear();
} }
break; break;
} }
} }
calculateShardId(guildId: string) {
return calculateShardId(guildId, this.workerData.totalShards);
}
private generateNonce(): UUID { private generateNonce(): UUID {
const uuid = randomUUID(); const uuid = randomUUID();
if (this.promises.has(uuid)) return this.generateNonce(); if (this.promises.has(uuid)) return this.generateNonce();
@ -441,7 +420,7 @@ export class WorkerClient<Ready extends boolean = boolean> extends BaseClient {
return Promise.all(promises); return Promise.all(promises);
} }
createShard(id: number, data: Pick<ManagerSpawnShards, 'info' | 'compress' | 'properties'>) { createShard(id: number, data: Pick<ManagerSpawnShards, 'info' | 'compress'>) {
const onPacket = this.onPacket.bind(this); const onPacket = this.onPacket.bind(this);
const handlePayload = this.options?.handlePayload?.bind(this); const handlePayload = this.options?.handlePayload?.bind(this);
const self = this; const self = this;
@ -453,7 +432,6 @@ export class WorkerClient<Ready extends boolean = boolean> extends BaseClient {
debugger: this.debugger, debugger: this.debugger,
properties: { properties: {
...properties, ...properties,
...data.properties,
...this.options.gateway?.properties, ...this.options.gateway?.properties,
}, },
async handlePayload(shardId, payload) { async handlePayload(shardId, payload) {
@ -575,12 +553,12 @@ export function generateShardInfo(shard: Shard): WorkerShardInfo {
}; };
} }
export interface WorkerClientOptions extends BaseClientOptions { interface WorkerClientOptions extends BaseClientOptions {
commands?: NonNullable<Client['options']>['commands']; commands?: NonNullable<Client['options']>['commands'];
handlePayload?: ShardManagerOptions['handlePayload']; handlePayload?: ShardManagerOptions['handlePayload'];
gateway?: ClientOptions['gateway']; gateway?: ClientOptions['gateway'];
postMessage?: (body: unknown) => Awaitable<unknown>; postMessage?: (body: unknown) => unknown;
/** can have perfomance issues in big bots if the client sends every event, specially in startup (false by default) */ /** can have perfomance issues in big bots if the client sends every event, specially in startup (false by default) */
sendPayloadToParent?: boolean; sendPayloadToParent?: boolean;
handleManagerMessages?(message: ManagerMessages | WorkerHeartbeaterMessages): Awaitable<unknown>; handleManagerMessages?(message: ManagerMessages): any;
} }

View File

@ -79,7 +79,7 @@ export class CommandContext<
if (this.interaction) return this.interaction.write(body, withResponse); if (this.interaction) return this.interaction.write(body, withResponse);
const options = (this.client as Client | WorkerClient).options?.commands; const options = (this.client as Client | WorkerClient).options?.commands;
return (this.messageResponse = await (this.message! as Message)[ return (this.messageResponse = await (this.message! as Message)[
!this.messageResponse && (await options?.reply?.(this)) ? 'reply' : 'write' !this.messageResponse && options?.reply?.(this) ? 'reply' : 'write'
](body)) as never; ](body)) as never;
} }
@ -97,8 +97,8 @@ export class CommandContext<
return this.interaction.deferReply(ephemeral ? MessageFlags.Ephemeral : undefined, withResponse); return this.interaction.deferReply(ephemeral ? MessageFlags.Ephemeral : undefined, withResponse);
this.__deferred = true; this.__deferred = true;
const options = (this.client as Client | WorkerClient).options?.commands; const options = (this.client as Client | WorkerClient).options?.commands;
return (this.messageResponse = await (this.message! as Message)[(await options?.reply?.(this)) ? 'reply' : 'write']( return (this.messageResponse = await (this.message! as Message)[options?.reply?.(this) ? 'reply' : 'write'](
(await options?.deferReplyResponse?.(this)) ?? { content: 'Thinking...' }, options?.deferReplyResponse?.(this) ?? { content: 'Thinking...' },
)) as never; )) as never;
} }

View File

@ -1,4 +1,4 @@
import { magicImport, type PermissionStrings } from '../../common'; import { type PermissionStrings, magicImport } from '../../common';
import { import {
ApplicationCommandType, ApplicationCommandType,
type ApplicationIntegrationType, type ApplicationIntegrationType,

View File

@ -12,11 +12,10 @@ import type {
MakeRequired, MakeRequired,
MessageWebhookCreateBodyRequest, MessageWebhookCreateBodyRequest,
ModalCreateBodyRequest, ModalCreateBodyRequest,
ModalCreateOptions,
UnionToTuple, UnionToTuple,
When, When,
} from '../../common'; } from '../../common';
import type { AllChannels, EntryPointInteraction, ModalSubmitInteraction } from '../../structures'; import type { AllChannels, EntryPointInteraction } from '../../structures';
import { MessageFlags, type RESTGetAPIGuildQuery } from '../../types'; import { MessageFlags, type RESTGetAPIGuildQuery } from '../../types';
import { BaseContext } from '../basecontext'; import { BaseContext } from '../basecontext';
import type { RegisteredMiddlewares } from '../decorators'; import type { RegisteredMiddlewares } from '../decorators';
@ -53,11 +52,8 @@ export class EntryPointContext<M extends keyof RegisteredMiddlewares = never> ex
return this.interaction.write<WR>(body, withResponse); return this.interaction.write<WR>(body, withResponse);
} }
modal(body: ModalCreateBodyRequest, options?: undefined): Promise<undefined>; modal(body: ModalCreateBodyRequest) {
modal(body: ModalCreateBodyRequest, options: ModalCreateOptions): Promise<ModalSubmitInteraction | null>; return this.interaction.modal(body);
modal(body: ModalCreateBodyRequest, options?: ModalCreateOptions | undefined) {
if (options === undefined) return this.interaction.modal(body);
return this.interaction.modal(body, options);
} }
deferReply<WR extends boolean = false>( deferReply<WR extends boolean = false>(

View File

@ -1,4 +1,4 @@
import { magicImport, type PermissionStrings } from '../../common'; import { type PermissionStrings, magicImport } from '../../common';
import type { import type {
ApplicationCommandType, ApplicationCommandType,
ApplicationIntegrationType, ApplicationIntegrationType,

View File

@ -8,22 +8,16 @@ import {
type WebhookMessageStructure, type WebhookMessageStructure,
} from '../../client/transformers'; } from '../../client/transformers';
import { import {
InteractionCreateBodyRequest, type InteractionCreateBodyRequest,
InteractionMessageUpdateBodyRequest, type InteractionMessageUpdateBodyRequest,
MakeRequired, type MakeRequired,
MessageWebhookCreateBodyRequest, type MessageWebhookCreateBodyRequest,
ModalCreateBodyRequest, type ModalCreateBodyRequest,
ModalCreateOptions, type UnionToTuple,
type When,
toSnakeCase, toSnakeCase,
UnionToTuple,
When,
} from '../../common'; } from '../../common';
import { import type { AllChannels, MessageCommandInteraction, UserCommandInteraction } from '../../structures';
AllChannels,
MessageCommandInteraction,
ModalSubmitInteraction,
UserCommandInteraction,
} from '../../structures';
import { type APIMessage, ApplicationCommandType, MessageFlags, type RESTGetAPIGuildQuery } from '../../types'; import { type APIMessage, ApplicationCommandType, MessageFlags, type RESTGetAPIGuildQuery } from '../../types';
import { BaseContext } from '../basecontext'; import { BaseContext } from '../basecontext';
import type { RegisteredMiddlewares } from '../decorators'; import type { RegisteredMiddlewares } from '../decorators';
@ -53,6 +47,7 @@ export class MenuCommandContext<
metadata: CommandMetadata<UnionToTuple<M>> = {} as never; metadata: CommandMetadata<UnionToTuple<M>> = {} as never;
globalMetadata: GlobalMetadata = {}; globalMetadata: GlobalMetadata = {};
// biome-ignore lint/suspicious/useGetterReturn: default don't exist.
get target(): InteractionTarget<T> { get target(): InteractionTarget<T> {
switch (this.interaction.data.type) { switch (this.interaction.data.type) {
case ApplicationCommandType.Message: { case ApplicationCommandType.Message: {
@ -81,11 +76,8 @@ export class MenuCommandContext<
return this.interaction.write<WR>(body, withResponse); return this.interaction.write<WR>(body, withResponse);
} }
modal(body: ModalCreateBodyRequest, options?: undefined): Promise<undefined>; modal(body: ModalCreateBodyRequest) {
modal(body: ModalCreateBodyRequest, options: ModalCreateOptions): Promise<ModalSubmitInteraction | null>; return this.interaction.modal(body);
modal(body: ModalCreateBodyRequest, options?: ModalCreateOptions | undefined) {
if (options === undefined) return this.interaction.modal(body);
return this.interaction.modal(body, options);
} }
deferReply<WR extends boolean = false>( deferReply<WR extends boolean = false>(

View File

@ -1,3 +1,10 @@
import type {
AutocompleteCallback,
EntryPointContext,
MenuCommandContext,
OnAutocompleteErrorCallback,
ReturnOptionsTypes,
} from '..';
import type { Awaitable, FlatObjectKeys } from '../../common'; import type { Awaitable, FlatObjectKeys } from '../../common';
import type { ModalContext } from '../../components'; import type { ModalContext } from '../../components';
import type { ComponentContext } from '../../components/componentcontext'; import type { ComponentContext } from '../../components/componentcontext';
@ -8,13 +15,6 @@ import {
ApplicationCommandOptionType, ApplicationCommandOptionType,
} from '../../types'; } from '../../types';
import type { LocalizationMap } from '../../types/payloads'; import type { LocalizationMap } from '../../types/payloads';
import type {
AutocompleteCallback,
EntryPointContext,
MenuCommandContext,
OnAutocompleteErrorCallback,
ReturnOptionsTypes,
} from '..';
import type { CommandContext } from './chatcontext'; import type { CommandContext } from './chatcontext';
import type { DefaultLocale, MiddlewareContext, OKFunction, SeyfertChannelMap, StopFunction } from './shared'; import type { DefaultLocale, MiddlewareContext, OKFunction, SeyfertChannelMap, StopFunction } from './shared';

View File

@ -1,7 +1,7 @@
import type { import type {
CategoryChannelStructure, CategoryChannelStructure,
DirectoryChannelStructure,
DMChannelStructure, DMChannelStructure,
DirectoryChannelStructure,
ForumChannelStructure, ForumChannelStructure,
MediaChannelStructure, MediaChannelStructure,
NewsChannelStructure, NewsChannelStructure,

View File

@ -1,32 +1,3 @@
import type { Client, WorkerClient } from '../client';
import { type MessageStructure, type OptionResolverStructure, Transformers } from '../client/transformers';
import type { MakeRequired } from '../common';
import { INTEGER_OPTION_VALUE_LIMIT } from '../common/it/constants';
import { ComponentContext, ModalContext } from '../components';
import {
type __InternalReplyFunction,
AutocompleteInteraction,
BaseInteraction,
type ChatInputCommandInteraction,
type ComponentInteraction,
type EntryPointInteraction,
type MessageCommandInteraction,
type ModalSubmitInteraction,
type UserCommandInteraction,
} from '../structures';
import type { PermissionsBitField } from '../structures/extra/Permissions';
import {
type APIApplicationCommandInteraction,
type APIApplicationCommandInteractionDataOption,
type APIInteraction,
type APIInteractionDataResolvedChannel,
ApplicationCommandOptionType,
ApplicationCommandType,
ChannelType,
type GatewayMessageCreateDispatchData,
InteractionContextType,
InteractionType,
} from '../types';
import { import {
BaseCommand, BaseCommand,
Command, Command,
@ -48,6 +19,35 @@ import {
SubCommand, SubCommand,
type UsingClient, 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 { INTEGER_OPTION_VALUE_LIMIT } from '../common/it/constants';
import { ComponentContext, ModalContext } from '../components';
import {
AutocompleteInteraction,
BaseInteraction,
type ChatInputCommandInteraction,
type ComponentInteraction,
type EntryPointInteraction,
type MessageCommandInteraction,
type ModalSubmitInteraction,
type UserCommandInteraction,
type __InternalReplyFunction,
} from '../structures';
import type { PermissionsBitField } from '../structures/extra/Permissions';
import {
type APIApplicationCommandInteraction,
type APIApplicationCommandInteractionDataOption,
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;

View File

@ -1,5 +1,6 @@
import { promises } from 'node:fs'; import { promises } from 'node:fs';
import { basename, dirname } from 'node:path'; import { basename, dirname } from 'node:path';
import type { EntryPointCommand } from '.';
import type { Logger, NulleableCoalising, OmitInsert } from '../common'; import type { Logger, NulleableCoalising, OmitInsert } from '../common';
import { BaseHandler, isCloudfareWorker } from '../common'; import { BaseHandler, isCloudfareWorker } from '../common';
import { PermissionsBitField } from '../structures/extra/Permissions'; import { PermissionsBitField } from '../structures/extra/Permissions';
@ -16,7 +17,6 @@ import {
type LocaleString, type LocaleString,
type LocalizationMap, type LocalizationMap,
} from '../types'; } from '../types';
import type { EntryPointCommand } from '.';
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 { IgnoreCommand, type UsingClient } from './applications/shared'; import { IgnoreCommand, type UsingClient } from './applications/shared';

View File

@ -1,11 +1,11 @@
export * from './applications/shared';
// //
export * from './applications/chat'; export * from './applications/chat';
export * from './applications/chatcontext'; export * from './applications/chatcontext';
export * from './applications/entrycontext';
export * from './applications/entryPoint';
export * from './applications/menu'; export * from './applications/menu';
export * from './applications/menucontext'; export * from './applications/menucontext';
export * from './applications/options'; export * from './applications/options';
export * from './applications/shared'; export * from './applications/entryPoint';
export * from './applications/entrycontext';
export * from './decorators'; export * from './decorators';
export * from './optionresolver'; export * from './optionresolver';

View File

@ -1,28 +1,28 @@
//
export * from './bot/watcher';
export * from './it/colors';
export * from './it/constants'; export * from './it/constants';
export * from './it/formatter';
export { AssignFilenameCallback, CustomizeLoggerCallback, Logger, LoggerOptions, LogLevels } from './it/logger';
export * from './it/utils'; export * from './it/utils';
export * from './shorters/application'; export * from './it/colors';
export { CustomizeLoggerCallback, AssignFilenameCallback, LogLevels, Logger, LoggerOptions } from './it/logger';
export * from './it/formatter';
// circular lol
export * from './shorters/invites';
// //
export * from './shorters/channels'; export * from './shorters/channels';
export * from './shorters/emojis'; export * from './shorters/emojis';
export * from './shorters/guilds'; export * from './shorters/guilds';
export * from './shorters/interaction';
// circular lol
export * from './shorters/invites';
export * from './shorters/members'; export * from './shorters/members';
export * from './shorters/messages'; export * from './shorters/messages';
export * from './shorters/reactions'; export * from './shorters/reactions';
export * from './shorters/roles'; export * from './shorters/roles';
export * from './shorters/templates'; export * from './shorters/templates';
export * from './shorters/threads';
export * from './shorters/users'; export * from './shorters/users';
export * from './shorters/threads';
export * from './shorters/webhook'; export * from './shorters/webhook';
export * from './shorters/interaction';
export * from './shorters/application';
// //
export * from './types/options'; export * from './types/options';
export * from './types/resolvables'; export * from './types/resolvables';
export * from './types/util'; export * from './types/util';
export * from './types/write'; export * from './types/write';
//
export * from './bot/watcher';

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';

View File

@ -1,7 +1,5 @@
import { promises } from 'node:fs'; import { promises } from 'node:fs';
import { basename, join } from 'node:path'; import { basename, join } from 'node:path';
import type { Cache } from '../../cache';
import { type APIPartialEmoji, FormattingPatterns, GatewayIntentBits } from '../../types';
import { import {
type ColorResolvable, type ColorResolvable,
DiscordEpoch, DiscordEpoch,
@ -12,6 +10,8 @@ import {
type ObjectToSnake, type ObjectToSnake,
type TypeArray, type TypeArray,
} from '..'; } from '..';
import type { Cache } from '../../cache';
import { type APIPartialEmoji, FormattingPatterns, GatewayIntentBits } from '../../types';
/** /**
* Calculates the shard ID for a guild based on its ID. * Calculates the shard ID for a guild based on its ID.
@ -304,6 +304,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,7 +1,7 @@
import { CacheFrom } from '../../cache'; import { CacheFrom } from '../../cache';
import type { Overwrites } from '../../cache/resources/overwrites'; import type { Overwrites } from '../../cache/resources/overwrites';
import { type MessageStructure, type ThreadChannelStructure, Transformers } from '../../client/transformers'; import { type MessageStructure, type ThreadChannelStructure, Transformers } from '../../client/transformers';
import { type AllChannels, BaseChannel, channelFrom, type GuildMember, type GuildRole } from '../../structures'; import { type AllChannels, BaseChannel, type GuildMember, type GuildRole, channelFrom } from '../../structures';
import { PermissionsBitField } from '../../structures/extra/Permissions'; import { PermissionsBitField } from '../../structures/extra/Permissions';
import type { import type {
APIChannel, APIChannel,

View File

@ -14,8 +14,8 @@ import {
type AllChannels, type AllChannels,
BaseChannel, BaseChannel,
type CreateStickerBodyRequest, type CreateStickerBodyRequest,
channelFrom,
type GuildChannelTypes, type GuildChannelTypes,
channelFrom,
} from '../../structures'; } from '../../structures';
import type { import type {
APIChannel, APIChannel,

View File

@ -1,6 +1,5 @@
import { BaseInteraction, Modal, type ReplyInteractionBody, resolveFiles } from '../..'; import { BaseInteraction, Modal, type ReplyInteractionBody, resolveFiles } from '../..';
import { Transformers, type WebhookMessageStructure } from '../../client/transformers'; import { Transformers, type WebhookMessageStructure } from '../../client/transformers';
import type { RESTPostAPIWebhookWithTokenWaitResult } from '../../types';
import type { InteractionMessageUpdateBodyRequest, MessageWebhookCreateBodyRequest } from '../types/write'; import type { InteractionMessageUpdateBodyRequest, MessageWebhookCreateBodyRequest } from '../types/write';
import { BaseShorter } from './base'; import { BaseShorter } from './base';
@ -70,12 +69,12 @@ export class InteractionShorter extends BaseShorter {
async followup(token: string, { files, ...body }: MessageWebhookCreateBodyRequest): Promise<WebhookMessageStructure> { async followup(token: string, { files, ...body }: MessageWebhookCreateBodyRequest): Promise<WebhookMessageStructure> {
const parsedFiles = files ? await resolveFiles(files) : undefined; const parsedFiles = files ? await resolveFiles(files) : undefined;
const apiMessage = (await this.client.proxy const apiMessage = await this.client.proxy
.webhooks(this.client.applicationId)(token) .webhooks(this.client.applicationId)(token)
.post({ .post({
body: BaseInteraction.transformBody(body, parsedFiles, this.client), body: BaseInteraction.transformBody(body, parsedFiles, this.client),
files: parsedFiles, files: parsedFiles,
})) as RESTPostAPIWebhookWithTokenWaitResult; });
return Transformers.WebhookMessage(this.client, apiMessage, this.client.applicationId, token); return Transformers.WebhookMessage(this.client, apiMessage, this.client.applicationId, token);
} }
} }

View File

@ -1,7 +1,4 @@
import type { ValidAnswerId } from '../../api/Routes/channels';
import { resolveFiles } from '../../builders'; import { resolveFiles } from '../../builders';
import { CacheFrom } from '../../cache';
import { type MessageStructure, type ThreadChannelStructure, Transformers, type UserStructure } from '../../client';
import { MessagesMethods } from '../../structures'; import { MessagesMethods } from '../../structures';
import type { import type {
RESTGetAPIChannelMessagesQuery, RESTGetAPIChannelMessagesQuery,
@ -9,6 +6,10 @@ import type {
RESTPostAPIChannelMessageJSONBody, RESTPostAPIChannelMessageJSONBody,
RESTPostAPIChannelMessagesThreadsJSONBody, RESTPostAPIChannelMessagesThreadsJSONBody,
} from '../../types'; } from '../../types';
import type { ValidAnswerId } from '../../api/Routes/channels';
import { CacheFrom } from '../../cache';
import { type MessageStructure, type ThreadChannelStructure, Transformers, type UserStructure } from '../../client';
import type { MessageCreateBodyRequest, MessageUpdateBodyRequest } from '../types/write'; import type { MessageCreateBodyRequest, MessageUpdateBodyRequest } from '../types/write';
import { BaseShorter } from './base'; import { BaseShorter } from './base';

View File

@ -92,9 +92,10 @@ export class RoleShorter extends BaseShorter {
* @param reason The reason for deleting the role. * @param reason The reason for deleting the role.
* @returns A Promise that resolves when the role is deleted. * @returns A Promise that resolves when the role is deleted.
*/ */
async delete(guildId: string, roleId: string, reason?: string) { async delete(guildId: string, roleId: string, reason?: string): Promise<GuildRoleStructure> {
await this.client.proxy.guilds(guildId).roles(roleId).delete({ reason }); const res = await this.client.proxy.guilds(guildId).roles(roleId).delete({ reason });
this.client.cache.roles?.removeIfNI('Guilds', roleId, guildId); this.client.cache.roles?.removeIfNI('Guilds', roleId, guildId);
return Transformers.GuildRole(this.client, res, guildId);
} }
/** /**

View File

@ -1,16 +1,15 @@
import { CacheFrom } from '../..'; import { CacheFrom } from '../..';
import type { ThreadChannelStructure } from '../../client/transformers'; import type { ThreadChannelStructure } from '../../client/transformers';
import { channelFrom } from '../../structures'; import { channelFrom } from '../../structures';
import { import type {
type APIThreadChannel, APIThreadChannel,
type APIThreadMember, APIThreadMember,
ChannelType, RESTGetAPIChannelThreadMembersQuery,
type RESTGetAPIChannelThreadMembersQuery, RESTGetAPIChannelThreadsArchivedQuery,
type RESTGetAPIChannelThreadsArchivedQuery, RESTPatchAPIChannelJSONBody,
type RESTPatchAPIChannelJSONBody, RESTPostAPIChannelMessagesThreadsJSONBody,
type RESTPostAPIChannelMessagesThreadsJSONBody, RESTPostAPIChannelThreadsJSONBody,
type RESTPostAPIChannelThreadsJSONBody, RESTPostAPIGuildForumThreadsJSONBody,
type RESTPostAPIGuildForumThreadsJSONBody,
} from '../../types'; } from '../../types';
import type { MakeRequired, When } from '../types/util'; import type { MakeRequired, When } from '../types/util';
import { BaseShorter } from './base'; import { BaseShorter } from './base';
@ -45,22 +44,27 @@ export class ThreadShorter extends BaseShorter {
); );
} }
async fromMessage( fromMessage(
channelId: string, channelId: string,
messageId: string, messageId: string,
options: RESTPostAPIChannelMessagesThreadsJSONBody & { reason?: string }, options: RESTPostAPIChannelMessagesThreadsJSONBody & { reason?: string },
): Promise<ThreadChannelStructure> { ): Promise<ThreadChannelStructure> {
const { reason, ...body } = options; const { reason, ...body } = options;
const thread = await this.client.proxy.channels(channelId).messages(messageId).threads.post({ body, reason }); return this.client.proxy
await this.client.cache.channels?.setIfNI( .channels(channelId)
CacheFrom.Rest, .messages(messageId)
'Guilds', .threads.post({ body, reason })
thread.id, .then(async thread => {
(thread as APIThreadChannel).guild_id!, await this.client.cache.channels?.setIfNI(
thread, CacheFrom.Rest,
); 'Guilds',
return await (channelFrom(thread, this.client) as ThreadChannelStructure); thread.id,
(thread as APIThreadChannel).guild_id!,
thread,
);
return channelFrom(thread, this.client) as ThreadChannelStructure;
});
} }
join(threadId: string) { join(threadId: string) {
@ -71,9 +75,8 @@ export class ThreadShorter extends BaseShorter {
return this.client.proxy.channels(threadId)['thread-members']('@me').delete(); return this.client.proxy.channels(threadId)['thread-members']('@me').delete();
} }
async lock(threadId: string, locked = true, reason?: string): Promise<ThreadChannelStructure> { lock(threadId: string, locked = true, reason?: string): Promise<ThreadChannelStructure> {
const x = await this.edit(threadId, { locked }, reason); return this.edit(threadId, { locked }, reason).then(x => channelFrom(x, this.client) as ThreadChannelStructure);
return channelFrom(x, this.client) as ThreadChannelStructure;
} }
async edit(threadId: string, body: RESTPatchAPIChannelJSONBody, reason?: string): Promise<ThreadChannelStructure> { async edit(threadId: string, body: RESTPatchAPIChannelJSONBody, reason?: string): Promise<ThreadChannelStructure> {
@ -107,7 +110,7 @@ export class ThreadShorter extends BaseShorter {
return this.client.proxy.channels(threadId)['thread-members'].get({ query }) as never; return this.client.proxy.channels(threadId)['thread-members'].get({ query }) as never;
} }
async listArchived( async listArchivedThreads(
channelId: string, channelId: string,
type: 'public' | 'private', type: 'public' | 'private',
query?: RESTGetAPIChannelThreadsArchivedQuery, query?: RESTGetAPIChannelThreadsArchivedQuery,
@ -125,25 +128,6 @@ export class ThreadShorter extends BaseShorter {
}; };
} }
async listGuildActive(guildId: string, force = false): Promise<ThreadChannelStructure[]> {
if (!force) {
const cached = await this.client.cache.channels?.valuesRaw(guildId);
if (cached)
return cached
.filter(x =>
[ChannelType.PublicThread, ChannelType.PrivateThread, ChannelType.AnnouncementThread].includes(x.type),
)
.map(x => channelFrom(x, this.client) as ThreadChannelStructure);
}
const data = await this.client.proxy.guilds(guildId).threads.active.get();
return Promise.all(
data.threads.map(async thread => {
await this.client.cache.channels?.setIfNI(CacheFrom.Rest, 'Guilds', thread.id, guildId, thread);
return channelFrom(thread, this.client) as ThreadChannelStructure;
}),
);
}
async listJoinedArchivedPrivate( async listJoinedArchivedPrivate(
channelId: string, channelId: string,
query?: RESTGetAPIChannelThreadsArchivedQuery, query?: RESTGetAPIChannelThreadsArchivedQuery,

View File

@ -1,9 +1,9 @@
import { resolveFiles } from '../../builders'; import { resolveFiles } from '../../builders';
import { Transformers, type WebhookMessageStructure, type WebhookStructure } from '../../client/transformers'; import { Transformers, type WebhookMessageStructure, type WebhookStructure } from '../../client/transformers';
import { import {
MessagesMethods,
type MessageWebhookMethodEditParams, type MessageWebhookMethodEditParams,
type MessageWebhookMethodWriteParams, type MessageWebhookMethodWriteParams,
MessagesMethods,
} from '../../structures'; } from '../../structures';
import type { import type {
APIWebhook, APIWebhook,

View File

@ -1,6 +1,6 @@
import type { Identify } from '..';
import type { CDNUrlOptions } from '../../api'; import type { CDNUrlOptions } from '../../api';
import type { UsingClient } from '../../commands'; import type { UsingClient } from '../../commands';
import type { Identify } from '..';
export type ImageOptions = CDNUrlOptions; export type ImageOptions = CDNUrlOptions;

View File

@ -1,7 +1,7 @@
import type { EmbedColors, OmitInsert } from '..';
import type { Attachment, AttachmentDataType, AttachmentResolvable } from '../../builders'; import type { Attachment, AttachmentDataType, AttachmentResolvable } from '../../builders';
import type { GuildMember } from '../../structures'; import type { GuildMember } from '../../structures';
import type { APIGuildMember, APIPartialEmoji, RESTPostAPIApplicationEmojiJSONBody } from '../../types'; import type { APIGuildMember, APIPartialEmoji, RESTPostAPIApplicationEmojiJSONBody } from '../../types';
import type { EmbedColors, OmitInsert } from '..';
export type EmojiResolvable = string | Partial<APIPartialEmoji> | `<${string | undefined}:${string}:${string}>`; export type EmojiResolvable = string | Partial<APIPartialEmoji> | `<${string | undefined}:${string}:${string}>`;
export type GuildMemberResolvable = string | Partial<GuildMember> | APIGuildMember; export type GuildMemberResolvable = string | Partial<GuildMember> | APIGuildMember;

View File

@ -107,7 +107,7 @@ export type SnakeCase<S extends string> = S extends `${infer A}${infer Rest}`
export type ObjectToLower<T> = T extends unknown[] export type ObjectToLower<T> = T extends unknown[]
? ObjectToLower<T[0]>[] ? ObjectToLower<T[0]>[]
: Identify<{ : Identify<{
[K in keyof T as K extends number ? K : CamelCase<Exclude<K, symbol | number>>]: T[K] extends unknown[] [K in keyof T as CamelCase<Exclude<K, symbol | number>>]: T[K] extends unknown[]
? Identify<ObjectToLower<T[K][0]>[]> ? Identify<ObjectToLower<T[K][0]>[]>
: T[K] extends object : T[K] extends object
? Identify<ObjectToLower<T[K]>> ? Identify<ObjectToLower<T[K]>>
@ -119,7 +119,7 @@ export type ObjectToLower<T> = T extends unknown[]
export type ObjectToLowerUndefined<T> = T extends unknown[] export type ObjectToLowerUndefined<T> = T extends unknown[]
? ObjectToLower<T[0]>[] ? ObjectToLower<T[0]>[]
: Identify<{ : Identify<{
[K in keyof T as K extends number ? K : CamelCase<Exclude<K, symbol | number>>]: T[K] extends unknown[] [K in keyof T as CamelCase<Exclude<K, symbol | number>>]: T[K] extends unknown[]
? ObjectToLower<T[K][0]>[] ? ObjectToLower<T[K][0]>[]
: T[K] extends object : T[K] extends object
? ObjectToLower<T[K]> ? ObjectToLower<T[K]>
@ -127,7 +127,7 @@ export type ObjectToLowerUndefined<T> = T extends unknown[]
}>; }>;
export type ObjectToSnake<T> = Identify<{ export type ObjectToSnake<T> = Identify<{
[K in keyof T as K extends number ? K : SnakeCase<Exclude<K, symbol | number>>]: T[K] extends unknown[] [K in keyof T as SnakeCase<Exclude<K, symbol | number>>]: T[K] extends unknown[]
? Identify<ObjectToSnake<T[K][0]>[]> ? Identify<ObjectToSnake<T[K][0]>[]>
: T[K] extends object : T[K] extends object
? Identify<ObjectToSnake<T[K]>> ? Identify<ObjectToSnake<T[K]>>
@ -139,7 +139,7 @@ export type ObjectToSnake<T> = Identify<{
export type ObjectToSnakeUndefined<T> = T extends unknown[] export type ObjectToSnakeUndefined<T> = T extends unknown[]
? ObjectToSnake<T[0]>[] ? ObjectToSnake<T[0]>[]
: Identify<{ : Identify<{
[K in keyof T as K extends number ? K : SnakeCase<Exclude<K, symbol | number>>]: T[K] extends unknown[] [K in keyof T as SnakeCase<Exclude<K, symbol | number>>]: T[K] extends unknown[]
? ObjectToSnake<T[K][0]>[] ? ObjectToSnake<T[K][0]>[]
: T[K] extends object : T[K] extends object
? ObjectToSnake<T[K]> ? ObjectToSnake<T[K]>
@ -171,10 +171,14 @@ type OptionalizeAux<T extends object> = Identify<
* it is recursive * it is recursive
*/ */
export type Optionalize<T> = T extends object export type Optionalize<T> = T extends object
? T extends Array<unknown> ? // biome-ignore lint/style/useShorthandArrayType: typescript things
// biome-ignore lint/style/useConsistentArrayType: <explanation>
T extends Array<unknown>
? number extends T['length'] ? number extends T['length']
? T[number] extends object ? T[number] extends object
? Array<OptionalizeAux<T[number]>> ? // biome-ignore lint/style/useShorthandArrayType: <explanation>
// biome-ignore lint/style/useConsistentArrayType: <explanation>
Array<OptionalizeAux<T[number]>>
: T : T
: Partial<T> : Partial<T>
: OptionalizeAux<T> : OptionalizeAux<T>

View File

@ -16,9 +16,8 @@ import type {
import type { OmitInsert } from './util'; import type { OmitInsert } from './util';
export interface ResolverProps { export interface ResolverProps {
content?: string | undefined | null;
embeds?: Embed[] | APIEmbed[] | undefined; embeds?: Embed[] | APIEmbed[] | undefined;
components?: TopLevelBuilders[] | ReturnType<TopLevelBuilders['toJSON']>[]; components?: TopLevelBuilders[];
files?: AttachmentBuilder[] | Attachment[] | RawFile[] | undefined; files?: AttachmentBuilder[] | Attachment[] | RawFile[] | undefined;
} }
@ -28,31 +27,31 @@ export interface SendResolverProps extends ResolverProps {
export type MessageCreateBodyRequest = OmitInsert< export type MessageCreateBodyRequest = OmitInsert<
RESTPostAPIChannelMessageJSONBody, RESTPostAPIChannelMessageJSONBody,
'components' | 'embeds' | 'poll' | 'content', 'components' | 'embeds' | 'poll',
SendResolverProps SendResolverProps
>; >;
export type MessageUpdateBodyRequest = OmitInsert< export type MessageUpdateBodyRequest = OmitInsert<
RESTPatchAPIChannelMessageJSONBody, RESTPatchAPIChannelMessageJSONBody,
'components' | 'embeds' | 'content', 'components' | 'embeds',
ResolverProps ResolverProps
>; >;
export type MessageWebhookCreateBodyRequest = OmitInsert< export type MessageWebhookCreateBodyRequest = OmitInsert<
RESTPostAPIWebhookWithTokenJSONBody, RESTPostAPIWebhookWithTokenJSONBody,
'components' | 'embeds' | 'poll' | 'content', 'components' | 'embeds' | 'poll',
SendResolverProps SendResolverProps
>; >;
export type MessageWebhookUpdateBodyRequest = OmitInsert< export type MessageWebhookUpdateBodyRequest = OmitInsert<
RESTPatchAPIWebhookWithTokenMessageJSONBody, RESTPatchAPIWebhookWithTokenMessageJSONBody,
'components' | 'embeds' | 'poll' | 'content', 'components' | 'embeds' | 'poll',
ResolverProps ResolverProps
>; >;
export type InteractionMessageUpdateBodyRequest = OmitInsert< export type InteractionMessageUpdateBodyRequest = OmitInsert<
RESTPatchAPIWebhookWithTokenMessageJSONBody, RESTPatchAPIWebhookWithTokenMessageJSONBody,
'components' | 'embeds' | 'poll' | 'content', 'components' | 'embeds' | 'poll',
SendResolverProps SendResolverProps
> & { > & {
flags?: MessageFlags; flags?: MessageFlags;
@ -60,18 +59,14 @@ export type InteractionMessageUpdateBodyRequest = OmitInsert<
export type ComponentInteractionMessageUpdate = OmitInsert< export type ComponentInteractionMessageUpdate = OmitInsert<
APIInteractionResponseCallbackData, APIInteractionResponseCallbackData,
'components' | 'embeds' | 'content', 'components' | 'embeds',
ResolverProps ResolverProps
>; >;
export type InteractionCreateBodyRequest = OmitInsert< export type InteractionCreateBodyRequest = OmitInsert<
APIInteractionResponseChannelMessageWithSource['data'], APIInteractionResponseChannelMessageWithSource['data'],
'components' | 'embeds' | 'poll' | 'content', 'components' | 'embeds' | 'poll',
SendResolverProps SendResolverProps
>; >;
export type ModalCreateBodyRequest = APIModalInteractionResponse['data'] | Modal; export type ModalCreateBodyRequest = APIModalInteractionResponse['data'] | Modal;
export interface ModalCreateOptions {
waitFor?: number;
}

View File

@ -4,7 +4,6 @@ import {
type ChannelSelectMenu, type ChannelSelectMenu,
type Container, type Container,
type File, type File,
fromComponent,
type MediaGallery, type MediaGallery,
type MentionableSelectMenu, type MentionableSelectMenu,
type RoleSelectMenu, type RoleSelectMenu,
@ -15,6 +14,7 @@ import {
type TextInput, type TextInput,
type Thumbnail, type Thumbnail,
type UserSelectMenu, type UserSelectMenu,
fromComponent,
} from '../builders'; } from '../builders';
import { import {
type APIActionRowComponent, type APIActionRowComponent,
@ -29,7 +29,7 @@ import {
type APISectionComponent, type APISectionComponent,
type APISeparatorComponent, type APISeparatorComponent,
type APIStringSelectComponent, type APIStringSelectComponent,
type APITextDisplayComponent, type APITextDispalyComponent,
type APITextInputComponent, type APITextInputComponent,
type APIThumbnailComponent, type APIThumbnailComponent,
type APIUserSelectComponent, type APIUserSelectComponent,
@ -66,7 +66,7 @@ export interface APIComponentsMap {
[ComponentType.Container]: APIContainerComponent; [ComponentType.Container]: APIContainerComponent;
[ComponentType.MediaGallery]: APIMediaGalleryComponent; [ComponentType.MediaGallery]: APIMediaGalleryComponent;
[ComponentType.Separator]: APISeparatorComponent; [ComponentType.Separator]: APISeparatorComponent;
[ComponentType.TextDisplay]: APITextDisplayComponent; [ComponentType.TextDisplay]: APITextDispalyComponent;
} }
export interface BuilderComponentsMap { export interface BuilderComponentsMap {

View File

@ -1,5 +1,5 @@
import type { APIContainerComponent, ComponentType } from '../types';
import { type ContainerComponents, componentFactory } from '.'; import { type ContainerComponents, componentFactory } from '.';
import type { APIContainerComponent, ComponentType } from '../types';
import { BaseComponent } from './BaseComponent'; import { BaseComponent } from './BaseComponent';
export class ContainerComponent extends BaseComponent<ComponentType.Container> { export class ContainerComponent extends BaseComponent<ComponentType.Container> {

View File

@ -1,5 +1,5 @@
import type { APISectionComponent, ComponentType } from '../types';
import { componentFactory } from '.'; import { componentFactory } from '.';
import type { APISectionComponent, ComponentType } from '../types';
import { BaseComponent } from './BaseComponent'; import { BaseComponent } from './BaseComponent';
import type { ButtonComponent } from './ButtonComponent'; import type { ButtonComponent } from './ButtonComponent';
import type { TextDisplayComponent } from './TextDisplay'; import type { TextDisplayComponent } from './TextDisplay';

View File

@ -14,17 +14,13 @@ export interface ComponentCommand {
export abstract class ComponentCommand { export abstract class ComponentCommand {
type = InteractionCommandType.COMPONENT; type = InteractionCommandType.COMPONENT;
abstract componentType: keyof ContextComponentCommandInteractionMap; abstract componentType: keyof ContextComponentCommandInteractionMap;
customId?: string | RegExp; customId?: string;
filter?(context: ComponentContext<typeof this.componentType>): Promise<boolean> | boolean; filter?(context: ComponentContext<typeof this.componentType>): Promise<boolean> | boolean;
abstract run(context: ComponentContext<typeof this.componentType>): any; abstract run(context: ComponentContext<typeof this.componentType>): any;
/** @internal */ /** @internal */
_filter(context: ComponentContext) { _filter(context: ComponentContext) {
if (this.customId) { if (this.customId && this.customId !== context.customId) return false;
const matches =
typeof this.customId === 'string' ? this.customId === context.customId : context.customId.match(this.customId);
if (!matches) return false;
}
if (this.filter) return this.filter(context); if (this.filter) return this.filter(context);
return true; return true;
} }

View File

@ -18,18 +18,16 @@ import type {
} from '../client/transformers'; } from '../client/transformers';
import type { CommandMetadata, ExtendContext, GlobalMetadata, RegisteredMiddlewares, UsingClient } from '../commands'; import type { CommandMetadata, ExtendContext, GlobalMetadata, RegisteredMiddlewares, UsingClient } from '../commands';
import { BaseContext } from '../commands/basecontext'; import { BaseContext } from '../commands/basecontext';
import { import type {
ComponentInteractionMessageUpdate, ComponentInteractionMessageUpdate,
InteractionCreateBodyRequest, InteractionCreateBodyRequest,
InteractionMessageUpdateBodyRequest, InteractionMessageUpdateBodyRequest,
MakeRequired, MakeRequired,
MessageWebhookCreateBodyRequest, MessageWebhookCreateBodyRequest,
ModalCreateBodyRequest, ModalCreateBodyRequest,
ModalCreateOptions,
UnionToTuple, UnionToTuple,
When, When,
} from '../common'; } from '../common';
import { ModalSubmitInteraction } from '../structures';
import { ComponentType, MessageFlags, type RESTGetAPIGuildQuery } from '../types'; import { ComponentType, MessageFlags, type RESTGetAPIGuildQuery } from '../types';
export interface ComponentContext< export interface ComponentContext<
@ -152,11 +150,8 @@ export class ComponentContext<
return this.interaction.deleteResponse(); return this.interaction.deleteResponse();
} }
modal(body: ModalCreateBodyRequest, options?: undefined): Promise<undefined>; modal(body: ModalCreateBodyRequest) {
modal(body: ModalCreateBodyRequest, options: ModalCreateOptions): Promise<ModalSubmitInteraction | null>; return this.interaction.modal(body);
modal(body: ModalCreateBodyRequest, options?: ModalCreateOptions | undefined) {
if (options === undefined) return this.interaction.modal(body);
return this.interaction.modal(body, options);
} }
/** /**

View File

@ -9,7 +9,7 @@ import type {
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, type Logger, magicImport, 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';
@ -38,11 +38,6 @@ export interface CreateComponentCollectorResult {
callback: ComponentCallback<T>, callback: ComponentCallback<T>,
): void; ): void;
stop(reason?: string): void; stop(reason?: string): void;
waitFor<T extends CollectorInteraction = CollectorInteraction>(
customId: UserMatches,
timeout?: number,
): Promise<T | null>;
resetTimeouts(): void;
} }
export class ComponentHandler extends BaseHandler { export class ComponentHandler extends BaseHandler {
@ -120,28 +115,6 @@ export class ComponentHandler extends BaseHandler {
this.createComponentCollector(messageId, channelId, guildId, options, old.components); this.createComponentCollector(messageId, channelId, guildId, options, old.components);
}); });
}, },
waitFor: (customId, timeout) =>
new Promise(resolve => {
const collector = this.values.get(messageId);
if (!collector) return resolve(null);
let nodeTimeout: NodeJS.Timeout | undefined;
this.values.get(messageId)!.__run(customId, interaction => {
clearTimeout(nodeTimeout);
//@ts-expect-error generic
resolve(interaction);
});
if (timeout && timeout > 0)
nodeTimeout = setTimeout(() => {
resolve(null);
// by default 15 seconds in case user don't do anything
}, timeout);
}),
resetTimeouts: () => {
this.resetTimeouts(messageId);
},
}; };
} }

View File

@ -1,4 +1,4 @@
import type { AllChannels, ModalCommand, ModalSubmitInteraction, ReturnCache } from '..'; import type { AllChannels, Interaction, ModalCommand, ModalSubmitInteraction, ReturnCache } from '..';
import type { import type {
GuildMemberStructure, GuildMemberStructure,
GuildStructure, GuildStructure,
@ -8,13 +8,12 @@ import type {
} from '../client/transformers'; } from '../client/transformers';
import type { CommandMetadata, ExtendContext, GlobalMetadata, RegisteredMiddlewares, UsingClient } from '../commands'; import type { CommandMetadata, ExtendContext, GlobalMetadata, RegisteredMiddlewares, UsingClient } from '../commands';
import { BaseContext } from '../commands/basecontext'; import { BaseContext } from '../commands/basecontext';
import { import type {
InteractionCreateBodyRequest, InteractionCreateBodyRequest,
InteractionMessageUpdateBodyRequest, InteractionMessageUpdateBodyRequest,
MakeRequired, MakeRequired,
MessageWebhookCreateBodyRequest, MessageWebhookCreateBodyRequest,
ModalCreateBodyRequest, ModalCreateBodyRequest,
ModalCreateOptions,
UnionToTuple, UnionToTuple,
When, When,
} from '../common'; } from '../common';
@ -120,11 +119,9 @@ export class ModalContext<M extends keyof RegisteredMiddlewares = never> extends
return this.interaction.deleteResponse(); return this.interaction.deleteResponse();
} }
modal(body: ModalCreateBodyRequest, options?: undefined): Promise<undefined>; modal(body: ModalCreateBodyRequest): ReturnType<Interaction['modal']> {
modal(body: ModalCreateBodyRequest, options: ModalCreateOptions): Promise<ModalSubmitInteraction | null>; //@ts-expect-error
modal(body: ModalCreateBodyRequest, options?: ModalCreateOptions | undefined) { return this.interaction.modal(body);
// @ts-expect-error
return this.interaction.modal(body, options);
} }
/** /**

View File

@ -4,11 +4,11 @@ import type { FileLoaded } from '../commands/handler';
import { import {
BaseHandler, BaseHandler,
type CamelCase, type CamelCase,
isCloudfareWorker,
type MakeRequired, type MakeRequired,
magicImport,
ReplaceRegex, ReplaceRegex,
type SnakeCase, type SnakeCase,
isCloudfareWorker,
magicImport,
} from '../common'; } from '../common';
import type { ClientEvents } from '../events/hooks'; import type { ClientEvents } from '../events/hooks';
import * as RawEvents from '../events/hooks'; import * as RawEvents from '../events/hooks';

View File

@ -1,6 +1,3 @@
import type { UsingClient } from '../../commands';
import { toCamelCase } from '../../common';
import { type AllChannels, channelFrom } from '../../structures';
import type { import type {
GatewayChannelCreateDispatchData, GatewayChannelCreateDispatchData,
GatewayChannelDeleteDispatchData, GatewayChannelDeleteDispatchData,
@ -8,6 +5,10 @@ import type {
GatewayChannelUpdateDispatchData, GatewayChannelUpdateDispatchData,
} from '../../types'; } from '../../types';
import type { UsingClient } from '../../commands';
import { toCamelCase } from '../../common';
import { type AllChannels, channelFrom } from '../../structures';
export const CHANNEL_CREATE = (self: UsingClient, data: GatewayChannelCreateDispatchData): AllChannels => { export const CHANNEL_CREATE = (self: UsingClient, data: GatewayChannelCreateDispatchData): AllChannels => {
return channelFrom(data, self); return channelFrom(data, self);
}; };

View File

@ -20,8 +20,8 @@ import type {
GatewayGuildIntegrationsUpdateDispatchData, GatewayGuildIntegrationsUpdateDispatchData,
GatewayGuildMemberAddDispatchData, GatewayGuildMemberAddDispatchData,
GatewayGuildMemberRemoveDispatchData, GatewayGuildMemberRemoveDispatchData,
GatewayGuildMembersChunkDispatchData,
GatewayGuildMemberUpdateDispatchData, GatewayGuildMemberUpdateDispatchData,
GatewayGuildMembersChunkDispatchData,
GatewayGuildRoleCreateDispatchData, GatewayGuildRoleCreateDispatchData,
GatewayGuildRoleDeleteDispatchData, GatewayGuildRoleDeleteDispatchData,
GatewayGuildRoleUpdateDispatchData, GatewayGuildRoleUpdateDispatchData,

View File

@ -10,13 +10,13 @@ export * from './interactions';
export * from './invite'; export * from './invite';
export * from './message'; export * from './message';
export * from './presence'; export * from './presence';
export * from './soundboard';
export * from './stage'; export * from './stage';
export * from './thread'; export * from './thread';
export * from './typing'; export * from './typing';
export * from './user'; export * from './user';
export * from './voice'; export * from './voice';
export * from './webhook'; export * from './webhook';
export * from './soundboard';
import type { CamelCase } from '../../common'; import type { CamelCase } from '../../common';
import type * as RawEvents from './index'; import type * as RawEvents from './index';

View File

@ -1,6 +1,6 @@
import { type MessageStructure, Transformers } from '../../client/transformers'; import { type MessageStructure, Transformers } from '../../client/transformers';
import type { UsingClient } from '../../commands'; import type { UsingClient } from '../../commands';
import { fakePromise, type ObjectToLower, type OmitInsert, toCamelCase } from '../../common'; import { type ObjectToLower, type OmitInsert, fakePromise, toCamelCase } from '../../common';
import type { import type {
GatewayMessageCreateDispatchData, GatewayMessageCreateDispatchData,
GatewayMessageDeleteBulkDispatchData, GatewayMessageDeleteBulkDispatchData,

View File

@ -5,8 +5,8 @@ import type {
APISoundBoard, APISoundBoard,
GatewayGuildSoundboardSoundCreateDispatchData, GatewayGuildSoundboardSoundCreateDispatchData,
GatewayGuildSoundboardSoundDeleteDispatchData, GatewayGuildSoundboardSoundDeleteDispatchData,
GatewayGuildSoundboardSoundsUpdateDispatchData,
GatewayGuildSoundboardSoundUpdateDispatchData, GatewayGuildSoundboardSoundUpdateDispatchData,
GatewayGuildSoundboardSoundsUpdateDispatchData,
GatewaySoundboardSoundsDispatchData, GatewaySoundboardSoundsDispatchData,
} from '../../types'; } from '../../types';

View File

@ -5,8 +5,8 @@ import type {
GatewayThreadCreateDispatchData, GatewayThreadCreateDispatchData,
GatewayThreadDeleteDispatchData, GatewayThreadDeleteDispatchData,
GatewayThreadListSyncDispatchData, GatewayThreadListSyncDispatchData,
GatewayThreadMembersUpdateDispatchData,
GatewayThreadMemberUpdateDispatchData, GatewayThreadMemberUpdateDispatchData,
GatewayThreadMembersUpdateDispatchData,
GatewayThreadUpdateDispatchData, GatewayThreadUpdateDispatchData,
} from '../../types'; } from '../../types';

View File

@ -1,5 +1,4 @@
export * from './client'; export * from './client';
import { import {
BaseClient, BaseClient,
type BaseClientOptions, type BaseClientOptions,
@ -11,22 +10,21 @@ import {
import { isCloudfareWorker } from './common'; import { isCloudfareWorker } from './common';
import type { ClientNameEvents, CustomEventsKeys, ResolveEventParams } from './events'; import type { ClientNameEvents, CustomEventsKeys, ResolveEventParams } from './events';
import { GatewayIntentBits } from './types'; import { GatewayIntentBits } from './types';
export { Logger, PermissionStrings, Formatter } from './common';
//
export { Collection, LimitedCollection } from './collection';
// //
export * from './api'; export * from './api';
export * from './builders'; export * from './builders';
export * from './cache'; export * from './cache';
//
export { Collection, LimitedCollection } from './collection';
export * from './commands'; export * from './commands';
export { Formatter, Logger, PermissionStrings } from './common';
export * from './components'; export * from './components';
export * from './events'; export * from './events';
export * from './langs'; export * from './langs';
// //
export * from './structures';
//
export { ShardManager, WorkerManager } from './websocket/discord'; export { ShardManager, WorkerManager } from './websocket/discord';
//
export * from './structures';
/** /**
* Creates an event with the specified data and run function. * Creates an event with the specified data and run function.

View File

@ -14,7 +14,6 @@ export const LangRouter = (userLocale: string, defaultLang: string, langs: Parti
function getValue(locale?: string) { function getValue(locale?: string) {
if (typeof locale === 'undefined') throw new Error('Undefined locale'); if (typeof locale === 'undefined') throw new Error('Undefined locale');
let value = langs[locale] as Record<string, any>; let value = langs[locale] as Record<string, any>;
if (typeof value === 'undefined') throw new Error(`Locale "${locale}" not found`);
for (const i of route) value = value[i]; for (const i of route) value = value[i];
return value; return value;
} }
@ -52,4 +51,4 @@ export type __InternalParseLocale<T extends Record<string, any>> = {
}; };
export type ParseLocales<T extends Record<string, any>> = T; export type ParseLocales<T extends Record<string, any>> = T;
/**Idea inspiration from: FreeAoi | Fixed by: Drylozu */ /**Idea inspiration from: FreeAoi */

View File

@ -1,18 +1,18 @@
import type { GuildMemberStructure, GuildStructure, ThreadChannelStructure } from '../client'; import type { GuildMemberStructure, GuildStructure } from '../client';
import type { UsingClient } from '../commands'; import type { UsingClient } from '../commands';
import type { CreateInviteFromChannel } from '../common'; import type { CreateInviteFromChannel } from '../common';
import type { ObjectToLower, StructPropState, StructStates, ToClass } from '../common/types/util'; import type { ObjectToLower, StructPropState, StructStates, ToClass } from '../common/types/util';
import type { APIGuild, APIPartialGuild, GatewayGuildCreateDispatchData, RESTPatchAPIGuildJSONBody } from '../types'; import type { APIGuild, APIPartialGuild, GatewayGuildCreateDispatchData, RESTPatchAPIGuildJSONBody } from '../types';
import { AutoModerationRule } from './AutoModerationRule'; import { AutoModerationRule } from './AutoModerationRule';
import { BaseChannel, WebhookGuildMethods } from './channels';
import { GuildEmoji } from './Emoji'; import { GuildEmoji } from './Emoji';
import { BaseGuild } from './extra/BaseGuild';
import type { DiscordBase } from './extra/DiscordBase';
import { GuildBan } from './GuildBan'; import { GuildBan } from './GuildBan';
import { GuildMember } from './GuildMember'; import { GuildMember } from './GuildMember';
import { GuildRole } from './GuildRole'; import { GuildRole } from './GuildRole';
import { GuildTemplate } from './GuildTemplate'; import { GuildTemplate } from './GuildTemplate';
import { Sticker } from './Sticker'; import { Sticker } from './Sticker';
import { BaseChannel, WebhookGuildMethods } from './channels';
import { BaseGuild } from './extra/BaseGuild';
import type { DiscordBase } from './extra/DiscordBase';
export interface Guild extends ObjectToLower<Omit<APIGuild, 'stickers' | 'emojis' | 'roles'>>, DiscordBase {} export interface Guild extends ObjectToLower<Omit<APIGuild, 'stickers' | 'emojis' | 'roles'>>, DiscordBase {}
export class Guild<State extends StructStates = 'api'> extends (BaseGuild as unknown as ToClass< export class Guild<State extends StructStates = 'api'> extends (BaseGuild as unknown as ToClass<
@ -71,10 +71,6 @@ export class Guild<State extends StructStates = 'api'> extends (BaseGuild as unk
return this.members.fetch(this.ownerId, force); return this.members.fetch(this.ownerId, force);
} }
listActiveThreads(force = false): Promise<ThreadChannelStructure[]> {
return this.client.threads.listGuildActive(this.id, force);
}
templates = GuildTemplate.methods({ client: this.client, guildId: this.id }); templates = GuildTemplate.methods({ client: this.client, guildId: this.id });
stickers = Sticker.methods({ client: this.client, guildId: this.id }); stickers = Sticker.methods({ client: this.client, guildId: this.id });
members = GuildMember.methods({ client: this.client, guildId: this.id }); members = GuildMember.methods({ client: this.client, guildId: this.id });

View File

@ -3,7 +3,7 @@ import type { GuildBanStructure, GuildStructure } from '../client';
import type { UsingClient } from '../commands'; import type { UsingClient } from '../commands';
import { Formatter, type MethodContext, type ObjectToLower } from '../common'; import { Formatter, type MethodContext, type ObjectToLower } from '../common';
import type { BanShorter } from '../common/shorters/bans'; import type { BanShorter } from '../common/shorters/bans';
import type { ActuallyBan, APIBan, RESTGetAPIGuildBansQuery } from '../types'; import type { APIBan, ActuallyBan, RESTGetAPIGuildBansQuery } from '../types';
import { DiscordBase } from './extra/DiscordBase'; import { DiscordBase } from './extra/DiscordBase';
export interface GuildBan extends DiscordBase, ObjectToLower<Omit<APIBan, 'id'>> {} export interface GuildBan extends DiscordBase, ObjectToLower<Omit<APIBan, 'id'>> {}

View File

@ -46,7 +46,7 @@ export class GuildRole extends DiscordBase {
return this.client.roles.edit(this.guildId, this.id, body); return this.client.roles.edit(this.guildId, this.id, body);
} }
delete(reason?: string) { delete(reason?: string): Promise<GuildRoleStructure> {
return this.client.roles.delete(this.guildId, this.id, reason); return this.client.roles.delete(this.guildId, this.id, reason);
} }
@ -61,7 +61,8 @@ export class GuildRole extends DiscordBase {
list: (force = false): Promise<GuildRoleStructure[]> => ctx.client.roles.list(ctx.guildId, force), list: (force = false): Promise<GuildRoleStructure[]> => ctx.client.roles.list(ctx.guildId, force),
edit: (roleId: string, body: RESTPatchAPIGuildRoleJSONBody, reason?: string): Promise<GuildRoleStructure> => edit: (roleId: string, body: RESTPatchAPIGuildRoleJSONBody, reason?: string): Promise<GuildRoleStructure> =>
ctx.client.roles.edit(ctx.guildId, roleId, body, reason), ctx.client.roles.edit(ctx.guildId, roleId, body, reason),
delete: (roleId: string, reason?: string) => ctx.client.roles.delete(ctx.guildId, roleId, reason), delete: (roleId: string, reason?: string): Promise<GuildRoleStructure> =>
ctx.client.roles.delete(ctx.guildId, roleId, reason),
editPositions: (body: RESTPatchAPIGuildRolePositionsJSONBody): Promise<GuildRoleStructure[]> => editPositions: (body: RESTPatchAPIGuildRolePositionsJSONBody): Promise<GuildRoleStructure[]> =>
ctx.client.roles.editPositions(ctx.guildId, body), ctx.client.roles.editPositions(ctx.guildId, body),
}; };

View File

@ -1,34 +1,3 @@
import type { RawFile } from '../api';
import { ActionRow, Embed, Modal, PollBuilder, resolveAttachment, resolveFiles } from '../builders';
import type { ReturnCache } from '../cache';
import {
type EntitlementStructure,
type GuildRoleStructure,
type GuildStructure,
type InteractionGuildMemberStructure,
type MessageStructure,
type OptionResolverStructure,
Transformers,
type UserStructure,
type WebhookMessageStructure,
} from '../client/transformers';
import type { ContextOptionsResolved, UsingClient } from '../commands';
import {
type ComponentInteractionMessageUpdate,
type InteractionCreateBodyRequest,
type InteractionMessageUpdateBodyRequest,
type MessageCreateBodyRequest,
type MessageUpdateBodyRequest,
type MessageWebhookCreateBodyRequest,
type ModalCreateBodyRequest,
ModalCreateOptions,
type ObjectToLower,
type OmitInsert,
type ToClass,
toCamelCase,
type When,
} from '../common';
import { mix } from '../deps/mixer';
import { import {
type APIActionRowComponent, type APIActionRowComponent,
type APIApplicationCommandAutocompleteInteraction, type APIApplicationCommandAutocompleteInteraction,
@ -72,6 +41,37 @@ import {
type RESTPostAPIInteractionCallbackJSONBody, type RESTPostAPIInteractionCallbackJSONBody,
type RESTPostAPIInteractionCallbackResult, type RESTPostAPIInteractionCallbackResult,
} from '../types'; } from '../types';
import type { RawFile } from '../api';
import { ActionRow, Embed, Modal, PollBuilder, resolveAttachment, resolveFiles } from '../builders';
import type { ReturnCache } from '../cache';
import {
type EntitlementStructure,
type GuildRoleStructure,
type GuildStructure,
type InteractionGuildMemberStructure,
type MessageStructure,
type OptionResolverStructure,
Transformers,
type UserStructure,
type WebhookMessageStructure,
} from '../client/transformers';
import type { ContextOptionsResolved, UsingClient } from '../commands';
import {
type ComponentInteractionMessageUpdate,
type InteractionCreateBodyRequest,
type InteractionMessageUpdateBodyRequest,
type MessageCreateBodyRequest,
type MessageUpdateBodyRequest,
type MessageWebhookCreateBodyRequest,
type ModalCreateBodyRequest,
type ObjectToLower,
type OmitInsert,
type ToClass,
type When,
toCamelCase,
} from '../common';
import { mix } from '../deps/mixer';
import { type AllChannels, channelFrom } from './'; import { type AllChannels, channelFrom } from './';
import { DiscordBase } from './extra/DiscordBase'; import { DiscordBase } from './extra/DiscordBase';
import { PermissionsBitField } from './extra/Permissions'; import { PermissionsBitField } from './extra/Permissions';
@ -196,7 +196,7 @@ export class BaseInteraction<
poll: poll ? (poll instanceof PollBuilder ? poll.toJSON() : poll) : undefined, poll: poll ? (poll instanceof PollBuilder ? poll.toJSON() : poll) : undefined,
}; };
if (Array.isArray(body.attachments)) { if ('attachments' in body) {
payload.attachments = payload.attachments =
body.attachments?.map((x, i) => ({ body.attachments?.map((x, i) => ({
id: x.id ?? i.toString(), id: x.id ?? i.toString(),
@ -315,6 +315,7 @@ export class BaseInteraction<
switch (gateway.type) { switch (gateway.type) {
case InteractionType.ApplicationCommandAutocomplete: case InteractionType.ApplicationCommandAutocomplete:
return new AutocompleteInteraction(client, gateway, undefined, __reply); return new AutocompleteInteraction(client, gateway, undefined, __reply);
// biome-ignore lint/suspicious/noFallthroughSwitchClause: bad interaction between biome and ts-server
case InteractionType.ApplicationCommand: case InteractionType.ApplicationCommand:
switch (gateway.data.type) { switch (gateway.data.type) {
case ApplicationCommandType.ChatInput: case ApplicationCommandType.ChatInput:
@ -473,37 +474,11 @@ export class Interaction<
) as never; ) as never;
} }
modal(body: ModalCreateBodyRequest, options?: undefined): Promise<undefined>; modal(body: ModalCreateBodyRequest) {
modal(body: ModalCreateBodyRequest, options: ModalCreateOptions): Promise<ModalSubmitInteraction | null>; return this.reply({
async modal(body: ModalCreateBodyRequest, options?: ModalCreateOptions | undefined) {
if (options !== undefined && !(body instanceof Modal)) {
body = new Modal(body);
}
if (options === undefined)
return this.reply({
type: InteractionResponseType.Modal,
data: body,
});
const promise = new Promise<ModalSubmitInteraction | null>(res => {
let nodeTimeout: NodeJS.Timeout | undefined;
// body is always a modal here, so we can safely cast it
(body as Modal).__exec = (interaction: ModalSubmitInteraction) => {
res(interaction);
clearTimeout(nodeTimeout);
};
if (options?.waitFor && options?.waitFor > 0) {
nodeTimeout = setTimeout(() => {
res(null);
}, options.waitFor);
}
});
await this.reply({
type: InteractionResponseType.Modal, type: InteractionResponseType.Modal,
data: body, data: body,
}); });
return promise;
} }
async editOrReply<FR extends boolean = false>( async editOrReply<FR extends boolean = false>(

View File

@ -1,4 +1,4 @@
import { type AllChannels, componentFactory, Embed, type ReturnCache } from '..'; import { type AllChannels, Embed, type ReturnCache, componentFactory } from '..';
import type { ListenerOptions } from '../builders'; import type { ListenerOptions } from '../builders';
import { import {
type GuildMemberStructure, type GuildMemberStructure,
@ -11,7 +11,8 @@ import {
type WebhookStructure, type WebhookStructure,
} from '../client/transformers'; } from '../client/transformers';
import type { UsingClient } from '../commands'; import type { UsingClient } from '../commands';
import { Formatter, type ObjectToLower, toCamelCase } from '../common'; import { type ObjectToLower, toCamelCase } from '../common';
import { Formatter } from '../common';
import type { EmojiResolvable } from '../common/types/resolvables'; import type { EmojiResolvable } from '../common/types/resolvables';
import type { MessageCreateBodyRequest, MessageUpdateBodyRequest } from '../common/types/write'; import type { MessageCreateBodyRequest, MessageUpdateBodyRequest } from '../common/types/write';
import type { TopLevelComponents } from '../components'; import type { TopLevelComponents } from '../components';
@ -23,8 +24,8 @@ import type {
APIUser, APIUser,
GatewayMessageCreateDispatchData, GatewayMessageCreateDispatchData,
} from '../types'; } from '../types';
import { DiscordBase } from './extra/DiscordBase';
import type { MessageWebhookMethodEditParams, MessageWebhookMethodWriteParams } from './Webhook'; import type { MessageWebhookMethodEditParams, MessageWebhookMethodWriteParams } from './Webhook';
import { DiscordBase } from './extra/DiscordBase';
export type MessageData = APIMessage | GatewayMessageCreateDispatchData; export type MessageData = APIMessage | GatewayMessageCreateDispatchData;

View File

@ -5,8 +5,8 @@ import {
type BaseChannelStructure, type BaseChannelStructure,
type BaseGuildChannelStructure, type BaseGuildChannelStructure,
type CategoryChannelStructure, type CategoryChannelStructure,
type DirectoryChannelStructure,
type DMChannelStructure, type DMChannelStructure,
type DirectoryChannelStructure,
type ForumChannelStructure, type ForumChannelStructure,
type GuildMemberStructure, type GuildMemberStructure,
type GuildStructure, type GuildStructure,
@ -26,13 +26,13 @@ import type { SeyfertChannelMap, UsingClient } from '../commands';
import { import {
type CreateInviteFromChannel, type CreateInviteFromChannel,
type EmojiResolvable, type EmojiResolvable,
fakePromise,
type MessageCreateBodyRequest, type MessageCreateBodyRequest,
type MessageUpdateBodyRequest, type MessageUpdateBodyRequest,
type MethodContext, type MethodContext,
type ObjectToLower, type ObjectToLower,
type StringToNumber, type StringToNumber,
type ToClass, type ToClass,
fakePromise,
} from '../common'; } from '../common';
import { mix } from '../deps/mixer'; import { mix } from '../deps/mixer';
import { import {
@ -63,9 +63,9 @@ import {
type ThreadAutoArchiveDuration, type ThreadAutoArchiveDuration,
VideoQualityMode, VideoQualityMode,
} from '../types'; } from '../types';
import { DiscordBase } from './extra/DiscordBase';
import type { GuildMember } from './GuildMember'; import type { GuildMember } from './GuildMember';
import type { GuildRole } from './GuildRole'; import type { GuildRole } from './GuildRole';
import { DiscordBase } from './extra/DiscordBase';
export class BaseNoEditableChannel<T extends ChannelType> extends DiscordBase<APIChannelBase<ChannelType>> { export class BaseNoEditableChannel<T extends ChannelType> extends DiscordBase<APIChannelBase<ChannelType>> {
declare type: T; declare type: T;
@ -581,15 +581,13 @@ export class ForumChannel extends BaseGuildChannel {
export interface ThreadChannel export interface ThreadChannel
extends ObjectToLower<Omit<APIThreadChannel, 'permission_overwrites' | 'guild_id'>>, extends ObjectToLower<Omit<APIThreadChannel, 'permission_overwrites' | 'guild_id'>>,
Omit<TextBaseGuildChannel, 'edit' | 'parentId'> { Omit<TextBaseGuildChannel, 'edit' | 'parentId'> {}
parentId: string;
}
@mix(TextBaseGuildChannel) @mix(TextBaseGuildChannel)
export class ThreadChannel extends BaseChannel< export class ThreadChannel extends BaseChannel<
ChannelType.PublicThread | ChannelType.AnnouncementThread | ChannelType.PrivateThread ChannelType.PublicThread | ChannelType.AnnouncementThread | ChannelType.PrivateThread
> { > {
parentId!: string;
declare type: ChannelType.PublicThread | ChannelType.AnnouncementThread | ChannelType.PrivateThread; declare type: ChannelType.PublicThread | ChannelType.AnnouncementThread | ChannelType.PrivateThread;
webhooks = WebhookChannelMethods.channel({ webhooks = WebhookChannelMethods.channel({
client: this.client, client: this.client,
channelId: this.parentId, channelId: this.parentId,

View File

@ -1,6 +1,6 @@
import type { ReturnCache, WorkerClient } from '../..'; import type { ReturnCache, WorkerClient } from '../..';
import type { GuildStructure } from '../../client'; import type { GuildStructure } from '../../client';
import { calculateShardId, type ObjectToLower } from '../../common'; import { type ObjectToLower, calculateShardId } from '../../common';
import type { ImageOptions } from '../../common/types/options'; import type { ImageOptions } from '../../common/types/options';
import { type APIPartialGuild, GuildFeature } from '../../types'; import { type APIPartialGuild, GuildFeature } from '../../types';
import type { ShardManager } from '../../websocket'; import type { ShardManager } from '../../websocket';

View File

@ -1,19 +1,19 @@
export * from './AnonymousGuild'; export * from './AnonymousGuild';
export * from './AutoModerationRule'; export * from './AutoModerationRule';
export * from './ClientUser'; export * from './ClientUser';
export * from './channels';
export * from './Emoji';
export * from './Entitlement';
export * from './Guild'; export * from './Guild';
export * from './GuildBan'; export * from './Emoji';
export * from './GuildMember'; export * from './GuildMember';
export * from './GuildPreview'; export * from './GuildPreview';
export * from './GuildRole'; export * from './GuildRole';
export * from './GuildTemplate'; export * from './GuildTemplate';
export * from './Interaction'; export * from './Interaction';
export * from './Message'; export * from './Message';
export * from './Poll';
export * from './Sticker'; export * from './Sticker';
export * from './User'; export * from './User';
export * from './VoiceState'; export * from './VoiceState';
export * from './Webhook'; export * from './Webhook';
export * from './channels';
export * from './Poll';
export * from './GuildBan';
export * from './Entitlement';

View File

@ -23,8 +23,8 @@
*/ */
export * from './gateway'; export * from './gateway';
export * from './payloads';
export * from './rest'; export * from './rest';
export * from './payloads';
export * from './rest'; export * from './rest';
export * from './utils'; export * from './utils';

View File

@ -1,6 +1,7 @@
import type { ChannelType, Permissions, Snowflake } from '../..';
import type { LocaleString } from '../../rest';
import type { ApplicationIntegrationType, InteractionContextType } from '..'; import type { ApplicationIntegrationType, InteractionContextType } from '..';
import type { ChannelType, Permissions, Snowflake } from '../..';
import type { LocaleString } from '../../rest';
import type { import type {
APIAttachment, APIAttachment,
APIChannel, APIChannel,

View File

@ -2,9 +2,9 @@
* Types extracted from https://discord.com/developers/docs/resources/application * Types extracted from https://discord.com/developers/docs/resources/application
*/ */
import type { MakeRequired } from '../../common';
import type { Permissions, Snowflake } from '..';
import type { APIEmoji, LocalizationMap } from '.'; import type { APIEmoji, LocalizationMap } from '.';
import type { Permissions, Snowflake } from '..';
import type { MakeRequired } from '../../common';
import type { APIPartialGuild } from './guild'; import type { APIPartialGuild } from './guild';
import type { ApplicationIntegrationType } from './interactions'; import type { ApplicationIntegrationType } from './interactions';
import type { OAuth2Scopes } from './oauth2'; import type { OAuth2Scopes } from './oauth2';

View File

@ -1,5 +1,5 @@
import type { Identify, MakeRequired } from '../../common';
import type { APIAttachment, Snowflake } from '..'; import type { APIAttachment, Snowflake } from '..';
import type { Identify, MakeRequired } from '../../common';
import type { ChannelType } from '../utils'; import type { ChannelType } from '../utils';
/** /**
@ -260,7 +260,7 @@ export type APIRoleSelectComponent = APIBaseAutoPopulatedSelectMenuComponent<
*/ */
export type APIMentionableSelectComponent = APIBaseAutoPopulatedSelectMenuComponent< export type APIMentionableSelectComponent = APIBaseAutoPopulatedSelectMenuComponent<
ComponentType.MentionableSelect, ComponentType.MentionableSelect,
SelectMenuDefaultValueType SelectMenuDefaultValueType.Role | SelectMenuDefaultValueType.User
>; >;
/** /**
@ -448,7 +448,7 @@ export interface APISectionComponent {
/** Optional identifier for component */ /** Optional identifier for component */
id?: number; id?: number;
/** One to three text components */ /** One to three text components */
components: APITextDisplayComponent[]; components: APITextDispalyComponent[];
/** A thumbnail or a button component, with a future possibility of adding more compatible components */ /** A thumbnail or a button component, with a future possibility of adding more compatible components */
accessory: APIButtonComponent | APIThumbnailComponent; accessory: APIButtonComponent | APIThumbnailComponent;
} }
@ -459,7 +459,7 @@ export interface APISectionComponent {
* A Text Display is a top-level content component that allows you to add text to your message formatted with markdown and mention users and roles. This is similar to the content field of a message, but allows you to add multiple text components, controlling the layout of your message. * A Text Display is a top-level content component that allows you to add text to your message formatted with markdown and mention users and roles. This is similar to the content field of a message, but allows you to add multiple text components, controlling the layout of your message.
* Text Displays are only available in messages. * Text Displays are only available in messages.
*/ */
export interface APITextDisplayComponent { export interface APITextDispalyComponent {
/** 10 for text display */ /** 10 for text display */
type: ComponentType.TextDisplay; type: ComponentType.TextDisplay;
/** Optional identifier for component */ /** Optional identifier for component */
@ -553,7 +553,7 @@ export enum Spacing {
export type APIContainerComponents = export type APIContainerComponents =
| APIActionRowComponent<APIActionRowComponentTypes> | APIActionRowComponent<APIActionRowComponentTypes>
| APITextDisplayComponent | APITextDispalyComponent
| APISectionComponent | APISectionComponent
| APIMediaGalleryComponent | APIMediaGalleryComponent
| APIFileComponent | APIFileComponent
@ -591,4 +591,4 @@ export type APITopLevelComponent =
| APIMediaGalleryComponent | APIMediaGalleryComponent
| APISectionComponent | APISectionComponent
| APISeparatorComponent | APISeparatorComponent
| APITextDisplayComponent; | APITextDispalyComponent;

View File

@ -1,7 +1,6 @@
import type { Snowflake } from '..'; import type { Snowflake } from '..';
import type { APIGuildMember } from './guild'; import type { APIGuildMember } from './guild';
import type { APIUser } from './user'; import type { APIUser } from './user';
interface APIGuildScheduledEventBase<Type extends GuildScheduledEventEntityType> { interface APIGuildScheduledEventBase<Type extends GuildScheduledEventEntityType> {
/** /**
* The id of the guild event * The id of the guild event

View File

@ -2,18 +2,15 @@ export * from './application';
export * from './auditLog'; export * from './auditLog';
export * from './autoModeration'; export * from './autoModeration';
export * from './channel'; export * from './channel';
export * from './components';
export * from './emoji'; export * from './emoji';
export * from './gateway'; export * from './gateway';
export * from './guild'; export * from './guild';
export * from './guildScheduledEvent'; export * from './guildScheduledEvent';
export * from './interactions'; export * from './interactions';
export * from './invite'; export * from './invite';
export * from './monetization';
export * from './oauth2'; export * from './oauth2';
export * from './permissions';
export * from './poll'; export * from './poll';
export * from './soundboard'; export * from './permissions';
export * from './stageInstance'; export * from './stageInstance';
export * from './sticker'; export * from './sticker';
export * from './teams'; export * from './teams';
@ -21,6 +18,9 @@ export * from './template';
export * from './user'; export * from './user';
export * from './voice'; export * from './voice';
export * from './webhook'; export * from './webhook';
export * from './monetization';
export * from './soundboard';
export * from './components';
import type { LocaleString } from '../rest'; import type { LocaleString } from '../rest';

View File

@ -85,7 +85,7 @@ export type RESTPatchAPIApplicationEmojiResult = APIApplicationEmoji;
/** /**
* https://discord.com/developers/docs/resources/emoji#delete-application-emoji * https://discord.com/developers/docs/resources/emoji#delete-application-emoji
*/ */
export type RESTDeleteAPIApplicationEmojiResult = undefined; export type RESTDeleteAPIApplicationEmojiResult = never;
/** /**
* https://discord.com/developers/docs/resources/application#get-application-activity-instance * https://discord.com/developers/docs/resources/application#get-application-activity-instance

View File

@ -80,4 +80,4 @@ export type RESTPatchAPIAutoModerationRuleResult = APIAutoModerationRule;
/** /**
* https://discord.com/developers/docs/resources/auto-moderation#delete-auto-moderation-rule * https://discord.com/developers/docs/resources/auto-moderation#delete-auto-moderation-rule
*/ */
export type RESTDeleteAPIAutoModerationRuleResult = undefined; export type RESTDeleteAPIAutoModerationRuleResult = never;

View File

@ -344,17 +344,17 @@ export type RESTPostAPIChannelMessageCrosspostResult = APIMessage;
/** /**
* https://discord.com/developers/docs/resources/channel#create-reaction * https://discord.com/developers/docs/resources/channel#create-reaction
*/ */
export type RESTPutAPIChannelMessageReactionResult = undefined; export type RESTPutAPIChannelMessageReactionResult = never;
/** /**
* https://discord.com/developers/docs/resources/channel#delete-own-reaction * https://discord.com/developers/docs/resources/channel#delete-own-reaction
*/ */
export type RESTDeleteAPIChannelMessageOwnReaction = undefined; export type RESTDeleteAPIChannelMessageOwnReaction = never;
/** /**
* https://discord.com/developers/docs/resources/channel#delete-user-reaction * https://discord.com/developers/docs/resources/channel#delete-user-reaction
*/ */
export type RESTDeleteAPIChannelMessageUserReactionResult = undefined; export type RESTDeleteAPIChannelMessageUserReactionResult = never;
/** /**
* https://discord.com/developers/docs/resources/channel#get-reactions * https://discord.com/developers/docs/resources/channel#get-reactions
@ -392,12 +392,12 @@ export type RESTGetAPIChannelMessageReactionUsersResult = APIUser[];
/** /**
* https://discord.com/developers/docs/resources/channel#delete-all-reactions * https://discord.com/developers/docs/resources/channel#delete-all-reactions
*/ */
export type RESTDeleteAPIChannelAllMessageReactionsResult = undefined; export type RESTDeleteAPIChannelAllMessageReactionsResult = never;
/** /**
* https://discord.com/developers/docs/resources/channel#delete-all-reactions-for-emoji * https://discord.com/developers/docs/resources/channel#delete-all-reactions-for-emoji
*/ */
export type RESTDeleteAPIChannelMessageReactionResult = undefined; export type RESTDeleteAPIChannelMessageReactionResult = never;
/** /**
* https://discord.com/developers/docs/resources/channel#edit-message * https://discord.com/developers/docs/resources/channel#edit-message
@ -464,7 +464,7 @@ export type RESTPatchAPIChannelMessageResult = APIMessage;
/** /**
* https://discord.com/developers/docs/resources/channel#delete-message * https://discord.com/developers/docs/resources/channel#delete-message
*/ */
export type RESTDeleteAPIChannelMessageResult = undefined; export type RESTDeleteAPIChannelMessageResult = never;
/** /**
* https://discord.com/developers/docs/resources/channel#bulk-delete-messages * https://discord.com/developers/docs/resources/channel#bulk-delete-messages
@ -479,7 +479,7 @@ export interface RESTPostAPIChannelMessagesBulkDeleteJSONBody {
/** /**
* https://discord.com/developers/docs/resources/channel#bulk-delete-messages * https://discord.com/developers/docs/resources/channel#bulk-delete-messages
*/ */
export type RESTPostAPIChannelMessagesBulkDeleteResult = undefined; export type RESTPostAPIChannelMessagesBulkDeleteResult = never;
/** /**
* https://discord.com/developers/docs/resources/channel#edit-channel-permissions * https://discord.com/developers/docs/resources/channel#edit-channel-permissions
@ -510,7 +510,7 @@ export interface RESTPutAPIChannelPermissionJSONBody {
/** /**
* https://discord.com/developers/docs/resources/channel#edit-channel-permissions * https://discord.com/developers/docs/resources/channel#edit-channel-permissions
*/ */
export type RESTPutAPIChannelPermissionResult = undefined; export type RESTPutAPIChannelPermissionResult = never;
/** /**
* https://discord.com/developers/docs/resources/channel#get-channel-invites * https://discord.com/developers/docs/resources/channel#get-channel-invites
@ -574,7 +574,7 @@ export type RESTPostAPIChannelInviteResult = APIExtendedInvite;
/** /**
* https://discord.com/developers/docs/resources/channel#delete-channel-permission * https://discord.com/developers/docs/resources/channel#delete-channel-permission
*/ */
export type RESTDeleteAPIChannelPermissionResult = undefined; export type RESTDeleteAPIChannelPermissionResult = never;
/** /**
* https://discord.com/developers/docs/resources/channel#follow-news-channel * https://discord.com/developers/docs/resources/channel#follow-news-channel
@ -594,7 +594,7 @@ export type RESTPostAPIChannelFollowersResult = APIFollowedChannel;
/** /**
* https://discord.com/developers/docs/resources/channel#trigger-typing-indicator * https://discord.com/developers/docs/resources/channel#trigger-typing-indicator
*/ */
export type RESTPostAPIChannelTypingResult = undefined; export type RESTPostAPIChannelTypingResult = never;
/** /**
* https://discord.com/developers/docs/resources/channel#get-pinned-messages * https://discord.com/developers/docs/resources/channel#get-pinned-messages
@ -604,12 +604,12 @@ export type RESTGetAPIChannelPinsResult = APIMessage[];
/** /**
* https://discord.com/developers/docs/resources/channel#pin-message * https://discord.com/developers/docs/resources/channel#pin-message
*/ */
export type RESTPutAPIChannelPinResult = undefined; export type RESTPutAPIChannelPinResult = never;
/** /**
* https://discord.com/developers/docs/resources/channel#unpin-message * https://discord.com/developers/docs/resources/channel#unpin-message
*/ */
export type RESTDeleteAPIChannelPinResult = undefined; export type RESTDeleteAPIChannelPinResult = never;
/** /**
* https://discord.com/developers/docs/resources/channel#group-dm-add-recipient * https://discord.com/developers/docs/resources/channel#group-dm-add-recipient
@ -711,12 +711,12 @@ export type RESTPostAPIChannelThreadsResult = APIChannel;
/** /**
* https://discord.com/developers/docs/resources/channel#join-thread * https://discord.com/developers/docs/resources/channel#join-thread
*/ */
export type RESTPutAPIChannelThreadMembersResult = undefined; export type RESTPutAPIChannelThreadMembersResult = never;
/** /**
* https://discord.com/developers/docs/resources/channel#leave-thread * https://discord.com/developers/docs/resources/channel#leave-thread
*/ */
export type RESTDeleteAPIChannelThreadMembersResult = undefined; export type RESTDeleteAPIChannelThreadMembersResult = never;
/** /**
* https://discord.com/developers/docs/resources/channel#get-thread-member * https://discord.com/developers/docs/resources/channel#get-thread-member

View File

@ -58,4 +58,4 @@ export type RESTPatchAPIGuildEmojiResult = APIEmoji;
/** /**
* https://discord.com/developers/docs/resources/emoji#delete-guild-emoji * https://discord.com/developers/docs/resources/emoji#delete-guild-emoji
*/ */
export type RESTDeleteAPIGuildEmojiResult = undefined; export type RESTDeleteAPIGuildEmojiResult = never;

View File

@ -322,7 +322,7 @@ export type RESTPatchAPIGuildResult = APIGuild;
/** /**
* https://discord.com/developers/docs/resources/guild#delete-guild * https://discord.com/developers/docs/resources/guild#delete-guild
*/ */
export type RESTDeleteAPIGuildResult = undefined; export type RESTDeleteAPIGuildResult = never;
/** /**
* https://discord.com/developers/docs/resources/guild#get-guild-channels * https://discord.com/developers/docs/resources/guild#get-guild-channels
@ -364,7 +364,7 @@ export type RESTPatchAPIGuildChannelPositionsJSONBody = {
/** /**
* https://discord.com/developers/docs/resources/guild#modify-guild-channel-positions * https://discord.com/developers/docs/resources/guild#modify-guild-channel-positions
*/ */
export type RESTPatchAPIGuildChannelPositionsResult = undefined; export type RESTPatchAPIGuildChannelPositionsResult = never;
/** /**
* https://discord.com/developers/docs/resources/guild#list-active-guild-threads * https://discord.com/developers/docs/resources/guild#list-active-guild-threads
@ -513,17 +513,17 @@ export interface RESTPatchAPICurrentGuildMemberJSONBody {
/** /**
* https://discord.com/developers/docs/resources/guild#add-guild-member-role * https://discord.com/developers/docs/resources/guild#add-guild-member-role
*/ */
export type RESTPutAPIGuildMemberRoleResult = undefined; export type RESTPutAPIGuildMemberRoleResult = never;
/** /**
* https://discord.com/developers/docs/resources/guild#remove-guild-member-role * https://discord.com/developers/docs/resources/guild#remove-guild-member-role
*/ */
export type RESTDeleteAPIGuildMemberRoleResult = undefined; export type RESTDeleteAPIGuildMemberRoleResult = never;
/** /**
* https://discord.com/developers/docs/resources/guild#remove-guild-member * https://discord.com/developers/docs/resources/guild#remove-guild-member
*/ */
export type RESTDeleteAPIGuildMemberResult = undefined; export type RESTDeleteAPIGuildMemberResult = never;
/** /**
* https://discord.com/developers/docs/resources/guild#get-guild-bans * https://discord.com/developers/docs/resources/guild#get-guild-bans
@ -568,12 +568,12 @@ export interface RESTPutAPIGuildBanJSONBody {
/** /**
* https://discord.com/developers/docs/resources/guild#create-guild-ban * https://discord.com/developers/docs/resources/guild#create-guild-ban
*/ */
export type RESTPutAPIGuildBanResult = undefined; export type RESTPutAPIGuildBanResult = never;
/** /**
* https://discord.com/developers/docs/resources/guild#remove-guild-ban * https://discord.com/developers/docs/resources/guild#remove-guild-ban
*/ */
export type RESTDeleteAPIGuildBanResult = undefined; export type RESTDeleteAPIGuildBanResult = never;
/** /**
* https://discord.com/developers/docs/resources/guild#bulk-guild-ban * https://discord.com/developers/docs/resources/guild#bulk-guild-ban
@ -723,7 +723,7 @@ export type RESTPatchAPIGuildRoleResult = APIRole;
/** /**
* https://discord.com/developers/docs/resources/guild#delete-guild-role * https://discord.com/developers/docs/resources/guild#delete-guild-role
*/ */
export type RESTDeleteAPIGuildRoleResult = undefined; export type RESTDeleteAPIGuildRoleResult = never;
/** /**
* https://discord.com/developers/docs/resources/guild#get-guild-prune-count * https://discord.com/developers/docs/resources/guild#get-guild-prune-count
@ -800,7 +800,7 @@ export type RESTGetAPIGuildIntegrationsResult = APIGuildIntegration[];
/** /**
* https://discord.com/developers/docs/resources/guild#delete-guild-integration * https://discord.com/developers/docs/resources/guild#delete-guild-integration
*/ */
export type RESTDeleteAPIGuildIntegrationResult = undefined; export type RESTDeleteAPIGuildIntegrationResult = never;
/** /**
* https://discord.com/developers/docs/resources/guild#get-guild-widget-settings * https://discord.com/developers/docs/resources/guild#get-guild-widget-settings
@ -888,7 +888,7 @@ export interface RESTPatchAPIGuildVoiceStateCurrentMemberJSONBody {
/** /**
* https://discord.com/developers/docs/resources/guild#modify-current-user-voice-state * https://discord.com/developers/docs/resources/guild#modify-current-user-voice-state
*/ */
export type RESTPatchAPIGuildVoiceStateCurrentMemberResult = undefined; export type RESTPatchAPIGuildVoiceStateCurrentMemberResult = never;
/** /**
* https://discord.com/developers/docs/resources/guild#modify-user-voice-state * https://discord.com/developers/docs/resources/guild#modify-user-voice-state
@ -907,7 +907,7 @@ export interface RESTPatchAPIGuildVoiceStateUserJSONBody {
/** /**
* https://discord.com/developers/docs/resources/guild#modify-user-voice-state * https://discord.com/developers/docs/resources/guild#modify-user-voice-state
*/ */
export type RESTPatchAPIGuildVoiceStateUserResult = undefined; export type RESTPatchAPIGuildVoiceStateUserResult = never;
/** /**
* https://discord.com/developers/docs/resources/guild#get-guild-welcome-screen * https://discord.com/developers/docs/resources/guild#get-guild-welcome-screen

View File

@ -106,7 +106,7 @@ export type RESTPatchAPIGuildScheduledEventResult = APIGuildScheduledEvent;
/** /**
* https://discord.com/developers/docs/resources/guild-scheduled-event#delete-guild-scheduled-event * https://discord.com/developers/docs/resources/guild-scheduled-event#delete-guild-scheduled-event
*/ */
export type RESTDeleteAPIGuildScheduledEventResult = undefined; export type RESTDeleteAPIGuildScheduledEventResult = never;
/** /**
* https://discord.com/developers/docs/resources/guild-scheduled-event#get-guild-scheduled-event-users * https://discord.com/developers/docs/resources/guild-scheduled-event#get-guild-scheduled-event-users

View File

@ -10,16 +10,16 @@ export * from './guild';
export * from './guildScheduledEvent'; export * from './guildScheduledEvent';
export * from './interactions'; export * from './interactions';
export * from './invite'; export * from './invite';
export * from './monetization';
export * from './oauth2'; export * from './oauth2';
export * from './poll'; export * from './poll';
export * from './soundboard';
export * from './stageInstance'; export * from './stageInstance';
export * from './sticker'; export * from './sticker';
export * from './template'; export * from './template';
export * from './user'; export * from './user';
export * from './voice'; export * from './voice';
export * from './webhook'; export * from './webhook';
export * from './monetization';
export * from './soundboard';
export type DefaultUserAvatarAssets = 0 | 1 | 2 | 3 | 4 | 5; export type DefaultUserAvatarAssets = 0 | 1 | 2 | 3 | 4 | 5;

View File

@ -86,7 +86,7 @@ export enum EntitlementOwnerType {
/** /**
* https://discord.com/developers/docs/monetization/entitlements#delete-test-entitlement * https://discord.com/developers/docs/monetization/entitlements#delete-test-entitlement
*/ */
export type RESTDeleteAPIEntitlementResult = undefined; export type RESTDeleteAPIEntitlementResult = never;
/** /**
* https://discord.com/developers/docs/monetization/skus#list-skus * https://discord.com/developers/docs/monetization/skus#list-skus
@ -96,7 +96,7 @@ export type RESTGetAPISKUsResult = APISKU[];
/** /**
* https://discord.com/developers/docs/monetization/entitlements#consume-an-entitlement * https://discord.com/developers/docs/monetization/entitlements#consume-an-entitlement
*/ */
export type RESTPostAPIEntitlementConsumeResult = undefined; export type RESTPostAPIEntitlementConsumeResult = never;
/** /**
* https://canary.discord.com/developers/docs/resources/subscription#query-string-params * https://canary.discord.com/developers/docs/resources/subscription#query-string-params

View File

@ -67,4 +67,4 @@ export type RESTPatchAPIGuildSoundboardSoundResult = APISoundBoard;
* This endpoint supports the X-Audit-Log-Reason header. * This endpoint supports the X-Audit-Log-Reason header.
* @fires GuildSoundboardSoundDelete * @fires GuildSoundboardSoundDelete
*/ */
export type RESTDeleteAPIGuildSoundboardSoundResult = undefined; export type RESTDeleteAPIGuildSoundboardSoundResult = never;

View File

@ -61,4 +61,4 @@ export type RESTPatchAPIStageInstanceResult = APIStageInstance;
/** /**
* https://discord.com/developers/docs/resources/stage-instance#delete-stage-instance * https://discord.com/developers/docs/resources/stage-instance#delete-stage-instance
*/ */
export type RESTDeleteAPIStageInstanceResult = undefined; export type RESTDeleteAPIStageInstanceResult = never;

View File

@ -82,4 +82,4 @@ export type RESTPatchAPIGuildStickerResult = APISticker;
/** /**
* https://discord.com/developers/docs/resources/sticker#delete-guild-sticker * https://discord.com/developers/docs/resources/sticker#delete-guild-sticker
*/ */
export type RESTDeleteAPIGuildStickerResult = undefined; export type RESTDeleteAPIGuildStickerResult = never;

View File

@ -91,7 +91,7 @@ export type RESTGetAPICurrentUserGuildsResult = RESTAPIPartialCurrentUserGuild[]
/** /**
* https://discord.com/developers/docs/resources/user#leave-guild * https://discord.com/developers/docs/resources/user#leave-guild
*/ */
export type RESTDeleteAPICurrentUserGuildResult = undefined; export type RESTDeleteAPICurrentUserGuildResult = never;
/** /**
* https://discord.com/developers/docs/resources/user#create-dm * https://discord.com/developers/docs/resources/user#create-dm

View File

@ -89,12 +89,12 @@ export type RESTPatchAPIWebhookWithTokenResult = RESTGetAPIWebhookWithTokenResul
/** /**
* https://discord.com/developers/docs/resources/webhook#delete-webhook * https://discord.com/developers/docs/resources/webhook#delete-webhook
*/ */
export type RESTDeleteAPIWebhookResult = undefined; export type RESTDeleteAPIWebhookResult = never;
/** /**
* https://discord.com/developers/docs/resources/webhook#delete-webhook-with-token * https://discord.com/developers/docs/resources/webhook#delete-webhook-with-token
*/ */
export type RESTDeleteAPIWebhookWithTokenResult = undefined; export type RESTDeleteAPIWebhookWithTokenResult = never;
/** /**
* https://discord.com/developers/docs/resources/webhook#execute-webhook * https://discord.com/developers/docs/resources/webhook#execute-webhook
@ -202,7 +202,7 @@ export interface RESTPostAPIWebhookWithTokenQuery {
/** /**
* https://discord.com/developers/docs/resources/webhook#execute-webhook * https://discord.com/developers/docs/resources/webhook#execute-webhook
*/ */
export type RESTPostAPIWebhookWithTokenResult = undefined; export type RESTPostAPIWebhookWithTokenResult = never;
/** /**
* Received when a call to https://discord.com/developers/docs/resources/webhook#execute-webhook receives * Received when a call to https://discord.com/developers/docs/resources/webhook#execute-webhook receives
@ -220,7 +220,7 @@ export type RESTPostAPIWebhookWithTokenSlackQuery = Omit<RESTPostAPIWebhookWithT
/** /**
* https://discord.com/developers/docs/resources/webhook#execute-slackcompatible-webhook * https://discord.com/developers/docs/resources/webhook#execute-slackcompatible-webhook
*/ */
export type RESTPostAPIWebhookWithTokenSlackResult = undefined; export type RESTPostAPIWebhookWithTokenSlackResult = never;
/** /**
* Received when a call to https://discord.com/developers/docs/resources/webhook#execute-webhook receives * Received when a call to https://discord.com/developers/docs/resources/webhook#execute-webhook receives
@ -238,7 +238,7 @@ export type RESTPostAPIWebhookWithTokenGitHubQuery = Omit<RESTPostAPIWebhookWith
/** /**
* https://discord.com/developers/docs/resources/webhook#execute-githubcompatible-webhook * https://discord.com/developers/docs/resources/webhook#execute-githubcompatible-webhook
*/ */
export type RESTPostAPIWebhookWithTokenGitHubResult = undefined; export type RESTPostAPIWebhookWithTokenGitHubResult = never;
/** /**
* Received when a call to https://discord.com/developers/docs/resources/webhook#execute-webhook receives * Received when a call to https://discord.com/developers/docs/resources/webhook#execute-webhook receives
@ -297,4 +297,4 @@ export type RESTPatchAPIWebhookWithTokenMessageResult = APIMessage;
/** /**
* https://discord.com/developers/docs/resources/webhook#delete-webhook-message * https://discord.com/developers/docs/resources/webhook#delete-webhook-message
*/ */
export type RESTDeleteAPIWebhookWithTokenMessageResult = undefined; export type RESTDeleteAPIWebhookWithTokenMessageResult = never;

View File

@ -23,8 +23,8 @@ import type {
GatewayGuildIntegrationsUpdateDispatchData, GatewayGuildIntegrationsUpdateDispatchData,
GatewayGuildMemberAddDispatchData, GatewayGuildMemberAddDispatchData,
GatewayGuildMemberRemoveDispatchData, GatewayGuildMemberRemoveDispatchData,
GatewayGuildMembersChunkDispatchData,
GatewayGuildMemberUpdateDispatchData, GatewayGuildMemberUpdateDispatchData,
GatewayGuildMembersChunkDispatchData,
GatewayGuildRoleCreateDispatchData, GatewayGuildRoleCreateDispatchData,
GatewayGuildRoleDeleteDispatchData, GatewayGuildRoleDeleteDispatchData,
GatewayGuildRoleUpdateDispatchData, GatewayGuildRoleUpdateDispatchData,
@ -55,8 +55,8 @@ import type {
GatewayThreadCreateDispatchData, GatewayThreadCreateDispatchData,
GatewayThreadDeleteDispatchData, GatewayThreadDeleteDispatchData,
GatewayThreadListSyncDispatchData, GatewayThreadListSyncDispatchData,
GatewayThreadMembersUpdateDispatchData,
GatewayThreadMemberUpdateDispatchData, GatewayThreadMemberUpdateDispatchData,
GatewayThreadMembersUpdateDispatchData,
GatewayTypingStartDispatchData, GatewayTypingStartDispatchData,
GatewayUserUpdateDispatchData, GatewayUserUpdateDispatchData,
GatewayVoiceChannelEffectSendDispachData, GatewayVoiceChannelEffectSendDispachData,

View File

@ -25,14 +25,14 @@ export class BaseSocket {
return new Promise<number>(res => { return new Promise<number>(res => {
const nonce = randomUUID(); const nonce = randomUUID();
const start = performance.now(); const start = performance.now();
const listener = ({ data }: MessageEvent) => { const listener = (data: Buffer) => {
if (data.toString() !== nonce) return; if (data.toString() !== nonce) return;
//@ts-expect-error //@ts-expect-error
ws.removeEventListener('pong', listener); ws.removeListener('pong', listener);
res(performance.now() - start); res(performance.now() - start);
}; };
//@ts-expect-error //@ts-expect-error
ws.addEventListener('pong', listener); ws.on('pong', listener);
//@ts-expect-error //@ts-expect-error
ws.ping(nonce); ws.ping(nonce);
}); });

View File

@ -1,43 +0,0 @@
import type { Awaitable } from '../../common';
export type WorkerHeartbeaterMessages = SendHeartbeat;
export type CreateHeartbeaterMessage<T extends string, D extends object = object> = { type: T } & D;
export type SendHeartbeat = CreateHeartbeaterMessage<'HEARTBEAT'>;
export class Heartbeater {
store = new Map<
number,
{
ack: boolean;
interval: NodeJS.Timeout;
}
>();
constructor(
public sendMethod: (workerId: number, data: WorkerHeartbeaterMessages) => Awaitable<void>,
public interval: number,
) {}
register(workerId: number, recreate: (workerId: number) => Awaitable<void>) {
if (this.interval <= 0) return;
this.store.set(workerId, {
ack: true,
interval: setInterval(() => {
const heartbeat = this.store.get(workerId)!;
if (!heartbeat.ack) {
heartbeat.ack = true;
return recreate(workerId);
}
heartbeat.ack = false;
this.sendMethod(workerId, { type: 'HEARTBEAT' });
}, this.interval),
});
}
acknowledge(workerId: number) {
const heartbeat = this.store.get(workerId);
if (!heartbeat) return;
heartbeat.ack = true;
}
}

View File

@ -1,5 +1,5 @@
import { inflateSync } from 'node:zlib'; import { inflateSync } from 'node:zlib';
import { delay, hasIntent, Logger, LogLevels, type MakeRequired, MergeOptions } from '../../common'; import { LogLevels, Logger, type MakeRequired, MergeOptions, delay, hasIntent } from '../../common';
import { import {
type APIGuildMember, type APIGuildMember,
GatewayCloseCodes, GatewayCloseCodes,
@ -45,7 +45,7 @@ export class Shard {
bucket: DynamicBucket; bucket: DynamicBucket;
offlineSendQueue: ((_?: unknown) => void)[] = []; offlineSendQueue: ((_?: unknown) => void)[] = [];
pendingGuilds?: Set<string>; pendingGuilds = new Set<string>();
options: MakeRequired<ShardOptions, 'properties' | 'ratelimitOptions' | 'reconnectTimeout' | 'connectionTimeout'>; options: MakeRequired<ShardOptions, 'properties' | 'ratelimitOptions' | 'reconnectTimeout' | 'connectionTimeout'>;
isReady = false; isReady = false;
@ -56,7 +56,10 @@ export class Shard {
{ {
members: APIGuildMember[]; members: APIGuildMember[];
presences: GatewayGuildMembersChunkPresence[]; presences: GatewayGuildMembersChunkPresence[];
resolve: (value: { members: APIGuildMember[]; presences: GatewayGuildMembersChunkPresence[] }) => void; resolve: (value: {
members: APIGuildMember[];
presences: GatewayGuildMembersChunkPresence[];
}) => void;
reject: (reason?: any) => void; reject: (reason?: any) => void;
} }
>(); >();
@ -135,6 +138,7 @@ export class Shard {
); );
// @ts-expect-error Use native websocket when using Bun // @ts-expect-error Use native websocket when using Bun
// biome-ignore lint/correctness/noUndeclaredVariables: /\
this.websocket = new BaseSocket(typeof Bun === 'undefined' ? 'ws' : 'bun', this.currentGatewayURL); this.websocket = new BaseSocket(typeof Bun === 'undefined' ? 'ws' : 'bun', this.currentGatewayURL);
this.websocket.onmessage = ({ data }: { data: string | Buffer }) => { this.websocket.onmessage = ({ data }: { data: string | Buffer }) => {
@ -297,14 +301,16 @@ export class Shard {
clearTimeout(this.connectionTimeout); clearTimeout(this.connectionTimeout);
this.connectionTimeout = undefined; this.connectionTimeout = undefined;
if (hasIntent(this.options.intents, 'Guilds')) { if (hasIntent(this.options.intents, 'Guilds')) {
this.pendingGuilds = new Set(packet.d.guilds.map(guild => guild.id)); for (let i = 0; i < packet.d.guilds.length; i++) {
this.pendingGuilds.add(packet.d.guilds.at(i)!.id);
}
} }
this.data.resume_gateway_url = packet.d.resume_gateway_url; this.data.resume_gateway_url = packet.d.resume_gateway_url;
this.data.session_id = packet.d.session_id; this.data.session_id = packet.d.session_id;
this.offlineSendQueue.map(resolve => resolve()); this.offlineSendQueue.map(resolve => resolve());
this.options.handlePayload(this.id, packet); this.options.handlePayload(this.id, packet);
if (this.pendingGuilds?.size === 0) { if (this.pendingGuilds.size === 0) {
this.isReady = true; this.isReady = true;
this.options.handlePayload(this.id, { this.options.handlePayload(this.id, {
t: GatewayDispatchEvents.GuildsReady, t: GatewayDispatchEvents.GuildsReady,
@ -316,7 +322,7 @@ export class Shard {
} }
case GatewayDispatchEvents.GuildCreate: case GatewayDispatchEvents.GuildCreate:
case GatewayDispatchEvents.GuildDelete: case GatewayDispatchEvents.GuildDelete:
if (this.pendingGuilds?.delete(packet.d.id)) { if (this.pendingGuilds.delete(packet.d.id)) {
(packet as any).t = `RAW_${packet.t}`; (packet as any).t = `RAW_${packet.t}`;
this.options.handlePayload(this.id, packet); this.options.handlePayload(this.id, packet);
if (this.pendingGuilds.size === 0) { if (this.pendingGuilds.size === 0) {
@ -370,7 +376,10 @@ export class Shard {
) { ) {
const nonce = Date.now().toString() + Math.random().toString(36); const nonce = Date.now().toString() + Math.random().toString(36);
let resolve: (value: { members: APIGuildMember[]; presences: GatewayGuildMembersChunkPresence[] }) => void = () => { let resolve: (value: {
members: APIGuildMember[];
presences: GatewayGuildMembersChunkPresence[];
}) => void = () => {
// //
}; };
let reject: (reason?: any) => void = () => { let reject: (reason?: any) => void = () => {

View File

@ -1,11 +1,11 @@
import { import {
calculateShardId,
Logger,
LogLevels, LogLevels,
lazyLoadPackage, Logger,
type MakeRequired, type MakeRequired,
MergeOptions, MergeOptions,
type WatcherSendToShard, type WatcherSendToShard,
calculateShardId,
lazyLoadPackage,
} from '../../common'; } from '../../common';
import type { DeepPartial, MakeDeepPartial } from '../../common/types/util'; import type { DeepPartial, MakeDeepPartial } from '../../common/types/util';
import { import {

View File

@ -69,9 +69,6 @@ export interface WorkerManagerOptions extends Omit<ShardManagerOptions, 'handleP
workerProxy?: boolean; workerProxy?: boolean;
/** @default 15000 */
heartbeaterInterval?: number;
path: string; path: string;
handlePayload?(shardId: number, workerId: number, packet: GatewayDispatchPayload): any; handlePayload?(shardId: number, workerId: number, packet: GatewayDispatchPayload): any;

View File

@ -1,4 +1,4 @@
import { createHash, randomBytes, randomUUID, type UUID } from 'node:crypto'; import { type UUID, 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';

View File

@ -114,12 +114,7 @@ export type CustomWorkerClientMessages = {
>; >;
}; };
export type ClientHeartbeaterMessages = ACKHeartbeat;
export type ACKHeartbeat = CreateWorkerMessage<'ACK_HEARTBEAT'>;
export type WorkerMessages = export type WorkerMessages =
| ClientHeartbeaterMessages
| { | {
[K in BaseWorkerMessage['type']]: Identify<Extract<BaseWorkerMessage, { type: K }>>; [K in BaseWorkerMessage['type']]: Identify<Extract<BaseWorkerMessage, { type: K }>>;
}[BaseWorkerMessage['type']] }[BaseWorkerMessage['type']]

View File

@ -1,15 +1,14 @@
import cluster, { type Worker as ClusterWorker } from 'node:cluster'; import cluster, { type Worker as ClusterWorker } from 'node:cluster';
import { randomUUID, type UUID } from 'node:crypto'; import { type UUID, randomUUID } from 'node:crypto';
import type { Worker as WorkerThreadsWorker } from 'node:worker_threads'; import type { Worker as WorkerThreadsWorker } from 'node:worker_threads';
import { ApiHandler, type CustomWorkerManagerEvents, Logger, type UsingClient, type WorkerClient } from '../..'; import { ApiHandler, type CustomWorkerManagerEvents, Logger, type UsingClient, type WorkerClient } from '../..';
import { type Adapter, MemoryAdapter } from '../../cache'; import { type Adapter, MemoryAdapter } from '../../cache';
import { BaseClient, type InternalRuntimeConfig } from '../../client/base'; import { BaseClient, type InternalRuntimeConfig } from '../../client/base';
import { BASE_HOST, type Identify, lazyLoadPackage, MergeOptions, type PickPartial } from '../../common'; import { BASE_HOST, type Identify, MergeOptions, type PickPartial, lazyLoadPackage } from '../../common';
import type { GatewayPresenceUpdateData, GatewaySendPayload, RESTGetAPIGatewayBotResult } from '../../types'; import type { GatewayPresenceUpdateData, GatewaySendPayload, RESTGetAPIGatewayBotResult } from '../../types';
import { properties, WorkerManagerDefaults } 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';
import { Heartbeater, type WorkerHeartbeaterMessages } from './heartbeater';
import type { ShardOptions, WorkerData, WorkerManagerOptions } from './shared'; import type { ShardOptions, WorkerData, WorkerManagerOptions } from './shared';
import type { WorkerInfo, WorkerMessages, WorkerShardInfo } from './worker'; import type { WorkerInfo, WorkerMessages, WorkerShardInfo } from './worker';
@ -56,7 +55,6 @@ export class WorkerManager extends Map<
rest!: ApiHandler; rest!: ApiHandler;
reshardingWorkerQueue: (() => void)[] = []; reshardingWorkerQueue: (() => void)[] = [];
private _info?: RESTGetAPIGatewayBotResult; private _info?: RESTGetAPIGatewayBotResult;
heartbeater: Heartbeater;
constructor( constructor(
options: Omit< options: Omit<
@ -77,8 +75,6 @@ export class WorkerManager extends Map<
return oldFn(message); return oldFn(message);
}; };
} }
this.heartbeater = new Heartbeater(this.postMessage.bind(this), options.heartbeaterInterval ?? 15e3);
} }
setCache(adapter: Adapter) { setCache(adapter: Adapter) {
@ -148,12 +144,12 @@ export class WorkerManager extends Map<
return workerId; return workerId;
} }
postMessage(id: number, body: ManagerMessages | WorkerHeartbeaterMessages) { postMessage(id: number, body: ManagerMessages) {
const worker = this.get(id); const worker = this.get(id);
if (!worker) return this.debugger?.error(`Worker ${id} does not exists.`); if (!worker) return this.debugger?.error(`Worker ${id} does not exists.`);
switch (this.options.mode) { switch (this.options.mode) {
case 'clusters': case 'clusters':
if ((worker as ClusterWorker).isConnected()) (worker as ClusterWorker).send(body); (worker as ClusterWorker).send(body);
break; break;
case 'threads': case 'threads':
(worker as import('worker_threads').Worker).postMessage(body); (worker as import('worker_threads').Worker).postMessage(body);
@ -164,40 +160,33 @@ export class WorkerManager extends Map<
} }
} }
prepareWorkers(shards: number[][], rawResharding = false) { prepareWorkers(shards: number[][], resharding = false) {
const worker_threads = lazyLoadPackage<typeof import('node:worker_threads')>('node:worker_threads'); const worker_threads = lazyLoadPackage<typeof import('node:worker_threads')>('node:worker_threads');
if (!worker_threads) throw new Error('Cannot prepare workers without worker_threads.'); if (!worker_threads) throw new Error('Cannot prepare workers without worker_threads.');
for (let i = 0; i < shards.length; i++) { for (let i = 0; i < shards.length; i++) {
const registerWorker = (resharding: boolean) => {
const worker = this.createWorker({
path: this.options.path,
debug: this.options.debug,
token: this.options.token,
shards: shards[i],
intents: this.options.intents,
workerId: i,
workerProxy: this.options.workerProxy,
totalShards: resharding ? this._info!.shards : this.totalShards,
mode: this.options.mode,
resharding,
totalWorkers: shards.length,
info: {
...this.options.info,
shards: this.totalShards,
},
compress: this.options.compress,
});
this.set(i, worker);
};
const workerExists = this.has(i); const workerExists = this.has(i);
if (rawResharding || !workerExists) { if (resharding || !workerExists) {
this[rawResharding ? 'reshardingWorkerQueue' : 'workerQueue'].push(() => { this[resharding ? 'reshardingWorkerQueue' : 'workerQueue'].push(() => {
registerWorker(rawResharding); const worker = this.createWorker({
this.heartbeater.register(i, () => { path: this.options.path,
this.delete(i); debug: this.options.debug,
registerWorker(false); token: this.options.token,
shards: shards[i],
intents: this.options.intents,
workerId: i,
workerProxy: this.options.workerProxy,
totalShards: resharding ? this._info!.shards : this.totalShards,
mode: this.options.mode,
resharding,
totalWorkers: shards.length,
info: {
...this.options.info,
shards: this.totalShards,
},
compress: this.options.compress,
}); });
this.set(i, worker);
}); });
} }
} }
@ -229,9 +218,6 @@ export class WorkerManager extends Map<
env, env,
}); });
worker.on('message', data => this.handleWorkerMessage(data)); worker.on('message', data => this.handleWorkerMessage(data));
worker.on('error', err => {
this.debugger?.error(`[Worker #${workerData.workerId}]`, err);
});
return worker; return worker;
} }
case 'clusters': { case 'clusters': {
@ -268,9 +254,6 @@ export class WorkerManager extends Map<
async handleWorkerMessage(message: WorkerMessages) { async handleWorkerMessage(message: WorkerMessages) {
switch (message.type) { switch (message.type) {
case 'ACK_HEARTBEAT':
this.heartbeater.acknowledge(message.workerId);
break;
case 'WORKER_READY_RESHARDING': case 'WORKER_READY_RESHARDING':
{ {
this.get(message.workerId)!.resharded = true; this.get(message.workerId)!.resharded = true;
@ -305,7 +288,6 @@ export class WorkerManager extends Map<
for (const [id] of this.entries()) { for (const [id] of this.entries()) {
this.postMessage(id, { this.postMessage(id, {
type: 'CONNECT_ALL_SHARDS_RESHARDING', type: 'CONNECT_ALL_SHARDS_RESHARDING',
totalShards: this.options.totalShards,
} satisfies ConnnectAllShardsResharding); } satisfies ConnnectAllShardsResharding);
} }
this.forEach(w => { this.forEach(w => {
@ -674,12 +656,7 @@ export type ManagerSpawnShardsResharding = CreateManagerMessage<
Pick<ShardOptions, 'info' | 'properties' | 'compress'> Pick<ShardOptions, 'info' | 'properties' | 'compress'>
>; >;
export type DisconnectAllShardsResharding = CreateManagerMessage<'DISCONNECT_ALL_SHARDS_RESHARDING'>; export type DisconnectAllShardsResharding = CreateManagerMessage<'DISCONNECT_ALL_SHARDS_RESHARDING'>;
export type ConnnectAllShardsResharding = CreateManagerMessage< export type ConnnectAllShardsResharding = CreateManagerMessage<'CONNECT_ALL_SHARDS_RESHARDING'>;
'CONNECT_ALL_SHARDS_RESHARDING',
{
totalShards: number;
}
>;
export type ManagerSendPayload = CreateManagerMessage< export type ManagerSendPayload = CreateManagerMessage<
'SEND_PAYLOAD', 'SEND_PAYLOAD',
GatewaySendPayload & { shardId: number; nonce: string } GatewaySendPayload & { shardId: number; nonce: string }

Some files were not shown because too many files have changed in this diff Show More