onRatelimit callback & GuildCommandContext types(unnreaal update) (#279)

* feat: type GuildCommandContext, onRatelimit callback

* fix: test

* fix: use reduce
This commit is contained in:
MARCROCK22 2024-10-13 21:48:20 -04:00 committed by GitHub
parent 424970494b
commit 56246ed5cf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 162 additions and 103 deletions

View File

@ -1,5 +1,5 @@
import { type UUID, randomUUID } from 'node:crypto';
import { Logger, delay, lazyLoadPackage, snowflakeToTimestamp } from '../common';
import { type Awaitable, Logger, delay, lazyLoadPackage, snowflakeToTimestamp } from '../common';
import type { WorkerData } from '../websocket';
import type { WorkerSendApiRequest } from '../websocket/discord/worker';
import { CDNRouter, Router } from './Router';
@ -25,6 +25,8 @@ export interface ApiHandler {
debugger?: Logger;
}
export type OnRatelimitCallback = (response: Response, request: ApiRequestOptions) => Awaitable<any>;
export class ApiHandler {
options: ApiHandlerInternalOptions;
globalBlock = false;
@ -32,6 +34,7 @@ export class ApiHandler {
readyQueue: (() => void)[] = [];
cdn = CDNRouter.createProxy();
workerPromises?: Map<string, { resolve: (value: any) => any; reject: (error: any) => any }>;
onRatelimit?: OnRatelimitCallback;
constructor(options: ApiHandlerOptions) {
this.options = {
@ -246,6 +249,8 @@ export class ApiHandler {
reject: (err: unknown) => void,
now: number,
) {
await this.onRatelimit?.(response, request);
const content = `${JSON.stringify(request)} `;
let retryAfter =
Number(response.headers.get('x-ratelimit-reset-after') || response.headers.get('retry-after')) * 1000;

View File

@ -8,7 +8,7 @@ import type {
OptionResolverStructure,
WebhookMessageStructure,
} from '../../client/transformers';
import type { If, UnionToTuple, When } from '../../common';
import type { If, MakeRequired, UnionToTuple, When } from '../../common';
import type { InteractionCreateBodyRequest, InteractionMessageUpdateBodyRequest } from '../../common/types/write';
import { ChatInputCommandInteraction } from '../../structures';
import { MessageFlags } from '../../types';
@ -219,3 +219,9 @@ export class CommandContext<
return true;
}
}
export interface GuildCommandContext<T extends OptionsRecord = {}, M extends keyof RegisteredMiddlewares = never>
extends Omit<MakeRequired<CommandContext<T, M>, 'guildId'>, 'guild'> {
guild(mode?: 'rest' | 'flow'): Promise<GuildStructure<'cached' | 'api'>>;
guild(mode?: 'cache'): ReturnCache<GuildStructure<'cached'> | undefined>;
}

View File

@ -8,6 +8,7 @@ import type {
import type {
InteractionCreateBodyRequest,
InteractionMessageUpdateBodyRequest,
MakeRequired,
ModalCreateBodyRequest,
UnionToTuple,
When,
@ -128,3 +129,9 @@ export class EntryPointContext<M extends keyof RegisteredMiddlewares = never> ex
return this.interaction.member;
}
}
export interface GuildEntryPointContext<M extends keyof RegisteredMiddlewares = never>
extends Omit<MakeRequired<EntryPointContext<M>, 'guildId'>, 'guild'> {
guild(mode?: 'rest' | 'flow'): Promise<GuildStructure<'cached' | 'api'>>;
guild(mode?: 'cache'): ReturnCache<GuildStructure<'cached'> | undefined>;
}

View File

@ -10,6 +10,7 @@ import {
import {
type InteractionCreateBodyRequest,
type InteractionMessageUpdateBodyRequest,
type MakeRequired,
type ModalCreateBodyRequest,
type UnionToTuple,
type When,
@ -165,3 +166,11 @@ export class MenuCommandContext<
return this.interaction.data.type === ApplicationCommandType.Message;
}
}
export interface GuildMenuCommandContext<
T extends MessageCommandInteraction | UserCommandInteraction,
M extends keyof RegisteredMiddlewares = never,
> extends Omit<MakeRequired<MenuCommandContext<T, M>, 'guildId'>, 'guild'> {
guild(mode?: 'rest' | 'flow'): Promise<GuildStructure<'cached' | 'api'>>;
guild(mode?: 'cache'): ReturnCache<GuildStructure<'cached'> | undefined>;
}

View File

@ -484,13 +484,13 @@ export class CommandHandler extends BaseHandler {
option.onPermissionsFail?.bind(option) ??
commandInstance.onPermissionsFail?.bind(commandInstance) ??
this.client.options.commands?.defaults?.onPermissionsFail;
option.botPermissions = new PermissionsBitField().add(
option.botPermissions = PermissionsBitField.resolve(
option.botPermissions ?? PermissionsBitField.None,
commandInstance.botPermissions,
commandInstance.botPermissions ?? PermissionsBitField.None,
);
option.defaultMemberPermissions ??= new PermissionsBitField().add(
option.defaultMemberPermissions ??= PermissionsBitField.resolve(
option.defaultMemberPermissions ?? PermissionsBitField.None,
commandInstance.defaultMemberPermissions,
commandInstance.defaultMemberPermissions ?? PermissionsBitField.None,
);
option.contexts ??= commandInstance.contexts;
option.integrationTypes ??= commandInstance.integrationTypes;

View File

@ -21,6 +21,7 @@ import type {
ComponentInteractionMessageUpdate,
InteractionCreateBodyRequest,
InteractionMessageUpdateBodyRequest,
MakeRequired,
ModalCreateBodyRequest,
UnionToTuple,
When,
@ -243,3 +244,9 @@ export interface ContextComponentCommandInteractionMap {
MentionableSelect: MentionableSelectMenuInteraction;
ChannelSelect: ChannelSelectMenuInteraction;
}
export interface GuildComponentContext<M extends keyof RegisteredMiddlewares = never>
extends Omit<MakeRequired<ComponentContext<M>, 'guildId'>, 'guild'> {
guild(mode?: 'rest' | 'flow'): Promise<GuildStructure<'cached' | 'api'>>;
guild(mode?: 'cache'): ReturnCache<GuildStructure<'cached'> | undefined>;
}

View File

@ -10,6 +10,7 @@ import { BaseContext } from '../commands/basecontext';
import type {
InteractionCreateBodyRequest,
InteractionMessageUpdateBodyRequest,
MakeRequired,
ModalCreateBodyRequest,
UnionToTuple,
When,
@ -187,3 +188,9 @@ export class ModalContext<M extends keyof RegisteredMiddlewares = never> extends
return true;
}
}
export interface GuildModalContext<M extends keyof RegisteredMiddlewares = never>
extends Omit<MakeRequired<ModalContext<M>, 'guildId'>, 'guild'> {
guild(mode?: 'rest' | 'flow'): Promise<GuildStructure<'cached' | 'api'>>;
guild(mode?: 'cache'): ReturnCache<GuildStructure<'cached'> | undefined>;
}

View File

@ -69,24 +69,32 @@ export class BitField<T extends object> {
return this.bits;
}
resolve(bits: BitFieldResolvable<T>): bigint {
switch (typeof bits) {
resolve(...bits: BitFieldResolvable<T>[]): bigint {
let bitsResult = 0n;
for (const bit of bits) {
switch (typeof bit) {
case 'string':
return this.resolve(this.Flags[bits]);
bitsResult |= this.resolve(this.Flags[bit]);
break;
case 'number':
return BigInt(bits);
bitsResult |= BigInt(bit);
break;
case 'bigint':
return bits;
bitsResult |= bit;
break;
case 'object': {
if (!Array.isArray(bits)) {
throw new TypeError(`Cannot resolve permission: ${bits}`);
if (!Array.isArray(bit)) {
throw new TypeError(`Cannot resolve permission: ${bit}`);
}
return bits.map(x => this.resolve(x)).reduce((acc, cur) => acc | cur, BitField.None);
bitsResult |= bits.reduce<bigint>((acc, val) => this.resolve(val) | acc, BitField.None);
break;
}
default:
throw new TypeError(
`Cannot resolve permission: ${typeof bits === 'symbol' ? String(bits) : (bits as unknown)}`,
);
throw new TypeError(`Cannot resolve permission: ${typeof bit === 'symbol' ? String(bit) : (bit as unknown)}`);
}
}
return bitsResult;
}
}

View File

@ -21,26 +21,36 @@ export class PermissionsBitField extends BitField<typeof PermissionFlagsBits> {
return super.has(...bits);
}
resolve<T extends typeof PermissionFlagsBits>(bits: BitFieldResolvable<T>): bigint {
return PermissionsBitField.resolve(bits);
resolve<T extends typeof PermissionFlagsBits>(...bits: BitFieldResolvable<T>[]): bigint {
return bits.reduce<bigint>((acc, cur) => acc | PermissionsBitField.resolve(cur), BitField.None);
}
static resolve<T extends typeof PermissionFlagsBits>(bits: BitFieldResolvable<T>): bigint {
switch (typeof bits) {
static resolve<T extends typeof PermissionFlagsBits>(...bits: BitFieldResolvable<T>[]): bigint {
let bitsResult = 0n;
for (const bit of bits) {
switch (typeof bit) {
case 'string':
return PermissionsBitField.resolve(PermissionFlagsBits[bits as keyof typeof PermissionFlagsBits]);
bitsResult |= PermissionsBitField.resolve(PermissionFlagsBits[bit as keyof typeof PermissionFlagsBits]);
break;
case 'number':
return BigInt(bits);
bitsResult |= BigInt(bit);
break;
case 'bigint':
return bits;
bitsResult |= bit;
break;
case 'object': {
if (!Array.isArray(bits)) {
throw new TypeError(`Cannot resolve permission: ${bits}`);
if (!Array.isArray(bit)) {
throw new TypeError(`Cannot resolve permission: ${bit}`);
}
return bits.map(x => PermissionsBitField.resolve(x)).reduce((acc, cur) => acc | cur, BitField.None);
bitsResult |= bit.reduce<bigint>((acc, val) => PermissionsBitField.resolve(val) | acc, BitField.None);
break;
}
default:
throw new TypeError(`Cannot resolve permission: ${typeof bits === 'symbol' ? String(bits) : (bits as any)}`);
throw new TypeError(`Cannot resolve permission: ${typeof bit === 'symbol' ? String(bit) : (bit as any)}`);
}
}
return bitsResult;
}
}