mirror of
https://github.com/tiramisulabs/seyfert.git
synced 2025-07-01 20:46:08 +00:00
Compare commits
46 Commits
Author | SHA1 | Date | |
---|---|---|---|
6d5b162a2d | |||
a15eb2035f | |||
c4d1c1ce90 | |||
eadf63450b | |||
0720d0c170 | |||
798f648955 | |||
6e037ae964 | |||
0608c7ad85 | |||
db38f49ca9 | |||
325a39f1bf | |||
e810b6eb52 | |||
![]() |
b84d462ce2 | ||
61413181bb | |||
30a066e68d | |||
95619a8a89 | |||
84806f3c54 | |||
422cfb2a80 | |||
![]() |
3f6c6dc4d4 | ||
d6a405469d | |||
1903257e46 | |||
0b00e2d19b | |||
970ed980cf | |||
935cce99f6 | |||
5de23ffe58 | |||
e4f715515c | |||
7998577b07 | |||
05cdc20d7f | |||
e095edd20f | |||
d9aef4335d | |||
3350570334 | |||
c20f2fd0a3 | |||
0d8ad177b7 | |||
089cfab6da | |||
fb9c59a51b | |||
92ab65be7b | |||
23c9c2a710 | |||
b4324f9487 | |||
f74b75fcef | |||
9cbde76ad0 | |||
66b5ca34a9 | |||
4574ca018f | |||
34ca3e293e | |||
a358bb0a04 | |||
6cf75e9ad2 | |||
60108b4c42 | |||
e8c686a1df |
11
.github/workflows/dev.yml
vendored
11
.github/workflows/dev.yml
vendored
@ -12,8 +12,10 @@ jobs:
|
||||
permissions:
|
||||
id-token: write
|
||||
if: github.repository == 'tiramisulabs/seyfert'
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
steps:
|
||||
- name: check out code
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install Node
|
||||
@ -29,12 +31,13 @@ jobs:
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Verify npm token
|
||||
run: npm whoami
|
||||
|
||||
- name: Publish dev tag
|
||||
id: publish
|
||||
run: |
|
||||
new_version=$(npm version prerelease --preid dev-${{github.run_id}} --no-git-tag-version)
|
||||
echo "New version: $new_version"
|
||||
npm config set //registry.npmjs.org/:_authToken ${NODE_AUTH_TOKEN}
|
||||
npm publish --provenance --tag=dev
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
npm publish --provenance --tag=dev
|
80
.github/workflows/releases.yml
vendored
80
.github/workflows/releases.yml
vendored
@ -1,80 +0,0 @@
|
||||
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
|
@ -1 +1 @@
|
||||
npx lint-staged
|
||||
npx biome check --write
|
||||
|
32
biome.json
32
biome.json
@ -1,5 +1,5 @@
|
||||
{
|
||||
"$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
|
||||
"$schema": "https://biomejs.dev/schemas/2.0.0/schema.json",
|
||||
"vcs": {
|
||||
"enabled": true,
|
||||
"clientKind": "git",
|
||||
@ -8,7 +8,16 @@
|
||||
},
|
||||
"files": {
|
||||
"ignoreUnknown": true,
|
||||
"ignore": ["node_modules/", "build", "lib", "__test__", "package.json", "tsconfig.json", ".vscode"]
|
||||
"includes": [
|
||||
"**/src/**",
|
||||
"!/node_modules/",
|
||||
"!/build",
|
||||
"!/lib",
|
||||
"!/__test__",
|
||||
"!/package.json",
|
||||
"!/tsconfig.json",
|
||||
"!/.vscode"
|
||||
]
|
||||
},
|
||||
"formatter": {
|
||||
"enabled": true,
|
||||
@ -18,14 +27,17 @@
|
||||
"lineEnding": "crlf",
|
||||
"formatWithErrors": true
|
||||
},
|
||||
"organizeImports": {
|
||||
"enabled": true
|
||||
"assist": {
|
||||
"actions": {
|
||||
"source": {
|
||||
"organizeImports": "on"
|
||||
}
|
||||
}
|
||||
},
|
||||
"linter": {
|
||||
"enabled": true,
|
||||
"rules": {
|
||||
"recommended": false,
|
||||
"all": true,
|
||||
"security": {
|
||||
"noGlobalEval": "off"
|
||||
},
|
||||
@ -41,9 +53,7 @@
|
||||
},
|
||||
"correctness": {
|
||||
"noNodejsModules": "off",
|
||||
"useImportExtensions": "off",
|
||||
"noUnusedFunctionParameters": "off",
|
||||
"noUnusedVariables": "off"
|
||||
"useImportExtensions": "off"
|
||||
},
|
||||
"style": {
|
||||
"noDefaultExport": "off",
|
||||
@ -56,8 +66,7 @@
|
||||
"noParameterAssign": "off",
|
||||
"useFilenamingConvention": "off",
|
||||
"useEnumInitializers": "off",
|
||||
"useExplicitLengthCheck": "off",
|
||||
"noNamespaceImport": "off"
|
||||
"useExplicitLengthCheck": "off"
|
||||
},
|
||||
"complexity": {
|
||||
"noForEach": "off",
|
||||
@ -69,7 +78,8 @@
|
||||
"noBarrelFile": "off",
|
||||
"noDelete": "off",
|
||||
"noReExportAll": "off",
|
||||
"useTopLevelRegex": "off"
|
||||
"useTopLevelRegex": "off",
|
||||
"noNamespaceImport": "off"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
22
package.json
22
package.json
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "seyfert",
|
||||
"version": "3.1.1",
|
||||
"version": "3.2.4",
|
||||
"description": "The most advanced framework for discord bots",
|
||||
"main": "./lib/index.js",
|
||||
"module": "./lib/index.js",
|
||||
@ -21,15 +21,14 @@
|
||||
"author": "MARCROCK22",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "1.9.4",
|
||||
"@changesets/cli": "^2.28.1",
|
||||
"@commitlint/cli": "^19.8.0",
|
||||
"@commitlint/config-conventional": "^19.8.0",
|
||||
"@types/node": "^22.14.0",
|
||||
"@biomejs/biome": "2.0.0",
|
||||
"@changesets/cli": "^2.29.4",
|
||||
"@commitlint/cli": "^19.8.1",
|
||||
"@commitlint/config-conventional": "^19.8.1",
|
||||
"@types/node": "^24.0.3",
|
||||
"husky": "^9.1.7",
|
||||
"lint-staged": "^15.5.0",
|
||||
"typescript": "^5.8.2",
|
||||
"vitest": "^3.1.1"
|
||||
"typescript": "^5.8.3",
|
||||
"vitest": "^3.2.4"
|
||||
},
|
||||
"homepage": "https://seyfert.dev",
|
||||
"repository": {
|
||||
@ -65,11 +64,6 @@
|
||||
"url": "https://github.com/Drylozu"
|
||||
}
|
||||
],
|
||||
"lint-staged": {
|
||||
"*.ts": [
|
||||
"biome check --write"
|
||||
]
|
||||
},
|
||||
"pnpm": {
|
||||
"onlyBuiltDependencies": [
|
||||
"@biomejs/biome",
|
||||
|
1311
pnpm-lock.yaml
generated
1311
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -71,7 +71,7 @@ export interface ApplicationRoutes {
|
||||
patch(
|
||||
args: RestArguments<RESTPatchAPIApplicationGuildCommandJSONBody>,
|
||||
): Promise<RESTPatchAPIApplicationGuildCommandResult>;
|
||||
delete(args?: RestArgumentsNoBody): Promise<never>;
|
||||
delete(args?: RestArgumentsNoBody): Promise<undefined>;
|
||||
permissions: {
|
||||
get(args?: RestArgumentsNoBody): Promise<RESTGetAPIGuildApplicationCommandsPermissionsResult>;
|
||||
put(
|
||||
@ -92,7 +92,7 @@ export interface ApplicationRoutes {
|
||||
patch(
|
||||
args: RestArguments<RESTPatchAPIApplicationCommandJSONBody>,
|
||||
): Promise<RESTPatchAPIApplicationCommandResult>;
|
||||
delete(args?: RestArgumentsNoBody): Promise<never>;
|
||||
delete(args?: RestArgumentsNoBody): Promise<undefined>;
|
||||
};
|
||||
};
|
||||
'role-connections': {
|
||||
@ -122,10 +122,10 @@ export interface ApplicationRoutes {
|
||||
(
|
||||
id: string,
|
||||
): {
|
||||
get(args?: RestArgumentsNoBody<never>): Promise<RESTGetAPIEntitlementResult>;
|
||||
delete(args?: RestArgumentsNoBody): Promise<never>;
|
||||
get(args?: RestArgumentsNoBody): Promise<RESTGetAPIEntitlementResult>;
|
||||
delete(args?: RestArgumentsNoBody): Promise<undefined>;
|
||||
consume: {
|
||||
post(args?: RestArgumentsNoBody): Promise<never>;
|
||||
post(args?: RestArgumentsNoBody): Promise<undefined>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -190,7 +190,7 @@ export interface ChannelRoutes {
|
||||
post(args: RestArguments<RESTPostAPIChannelWebhookJSONBody>): Promise<RESTPostAPIChannelWebhookResult>;
|
||||
};
|
||||
'voice-status': {
|
||||
put(args: RestArguments<{ status: string | null }>): Promise<never>;
|
||||
put(args: RestArguments<{ status: string | null }>): Promise<undefined>;
|
||||
};
|
||||
polls(messageId: string): {
|
||||
answers(id: ValidAnswerId): {
|
||||
@ -201,7 +201,7 @@ export interface ChannelRoutes {
|
||||
};
|
||||
};
|
||||
'send-soundboard-sound': {
|
||||
post(args: RestArguments<RESTPostAPISendSoundboardSound>): Promise<never>;
|
||||
post(args: RestArguments<RESTPostAPISendSoundboardSound>): Promise<undefined>;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
@ -39,10 +39,10 @@ import type {
|
||||
RESTGetAPIGuildRolesResult,
|
||||
RESTGetAPIGuildScheduledEventQuery,
|
||||
RESTGetAPIGuildScheduledEventResult,
|
||||
RESTGetAPIGuildScheduledEventUsersQuery,
|
||||
RESTGetAPIGuildScheduledEventUsersResult,
|
||||
RESTGetAPIGuildScheduledEventsQuery,
|
||||
RESTGetAPIGuildScheduledEventsResult,
|
||||
RESTGetAPIGuildScheduledEventUsersQuery,
|
||||
RESTGetAPIGuildScheduledEventUsersResult,
|
||||
RESTGetAPIGuildSoundboardSoundsResult,
|
||||
RESTGetAPIGuildStickerResult,
|
||||
RESTGetAPIGuildStickersResult,
|
||||
@ -107,12 +107,12 @@ import type {
|
||||
RESTPostAPIGuildSoundboardSoundResult,
|
||||
RESTPostAPIGuildStickerFormDataBody,
|
||||
RESTPostAPIGuildStickerResult,
|
||||
RESTPostAPIGuildTemplatesJSONBody,
|
||||
RESTPostAPIGuildTemplatesResult,
|
||||
RESTPostAPIGuildsJSONBody,
|
||||
RESTPostAPIGuildsMFAJSONBody,
|
||||
RESTPostAPIGuildsMFAResult,
|
||||
RESTPostAPIGuildsResult,
|
||||
RESTPostAPIGuildTemplatesJSONBody,
|
||||
RESTPostAPIGuildTemplatesResult,
|
||||
RESTPostAPITemplateCreateGuildJSONBody,
|
||||
RESTPostAPITemplateCreateGuildResult,
|
||||
RESTPutAPIGuildBanJSONBody,
|
||||
@ -361,7 +361,7 @@ export interface GuildRoutes {
|
||||
patch(
|
||||
args?: RestArguments<RESTPatchAPIGuildSoundboardSound>,
|
||||
): Promise<RESTPatchAPIGuildSoundboardSoundResult>;
|
||||
delete(args?: RestArgumentsNoBody): Promise<never>;
|
||||
delete(args?: RestArgumentsNoBody): Promise<undefined>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -1,11 +1,11 @@
|
||||
import { type UUID, randomUUID } from 'node:crypto';
|
||||
import { type Awaitable, BASE_HOST, Logger, delay, lazyLoadPackage, snowflakeToTimestamp } from '../common';
|
||||
import { randomUUID, type UUID } from 'node:crypto';
|
||||
import { type Awaitable, BASE_HOST, delay, Logger, lazyLoadPackage, snowflakeToTimestamp } from '../common';
|
||||
import { toArrayBuffer, toBuffer } from '../common/it/utils';
|
||||
import type { WorkerData } from '../websocket';
|
||||
import type { WorkerSendApiRequest } from '../websocket/discord/worker';
|
||||
import { Bucket } from './bucket';
|
||||
import { CDNRouter, Router } from './Router';
|
||||
import type { APIRoutes } from './Routes';
|
||||
import { Bucket } from './bucket';
|
||||
import {
|
||||
type ApiHandlerInternalOptions,
|
||||
type ApiHandlerOptions,
|
||||
@ -291,17 +291,19 @@ export class ApiHandler {
|
||||
await this.onRatelimit?.(response, request);
|
||||
|
||||
const content = `${JSON.stringify(request)} `;
|
||||
let retryAfter =
|
||||
let retryAfter: number | undefined;
|
||||
|
||||
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;
|
||||
|
||||
if (Number.isNaN(retryAfter)) {
|
||||
try {
|
||||
retryAfter = JSON.parse(result).retry_after * 1000;
|
||||
} catch (err) {
|
||||
this.debugger?.warn(`Unexpected error: ${err}`);
|
||||
reject(err);
|
||||
return false;
|
||||
}
|
||||
this.debugger?.warn(`${route} Could not extract retry_after from 429 response. ${result}`);
|
||||
next();
|
||||
reject(new Error('Could not extract retry_after from 429 response.'));
|
||||
return false;
|
||||
}
|
||||
|
||||
this.debugger?.info(
|
||||
@ -384,11 +386,7 @@ export class ApiHandler {
|
||||
}
|
||||
}
|
||||
|
||||
parseRequest(options: {
|
||||
url: string;
|
||||
headers: RequestHeaders;
|
||||
request: ApiRequestOptions;
|
||||
}) {
|
||||
parseRequest(options: { url: string; headers: RequestHeaders; request: ApiRequestOptions }) {
|
||||
let finalUrl = options.url;
|
||||
let data: string | FormData | undefined;
|
||||
if (options.request.auth) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
export * from './api';
|
||||
export * from './Router';
|
||||
export * from './Routes';
|
||||
export * from './api';
|
||||
export * from './shared';
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { type ActionRow, fromComponent } from '.';
|
||||
import { type ColorResolvable, type RestOrArray, resolveColor } from '../common';
|
||||
import { type APIContainerComponent, ComponentType } from '../types';
|
||||
import { type ActionRow, fromComponent } from '.';
|
||||
import { BaseComponentBuilder } from './Base';
|
||||
import type { File } from './File';
|
||||
import type { MediaGallery } from './MediaGallery';
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { type Button, fromComponent } from '.';
|
||||
import type { RestOrArray } from '../common';
|
||||
import { type APISectionComponent, ComponentType } from '../types';
|
||||
import { type Button, fromComponent } from '.';
|
||||
import { BaseComponentBuilder } from './Base';
|
||||
import type { TextDisplay } from './TextDisplay';
|
||||
import type { Thumbnail } from './Thumbnail';
|
||||
@ -9,7 +9,7 @@ export class Section<
|
||||
Ac extends Button | Thumbnail = Button | Thumbnail,
|
||||
> extends BaseComponentBuilder<APISectionComponent> {
|
||||
components: TextDisplay[];
|
||||
accessory!: Ac;
|
||||
accessory?: Ac;
|
||||
constructor({ components, accessory, ...data }: Partial<APISectionComponent> = {}) {
|
||||
super({ type: ComponentType.Section, ...data });
|
||||
this.components = (components?.map(component => fromComponent(component)) ?? []) as TextDisplay[];
|
||||
@ -46,6 +46,7 @@ export class Section<
|
||||
* @returns The JSON representation of this section
|
||||
*/
|
||||
toJSON() {
|
||||
if (!this.accessory) throw new Error('Cannot convert to JSON without an accessory.');
|
||||
return {
|
||||
...this.data,
|
||||
components: this.components.map(component => component.toJSON()),
|
||||
|
@ -161,7 +161,7 @@ export class RoleSelectMenu extends SelectMenu<APIRoleSelectComponent> {
|
||||
}
|
||||
}
|
||||
|
||||
export type MentionableDefaultElement = { id: string; type: keyof Omit<typeof SelectMenuDefaultValueType, 'Channel'> };
|
||||
export type MentionableDefaultElement = { id: string; type: keyof typeof SelectMenuDefaultValueType };
|
||||
|
||||
/**
|
||||
* Represents a Select Menu for selecting mentionable entities.
|
||||
|
6
src/cache/adapters/limited.ts
vendored
6
src/cache/adapters/limited.ts
vendored
@ -94,7 +94,11 @@ export class LimitedMemoryAdapter<T> implements Adapter {
|
||||
}
|
||||
|
||||
private __set(key: string, data: any) {
|
||||
const __guildId = Array.isArray(data) ? data[0].guild_id : data.guild_id;
|
||||
const isArray = Array.isArray(data);
|
||||
if (isArray && data.length === 0) {
|
||||
return;
|
||||
}
|
||||
const __guildId = isArray ? data[0].guild_id : data.guild_id;
|
||||
const namespace = `${key.split('.')[0]}${__guildId ? `.${__guildId}` : ''}`;
|
||||
const self = this;
|
||||
if (!this.storage.has(namespace)) {
|
||||
|
12
src/cache/index.ts
vendored
12
src/cache/index.ts
vendored
@ -1,11 +1,5 @@
|
||||
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 { type If, Logger } from '../common';
|
||||
import {
|
||||
type APIChannel,
|
||||
type APIEmoji,
|
||||
@ -20,9 +14,11 @@ import {
|
||||
GuildMemberFlags,
|
||||
OverwriteType,
|
||||
} from '../types';
|
||||
import type { Adapter } from './adapters';
|
||||
import { Bans } from './resources/bans';
|
||||
import { Channels } from './resources/channels';
|
||||
import { Emojis } from './resources/emojis';
|
||||
import { Guilds } from './resources/guilds';
|
||||
import { Members } from './resources/members';
|
||||
import { Messages } from './resources/messages';
|
||||
import { Overwrites } from './resources/overwrites';
|
||||
@ -30,7 +26,9 @@ import { Presences } from './resources/presence';
|
||||
import { Roles } from './resources/roles';
|
||||
import { StageInstances } from './resources/stage-instances';
|
||||
import { Stickers } from './resources/stickers';
|
||||
import { Users } from './resources/users';
|
||||
import { VoiceStates } from './resources/voice-states';
|
||||
|
||||
export { BaseResource } from './resources/default/base';
|
||||
export { GuildBasedResource } from './resources/default/guild-based';
|
||||
export { GuildRelatedResource } from './resources/default/guild-related';
|
||||
|
2
src/cache/resources/guilds.ts
vendored
2
src/cache/resources/guilds.ts
vendored
@ -1,7 +1,7 @@
|
||||
import type { Cache, CacheFrom, ReturnCache } from '..';
|
||||
import { type GuildStructure, Transformers } from '../../client/transformers';
|
||||
import { fakePromise } from '../../common';
|
||||
import type { APIGuild, GatewayGuildCreateDispatchData } from '../../types';
|
||||
import type { Cache, CacheFrom, ReturnCache } from '..';
|
||||
import { BaseResource } from './default/base';
|
||||
|
||||
export class Guilds extends BaseResource<any, APIGuild | GatewayGuildCreateDispatchData> {
|
||||
|
@ -1,5 +1,7 @@
|
||||
import { promises } from 'node:fs';
|
||||
import { join } from 'node:path';
|
||||
import { ApiHandler } from '../api';
|
||||
import { isBufferLike } from '../api/utils/utils';
|
||||
import type { Adapter, DisabledCache } from '../cache';
|
||||
import { Cache, MemoryAdapter } from '../cache';
|
||||
import type {
|
||||
@ -16,34 +18,31 @@ import type {
|
||||
UsingClient,
|
||||
} from '../commands';
|
||||
import { IgnoreCommand, type InferWithPrefix, type MiddlewareContext } from '../commands/applications/shared';
|
||||
import { HandleCommand } from '../commands/handle';
|
||||
import { CommandHandler } from '../commands/handler';
|
||||
import {
|
||||
ApplicationShorter,
|
||||
assertString,
|
||||
ChannelShorter,
|
||||
EmojiShorter,
|
||||
filterSplit,
|
||||
GuildShorter,
|
||||
InteractionShorter,
|
||||
InvitesShorter,
|
||||
LogLevels,
|
||||
Logger,
|
||||
LogLevels,
|
||||
type MakeRequired,
|
||||
MemberShorter,
|
||||
MergeOptions,
|
||||
MessageShorter,
|
||||
magicImport,
|
||||
ReactionShorter,
|
||||
RoleShorter,
|
||||
TemplateShorter,
|
||||
ThreadShorter,
|
||||
UsersShorter,
|
||||
WebhookShorter,
|
||||
assertString,
|
||||
filterSplit,
|
||||
magicImport,
|
||||
} 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 { SoundboardShorter } from '../common/shorters/soundboard';
|
||||
import { VoiceStateShorter } from '../common/shorters/voiceStates';
|
||||
|
@ -1,17 +1,17 @@
|
||||
import type { CommandContext, Message } from '..';
|
||||
import {
|
||||
type Awaitable,
|
||||
assertString,
|
||||
type DeepPartial,
|
||||
type If,
|
||||
lazyLoadPackage,
|
||||
type PickPartial,
|
||||
type WatcherPayload,
|
||||
type WatcherSendToShard,
|
||||
assertString,
|
||||
lazyLoadPackage,
|
||||
} from '../common';
|
||||
import { EventHandler } from '../events';
|
||||
import type { GatewayDispatchPayload, GatewayPresenceUpdateData } from '../types';
|
||||
import { ShardManager, type ShardManagerOptions, properties } from '../websocket';
|
||||
import { properties, ShardManager, type ShardManagerOptions } from '../websocket';
|
||||
import { MemberUpdateHandler } from '../websocket/discord/events/memberUpdate';
|
||||
import { PresenceUpdateHandler } from '../websocket/discord/events/presenceUpdate';
|
||||
import type { BaseClientOptions, InternalRuntimeConfig, ServicesOptions, StartOptions } from './base';
|
||||
@ -219,8 +219,8 @@ export interface ClientOptions extends BaseClientOptions {
|
||||
};
|
||||
commands?: BaseClientOptions['commands'] & {
|
||||
prefix?: (message: MessageStructure) => Awaitable<string[]>;
|
||||
deferReplyResponse?: (ctx: CommandContext) => Parameters<Message['write']>[0];
|
||||
reply?: (ctx: CommandContext) => boolean;
|
||||
deferReplyResponse?: (ctx: CommandContext) => Awaitable<Parameters<Message['write']>[0]>;
|
||||
reply?: (ctx: CommandContext) => Awaitable<boolean>;
|
||||
};
|
||||
handlePayload?: ShardManagerOptions['handlePayload'];
|
||||
resharding?: PickPartial<NonNullable<ShardManagerOptions['resharding']>, 'getInfo'>;
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { type UUID, randomUUID } from 'node:crypto';
|
||||
import { randomUUID, type UUID } from 'node:crypto';
|
||||
import type { UsingClient } from '../commands';
|
||||
import type { Awaitable, CamelCase } from '../common';
|
||||
import type { CallbackEventHandler, CustomEventsKeys, GatewayEvents } from '../events';
|
||||
|
@ -1,5 +1,5 @@
|
||||
export type { RuntimeConfig, RuntimeConfigHTTP } from './base';
|
||||
export * from './client';
|
||||
export * from './httpclient';
|
||||
export * from './workerclient';
|
||||
export * from './transformers';
|
||||
export * from './workerclient';
|
||||
|
@ -8,8 +8,8 @@ import {
|
||||
BaseGuildChannel,
|
||||
CategoryChannel,
|
||||
ClientUser,
|
||||
DMChannel,
|
||||
DirectoryChannel,
|
||||
DMChannel,
|
||||
Emoji,
|
||||
Entitlement,
|
||||
ForumChannel,
|
||||
|
@ -1,11 +1,24 @@
|
||||
import { type UUID, randomUUID } from 'node:crypto';
|
||||
import { randomUUID, type UUID } from 'node:crypto';
|
||||
import { ApiHandler, Logger } from '..';
|
||||
import { WorkerAdapter } from '../cache';
|
||||
import { type DeepPartial, LogLevels, type MakeRequired, type When, lazyLoadPackage } from '../common';
|
||||
import {
|
||||
type Awaitable,
|
||||
calculateShardId,
|
||||
type DeepPartial,
|
||||
LogLevels,
|
||||
lazyLoadPackage,
|
||||
type MakeRequired,
|
||||
type When,
|
||||
} from '../common';
|
||||
import { EventHandler } from '../events';
|
||||
import type { GatewayDispatchPayload, GatewaySendPayload } from '../types';
|
||||
import { Shard, type ShardManagerOptions, ShardSocketCloseCodes, type WorkerData, properties } from '../websocket';
|
||||
import { properties, Shard, type ShardManagerOptions, ShardSocketCloseCodes, type WorkerData } 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 {
|
||||
ClientHeartbeaterMessages,
|
||||
WorkerDisconnectedAllShardsResharding,
|
||||
WorkerMessages,
|
||||
WorkerReady,
|
||||
@ -27,10 +40,6 @@ import type { ManagerMessages, ManagerSpawnShards } from '../websocket/discord/w
|
||||
import type { BaseClientOptions, ServicesOptions, StartOptions } from './base';
|
||||
import { BaseClient } from './base';
|
||||
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 { type ClientUserStructure, Transformers } from './transformers';
|
||||
|
||||
@ -166,13 +175,19 @@ export class WorkerClient<Ready extends boolean = boolean> extends BaseClient {
|
||||
}
|
||||
}
|
||||
|
||||
postMessage(body: WorkerMessages): unknown {
|
||||
postMessage(body: WorkerMessages | ClientHeartbeaterMessages): unknown {
|
||||
if (manager) return manager.postMessage(body);
|
||||
return process.send!(body);
|
||||
}
|
||||
|
||||
async handleManagerMessages(data: ManagerMessages) {
|
||||
async handleManagerMessages(data: ManagerMessages | WorkerHeartbeaterMessages) {
|
||||
switch (data.type) {
|
||||
case 'HEARTBEAT':
|
||||
this.postMessage({
|
||||
type: 'ACK_HEARTBEAT',
|
||||
workerId: workerData.workerId,
|
||||
});
|
||||
break;
|
||||
case 'CACHE_RESULT':
|
||||
if (this.cache.adapter instanceof WorkerAdapter && this.cache.adapter.promises.has(data.nonce)) {
|
||||
const cacheData = this.cache.adapter.promises.get(data.nonce)!;
|
||||
@ -377,12 +392,18 @@ export class WorkerClient<Ready extends boolean = boolean> extends BaseClient {
|
||||
return this.onPacket(packet, shardId);
|
||||
};
|
||||
}
|
||||
workerData.totalShards = data.totalShards;
|
||||
workerData.shards = [...this.shards.keys()];
|
||||
this.resharding.clear();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
calculateShardId(guildId: string) {
|
||||
return calculateShardId(guildId, this.workerData.totalShards);
|
||||
}
|
||||
|
||||
private generateNonce(): UUID {
|
||||
const uuid = randomUUID();
|
||||
if (this.promises.has(uuid)) return this.generateNonce();
|
||||
@ -420,7 +441,7 @@ export class WorkerClient<Ready extends boolean = boolean> extends BaseClient {
|
||||
return Promise.all(promises);
|
||||
}
|
||||
|
||||
createShard(id: number, data: Pick<ManagerSpawnShards, 'info' | 'compress'>) {
|
||||
createShard(id: number, data: Pick<ManagerSpawnShards, 'info' | 'compress' | 'properties'>) {
|
||||
const onPacket = this.onPacket.bind(this);
|
||||
const handlePayload = this.options?.handlePayload?.bind(this);
|
||||
const self = this;
|
||||
@ -432,6 +453,7 @@ export class WorkerClient<Ready extends boolean = boolean> extends BaseClient {
|
||||
debugger: this.debugger,
|
||||
properties: {
|
||||
...properties,
|
||||
...data.properties,
|
||||
...this.options.gateway?.properties,
|
||||
},
|
||||
async handlePayload(shardId, payload) {
|
||||
@ -553,12 +575,12 @@ export function generateShardInfo(shard: Shard): WorkerShardInfo {
|
||||
};
|
||||
}
|
||||
|
||||
interface WorkerClientOptions extends BaseClientOptions {
|
||||
export interface WorkerClientOptions extends BaseClientOptions {
|
||||
commands?: NonNullable<Client['options']>['commands'];
|
||||
handlePayload?: ShardManagerOptions['handlePayload'];
|
||||
gateway?: ClientOptions['gateway'];
|
||||
postMessage?: (body: unknown) => unknown;
|
||||
postMessage?: (body: unknown) => Awaitable<unknown>;
|
||||
/** can have perfomance issues in big bots if the client sends every event, specially in startup (false by default) */
|
||||
sendPayloadToParent?: boolean;
|
||||
handleManagerMessages?(message: ManagerMessages): any;
|
||||
handleManagerMessages?(message: ManagerMessages | WorkerHeartbeaterMessages): Awaitable<unknown>;
|
||||
}
|
||||
|
@ -79,7 +79,7 @@ export class CommandContext<
|
||||
if (this.interaction) return this.interaction.write(body, withResponse);
|
||||
const options = (this.client as Client | WorkerClient).options?.commands;
|
||||
return (this.messageResponse = await (this.message! as Message)[
|
||||
!this.messageResponse && options?.reply?.(this) ? 'reply' : 'write'
|
||||
!this.messageResponse && (await options?.reply?.(this)) ? 'reply' : 'write'
|
||||
](body)) as never;
|
||||
}
|
||||
|
||||
@ -97,8 +97,8 @@ export class CommandContext<
|
||||
return this.interaction.deferReply(ephemeral ? MessageFlags.Ephemeral : undefined, withResponse);
|
||||
this.__deferred = true;
|
||||
const options = (this.client as Client | WorkerClient).options?.commands;
|
||||
return (this.messageResponse = await (this.message! as Message)[options?.reply?.(this) ? 'reply' : 'write'](
|
||||
options?.deferReplyResponse?.(this) ?? { content: 'Thinking...' },
|
||||
return (this.messageResponse = await (this.message! as Message)[(await options?.reply?.(this)) ? 'reply' : 'write'](
|
||||
(await options?.deferReplyResponse?.(this)) ?? { content: 'Thinking...' },
|
||||
)) as never;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { type PermissionStrings, magicImport } from '../../common';
|
||||
import { magicImport, type PermissionStrings } from '../../common';
|
||||
import {
|
||||
ApplicationCommandType,
|
||||
type ApplicationIntegrationType,
|
||||
|
@ -12,10 +12,11 @@ import type {
|
||||
MakeRequired,
|
||||
MessageWebhookCreateBodyRequest,
|
||||
ModalCreateBodyRequest,
|
||||
ModalCreateOptions,
|
||||
UnionToTuple,
|
||||
When,
|
||||
} from '../../common';
|
||||
import type { AllChannels, EntryPointInteraction } from '../../structures';
|
||||
import type { AllChannels, EntryPointInteraction, ModalSubmitInteraction } from '../../structures';
|
||||
import { MessageFlags, type RESTGetAPIGuildQuery } from '../../types';
|
||||
import { BaseContext } from '../basecontext';
|
||||
import type { RegisteredMiddlewares } from '../decorators';
|
||||
@ -52,8 +53,11 @@ export class EntryPointContext<M extends keyof RegisteredMiddlewares = never> ex
|
||||
return this.interaction.write<WR>(body, withResponse);
|
||||
}
|
||||
|
||||
modal(body: ModalCreateBodyRequest) {
|
||||
return this.interaction.modal(body);
|
||||
modal(body: ModalCreateBodyRequest, options?: undefined): Promise<undefined>;
|
||||
modal(body: ModalCreateBodyRequest, options: ModalCreateOptions): Promise<ModalSubmitInteraction | null>;
|
||||
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>(
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { type PermissionStrings, magicImport } from '../../common';
|
||||
import { magicImport, type PermissionStrings } from '../../common';
|
||||
import type {
|
||||
ApplicationCommandType,
|
||||
ApplicationIntegrationType,
|
||||
|
@ -8,16 +8,22 @@ import {
|
||||
type WebhookMessageStructure,
|
||||
} from '../../client/transformers';
|
||||
import {
|
||||
type InteractionCreateBodyRequest,
|
||||
type InteractionMessageUpdateBodyRequest,
|
||||
type MakeRequired,
|
||||
type MessageWebhookCreateBodyRequest,
|
||||
type ModalCreateBodyRequest,
|
||||
type UnionToTuple,
|
||||
type When,
|
||||
InteractionCreateBodyRequest,
|
||||
InteractionMessageUpdateBodyRequest,
|
||||
MakeRequired,
|
||||
MessageWebhookCreateBodyRequest,
|
||||
ModalCreateBodyRequest,
|
||||
ModalCreateOptions,
|
||||
toSnakeCase,
|
||||
UnionToTuple,
|
||||
When,
|
||||
} from '../../common';
|
||||
import type { AllChannels, MessageCommandInteraction, UserCommandInteraction } from '../../structures';
|
||||
import {
|
||||
AllChannels,
|
||||
MessageCommandInteraction,
|
||||
ModalSubmitInteraction,
|
||||
UserCommandInteraction,
|
||||
} from '../../structures';
|
||||
import { type APIMessage, ApplicationCommandType, MessageFlags, type RESTGetAPIGuildQuery } from '../../types';
|
||||
import { BaseContext } from '../basecontext';
|
||||
import type { RegisteredMiddlewares } from '../decorators';
|
||||
@ -47,7 +53,6 @@ export class MenuCommandContext<
|
||||
metadata: CommandMetadata<UnionToTuple<M>> = {} as never;
|
||||
globalMetadata: GlobalMetadata = {};
|
||||
|
||||
// biome-ignore lint/suspicious/useGetterReturn: default don't exist.
|
||||
get target(): InteractionTarget<T> {
|
||||
switch (this.interaction.data.type) {
|
||||
case ApplicationCommandType.Message: {
|
||||
@ -76,8 +81,11 @@ export class MenuCommandContext<
|
||||
return this.interaction.write<WR>(body, withResponse);
|
||||
}
|
||||
|
||||
modal(body: ModalCreateBodyRequest) {
|
||||
return this.interaction.modal(body);
|
||||
modal(body: ModalCreateBodyRequest, options?: undefined): Promise<undefined>;
|
||||
modal(body: ModalCreateBodyRequest, options: ModalCreateOptions): Promise<ModalSubmitInteraction | null>;
|
||||
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>(
|
||||
|
@ -1,10 +1,3 @@
|
||||
import type {
|
||||
AutocompleteCallback,
|
||||
EntryPointContext,
|
||||
MenuCommandContext,
|
||||
OnAutocompleteErrorCallback,
|
||||
ReturnOptionsTypes,
|
||||
} from '..';
|
||||
import type { Awaitable, FlatObjectKeys } from '../../common';
|
||||
import type { ModalContext } from '../../components';
|
||||
import type { ComponentContext } from '../../components/componentcontext';
|
||||
@ -15,6 +8,13 @@ import {
|
||||
ApplicationCommandOptionType,
|
||||
} from '../../types';
|
||||
import type { LocalizationMap } from '../../types/payloads';
|
||||
import type {
|
||||
AutocompleteCallback,
|
||||
EntryPointContext,
|
||||
MenuCommandContext,
|
||||
OnAutocompleteErrorCallback,
|
||||
ReturnOptionsTypes,
|
||||
} from '..';
|
||||
import type { CommandContext } from './chatcontext';
|
||||
import type { DefaultLocale, MiddlewareContext, OKFunction, SeyfertChannelMap, StopFunction } from './shared';
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import type {
|
||||
CategoryChannelStructure,
|
||||
DMChannelStructure,
|
||||
DirectoryChannelStructure,
|
||||
DMChannelStructure,
|
||||
ForumChannelStructure,
|
||||
MediaChannelStructure,
|
||||
NewsChannelStructure,
|
||||
|
@ -1,3 +1,32 @@
|
||||
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 {
|
||||
BaseCommand,
|
||||
Command,
|
||||
@ -19,35 +48,6 @@ import {
|
||||
SubCommand,
|
||||
type UsingClient,
|
||||
} from '.';
|
||||
import type { Client, WorkerClient } from '../client';
|
||||
import { type MessageStructure, type OptionResolverStructure, Transformers } from '../client/transformers';
|
||||
import type { MakeRequired } from '../common';
|
||||
import { 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 & {
|
||||
type: ApplicationCommandOptionType;
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { promises } from 'node:fs';
|
||||
import { basename, dirname } from 'node:path';
|
||||
import type { EntryPointCommand } from '.';
|
||||
import type { Logger, NulleableCoalising, OmitInsert } from '../common';
|
||||
import { BaseHandler, isCloudfareWorker } from '../common';
|
||||
import { PermissionsBitField } from '../structures/extra/Permissions';
|
||||
@ -17,6 +16,7 @@ import {
|
||||
type LocaleString,
|
||||
type LocalizationMap,
|
||||
} from '../types';
|
||||
import type { EntryPointCommand } from '.';
|
||||
import { Command, type CommandOption, SubCommand } from './applications/chat';
|
||||
import { ContextMenuCommand } from './applications/menu';
|
||||
import { IgnoreCommand, type UsingClient } from './applications/shared';
|
||||
|
@ -1,11 +1,11 @@
|
||||
export * from './applications/shared';
|
||||
//
|
||||
export * from './applications/chat';
|
||||
export * from './applications/chatcontext';
|
||||
export * from './applications/entrycontext';
|
||||
export * from './applications/entryPoint';
|
||||
export * from './applications/menu';
|
||||
export * from './applications/menucontext';
|
||||
export * from './applications/options';
|
||||
export * from './applications/entryPoint';
|
||||
export * from './applications/entrycontext';
|
||||
export * from './applications/shared';
|
||||
export * from './decorators';
|
||||
export * from './optionresolver';
|
||||
|
@ -1,28 +1,28 @@
|
||||
export * from './it/constants';
|
||||
export * from './it/utils';
|
||||
//
|
||||
export * from './bot/watcher';
|
||||
export * from './it/colors';
|
||||
export { CustomizeLoggerCallback, AssignFilenameCallback, LogLevels, Logger, LoggerOptions } from './it/logger';
|
||||
export * from './it/constants';
|
||||
export * from './it/formatter';
|
||||
// circular lol
|
||||
export * from './shorters/invites';
|
||||
export { AssignFilenameCallback, CustomizeLoggerCallback, Logger, LoggerOptions, LogLevels } from './it/logger';
|
||||
export * from './it/utils';
|
||||
export * from './shorters/application';
|
||||
//
|
||||
export * from './shorters/channels';
|
||||
export * from './shorters/emojis';
|
||||
export * from './shorters/guilds';
|
||||
export * from './shorters/interaction';
|
||||
// circular lol
|
||||
export * from './shorters/invites';
|
||||
export * from './shorters/members';
|
||||
export * from './shorters/messages';
|
||||
export * from './shorters/reactions';
|
||||
export * from './shorters/roles';
|
||||
export * from './shorters/templates';
|
||||
export * from './shorters/users';
|
||||
export * from './shorters/threads';
|
||||
export * from './shorters/users';
|
||||
export * from './shorters/webhook';
|
||||
export * from './shorters/interaction';
|
||||
export * from './shorters/application';
|
||||
//
|
||||
export * from './types/options';
|
||||
export * from './types/resolvables';
|
||||
export * from './types/util';
|
||||
export * from './types/write';
|
||||
//
|
||||
export * from './bot/watcher';
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { type WriteStream, createWriteStream, existsSync, mkdirSync, promises } from 'node:fs';
|
||||
import { createWriteStream, existsSync, mkdirSync, promises, type WriteStream } from 'node:fs';
|
||||
import { join } from 'node:path';
|
||||
import { bgBrightWhite, black, bold, brightBlack, cyan, gray, italic, red, stripColor, yellow } from './colors';
|
||||
import { MergeOptions } from './utils';
|
||||
|
@ -1,5 +1,7 @@
|
||||
import { promises } from 'node:fs';
|
||||
import { basename, join } from 'node:path';
|
||||
import type { Cache } from '../../cache';
|
||||
import { type APIPartialEmoji, FormattingPatterns, GatewayIntentBits } from '../../types';
|
||||
import {
|
||||
type ColorResolvable,
|
||||
DiscordEpoch,
|
||||
@ -10,8 +12,6 @@ import {
|
||||
type ObjectToSnake,
|
||||
type TypeArray,
|
||||
} from '..';
|
||||
import type { Cache } from '../../cache';
|
||||
import { type APIPartialEmoji, FormattingPatterns, GatewayIntentBits } from '../../types';
|
||||
|
||||
/**
|
||||
* Calculates the shard ID for a guild based on its ID.
|
||||
@ -304,8 +304,6 @@ export function lazyLoadPackage<T>(mod: string): T | undefined {
|
||||
try {
|
||||
return require(mod);
|
||||
} catch (e) {
|
||||
// biome-ignore lint/suspicious/noConsoleLog:
|
||||
// biome-ignore lint/suspicious/noConsole:
|
||||
console.log(`Cannot import ${mod}`, e);
|
||||
return;
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { CacheFrom } from '../../cache';
|
||||
import type { Overwrites } from '../../cache/resources/overwrites';
|
||||
import { type MessageStructure, type ThreadChannelStructure, Transformers } from '../../client/transformers';
|
||||
import { type AllChannels, BaseChannel, type GuildMember, type GuildRole, channelFrom } from '../../structures';
|
||||
import { type AllChannels, BaseChannel, channelFrom, type GuildMember, type GuildRole } from '../../structures';
|
||||
import { PermissionsBitField } from '../../structures/extra/Permissions';
|
||||
import type {
|
||||
APIChannel,
|
||||
|
@ -14,8 +14,8 @@ import {
|
||||
type AllChannels,
|
||||
BaseChannel,
|
||||
type CreateStickerBodyRequest,
|
||||
type GuildChannelTypes,
|
||||
channelFrom,
|
||||
type GuildChannelTypes,
|
||||
} from '../../structures';
|
||||
import type {
|
||||
APIChannel,
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { BaseInteraction, Modal, type ReplyInteractionBody, resolveFiles } from '../..';
|
||||
import { Transformers, type WebhookMessageStructure } from '../../client/transformers';
|
||||
import type { RESTPostAPIWebhookWithTokenWaitResult } from '../../types';
|
||||
import type { InteractionMessageUpdateBodyRequest, MessageWebhookCreateBodyRequest } from '../types/write';
|
||||
import { BaseShorter } from './base';
|
||||
|
||||
@ -69,12 +70,12 @@ export class InteractionShorter extends BaseShorter {
|
||||
|
||||
async followup(token: string, { files, ...body }: MessageWebhookCreateBodyRequest): Promise<WebhookMessageStructure> {
|
||||
const parsedFiles = files ? await resolveFiles(files) : undefined;
|
||||
const apiMessage = await this.client.proxy
|
||||
const apiMessage = (await this.client.proxy
|
||||
.webhooks(this.client.applicationId)(token)
|
||||
.post({
|
||||
body: BaseInteraction.transformBody(body, parsedFiles, this.client),
|
||||
files: parsedFiles,
|
||||
});
|
||||
})) as RESTPostAPIWebhookWithTokenWaitResult;
|
||||
return Transformers.WebhookMessage(this.client, apiMessage, this.client.applicationId, token);
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,7 @@
|
||||
import type { ValidAnswerId } from '../../api/Routes/channels';
|
||||
import { resolveFiles } from '../../builders';
|
||||
import { CacheFrom } from '../../cache';
|
||||
import { type MessageStructure, type ThreadChannelStructure, Transformers, type UserStructure } from '../../client';
|
||||
import { MessagesMethods } from '../../structures';
|
||||
import type {
|
||||
RESTGetAPIChannelMessagesQuery,
|
||||
@ -6,10 +9,6 @@ import type {
|
||||
RESTPostAPIChannelMessageJSONBody,
|
||||
RESTPostAPIChannelMessagesThreadsJSONBody,
|
||||
} 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 { BaseShorter } from './base';
|
||||
|
||||
|
@ -92,10 +92,9 @@ export class RoleShorter extends BaseShorter {
|
||||
* @param reason The reason for deleting the role.
|
||||
* @returns A Promise that resolves when the role is deleted.
|
||||
*/
|
||||
async delete(guildId: string, roleId: string, reason?: string): Promise<GuildRoleStructure> {
|
||||
const res = await this.client.proxy.guilds(guildId).roles(roleId).delete({ reason });
|
||||
async delete(guildId: string, roleId: string, reason?: string) {
|
||||
await this.client.proxy.guilds(guildId).roles(roleId).delete({ reason });
|
||||
this.client.cache.roles?.removeIfNI('Guilds', roleId, guildId);
|
||||
return Transformers.GuildRole(this.client, res, guildId);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,15 +1,16 @@
|
||||
import { CacheFrom } from '../..';
|
||||
import type { ThreadChannelStructure } from '../../client/transformers';
|
||||
import { channelFrom } from '../../structures';
|
||||
import type {
|
||||
APIThreadChannel,
|
||||
APIThreadMember,
|
||||
RESTGetAPIChannelThreadMembersQuery,
|
||||
RESTGetAPIChannelThreadsArchivedQuery,
|
||||
RESTPatchAPIChannelJSONBody,
|
||||
RESTPostAPIChannelMessagesThreadsJSONBody,
|
||||
RESTPostAPIChannelThreadsJSONBody,
|
||||
RESTPostAPIGuildForumThreadsJSONBody,
|
||||
import {
|
||||
type APIThreadChannel,
|
||||
type APIThreadMember,
|
||||
ChannelType,
|
||||
type RESTGetAPIChannelThreadMembersQuery,
|
||||
type RESTGetAPIChannelThreadsArchivedQuery,
|
||||
type RESTPatchAPIChannelJSONBody,
|
||||
type RESTPostAPIChannelMessagesThreadsJSONBody,
|
||||
type RESTPostAPIChannelThreadsJSONBody,
|
||||
type RESTPostAPIGuildForumThreadsJSONBody,
|
||||
} from '../../types';
|
||||
import type { MakeRequired, When } from '../types/util';
|
||||
import { BaseShorter } from './base';
|
||||
@ -44,27 +45,22 @@ export class ThreadShorter extends BaseShorter {
|
||||
);
|
||||
}
|
||||
|
||||
fromMessage(
|
||||
async fromMessage(
|
||||
channelId: string,
|
||||
messageId: string,
|
||||
options: RESTPostAPIChannelMessagesThreadsJSONBody & { reason?: string },
|
||||
): Promise<ThreadChannelStructure> {
|
||||
const { reason, ...body } = options;
|
||||
|
||||
return this.client.proxy
|
||||
.channels(channelId)
|
||||
.messages(messageId)
|
||||
.threads.post({ body, reason })
|
||||
.then(async thread => {
|
||||
await this.client.cache.channels?.setIfNI(
|
||||
CacheFrom.Rest,
|
||||
'Guilds',
|
||||
thread.id,
|
||||
(thread as APIThreadChannel).guild_id!,
|
||||
thread,
|
||||
);
|
||||
return channelFrom(thread, this.client) as ThreadChannelStructure;
|
||||
});
|
||||
const thread = await this.client.proxy.channels(channelId).messages(messageId).threads.post({ body, reason });
|
||||
await this.client.cache.channels?.setIfNI(
|
||||
CacheFrom.Rest,
|
||||
'Guilds',
|
||||
thread.id,
|
||||
(thread as APIThreadChannel).guild_id!,
|
||||
thread,
|
||||
);
|
||||
return await (channelFrom(thread, this.client) as ThreadChannelStructure);
|
||||
}
|
||||
|
||||
join(threadId: string) {
|
||||
@ -75,8 +71,9 @@ export class ThreadShorter extends BaseShorter {
|
||||
return this.client.proxy.channels(threadId)['thread-members']('@me').delete();
|
||||
}
|
||||
|
||||
lock(threadId: string, locked = true, reason?: string): Promise<ThreadChannelStructure> {
|
||||
return this.edit(threadId, { locked }, reason).then(x => channelFrom(x, this.client) as ThreadChannelStructure);
|
||||
async lock(threadId: string, locked = true, reason?: string): Promise<ThreadChannelStructure> {
|
||||
const x = await this.edit(threadId, { locked }, reason);
|
||||
return channelFrom(x, this.client) as ThreadChannelStructure;
|
||||
}
|
||||
|
||||
async edit(threadId: string, body: RESTPatchAPIChannelJSONBody, reason?: string): Promise<ThreadChannelStructure> {
|
||||
@ -110,7 +107,7 @@ export class ThreadShorter extends BaseShorter {
|
||||
return this.client.proxy.channels(threadId)['thread-members'].get({ query }) as never;
|
||||
}
|
||||
|
||||
async listArchivedThreads(
|
||||
async listArchived(
|
||||
channelId: string,
|
||||
type: 'public' | 'private',
|
||||
query?: RESTGetAPIChannelThreadsArchivedQuery,
|
||||
@ -128,6 +125,25 @@ 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(
|
||||
channelId: string,
|
||||
query?: RESTGetAPIChannelThreadsArchivedQuery,
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { resolveFiles } from '../../builders';
|
||||
import { Transformers, type WebhookMessageStructure, type WebhookStructure } from '../../client/transformers';
|
||||
import {
|
||||
MessagesMethods,
|
||||
type MessageWebhookMethodEditParams,
|
||||
type MessageWebhookMethodWriteParams,
|
||||
MessagesMethods,
|
||||
} from '../../structures';
|
||||
import type {
|
||||
APIWebhook,
|
||||
|
@ -1,6 +1,6 @@
|
||||
import type { Identify } from '..';
|
||||
import type { CDNUrlOptions } from '../../api';
|
||||
import type { UsingClient } from '../../commands';
|
||||
import type { Identify } from '..';
|
||||
|
||||
export type ImageOptions = CDNUrlOptions;
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import type { EmbedColors, OmitInsert } from '..';
|
||||
import type { Attachment, AttachmentDataType, AttachmentResolvable } from '../../builders';
|
||||
import type { GuildMember } from '../../structures';
|
||||
import type { APIGuildMember, APIPartialEmoji, RESTPostAPIApplicationEmojiJSONBody } from '../../types';
|
||||
import type { EmbedColors, OmitInsert } from '..';
|
||||
|
||||
export type EmojiResolvable = string | Partial<APIPartialEmoji> | `<${string | undefined}:${string}:${string}>`;
|
||||
export type GuildMemberResolvable = string | Partial<GuildMember> | APIGuildMember;
|
||||
|
@ -107,7 +107,7 @@ export type SnakeCase<S extends string> = S extends `${infer A}${infer Rest}`
|
||||
export type ObjectToLower<T> = T extends unknown[]
|
||||
? ObjectToLower<T[0]>[]
|
||||
: Identify<{
|
||||
[K in keyof T as CamelCase<Exclude<K, symbol | number>>]: T[K] extends unknown[]
|
||||
[K in keyof T as K extends number ? K : CamelCase<Exclude<K, symbol | number>>]: T[K] extends unknown[]
|
||||
? Identify<ObjectToLower<T[K][0]>[]>
|
||||
: T[K] extends object
|
||||
? Identify<ObjectToLower<T[K]>>
|
||||
@ -119,7 +119,7 @@ export type ObjectToLower<T> = T extends unknown[]
|
||||
export type ObjectToLowerUndefined<T> = T extends unknown[]
|
||||
? ObjectToLower<T[0]>[]
|
||||
: Identify<{
|
||||
[K in keyof T as CamelCase<Exclude<K, symbol | number>>]: T[K] extends unknown[]
|
||||
[K in keyof T as K extends number ? K : CamelCase<Exclude<K, symbol | number>>]: T[K] extends unknown[]
|
||||
? ObjectToLower<T[K][0]>[]
|
||||
: T[K] extends object
|
||||
? ObjectToLower<T[K]>
|
||||
@ -127,7 +127,7 @@ export type ObjectToLowerUndefined<T> = T extends unknown[]
|
||||
}>;
|
||||
|
||||
export type ObjectToSnake<T> = Identify<{
|
||||
[K in keyof T as SnakeCase<Exclude<K, symbol | number>>]: T[K] extends unknown[]
|
||||
[K in keyof T as K extends number ? K : SnakeCase<Exclude<K, symbol | number>>]: T[K] extends unknown[]
|
||||
? Identify<ObjectToSnake<T[K][0]>[]>
|
||||
: T[K] extends object
|
||||
? Identify<ObjectToSnake<T[K]>>
|
||||
@ -139,7 +139,7 @@ export type ObjectToSnake<T> = Identify<{
|
||||
export type ObjectToSnakeUndefined<T> = T extends unknown[]
|
||||
? ObjectToSnake<T[0]>[]
|
||||
: Identify<{
|
||||
[K in keyof T as SnakeCase<Exclude<K, symbol | number>>]: T[K] extends unknown[]
|
||||
[K in keyof T as K extends number ? K : SnakeCase<Exclude<K, symbol | number>>]: T[K] extends unknown[]
|
||||
? ObjectToSnake<T[K][0]>[]
|
||||
: T[K] extends object
|
||||
? ObjectToSnake<T[K]>
|
||||
@ -171,14 +171,10 @@ type OptionalizeAux<T extends object> = Identify<
|
||||
* it is recursive
|
||||
*/
|
||||
export type Optionalize<T> = T extends object
|
||||
? // biome-ignore lint/style/useShorthandArrayType: typescript things
|
||||
// biome-ignore lint/style/useConsistentArrayType: <explanation>
|
||||
T extends Array<unknown>
|
||||
? T extends Array<unknown>
|
||||
? number extends T['length']
|
||||
? T[number] extends object
|
||||
? // biome-ignore lint/style/useShorthandArrayType: <explanation>
|
||||
// biome-ignore lint/style/useConsistentArrayType: <explanation>
|
||||
Array<OptionalizeAux<T[number]>>
|
||||
? Array<OptionalizeAux<T[number]>>
|
||||
: T
|
||||
: Partial<T>
|
||||
: OptionalizeAux<T>
|
||||
|
@ -16,6 +16,7 @@ import type {
|
||||
import type { OmitInsert } from './util';
|
||||
|
||||
export interface ResolverProps {
|
||||
content?: string | undefined | null;
|
||||
embeds?: Embed[] | APIEmbed[] | undefined;
|
||||
components?: TopLevelBuilders[] | ReturnType<TopLevelBuilders['toJSON']>[];
|
||||
files?: AttachmentBuilder[] | Attachment[] | RawFile[] | undefined;
|
||||
@ -27,31 +28,31 @@ export interface SendResolverProps extends ResolverProps {
|
||||
|
||||
export type MessageCreateBodyRequest = OmitInsert<
|
||||
RESTPostAPIChannelMessageJSONBody,
|
||||
'components' | 'embeds' | 'poll',
|
||||
'components' | 'embeds' | 'poll' | 'content',
|
||||
SendResolverProps
|
||||
>;
|
||||
|
||||
export type MessageUpdateBodyRequest = OmitInsert<
|
||||
RESTPatchAPIChannelMessageJSONBody,
|
||||
'components' | 'embeds',
|
||||
'components' | 'embeds' | 'content',
|
||||
ResolverProps
|
||||
>;
|
||||
|
||||
export type MessageWebhookCreateBodyRequest = OmitInsert<
|
||||
RESTPostAPIWebhookWithTokenJSONBody,
|
||||
'components' | 'embeds' | 'poll',
|
||||
'components' | 'embeds' | 'poll' | 'content',
|
||||
SendResolverProps
|
||||
>;
|
||||
|
||||
export type MessageWebhookUpdateBodyRequest = OmitInsert<
|
||||
RESTPatchAPIWebhookWithTokenMessageJSONBody,
|
||||
'components' | 'embeds' | 'poll',
|
||||
'components' | 'embeds' | 'poll' | 'content',
|
||||
ResolverProps
|
||||
>;
|
||||
|
||||
export type InteractionMessageUpdateBodyRequest = OmitInsert<
|
||||
RESTPatchAPIWebhookWithTokenMessageJSONBody,
|
||||
'components' | 'embeds' | 'poll',
|
||||
'components' | 'embeds' | 'poll' | 'content',
|
||||
SendResolverProps
|
||||
> & {
|
||||
flags?: MessageFlags;
|
||||
@ -59,14 +60,18 @@ export type InteractionMessageUpdateBodyRequest = OmitInsert<
|
||||
|
||||
export type ComponentInteractionMessageUpdate = OmitInsert<
|
||||
APIInteractionResponseCallbackData,
|
||||
'components' | 'embeds',
|
||||
'components' | 'embeds' | 'content',
|
||||
ResolverProps
|
||||
>;
|
||||
|
||||
export type InteractionCreateBodyRequest = OmitInsert<
|
||||
APIInteractionResponseChannelMessageWithSource['data'],
|
||||
'components' | 'embeds' | 'poll',
|
||||
'components' | 'embeds' | 'poll' | 'content',
|
||||
SendResolverProps
|
||||
>;
|
||||
|
||||
export type ModalCreateBodyRequest = APIModalInteractionResponse['data'] | Modal;
|
||||
|
||||
export interface ModalCreateOptions {
|
||||
waitFor?: number;
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import {
|
||||
type ChannelSelectMenu,
|
||||
type Container,
|
||||
type File,
|
||||
fromComponent,
|
||||
type MediaGallery,
|
||||
type MentionableSelectMenu,
|
||||
type RoleSelectMenu,
|
||||
@ -14,7 +15,6 @@ import {
|
||||
type TextInput,
|
||||
type Thumbnail,
|
||||
type UserSelectMenu,
|
||||
fromComponent,
|
||||
} from '../builders';
|
||||
import {
|
||||
type APIActionRowComponent,
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { type ContainerComponents, componentFactory } from '.';
|
||||
import type { APIContainerComponent, ComponentType } from '../types';
|
||||
import { type ContainerComponents, componentFactory } from '.';
|
||||
import { BaseComponent } from './BaseComponent';
|
||||
|
||||
export class ContainerComponent extends BaseComponent<ComponentType.Container> {
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { componentFactory } from '.';
|
||||
import type { APISectionComponent, ComponentType } from '../types';
|
||||
import { componentFactory } from '.';
|
||||
import { BaseComponent } from './BaseComponent';
|
||||
import type { ButtonComponent } from './ButtonComponent';
|
||||
import type { TextDisplayComponent } from './TextDisplay';
|
||||
|
@ -14,13 +14,17 @@ export interface ComponentCommand {
|
||||
export abstract class ComponentCommand {
|
||||
type = InteractionCommandType.COMPONENT;
|
||||
abstract componentType: keyof ContextComponentCommandInteractionMap;
|
||||
customId?: string;
|
||||
customId?: string | RegExp;
|
||||
filter?(context: ComponentContext<typeof this.componentType>): Promise<boolean> | boolean;
|
||||
abstract run(context: ComponentContext<typeof this.componentType>): any;
|
||||
|
||||
/** @internal */
|
||||
_filter(context: ComponentContext) {
|
||||
if (this.customId && this.customId !== context.customId) return false;
|
||||
if (this.customId) {
|
||||
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);
|
||||
return true;
|
||||
}
|
||||
|
@ -18,16 +18,18 @@ import type {
|
||||
} from '../client/transformers';
|
||||
import type { CommandMetadata, ExtendContext, GlobalMetadata, RegisteredMiddlewares, UsingClient } from '../commands';
|
||||
import { BaseContext } from '../commands/basecontext';
|
||||
import type {
|
||||
import {
|
||||
ComponentInteractionMessageUpdate,
|
||||
InteractionCreateBodyRequest,
|
||||
InteractionMessageUpdateBodyRequest,
|
||||
MakeRequired,
|
||||
MessageWebhookCreateBodyRequest,
|
||||
ModalCreateBodyRequest,
|
||||
ModalCreateOptions,
|
||||
UnionToTuple,
|
||||
When,
|
||||
} from '../common';
|
||||
import { ModalSubmitInteraction } from '../structures';
|
||||
import { ComponentType, MessageFlags, type RESTGetAPIGuildQuery } from '../types';
|
||||
|
||||
export interface ComponentContext<
|
||||
@ -150,8 +152,11 @@ export class ComponentContext<
|
||||
return this.interaction.deleteResponse();
|
||||
}
|
||||
|
||||
modal(body: ModalCreateBodyRequest) {
|
||||
return this.interaction.modal(body);
|
||||
modal(body: ModalCreateBodyRequest, options?: undefined): Promise<undefined>;
|
||||
modal(body: ModalCreateBodyRequest, options: ModalCreateOptions): Promise<ModalSubmitInteraction | null>;
|
||||
modal(body: ModalCreateBodyRequest, options?: ModalCreateOptions | undefined) {
|
||||
if (options === undefined) return this.interaction.modal(body);
|
||||
return this.interaction.modal(body, options);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -9,7 +9,7 @@ import type {
|
||||
import { LimitedCollection } from '../collection';
|
||||
import { BaseCommand, type RegisteredMiddlewares, type UsingClient } from '../commands';
|
||||
import type { FileLoaded } from '../commands/handler';
|
||||
import { BaseHandler, type Logger, type OnFailCallback, isCloudfareWorker, magicImport } from '../common';
|
||||
import { BaseHandler, isCloudfareWorker, type Logger, magicImport, type OnFailCallback } from '../common';
|
||||
import type { ComponentInteraction, ModalSubmitInteraction, StringSelectMenuInteraction } from '../structures';
|
||||
import { ComponentCommand, InteractionCommandType } from './componentcommand';
|
||||
import type { ComponentContext } from './componentcontext';
|
||||
@ -38,6 +38,11 @@ export interface CreateComponentCollectorResult {
|
||||
callback: ComponentCallback<T>,
|
||||
): void;
|
||||
stop(reason?: string): void;
|
||||
waitFor<T extends CollectorInteraction = CollectorInteraction>(
|
||||
customId: UserMatches,
|
||||
timeout?: number,
|
||||
): Promise<T | null>;
|
||||
resetTimeouts(): void;
|
||||
}
|
||||
|
||||
export class ComponentHandler extends BaseHandler {
|
||||
@ -115,6 +120,28 @@ export class ComponentHandler extends BaseHandler {
|
||||
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);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import type { AllChannels, Interaction, ModalCommand, ModalSubmitInteraction, ReturnCache } from '..';
|
||||
import type { AllChannels, ModalCommand, ModalSubmitInteraction, ReturnCache } from '..';
|
||||
import type {
|
||||
GuildMemberStructure,
|
||||
GuildStructure,
|
||||
@ -8,12 +8,13 @@ import type {
|
||||
} from '../client/transformers';
|
||||
import type { CommandMetadata, ExtendContext, GlobalMetadata, RegisteredMiddlewares, UsingClient } from '../commands';
|
||||
import { BaseContext } from '../commands/basecontext';
|
||||
import type {
|
||||
import {
|
||||
InteractionCreateBodyRequest,
|
||||
InteractionMessageUpdateBodyRequest,
|
||||
MakeRequired,
|
||||
MessageWebhookCreateBodyRequest,
|
||||
ModalCreateBodyRequest,
|
||||
ModalCreateOptions,
|
||||
UnionToTuple,
|
||||
When,
|
||||
} from '../common';
|
||||
@ -119,9 +120,11 @@ export class ModalContext<M extends keyof RegisteredMiddlewares = never> extends
|
||||
return this.interaction.deleteResponse();
|
||||
}
|
||||
|
||||
modal(body: ModalCreateBodyRequest): ReturnType<Interaction['modal']> {
|
||||
//@ts-expect-error
|
||||
return this.interaction.modal(body);
|
||||
modal(body: ModalCreateBodyRequest, options?: undefined): Promise<undefined>;
|
||||
modal(body: ModalCreateBodyRequest, options: ModalCreateOptions): Promise<ModalSubmitInteraction | null>;
|
||||
modal(body: ModalCreateBodyRequest, options?: ModalCreateOptions | undefined) {
|
||||
// @ts-expect-error
|
||||
return this.interaction.modal(body, options);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -4,11 +4,11 @@ import type { FileLoaded } from '../commands/handler';
|
||||
import {
|
||||
BaseHandler,
|
||||
type CamelCase,
|
||||
isCloudfareWorker,
|
||||
type MakeRequired,
|
||||
magicImport,
|
||||
ReplaceRegex,
|
||||
type SnakeCase,
|
||||
isCloudfareWorker,
|
||||
magicImport,
|
||||
} from '../common';
|
||||
import type { ClientEvents } from '../events/hooks';
|
||||
import * as RawEvents from '../events/hooks';
|
||||
|
@ -1,3 +1,6 @@
|
||||
import type { UsingClient } from '../../commands';
|
||||
import { toCamelCase } from '../../common';
|
||||
import { type AllChannels, channelFrom } from '../../structures';
|
||||
import type {
|
||||
GatewayChannelCreateDispatchData,
|
||||
GatewayChannelDeleteDispatchData,
|
||||
@ -5,10 +8,6 @@ import type {
|
||||
GatewayChannelUpdateDispatchData,
|
||||
} 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 => {
|
||||
return channelFrom(data, self);
|
||||
};
|
||||
|
@ -20,8 +20,8 @@ import type {
|
||||
GatewayGuildIntegrationsUpdateDispatchData,
|
||||
GatewayGuildMemberAddDispatchData,
|
||||
GatewayGuildMemberRemoveDispatchData,
|
||||
GatewayGuildMemberUpdateDispatchData,
|
||||
GatewayGuildMembersChunkDispatchData,
|
||||
GatewayGuildMemberUpdateDispatchData,
|
||||
GatewayGuildRoleCreateDispatchData,
|
||||
GatewayGuildRoleDeleteDispatchData,
|
||||
GatewayGuildRoleUpdateDispatchData,
|
||||
|
@ -10,13 +10,13 @@ export * from './interactions';
|
||||
export * from './invite';
|
||||
export * from './message';
|
||||
export * from './presence';
|
||||
export * from './soundboard';
|
||||
export * from './stage';
|
||||
export * from './thread';
|
||||
export * from './typing';
|
||||
export * from './user';
|
||||
export * from './voice';
|
||||
export * from './webhook';
|
||||
export * from './soundboard';
|
||||
|
||||
import type { CamelCase } from '../../common';
|
||||
import type * as RawEvents from './index';
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { type MessageStructure, Transformers } from '../../client/transformers';
|
||||
import type { UsingClient } from '../../commands';
|
||||
import { type ObjectToLower, type OmitInsert, fakePromise, toCamelCase } from '../../common';
|
||||
import { fakePromise, type ObjectToLower, type OmitInsert, toCamelCase } from '../../common';
|
||||
import type {
|
||||
GatewayMessageCreateDispatchData,
|
||||
GatewayMessageDeleteBulkDispatchData,
|
||||
|
@ -5,8 +5,8 @@ import type {
|
||||
APISoundBoard,
|
||||
GatewayGuildSoundboardSoundCreateDispatchData,
|
||||
GatewayGuildSoundboardSoundDeleteDispatchData,
|
||||
GatewayGuildSoundboardSoundUpdateDispatchData,
|
||||
GatewayGuildSoundboardSoundsUpdateDispatchData,
|
||||
GatewayGuildSoundboardSoundUpdateDispatchData,
|
||||
GatewaySoundboardSoundsDispatchData,
|
||||
} from '../../types';
|
||||
|
||||
|
@ -5,8 +5,8 @@ import type {
|
||||
GatewayThreadCreateDispatchData,
|
||||
GatewayThreadDeleteDispatchData,
|
||||
GatewayThreadListSyncDispatchData,
|
||||
GatewayThreadMemberUpdateDispatchData,
|
||||
GatewayThreadMembersUpdateDispatchData,
|
||||
GatewayThreadMemberUpdateDispatchData,
|
||||
GatewayThreadUpdateDispatchData,
|
||||
} from '../../types';
|
||||
|
||||
|
12
src/index.ts
12
src/index.ts
@ -1,4 +1,5 @@
|
||||
export * from './client';
|
||||
|
||||
import {
|
||||
BaseClient,
|
||||
type BaseClientOptions,
|
||||
@ -10,21 +11,22 @@ import {
|
||||
import { isCloudfareWorker } from './common';
|
||||
import type { ClientNameEvents, CustomEventsKeys, ResolveEventParams } from './events';
|
||||
import { GatewayIntentBits } from './types';
|
||||
export { Logger, PermissionStrings, Formatter } from './common';
|
||||
//
|
||||
export { Collection, LimitedCollection } from './collection';
|
||||
|
||||
//
|
||||
export * from './api';
|
||||
export * from './builders';
|
||||
export * from './cache';
|
||||
//
|
||||
export { Collection, LimitedCollection } from './collection';
|
||||
export * from './commands';
|
||||
export { Formatter, Logger, PermissionStrings } from './common';
|
||||
export * from './components';
|
||||
export * from './events';
|
||||
export * from './langs';
|
||||
//
|
||||
export { ShardManager, WorkerManager } from './websocket/discord';
|
||||
//
|
||||
export * from './structures';
|
||||
//
|
||||
export { ShardManager, WorkerManager } from './websocket/discord';
|
||||
|
||||
/**
|
||||
* Creates an event with the specified data and run function.
|
||||
|
@ -14,6 +14,7 @@ export const LangRouter = (userLocale: string, defaultLang: string, langs: Parti
|
||||
function getValue(locale?: string) {
|
||||
if (typeof locale === 'undefined') throw new Error('Undefined locale');
|
||||
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];
|
||||
return value;
|
||||
}
|
||||
@ -51,4 +52,4 @@ export type __InternalParseLocale<T extends Record<string, any>> = {
|
||||
};
|
||||
|
||||
export type ParseLocales<T extends Record<string, any>> = T;
|
||||
/**Idea inspiration from: FreeAoi */
|
||||
/**Idea inspiration from: FreeAoi | Fixed by: Drylozu */
|
||||
|
@ -1,18 +1,18 @@
|
||||
import type { GuildMemberStructure, GuildStructure } from '../client';
|
||||
import type { GuildMemberStructure, GuildStructure, ThreadChannelStructure } from '../client';
|
||||
import type { UsingClient } from '../commands';
|
||||
import type { CreateInviteFromChannel } from '../common';
|
||||
import type { ObjectToLower, StructPropState, StructStates, ToClass } from '../common/types/util';
|
||||
import type { APIGuild, APIPartialGuild, GatewayGuildCreateDispatchData, RESTPatchAPIGuildJSONBody } from '../types';
|
||||
import { AutoModerationRule } from './AutoModerationRule';
|
||||
import { BaseChannel, WebhookGuildMethods } from './channels';
|
||||
import { GuildEmoji } from './Emoji';
|
||||
import { BaseGuild } from './extra/BaseGuild';
|
||||
import type { DiscordBase } from './extra/DiscordBase';
|
||||
import { GuildBan } from './GuildBan';
|
||||
import { GuildMember } from './GuildMember';
|
||||
import { GuildRole } from './GuildRole';
|
||||
import { GuildTemplate } from './GuildTemplate';
|
||||
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 class Guild<State extends StructStates = 'api'> extends (BaseGuild as unknown as ToClass<
|
||||
@ -71,6 +71,10 @@ export class Guild<State extends StructStates = 'api'> extends (BaseGuild as unk
|
||||
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 });
|
||||
stickers = Sticker.methods({ client: this.client, guildId: this.id });
|
||||
members = GuildMember.methods({ client: this.client, guildId: this.id });
|
||||
|
@ -3,7 +3,7 @@ import type { GuildBanStructure, GuildStructure } from '../client';
|
||||
import type { UsingClient } from '../commands';
|
||||
import { Formatter, type MethodContext, type ObjectToLower } from '../common';
|
||||
import type { BanShorter } from '../common/shorters/bans';
|
||||
import type { APIBan, ActuallyBan, RESTGetAPIGuildBansQuery } from '../types';
|
||||
import type { ActuallyBan, APIBan, RESTGetAPIGuildBansQuery } from '../types';
|
||||
import { DiscordBase } from './extra/DiscordBase';
|
||||
|
||||
export interface GuildBan extends DiscordBase, ObjectToLower<Omit<APIBan, 'id'>> {}
|
||||
|
@ -46,7 +46,7 @@ export class GuildRole extends DiscordBase {
|
||||
return this.client.roles.edit(this.guildId, this.id, body);
|
||||
}
|
||||
|
||||
delete(reason?: string): Promise<GuildRoleStructure> {
|
||||
delete(reason?: string) {
|
||||
return this.client.roles.delete(this.guildId, this.id, reason);
|
||||
}
|
||||
|
||||
@ -61,8 +61,7 @@ export class GuildRole extends DiscordBase {
|
||||
list: (force = false): Promise<GuildRoleStructure[]> => ctx.client.roles.list(ctx.guildId, force),
|
||||
edit: (roleId: string, body: RESTPatchAPIGuildRoleJSONBody, reason?: string): Promise<GuildRoleStructure> =>
|
||||
ctx.client.roles.edit(ctx.guildId, roleId, body, reason),
|
||||
delete: (roleId: string, reason?: string): Promise<GuildRoleStructure> =>
|
||||
ctx.client.roles.delete(ctx.guildId, roleId, reason),
|
||||
delete: (roleId: string, reason?: string) => ctx.client.roles.delete(ctx.guildId, roleId, reason),
|
||||
editPositions: (body: RESTPatchAPIGuildRolePositionsJSONBody): Promise<GuildRoleStructure[]> =>
|
||||
ctx.client.roles.editPositions(ctx.guildId, body),
|
||||
};
|
||||
|
@ -1,3 +1,34 @@
|
||||
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 {
|
||||
type APIActionRowComponent,
|
||||
type APIApplicationCommandAutocompleteInteraction,
|
||||
@ -41,37 +72,6 @@ import {
|
||||
type RESTPostAPIInteractionCallbackJSONBody,
|
||||
type RESTPostAPIInteractionCallbackResult,
|
||||
} 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 { DiscordBase } from './extra/DiscordBase';
|
||||
import { PermissionsBitField } from './extra/Permissions';
|
||||
@ -315,7 +315,6 @@ export class BaseInteraction<
|
||||
switch (gateway.type) {
|
||||
case InteractionType.ApplicationCommandAutocomplete:
|
||||
return new AutocompleteInteraction(client, gateway, undefined, __reply);
|
||||
// biome-ignore lint/suspicious/noFallthroughSwitchClause: bad interaction between biome and ts-server
|
||||
case InteractionType.ApplicationCommand:
|
||||
switch (gateway.data.type) {
|
||||
case ApplicationCommandType.ChatInput:
|
||||
@ -474,11 +473,37 @@ export class Interaction<
|
||||
) as never;
|
||||
}
|
||||
|
||||
modal(body: ModalCreateBodyRequest) {
|
||||
return this.reply({
|
||||
modal(body: ModalCreateBodyRequest, options?: undefined): Promise<undefined>;
|
||||
modal(body: ModalCreateBodyRequest, options: ModalCreateOptions): Promise<ModalSubmitInteraction | null>;
|
||||
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,
|
||||
data: body,
|
||||
});
|
||||
return promise;
|
||||
}
|
||||
|
||||
async editOrReply<FR extends boolean = false>(
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { type AllChannels, Embed, type ReturnCache, componentFactory } from '..';
|
||||
import { type AllChannels, componentFactory, Embed, type ReturnCache } from '..';
|
||||
import type { ListenerOptions } from '../builders';
|
||||
import {
|
||||
type GuildMemberStructure,
|
||||
@ -11,8 +11,7 @@ import {
|
||||
type WebhookStructure,
|
||||
} from '../client/transformers';
|
||||
import type { UsingClient } from '../commands';
|
||||
import { type ObjectToLower, toCamelCase } from '../common';
|
||||
import { Formatter } from '../common';
|
||||
import { Formatter, type ObjectToLower, toCamelCase } from '../common';
|
||||
import type { EmojiResolvable } from '../common/types/resolvables';
|
||||
import type { MessageCreateBodyRequest, MessageUpdateBodyRequest } from '../common/types/write';
|
||||
import type { TopLevelComponents } from '../components';
|
||||
@ -24,8 +23,8 @@ import type {
|
||||
APIUser,
|
||||
GatewayMessageCreateDispatchData,
|
||||
} from '../types';
|
||||
import type { MessageWebhookMethodEditParams, MessageWebhookMethodWriteParams } from './Webhook';
|
||||
import { DiscordBase } from './extra/DiscordBase';
|
||||
import type { MessageWebhookMethodEditParams, MessageWebhookMethodWriteParams } from './Webhook';
|
||||
|
||||
export type MessageData = APIMessage | GatewayMessageCreateDispatchData;
|
||||
|
||||
|
@ -5,8 +5,8 @@ import {
|
||||
type BaseChannelStructure,
|
||||
type BaseGuildChannelStructure,
|
||||
type CategoryChannelStructure,
|
||||
type DMChannelStructure,
|
||||
type DirectoryChannelStructure,
|
||||
type DMChannelStructure,
|
||||
type ForumChannelStructure,
|
||||
type GuildMemberStructure,
|
||||
type GuildStructure,
|
||||
@ -26,13 +26,13 @@ import type { SeyfertChannelMap, UsingClient } from '../commands';
|
||||
import {
|
||||
type CreateInviteFromChannel,
|
||||
type EmojiResolvable,
|
||||
fakePromise,
|
||||
type MessageCreateBodyRequest,
|
||||
type MessageUpdateBodyRequest,
|
||||
type MethodContext,
|
||||
type ObjectToLower,
|
||||
type StringToNumber,
|
||||
type ToClass,
|
||||
fakePromise,
|
||||
} from '../common';
|
||||
import { mix } from '../deps/mixer';
|
||||
import {
|
||||
@ -63,9 +63,9 @@ import {
|
||||
type ThreadAutoArchiveDuration,
|
||||
VideoQualityMode,
|
||||
} from '../types';
|
||||
import { DiscordBase } from './extra/DiscordBase';
|
||||
import type { GuildMember } from './GuildMember';
|
||||
import type { GuildRole } from './GuildRole';
|
||||
import { DiscordBase } from './extra/DiscordBase';
|
||||
|
||||
export class BaseNoEditableChannel<T extends ChannelType> extends DiscordBase<APIChannelBase<ChannelType>> {
|
||||
declare type: T;
|
||||
@ -581,13 +581,15 @@ export class ForumChannel extends BaseGuildChannel {
|
||||
|
||||
export interface ThreadChannel
|
||||
extends ObjectToLower<Omit<APIThreadChannel, 'permission_overwrites' | 'guild_id'>>,
|
||||
Omit<TextBaseGuildChannel, 'edit' | 'parentId'> {}
|
||||
Omit<TextBaseGuildChannel, 'edit' | 'parentId'> {
|
||||
parentId: string;
|
||||
}
|
||||
@mix(TextBaseGuildChannel)
|
||||
export class ThreadChannel extends BaseChannel<
|
||||
ChannelType.PublicThread | ChannelType.AnnouncementThread | ChannelType.PrivateThread
|
||||
> {
|
||||
parentId!: string;
|
||||
declare type: ChannelType.PublicThread | ChannelType.AnnouncementThread | ChannelType.PrivateThread;
|
||||
|
||||
webhooks = WebhookChannelMethods.channel({
|
||||
client: this.client,
|
||||
channelId: this.parentId,
|
||||
|
@ -1,6 +1,6 @@
|
||||
import type { ReturnCache, WorkerClient } from '../..';
|
||||
import type { GuildStructure } from '../../client';
|
||||
import { type ObjectToLower, calculateShardId } from '../../common';
|
||||
import { calculateShardId, type ObjectToLower } from '../../common';
|
||||
import type { ImageOptions } from '../../common/types/options';
|
||||
import { type APIPartialGuild, GuildFeature } from '../../types';
|
||||
import type { ShardManager } from '../../websocket';
|
||||
|
@ -1,19 +1,19 @@
|
||||
export * from './AnonymousGuild';
|
||||
export * from './AutoModerationRule';
|
||||
export * from './ClientUser';
|
||||
export * from './Guild';
|
||||
export * from './channels';
|
||||
export * from './Emoji';
|
||||
export * from './Entitlement';
|
||||
export * from './Guild';
|
||||
export * from './GuildBan';
|
||||
export * from './GuildMember';
|
||||
export * from './GuildPreview';
|
||||
export * from './GuildRole';
|
||||
export * from './GuildTemplate';
|
||||
export * from './Interaction';
|
||||
export * from './Message';
|
||||
export * from './Poll';
|
||||
export * from './Sticker';
|
||||
export * from './User';
|
||||
export * from './VoiceState';
|
||||
export * from './Webhook';
|
||||
export * from './channels';
|
||||
export * from './Poll';
|
||||
export * from './GuildBan';
|
||||
export * from './Entitlement';
|
||||
|
@ -23,9 +23,9 @@
|
||||
*/
|
||||
|
||||
export * from './gateway';
|
||||
export * from './rest';
|
||||
export * from './payloads';
|
||||
export * from './rest';
|
||||
export * from './rest';
|
||||
export * from './utils';
|
||||
|
||||
/**
|
||||
|
@ -1,7 +1,6 @@
|
||||
import type { ApplicationIntegrationType, InteractionContextType } from '..';
|
||||
import type { ChannelType, Permissions, Snowflake } from '../..';
|
||||
|
||||
import type { LocaleString } from '../../rest';
|
||||
import type { ApplicationIntegrationType, InteractionContextType } from '..';
|
||||
import type {
|
||||
APIAttachment,
|
||||
APIChannel,
|
||||
|
@ -2,9 +2,9 @@
|
||||
* Types extracted from https://discord.com/developers/docs/resources/application
|
||||
*/
|
||||
|
||||
import type { APIEmoji, LocalizationMap } from '.';
|
||||
import type { Permissions, Snowflake } from '..';
|
||||
import type { MakeRequired } from '../../common';
|
||||
import type { Permissions, Snowflake } from '..';
|
||||
import type { APIEmoji, LocalizationMap } from '.';
|
||||
import type { APIPartialGuild } from './guild';
|
||||
import type { ApplicationIntegrationType } from './interactions';
|
||||
import type { OAuth2Scopes } from './oauth2';
|
||||
|
@ -1,5 +1,5 @@
|
||||
import type { APIAttachment, Snowflake } from '..';
|
||||
import type { Identify, MakeRequired } from '../../common';
|
||||
import type { APIAttachment, Snowflake } from '..';
|
||||
import type { ChannelType } from '../utils';
|
||||
|
||||
/**
|
||||
@ -260,7 +260,7 @@ export type APIRoleSelectComponent = APIBaseAutoPopulatedSelectMenuComponent<
|
||||
*/
|
||||
export type APIMentionableSelectComponent = APIBaseAutoPopulatedSelectMenuComponent<
|
||||
ComponentType.MentionableSelect,
|
||||
SelectMenuDefaultValueType.Role | SelectMenuDefaultValueType.User
|
||||
SelectMenuDefaultValueType
|
||||
>;
|
||||
|
||||
/**
|
||||
|
@ -1,6 +1,7 @@
|
||||
import type { Snowflake } from '..';
|
||||
import type { APIGuildMember } from './guild';
|
||||
import type { APIUser } from './user';
|
||||
|
||||
interface APIGuildScheduledEventBase<Type extends GuildScheduledEventEntityType> {
|
||||
/**
|
||||
* The id of the guild event
|
||||
|
@ -2,15 +2,18 @@ export * from './application';
|
||||
export * from './auditLog';
|
||||
export * from './autoModeration';
|
||||
export * from './channel';
|
||||
export * from './components';
|
||||
export * from './emoji';
|
||||
export * from './gateway';
|
||||
export * from './guild';
|
||||
export * from './guildScheduledEvent';
|
||||
export * from './interactions';
|
||||
export * from './invite';
|
||||
export * from './monetization';
|
||||
export * from './oauth2';
|
||||
export * from './poll';
|
||||
export * from './permissions';
|
||||
export * from './poll';
|
||||
export * from './soundboard';
|
||||
export * from './stageInstance';
|
||||
export * from './sticker';
|
||||
export * from './teams';
|
||||
@ -18,9 +21,6 @@ export * from './template';
|
||||
export * from './user';
|
||||
export * from './voice';
|
||||
export * from './webhook';
|
||||
export * from './monetization';
|
||||
export * from './soundboard';
|
||||
export * from './components';
|
||||
|
||||
import type { LocaleString } from '../rest';
|
||||
|
||||
|
@ -85,7 +85,7 @@ export type RESTPatchAPIApplicationEmojiResult = APIApplicationEmoji;
|
||||
/**
|
||||
* https://discord.com/developers/docs/resources/emoji#delete-application-emoji
|
||||
*/
|
||||
export type RESTDeleteAPIApplicationEmojiResult = never;
|
||||
export type RESTDeleteAPIApplicationEmojiResult = undefined;
|
||||
|
||||
/**
|
||||
* https://discord.com/developers/docs/resources/application#get-application-activity-instance
|
||||
|
@ -80,4 +80,4 @@ export type RESTPatchAPIAutoModerationRuleResult = APIAutoModerationRule;
|
||||
/**
|
||||
* https://discord.com/developers/docs/resources/auto-moderation#delete-auto-moderation-rule
|
||||
*/
|
||||
export type RESTDeleteAPIAutoModerationRuleResult = never;
|
||||
export type RESTDeleteAPIAutoModerationRuleResult = undefined;
|
||||
|
@ -344,17 +344,17 @@ export type RESTPostAPIChannelMessageCrosspostResult = APIMessage;
|
||||
/**
|
||||
* https://discord.com/developers/docs/resources/channel#create-reaction
|
||||
*/
|
||||
export type RESTPutAPIChannelMessageReactionResult = never;
|
||||
export type RESTPutAPIChannelMessageReactionResult = undefined;
|
||||
|
||||
/**
|
||||
* https://discord.com/developers/docs/resources/channel#delete-own-reaction
|
||||
*/
|
||||
export type RESTDeleteAPIChannelMessageOwnReaction = never;
|
||||
export type RESTDeleteAPIChannelMessageOwnReaction = undefined;
|
||||
|
||||
/**
|
||||
* https://discord.com/developers/docs/resources/channel#delete-user-reaction
|
||||
*/
|
||||
export type RESTDeleteAPIChannelMessageUserReactionResult = never;
|
||||
export type RESTDeleteAPIChannelMessageUserReactionResult = undefined;
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
export type RESTDeleteAPIChannelAllMessageReactionsResult = never;
|
||||
export type RESTDeleteAPIChannelAllMessageReactionsResult = undefined;
|
||||
|
||||
/**
|
||||
* https://discord.com/developers/docs/resources/channel#delete-all-reactions-for-emoji
|
||||
*/
|
||||
export type RESTDeleteAPIChannelMessageReactionResult = never;
|
||||
export type RESTDeleteAPIChannelMessageReactionResult = undefined;
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
export type RESTDeleteAPIChannelMessageResult = never;
|
||||
export type RESTDeleteAPIChannelMessageResult = undefined;
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
export type RESTPostAPIChannelMessagesBulkDeleteResult = never;
|
||||
export type RESTPostAPIChannelMessagesBulkDeleteResult = undefined;
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
export type RESTPutAPIChannelPermissionResult = never;
|
||||
export type RESTPutAPIChannelPermissionResult = undefined;
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
export type RESTDeleteAPIChannelPermissionResult = never;
|
||||
export type RESTDeleteAPIChannelPermissionResult = undefined;
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
export type RESTPostAPIChannelTypingResult = never;
|
||||
export type RESTPostAPIChannelTypingResult = undefined;
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
export type RESTPutAPIChannelPinResult = never;
|
||||
export type RESTPutAPIChannelPinResult = undefined;
|
||||
|
||||
/**
|
||||
* https://discord.com/developers/docs/resources/channel#unpin-message
|
||||
*/
|
||||
export type RESTDeleteAPIChannelPinResult = never;
|
||||
export type RESTDeleteAPIChannelPinResult = undefined;
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
export type RESTPutAPIChannelThreadMembersResult = never;
|
||||
export type RESTPutAPIChannelThreadMembersResult = undefined;
|
||||
|
||||
/**
|
||||
* https://discord.com/developers/docs/resources/channel#leave-thread
|
||||
*/
|
||||
export type RESTDeleteAPIChannelThreadMembersResult = never;
|
||||
export type RESTDeleteAPIChannelThreadMembersResult = undefined;
|
||||
|
||||
/**
|
||||
* https://discord.com/developers/docs/resources/channel#get-thread-member
|
||||
|
@ -58,4 +58,4 @@ export type RESTPatchAPIGuildEmojiResult = APIEmoji;
|
||||
/**
|
||||
* https://discord.com/developers/docs/resources/emoji#delete-guild-emoji
|
||||
*/
|
||||
export type RESTDeleteAPIGuildEmojiResult = never;
|
||||
export type RESTDeleteAPIGuildEmojiResult = undefined;
|
||||
|
@ -322,7 +322,7 @@ export type RESTPatchAPIGuildResult = APIGuild;
|
||||
/**
|
||||
* https://discord.com/developers/docs/resources/guild#delete-guild
|
||||
*/
|
||||
export type RESTDeleteAPIGuildResult = never;
|
||||
export type RESTDeleteAPIGuildResult = undefined;
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
export type RESTPatchAPIGuildChannelPositionsResult = never;
|
||||
export type RESTPatchAPIGuildChannelPositionsResult = undefined;
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
export type RESTPutAPIGuildMemberRoleResult = never;
|
||||
export type RESTPutAPIGuildMemberRoleResult = undefined;
|
||||
|
||||
/**
|
||||
* https://discord.com/developers/docs/resources/guild#remove-guild-member-role
|
||||
*/
|
||||
export type RESTDeleteAPIGuildMemberRoleResult = never;
|
||||
export type RESTDeleteAPIGuildMemberRoleResult = undefined;
|
||||
|
||||
/**
|
||||
* https://discord.com/developers/docs/resources/guild#remove-guild-member
|
||||
*/
|
||||
export type RESTDeleteAPIGuildMemberResult = never;
|
||||
export type RESTDeleteAPIGuildMemberResult = undefined;
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
export type RESTPutAPIGuildBanResult = never;
|
||||
export type RESTPutAPIGuildBanResult = undefined;
|
||||
|
||||
/**
|
||||
* https://discord.com/developers/docs/resources/guild#remove-guild-ban
|
||||
*/
|
||||
export type RESTDeleteAPIGuildBanResult = never;
|
||||
export type RESTDeleteAPIGuildBanResult = undefined;
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
export type RESTDeleteAPIGuildRoleResult = never;
|
||||
export type RESTDeleteAPIGuildRoleResult = undefined;
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
export type RESTDeleteAPIGuildIntegrationResult = never;
|
||||
export type RESTDeleteAPIGuildIntegrationResult = undefined;
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
export type RESTPatchAPIGuildVoiceStateCurrentMemberResult = never;
|
||||
export type RESTPatchAPIGuildVoiceStateCurrentMemberResult = undefined;
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
export type RESTPatchAPIGuildVoiceStateUserResult = never;
|
||||
export type RESTPatchAPIGuildVoiceStateUserResult = undefined;
|
||||
|
||||
/**
|
||||
* https://discord.com/developers/docs/resources/guild#get-guild-welcome-screen
|
||||
|
@ -106,7 +106,7 @@ export type RESTPatchAPIGuildScheduledEventResult = APIGuildScheduledEvent;
|
||||
/**
|
||||
* https://discord.com/developers/docs/resources/guild-scheduled-event#delete-guild-scheduled-event
|
||||
*/
|
||||
export type RESTDeleteAPIGuildScheduledEventResult = never;
|
||||
export type RESTDeleteAPIGuildScheduledEventResult = undefined;
|
||||
|
||||
/**
|
||||
* https://discord.com/developers/docs/resources/guild-scheduled-event#get-guild-scheduled-event-users
|
||||
|
@ -10,16 +10,16 @@ export * from './guild';
|
||||
export * from './guildScheduledEvent';
|
||||
export * from './interactions';
|
||||
export * from './invite';
|
||||
export * from './monetization';
|
||||
export * from './oauth2';
|
||||
export * from './poll';
|
||||
export * from './soundboard';
|
||||
export * from './stageInstance';
|
||||
export * from './sticker';
|
||||
export * from './template';
|
||||
export * from './user';
|
||||
export * from './voice';
|
||||
export * from './webhook';
|
||||
export * from './monetization';
|
||||
export * from './soundboard';
|
||||
|
||||
export type DefaultUserAvatarAssets = 0 | 1 | 2 | 3 | 4 | 5;
|
||||
|
||||
|
@ -86,7 +86,7 @@ export enum EntitlementOwnerType {
|
||||
/**
|
||||
* https://discord.com/developers/docs/monetization/entitlements#delete-test-entitlement
|
||||
*/
|
||||
export type RESTDeleteAPIEntitlementResult = never;
|
||||
export type RESTDeleteAPIEntitlementResult = undefined;
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
export type RESTPostAPIEntitlementConsumeResult = never;
|
||||
export type RESTPostAPIEntitlementConsumeResult = undefined;
|
||||
|
||||
/**
|
||||
* https://canary.discord.com/developers/docs/resources/subscription#query-string-params
|
||||
|
@ -67,4 +67,4 @@ export type RESTPatchAPIGuildSoundboardSoundResult = APISoundBoard;
|
||||
* This endpoint supports the X-Audit-Log-Reason header.
|
||||
* @fires GuildSoundboardSoundDelete
|
||||
*/
|
||||
export type RESTDeleteAPIGuildSoundboardSoundResult = never;
|
||||
export type RESTDeleteAPIGuildSoundboardSoundResult = undefined;
|
||||
|
@ -61,4 +61,4 @@ export type RESTPatchAPIStageInstanceResult = APIStageInstance;
|
||||
/**
|
||||
* https://discord.com/developers/docs/resources/stage-instance#delete-stage-instance
|
||||
*/
|
||||
export type RESTDeleteAPIStageInstanceResult = never;
|
||||
export type RESTDeleteAPIStageInstanceResult = undefined;
|
||||
|
@ -82,4 +82,4 @@ export type RESTPatchAPIGuildStickerResult = APISticker;
|
||||
/**
|
||||
* https://discord.com/developers/docs/resources/sticker#delete-guild-sticker
|
||||
*/
|
||||
export type RESTDeleteAPIGuildStickerResult = never;
|
||||
export type RESTDeleteAPIGuildStickerResult = undefined;
|
||||
|
@ -91,7 +91,7 @@ export type RESTGetAPICurrentUserGuildsResult = RESTAPIPartialCurrentUserGuild[]
|
||||
/**
|
||||
* https://discord.com/developers/docs/resources/user#leave-guild
|
||||
*/
|
||||
export type RESTDeleteAPICurrentUserGuildResult = never;
|
||||
export type RESTDeleteAPICurrentUserGuildResult = undefined;
|
||||
|
||||
/**
|
||||
* https://discord.com/developers/docs/resources/user#create-dm
|
||||
|
@ -89,12 +89,12 @@ export type RESTPatchAPIWebhookWithTokenResult = RESTGetAPIWebhookWithTokenResul
|
||||
/**
|
||||
* https://discord.com/developers/docs/resources/webhook#delete-webhook
|
||||
*/
|
||||
export type RESTDeleteAPIWebhookResult = never;
|
||||
export type RESTDeleteAPIWebhookResult = undefined;
|
||||
|
||||
/**
|
||||
* https://discord.com/developers/docs/resources/webhook#delete-webhook-with-token
|
||||
*/
|
||||
export type RESTDeleteAPIWebhookWithTokenResult = never;
|
||||
export type RESTDeleteAPIWebhookWithTokenResult = undefined;
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
export type RESTPostAPIWebhookWithTokenResult = never;
|
||||
export type RESTPostAPIWebhookWithTokenResult = undefined;
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
export type RESTPostAPIWebhookWithTokenSlackResult = never;
|
||||
export type RESTPostAPIWebhookWithTokenSlackResult = undefined;
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
export type RESTPostAPIWebhookWithTokenGitHubResult = never;
|
||||
export type RESTPostAPIWebhookWithTokenGitHubResult = undefined;
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
export type RESTDeleteAPIWebhookWithTokenMessageResult = never;
|
||||
export type RESTDeleteAPIWebhookWithTokenMessageResult = undefined;
|
||||
|
@ -23,8 +23,8 @@ import type {
|
||||
GatewayGuildIntegrationsUpdateDispatchData,
|
||||
GatewayGuildMemberAddDispatchData,
|
||||
GatewayGuildMemberRemoveDispatchData,
|
||||
GatewayGuildMemberUpdateDispatchData,
|
||||
GatewayGuildMembersChunkDispatchData,
|
||||
GatewayGuildMemberUpdateDispatchData,
|
||||
GatewayGuildRoleCreateDispatchData,
|
||||
GatewayGuildRoleDeleteDispatchData,
|
||||
GatewayGuildRoleUpdateDispatchData,
|
||||
@ -55,8 +55,8 @@ import type {
|
||||
GatewayThreadCreateDispatchData,
|
||||
GatewayThreadDeleteDispatchData,
|
||||
GatewayThreadListSyncDispatchData,
|
||||
GatewayThreadMemberUpdateDispatchData,
|
||||
GatewayThreadMembersUpdateDispatchData,
|
||||
GatewayThreadMemberUpdateDispatchData,
|
||||
GatewayTypingStartDispatchData,
|
||||
GatewayUserUpdateDispatchData,
|
||||
GatewayVoiceChannelEffectSendDispachData,
|
||||
|
@ -25,14 +25,14 @@ export class BaseSocket {
|
||||
return new Promise<number>(res => {
|
||||
const nonce = randomUUID();
|
||||
const start = performance.now();
|
||||
const listener = (data: Buffer) => {
|
||||
const listener = ({ data }: MessageEvent) => {
|
||||
if (data.toString() !== nonce) return;
|
||||
//@ts-expect-error
|
||||
ws.removeListener('pong', listener);
|
||||
ws.removeEventListener('pong', listener);
|
||||
res(performance.now() - start);
|
||||
};
|
||||
//@ts-expect-error
|
||||
ws.on('pong', listener);
|
||||
ws.addEventListener('pong', listener);
|
||||
//@ts-expect-error
|
||||
ws.ping(nonce);
|
||||
});
|
||||
|
43
src/websocket/discord/heartbeater.ts
Normal file
43
src/websocket/discord/heartbeater.ts
Normal file
@ -0,0 +1,43 @@
|
||||
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;
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
import { inflateSync } from 'node:zlib';
|
||||
import { LogLevels, Logger, type MakeRequired, MergeOptions, delay, hasIntent } from '../../common';
|
||||
import { delay, hasIntent, Logger, LogLevels, type MakeRequired, MergeOptions } from '../../common';
|
||||
import {
|
||||
type APIGuildMember,
|
||||
GatewayCloseCodes,
|
||||
@ -45,7 +45,7 @@ export class Shard {
|
||||
|
||||
bucket: DynamicBucket;
|
||||
offlineSendQueue: ((_?: unknown) => void)[] = [];
|
||||
pendingGuilds = new Set<string>();
|
||||
pendingGuilds?: Set<string>;
|
||||
options: MakeRequired<ShardOptions, 'properties' | 'ratelimitOptions' | 'reconnectTimeout' | 'connectionTimeout'>;
|
||||
isReady = false;
|
||||
|
||||
@ -56,10 +56,7 @@ export class Shard {
|
||||
{
|
||||
members: APIGuildMember[];
|
||||
presences: GatewayGuildMembersChunkPresence[];
|
||||
resolve: (value: {
|
||||
members: APIGuildMember[];
|
||||
presences: GatewayGuildMembersChunkPresence[];
|
||||
}) => void;
|
||||
resolve: (value: { members: APIGuildMember[]; presences: GatewayGuildMembersChunkPresence[] }) => void;
|
||||
reject: (reason?: any) => void;
|
||||
}
|
||||
>();
|
||||
@ -138,7 +135,6 @@ export class Shard {
|
||||
);
|
||||
|
||||
// @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.onmessage = ({ data }: { data: string | Buffer }) => {
|
||||
@ -301,16 +297,14 @@ export class Shard {
|
||||
clearTimeout(this.connectionTimeout);
|
||||
this.connectionTimeout = undefined;
|
||||
if (hasIntent(this.options.intents, 'Guilds')) {
|
||||
for (let i = 0; i < packet.d.guilds.length; i++) {
|
||||
this.pendingGuilds.add(packet.d.guilds.at(i)!.id);
|
||||
}
|
||||
this.pendingGuilds = new Set(packet.d.guilds.map(guild => guild.id));
|
||||
}
|
||||
|
||||
this.data.resume_gateway_url = packet.d.resume_gateway_url;
|
||||
this.data.session_id = packet.d.session_id;
|
||||
this.offlineSendQueue.map(resolve => resolve());
|
||||
this.options.handlePayload(this.id, packet);
|
||||
if (this.pendingGuilds.size === 0) {
|
||||
if (this.pendingGuilds?.size === 0) {
|
||||
this.isReady = true;
|
||||
this.options.handlePayload(this.id, {
|
||||
t: GatewayDispatchEvents.GuildsReady,
|
||||
@ -322,7 +316,7 @@ export class Shard {
|
||||
}
|
||||
case GatewayDispatchEvents.GuildCreate:
|
||||
case GatewayDispatchEvents.GuildDelete:
|
||||
if (this.pendingGuilds.delete(packet.d.id)) {
|
||||
if (this.pendingGuilds?.delete(packet.d.id)) {
|
||||
(packet as any).t = `RAW_${packet.t}`;
|
||||
this.options.handlePayload(this.id, packet);
|
||||
if (this.pendingGuilds.size === 0) {
|
||||
@ -376,10 +370,7 @@ export class Shard {
|
||||
) {
|
||||
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 = () => {
|
||||
|
@ -1,11 +1,11 @@
|
||||
import {
|
||||
LogLevels,
|
||||
calculateShardId,
|
||||
Logger,
|
||||
LogLevels,
|
||||
lazyLoadPackage,
|
||||
type MakeRequired,
|
||||
MergeOptions,
|
||||
type WatcherSendToShard,
|
||||
calculateShardId,
|
||||
lazyLoadPackage,
|
||||
} from '../../common';
|
||||
import type { DeepPartial, MakeDeepPartial } from '../../common/types/util';
|
||||
import {
|
||||
|
@ -69,6 +69,9 @@ export interface WorkerManagerOptions extends Omit<ShardManagerOptions, 'handleP
|
||||
|
||||
workerProxy?: boolean;
|
||||
|
||||
/** @default 15000 */
|
||||
heartbeaterInterval?: number;
|
||||
|
||||
path: string;
|
||||
|
||||
handlePayload?(shardId: number, workerId: number, packet: GatewayDispatchPayload): any;
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { type UUID, createHash, randomBytes, randomUUID } from 'node:crypto';
|
||||
import { createHash, randomBytes, randomUUID, type UUID } from 'node:crypto';
|
||||
import { request } from 'node:https';
|
||||
import type { Socket } from 'node:net';
|
||||
|
||||
|
@ -114,7 +114,12 @@ export type CustomWorkerClientMessages = {
|
||||
>;
|
||||
};
|
||||
|
||||
export type ClientHeartbeaterMessages = ACKHeartbeat;
|
||||
|
||||
export type ACKHeartbeat = CreateWorkerMessage<'ACK_HEARTBEAT'>;
|
||||
|
||||
export type WorkerMessages =
|
||||
| ClientHeartbeaterMessages
|
||||
| {
|
||||
[K in BaseWorkerMessage['type']]: Identify<Extract<BaseWorkerMessage, { type: K }>>;
|
||||
}[BaseWorkerMessage['type']]
|
||||
|
@ -1,14 +1,15 @@
|
||||
import cluster, { type Worker as ClusterWorker } from 'node:cluster';
|
||||
import { type UUID, randomUUID } from 'node:crypto';
|
||||
import { randomUUID, type UUID } from 'node:crypto';
|
||||
import type { Worker as WorkerThreadsWorker } from 'node:worker_threads';
|
||||
import { ApiHandler, type CustomWorkerManagerEvents, Logger, type UsingClient, type WorkerClient } from '../..';
|
||||
import { type Adapter, MemoryAdapter } from '../../cache';
|
||||
import { BaseClient, type InternalRuntimeConfig } from '../../client/base';
|
||||
import { BASE_HOST, type Identify, MergeOptions, type PickPartial, lazyLoadPackage } from '../../common';
|
||||
import { BASE_HOST, type Identify, lazyLoadPackage, MergeOptions, type PickPartial } from '../../common';
|
||||
import type { GatewayPresenceUpdateData, GatewaySendPayload, RESTGetAPIGatewayBotResult } from '../../types';
|
||||
import { WorkerManagerDefaults, properties } from '../constants';
|
||||
import { properties, WorkerManagerDefaults } from '../constants';
|
||||
import { DynamicBucket } from '../structures';
|
||||
import { ConnectQueue } from '../structures/timeout';
|
||||
import { Heartbeater, type WorkerHeartbeaterMessages } from './heartbeater';
|
||||
import type { ShardOptions, WorkerData, WorkerManagerOptions } from './shared';
|
||||
import type { WorkerInfo, WorkerMessages, WorkerShardInfo } from './worker';
|
||||
|
||||
@ -55,6 +56,7 @@ export class WorkerManager extends Map<
|
||||
rest!: ApiHandler;
|
||||
reshardingWorkerQueue: (() => void)[] = [];
|
||||
private _info?: RESTGetAPIGatewayBotResult;
|
||||
heartbeater: Heartbeater;
|
||||
|
||||
constructor(
|
||||
options: Omit<
|
||||
@ -75,6 +77,8 @@ export class WorkerManager extends Map<
|
||||
return oldFn(message);
|
||||
};
|
||||
}
|
||||
|
||||
this.heartbeater = new Heartbeater(this.postMessage.bind(this), options.heartbeaterInterval ?? 15e3);
|
||||
}
|
||||
|
||||
setCache(adapter: Adapter) {
|
||||
@ -144,12 +148,12 @@ export class WorkerManager extends Map<
|
||||
return workerId;
|
||||
}
|
||||
|
||||
postMessage(id: number, body: ManagerMessages) {
|
||||
postMessage(id: number, body: ManagerMessages | WorkerHeartbeaterMessages) {
|
||||
const worker = this.get(id);
|
||||
if (!worker) return this.debugger?.error(`Worker ${id} does not exists.`);
|
||||
switch (this.options.mode) {
|
||||
case 'clusters':
|
||||
(worker as ClusterWorker).send(body);
|
||||
if ((worker as ClusterWorker).isConnected()) (worker as ClusterWorker).send(body);
|
||||
break;
|
||||
case 'threads':
|
||||
(worker as import('worker_threads').Worker).postMessage(body);
|
||||
@ -160,33 +164,40 @@ export class WorkerManager extends Map<
|
||||
}
|
||||
}
|
||||
|
||||
prepareWorkers(shards: number[][], resharding = false) {
|
||||
prepareWorkers(shards: number[][], rawResharding = false) {
|
||||
const worker_threads = lazyLoadPackage<typeof import('node:worker_threads')>('node:worker_threads');
|
||||
if (!worker_threads) throw new Error('Cannot prepare workers without worker_threads.');
|
||||
|
||||
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);
|
||||
if (resharding || !workerExists) {
|
||||
this[resharding ? 'reshardingWorkerQueue' : 'workerQueue'].push(() => {
|
||||
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,
|
||||
if (rawResharding || !workerExists) {
|
||||
this[rawResharding ? 'reshardingWorkerQueue' : 'workerQueue'].push(() => {
|
||||
registerWorker(rawResharding);
|
||||
this.heartbeater.register(i, () => {
|
||||
this.delete(i);
|
||||
registerWorker(false);
|
||||
});
|
||||
this.set(i, worker);
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -218,6 +229,9 @@ export class WorkerManager extends Map<
|
||||
env,
|
||||
});
|
||||
worker.on('message', data => this.handleWorkerMessage(data));
|
||||
worker.on('error', err => {
|
||||
this.debugger?.error(`[Worker #${workerData.workerId}]`, err);
|
||||
});
|
||||
return worker;
|
||||
}
|
||||
case 'clusters': {
|
||||
@ -254,6 +268,9 @@ export class WorkerManager extends Map<
|
||||
|
||||
async handleWorkerMessage(message: WorkerMessages) {
|
||||
switch (message.type) {
|
||||
case 'ACK_HEARTBEAT':
|
||||
this.heartbeater.acknowledge(message.workerId);
|
||||
break;
|
||||
case 'WORKER_READY_RESHARDING':
|
||||
{
|
||||
this.get(message.workerId)!.resharded = true;
|
||||
@ -288,6 +305,7 @@ export class WorkerManager extends Map<
|
||||
for (const [id] of this.entries()) {
|
||||
this.postMessage(id, {
|
||||
type: 'CONNECT_ALL_SHARDS_RESHARDING',
|
||||
totalShards: this.options.totalShards,
|
||||
} satisfies ConnnectAllShardsResharding);
|
||||
}
|
||||
this.forEach(w => {
|
||||
@ -656,7 +674,12 @@ export type ManagerSpawnShardsResharding = CreateManagerMessage<
|
||||
Pick<ShardOptions, 'info' | 'properties' | 'compress'>
|
||||
>;
|
||||
export type DisconnectAllShardsResharding = CreateManagerMessage<'DISCONNECT_ALL_SHARDS_RESHARDING'>;
|
||||
export type ConnnectAllShardsResharding = CreateManagerMessage<'CONNECT_ALL_SHARDS_RESHARDING'>;
|
||||
export type ConnnectAllShardsResharding = CreateManagerMessage<
|
||||
'CONNECT_ALL_SHARDS_RESHARDING',
|
||||
{
|
||||
totalShards: number;
|
||||
}
|
||||
>;
|
||||
export type ManagerSendPayload = CreateManagerMessage<
|
||||
'SEND_PAYLOAD',
|
||||
GatewaySendPayload & { shardId: number; nonce: string }
|
||||
|
@ -1,3 +1,3 @@
|
||||
export * from './SharedTypes';
|
||||
export * from './constants';
|
||||
export * from './discord';
|
||||
export * from './SharedTypes';
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user