mirror of
https://github.com/tiramisulabs/seyfert.git
synced 2025-07-01 20:46:08 +00:00
onRatelimit callback & GuildCommandContext types(unnreaal update) (#279)
* feat: type GuildCommandContext, onRatelimit callback * fix: test * fix: use reduce
This commit is contained in:
parent
424970494b
commit
56246ed5cf
@ -1,5 +1,5 @@
|
|||||||
import { type UUID, randomUUID } from 'node:crypto';
|
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 { WorkerData } from '../websocket';
|
||||||
import type { WorkerSendApiRequest } from '../websocket/discord/worker';
|
import type { WorkerSendApiRequest } from '../websocket/discord/worker';
|
||||||
import { CDNRouter, Router } from './Router';
|
import { CDNRouter, Router } from './Router';
|
||||||
@ -25,6 +25,8 @@ export interface ApiHandler {
|
|||||||
debugger?: Logger;
|
debugger?: Logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type OnRatelimitCallback = (response: Response, request: ApiRequestOptions) => Awaitable<any>;
|
||||||
|
|
||||||
export class ApiHandler {
|
export class ApiHandler {
|
||||||
options: ApiHandlerInternalOptions;
|
options: ApiHandlerInternalOptions;
|
||||||
globalBlock = false;
|
globalBlock = false;
|
||||||
@ -32,6 +34,7 @@ export class ApiHandler {
|
|||||||
readyQueue: (() => void)[] = [];
|
readyQueue: (() => void)[] = [];
|
||||||
cdn = CDNRouter.createProxy();
|
cdn = CDNRouter.createProxy();
|
||||||
workerPromises?: Map<string, { resolve: (value: any) => any; reject: (error: any) => any }>;
|
workerPromises?: Map<string, { resolve: (value: any) => any; reject: (error: any) => any }>;
|
||||||
|
onRatelimit?: OnRatelimitCallback;
|
||||||
|
|
||||||
constructor(options: ApiHandlerOptions) {
|
constructor(options: ApiHandlerOptions) {
|
||||||
this.options = {
|
this.options = {
|
||||||
@ -246,6 +249,8 @@ export class ApiHandler {
|
|||||||
reject: (err: unknown) => void,
|
reject: (err: unknown) => void,
|
||||||
now: number,
|
now: number,
|
||||||
) {
|
) {
|
||||||
|
await this.onRatelimit?.(response, request);
|
||||||
|
|
||||||
const content = `${JSON.stringify(request)} `;
|
const content = `${JSON.stringify(request)} `;
|
||||||
let retryAfter =
|
let retryAfter =
|
||||||
Number(response.headers.get('x-ratelimit-reset-after') || response.headers.get('retry-after')) * 1000;
|
Number(response.headers.get('x-ratelimit-reset-after') || response.headers.get('retry-after')) * 1000;
|
||||||
|
@ -8,7 +8,7 @@ import type {
|
|||||||
OptionResolverStructure,
|
OptionResolverStructure,
|
||||||
WebhookMessageStructure,
|
WebhookMessageStructure,
|
||||||
} from '../../client/transformers';
|
} 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 type { InteractionCreateBodyRequest, InteractionMessageUpdateBodyRequest } from '../../common/types/write';
|
||||||
import { ChatInputCommandInteraction } from '../../structures';
|
import { ChatInputCommandInteraction } from '../../structures';
|
||||||
import { MessageFlags } from '../../types';
|
import { MessageFlags } from '../../types';
|
||||||
@ -219,3 +219,9 @@ export class CommandContext<
|
|||||||
return true;
|
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>;
|
||||||
|
}
|
||||||
|
@ -8,6 +8,7 @@ import type {
|
|||||||
import type {
|
import type {
|
||||||
InteractionCreateBodyRequest,
|
InteractionCreateBodyRequest,
|
||||||
InteractionMessageUpdateBodyRequest,
|
InteractionMessageUpdateBodyRequest,
|
||||||
|
MakeRequired,
|
||||||
ModalCreateBodyRequest,
|
ModalCreateBodyRequest,
|
||||||
UnionToTuple,
|
UnionToTuple,
|
||||||
When,
|
When,
|
||||||
@ -128,3 +129,9 @@ export class EntryPointContext<M extends keyof RegisteredMiddlewares = never> ex
|
|||||||
return this.interaction.member;
|
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>;
|
||||||
|
}
|
||||||
|
@ -10,6 +10,7 @@ import {
|
|||||||
import {
|
import {
|
||||||
type InteractionCreateBodyRequest,
|
type InteractionCreateBodyRequest,
|
||||||
type InteractionMessageUpdateBodyRequest,
|
type InteractionMessageUpdateBodyRequest,
|
||||||
|
type MakeRequired,
|
||||||
type ModalCreateBodyRequest,
|
type ModalCreateBodyRequest,
|
||||||
type UnionToTuple,
|
type UnionToTuple,
|
||||||
type When,
|
type When,
|
||||||
@ -165,3 +166,11 @@ export class MenuCommandContext<
|
|||||||
return this.interaction.data.type === ApplicationCommandType.Message;
|
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>;
|
||||||
|
}
|
||||||
|
@ -484,13 +484,13 @@ export class CommandHandler extends BaseHandler {
|
|||||||
option.onPermissionsFail?.bind(option) ??
|
option.onPermissionsFail?.bind(option) ??
|
||||||
commandInstance.onPermissionsFail?.bind(commandInstance) ??
|
commandInstance.onPermissionsFail?.bind(commandInstance) ??
|
||||||
this.client.options.commands?.defaults?.onPermissionsFail;
|
this.client.options.commands?.defaults?.onPermissionsFail;
|
||||||
option.botPermissions = new PermissionsBitField().add(
|
option.botPermissions = PermissionsBitField.resolve(
|
||||||
option.botPermissions ?? PermissionsBitField.None,
|
option.botPermissions ?? PermissionsBitField.None,
|
||||||
commandInstance.botPermissions,
|
commandInstance.botPermissions ?? PermissionsBitField.None,
|
||||||
);
|
);
|
||||||
option.defaultMemberPermissions ??= new PermissionsBitField().add(
|
option.defaultMemberPermissions ??= PermissionsBitField.resolve(
|
||||||
option.defaultMemberPermissions ?? PermissionsBitField.None,
|
option.defaultMemberPermissions ?? PermissionsBitField.None,
|
||||||
commandInstance.defaultMemberPermissions,
|
commandInstance.defaultMemberPermissions ?? PermissionsBitField.None,
|
||||||
);
|
);
|
||||||
option.contexts ??= commandInstance.contexts;
|
option.contexts ??= commandInstance.contexts;
|
||||||
option.integrationTypes ??= commandInstance.integrationTypes;
|
option.integrationTypes ??= commandInstance.integrationTypes;
|
||||||
|
@ -21,6 +21,7 @@ import type {
|
|||||||
ComponentInteractionMessageUpdate,
|
ComponentInteractionMessageUpdate,
|
||||||
InteractionCreateBodyRequest,
|
InteractionCreateBodyRequest,
|
||||||
InteractionMessageUpdateBodyRequest,
|
InteractionMessageUpdateBodyRequest,
|
||||||
|
MakeRequired,
|
||||||
ModalCreateBodyRequest,
|
ModalCreateBodyRequest,
|
||||||
UnionToTuple,
|
UnionToTuple,
|
||||||
When,
|
When,
|
||||||
@ -243,3 +244,9 @@ export interface ContextComponentCommandInteractionMap {
|
|||||||
MentionableSelect: MentionableSelectMenuInteraction;
|
MentionableSelect: MentionableSelectMenuInteraction;
|
||||||
ChannelSelect: ChannelSelectMenuInteraction;
|
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>;
|
||||||
|
}
|
||||||
|
@ -10,6 +10,7 @@ import { BaseContext } from '../commands/basecontext';
|
|||||||
import type {
|
import type {
|
||||||
InteractionCreateBodyRequest,
|
InteractionCreateBodyRequest,
|
||||||
InteractionMessageUpdateBodyRequest,
|
InteractionMessageUpdateBodyRequest,
|
||||||
|
MakeRequired,
|
||||||
ModalCreateBodyRequest,
|
ModalCreateBodyRequest,
|
||||||
UnionToTuple,
|
UnionToTuple,
|
||||||
When,
|
When,
|
||||||
@ -187,3 +188,9 @@ export class ModalContext<M extends keyof RegisteredMiddlewares = never> extends
|
|||||||
return true;
|
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>;
|
||||||
|
}
|
||||||
|
@ -69,24 +69,32 @@ export class BitField<T extends object> {
|
|||||||
return this.bits;
|
return this.bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
resolve(bits: BitFieldResolvable<T>): bigint {
|
resolve(...bits: BitFieldResolvable<T>[]): bigint {
|
||||||
switch (typeof bits) {
|
let bitsResult = 0n;
|
||||||
case 'string':
|
|
||||||
return this.resolve(this.Flags[bits]);
|
for (const bit of bits) {
|
||||||
case 'number':
|
switch (typeof bit) {
|
||||||
return BigInt(bits);
|
case 'string':
|
||||||
case 'bigint':
|
bitsResult |= this.resolve(this.Flags[bit]);
|
||||||
return bits;
|
break;
|
||||||
case 'object': {
|
case 'number':
|
||||||
if (!Array.isArray(bits)) {
|
bitsResult |= BigInt(bit);
|
||||||
throw new TypeError(`Cannot resolve permission: ${bits}`);
|
break;
|
||||||
|
case 'bigint':
|
||||||
|
bitsResult |= bit;
|
||||||
|
break;
|
||||||
|
case 'object': {
|
||||||
|
if (!Array.isArray(bit)) {
|
||||||
|
throw new TypeError(`Cannot resolve permission: ${bit}`);
|
||||||
|
}
|
||||||
|
bitsResult |= bits.reduce<bigint>((acc, val) => this.resolve(val) | acc, BitField.None);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return bits.map(x => this.resolve(x)).reduce((acc, cur) => acc | cur, BitField.None);
|
default:
|
||||||
|
throw new TypeError(`Cannot resolve permission: ${typeof bit === 'symbol' ? String(bit) : (bit as unknown)}`);
|
||||||
}
|
}
|
||||||
default:
|
|
||||||
throw new TypeError(
|
|
||||||
`Cannot resolve permission: ${typeof bits === 'symbol' ? String(bits) : (bits as unknown)}`,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return bitsResult;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,26 +21,36 @@ export class PermissionsBitField extends BitField<typeof PermissionFlagsBits> {
|
|||||||
return super.has(...bits);
|
return super.has(...bits);
|
||||||
}
|
}
|
||||||
|
|
||||||
resolve<T extends typeof PermissionFlagsBits>(bits: BitFieldResolvable<T>): bigint {
|
resolve<T extends typeof PermissionFlagsBits>(...bits: BitFieldResolvable<T>[]): bigint {
|
||||||
return PermissionsBitField.resolve(bits);
|
return bits.reduce<bigint>((acc, cur) => acc | PermissionsBitField.resolve(cur), BitField.None);
|
||||||
}
|
}
|
||||||
|
|
||||||
static resolve<T extends typeof PermissionFlagsBits>(bits: BitFieldResolvable<T>): bigint {
|
static resolve<T extends typeof PermissionFlagsBits>(...bits: BitFieldResolvable<T>[]): bigint {
|
||||||
switch (typeof bits) {
|
let bitsResult = 0n;
|
||||||
case 'string':
|
|
||||||
return PermissionsBitField.resolve(PermissionFlagsBits[bits as keyof typeof PermissionFlagsBits]);
|
for (const bit of bits) {
|
||||||
case 'number':
|
switch (typeof bit) {
|
||||||
return BigInt(bits);
|
case 'string':
|
||||||
case 'bigint':
|
bitsResult |= PermissionsBitField.resolve(PermissionFlagsBits[bit as keyof typeof PermissionFlagsBits]);
|
||||||
return bits;
|
break;
|
||||||
case 'object': {
|
case 'number':
|
||||||
if (!Array.isArray(bits)) {
|
bitsResult |= BigInt(bit);
|
||||||
throw new TypeError(`Cannot resolve permission: ${bits}`);
|
break;
|
||||||
|
case 'bigint':
|
||||||
|
bitsResult |= bit;
|
||||||
|
break;
|
||||||
|
case 'object': {
|
||||||
|
if (!Array.isArray(bit)) {
|
||||||
|
throw new TypeError(`Cannot resolve permission: ${bit}`);
|
||||||
|
}
|
||||||
|
bitsResult |= bit.reduce<bigint>((acc, val) => PermissionsBitField.resolve(val) | acc, BitField.None);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return bits.map(x => PermissionsBitField.resolve(x)).reduce((acc, cur) => acc | cur, BitField.None);
|
default:
|
||||||
|
throw new TypeError(`Cannot resolve permission: ${typeof bit === 'symbol' ? String(bit) : (bit as any)}`);
|
||||||
}
|
}
|
||||||
default:
|
|
||||||
throw new TypeError(`Cannot resolve permission: ${typeof bits === 'symbol' ? String(bits) : (bits as any)}`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return bitsResult;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,65 +1,65 @@
|
|||||||
import { assert, describe, test } from 'vitest';
|
import { assert, describe, test } from 'vitest';
|
||||||
import { BitField } from '../lib/structures/extra/BitField';
|
import { BitField } from '../lib/structures/extra/BitField';
|
||||||
import { PermissionsBitField } from '../lib/structures/extra/Permissions';
|
import { PermissionsBitField } from '../lib/structures/extra/Permissions';
|
||||||
import { PermissionFlagsBits } from '../lib/types';
|
import { PermissionFlagsBits } from '../lib/types';
|
||||||
|
|
||||||
describe('PermissionsBitField', () => {
|
describe('PermissionsBitField', () => {
|
||||||
test('constructor', () => {
|
test('constructor', () => {
|
||||||
const p = new PermissionsBitField(['CreateEvents']);
|
const p = new PermissionsBitField(['CreateEvents']);
|
||||||
assert.equal(p.bits, PermissionFlagsBits.CreateEvents);
|
assert.equal(p.bits, PermissionFlagsBits.CreateEvents);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('add', () => {
|
test('add', () => {
|
||||||
const p = new PermissionsBitField(['CreateEvents']);
|
const p = new PermissionsBitField(['CreateEvents']);
|
||||||
p.add(['AttachFiles']);
|
p.add(['AttachFiles']);
|
||||||
p.add('ChangeNickname');
|
p.add('ChangeNickname');
|
||||||
assert.equal(
|
assert.equal(
|
||||||
p.bits,
|
p.bits,
|
||||||
PermissionFlagsBits.CreateEvents | PermissionFlagsBits.AttachFiles | PermissionFlagsBits.ChangeNickname,
|
PermissionFlagsBits.CreateEvents | PermissionFlagsBits.AttachFiles | PermissionFlagsBits.ChangeNickname,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('remove', () => {
|
test('remove', () => {
|
||||||
const p = new PermissionsBitField(['CreateEvents']);
|
const p = new PermissionsBitField(['CreateEvents']);
|
||||||
p.remove('CreateEvents');
|
p.remove('CreateEvents');
|
||||||
assert.equal(p.bits, BitField.None);
|
assert.equal(p.bits, BitField.None);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('keys', () => {
|
test('keys', () => {
|
||||||
const p = new PermissionsBitField(['CreateEvents', 'Administrator']);
|
const p = new PermissionsBitField(['CreateEvents', 'Administrator']);
|
||||||
p.add(['AttachFiles']);
|
p.add(['AttachFiles']);
|
||||||
p.add('ChangeNickname');
|
p.add('ChangeNickname');
|
||||||
|
|
||||||
const keys = ['CreateEvents', 'Administrator', 'AttachFiles', 'ChangeNickname'];
|
const keys = ['CreateEvents', 'Administrator', 'AttachFiles', 'ChangeNickname'];
|
||||||
assert.equal(
|
assert.equal(
|
||||||
true,
|
true,
|
||||||
p.keys().every(x => keys.includes(x)),
|
p.keys().every(x => keys.includes(x)),
|
||||||
);
|
);
|
||||||
assert.equal(p.keys().length, 4);
|
assert.equal(p.keys().length, 4);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('values', () => {
|
test('values', () => {
|
||||||
const p = new PermissionsBitField(['CreateEvents']);
|
const p = new PermissionsBitField(['CreateEvents']);
|
||||||
p.add('Administrator');
|
p.add('Administrator');
|
||||||
p.add(['ChangeNickname']);
|
p.add(['ChangeNickname']);
|
||||||
assert.deepEqual(p.values(), [
|
assert.deepEqual(p.values(), [
|
||||||
PermissionFlagsBits.Administrator,
|
PermissionFlagsBits.Administrator,
|
||||||
PermissionFlagsBits.ChangeNickname,
|
PermissionFlagsBits.ChangeNickname,
|
||||||
PermissionFlagsBits.CreateEvents,
|
PermissionFlagsBits.CreateEvents,
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('missings', () => {
|
test('missings', () => {
|
||||||
const p = new PermissionsBitField(['CreateEvents']);
|
const p = new PermissionsBitField(['CreateEvents']);
|
||||||
p.add('Administrator');
|
p.add('Administrator');
|
||||||
p.add(['ChangeNickname']);
|
p.add(['ChangeNickname']);
|
||||||
assert.deepEqual(p.missings('Connect'), [PermissionFlagsBits.Connect]);
|
assert.deepEqual(p.missings('Connect'), [PermissionFlagsBits.Connect]);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('equals', () => {
|
test('equals', () => {
|
||||||
const p = new PermissionsBitField(['CreateEvents']);
|
const p = new PermissionsBitField(['CreateEvents']);
|
||||||
p.add(['ChangeNickname']);
|
p.add(['ChangeNickname']);
|
||||||
assert.deepEqual(p.equals(['ChangeNickname', 'CreateEvents']), true);
|
assert.deepEqual(p.equals(['ChangeNickname', 'CreateEvents']), true);
|
||||||
assert.deepEqual(p.equals('Connect'), false);
|
assert.deepEqual(p.equals('Connect'), false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user