feat: cache#testAdapter

This commit is contained in:
MARCROCK22 2024-06-24 21:01:14 +00:00
parent ef5370462b
commit 1ee3edfc5b
20 changed files with 385 additions and 68 deletions

294
src/cache/index.ts vendored
View File

@ -1,4 +1,4 @@
import type { If } from '../common';
import { Logger, type If } from '../common';
import type { Adapter } from './adapters';
@ -16,7 +16,20 @@ import { Threads } from './resources/threads';
import { VoiceStates } from './resources/voice-states';
import { Bans } from './resources/bans';
import { ChannelType, GatewayIntentBits, type GatewayDispatchPayload } from 'discord-api-types/v10';
import {
type APIChannel,
type APIEmoji,
type APIGuildMember,
type APIOverwrite,
type APISticker,
type APITextChannel,
type APIUser,
ChannelType,
GatewayIntentBits,
GuildMemberFlags,
OverwriteType,
type GatewayDispatchPayload,
} from 'discord-api-types/v10';
import type { InternalOptions, UsingClient } from '../commands';
import { Overwrites } from './resources/overwrites';
import { Messages } from './resources/messages';
@ -99,6 +112,8 @@ export class Cache {
messages?: Messages;
bans?: Bans;
__logger__?: Logger;
constructor(
public intents: number,
public adapter: Adapter,
@ -419,7 +434,6 @@ export class Cache {
case 'stageInstances':
case 'emojis':
case 'overwrites':
case 'bans':
case 'messages':
{
if (!this[type]?.filter(data, id, guildId)) continue;
@ -437,6 +451,7 @@ export class Cache {
allData.push([this[type]!.hashId(id), this[type]!.parse(data, id, guildId!)]);
}
break;
case 'bans':
case 'voiceStates':
case 'members':
{
@ -525,14 +540,14 @@ export class Cache {
case 'GUILD_EMOJIS_UPDATE':
await this.emojis?.remove(await this.emojis?.keys(event.d.guild_id), event.d.guild_id);
await this.emojis?.set(
event.d.emojis.map(x => [x.id!, x]),
event.d.emojis.map(x => [x.id!, x] as [string, APIEmoji]),
event.d.guild_id,
);
break;
case 'GUILD_STICKERS_UPDATE':
await this.stickers?.remove(await this.stickers?.keys(event.d.guild_id), event.d.guild_id);
await this.stickers?.set(
event.d.stickers.map(x => [x.id, x] as const),
event.d.stickers.map(x => [x.id, x] as [string, APISticker]),
event.d.guild_id,
);
break;
@ -594,4 +609,273 @@ export class Cache {
break;
}
}
async testAdapter() {
this.__logger__ ??= new Logger({
name: '[CACHE]',
});
await this.adapter.flush();
// this method will only check the cache for `users`, `members` y `channels`
// likewise these have the three types of resources (GuildRelatedResource, GuildBasedResource, BaseResource)
// will also check `overwrites`, since the latter stores an array not as an object but as data.
await this.testUsersAndMembers();
await this.testChannelsAndOverwrites();
this.__logger__.info('The adapter seems to work properly');
this.__logger__.debug('Flushing adapter');
delete this.__logger__;
await this.adapter.flush();
}
private async testUsersAndMembers() {
if (!this.users) throw new Error('Users cache disabled, you should enable it for this.');
if (!this.members) throw new Error('Members cache disabled, you should enable it for this.');
function createUser(name: string): APIUser {
return {
avatar: 'xdxd',
discriminator: '0',
global_name: name,
id: `${Math.random()}`.slice(2),
username: `@seyfert/${name}`,
};
}
function createMember(name: string): APIGuildMember {
return {
avatar: 'xdxd',
deaf: !false,
flags: GuildMemberFlags.StartedHomeActions,
joined_at: new Date().toISOString(),
mute: !true,
roles: ['111111111111'],
user: createUser(name),
};
}
const users: APIUser[] = [
createUser('witherking_'),
createUser('vanecia'),
createUser('socram'),
createUser('free'),
createUser('justevil'),
createUser('nobody'),
createUser('aaron'),
createUser('simxnet'),
createUser('yuzu'),
createUser('vyrek'),
createUser('marcrock'),
];
for (const user of users) {
await this.users.set(user.id, user);
}
if ((await this.users.values()).length !== users.length)
throw new Error('users.values() is not of the expected size.');
if ((await this.users.count()) !== users.length) throw new Error('users.count() is not of the expected amount');
for (const user of users) {
const cache = await this.users.raw(user.id);
if (!cache) throw new Error(`users.raw(${user.id}) has returned undefined!!!!!!`);
if (cache.username !== user.username)
throw new Error(
`users.raw(${user.id}).username is not of the expected value!!!!! (cache (${cache.username})) (expected value: (${user.username}))`,
);
if (cache.id !== user.id)
throw new Error(
`users.raw(${user.id}).id is not of the expected value!!!!!! (cache (${cache.id})) (expected value: (${user.id}))`,
);
}
this.__logger__!.info('the user cache seems to be alright.');
this.__logger__!.debug('Flushing adapter to clear users cache.');
await this.adapter.flush();
const guildMembers: Record<string, APIGuildMember[]> = {
'852531635252494346': [
createMember("witherking_'s member"),
createMember("vanecia's member"),
createMember("nobody's member"),
],
'1003825077969764412': [
createMember("free's member"),
createMember("socram's member"),
createMember("marcrock's member"),
createMember("justevil's member"),
createMember("vyrek's member"),
],
'876711213126520882': [
createMember("aaron's member"),
createMember("simxnet's member"),
createMember("yuzu's member"),
],
};
for (const guildId in guildMembers) {
const members = guildMembers[guildId];
for (const member of members) {
await this.members.set(member.user.id, guildId, member);
}
if ((await this.members.values(guildId)).length !== members.length)
throw new Error('members.values(guildId) is not of the expected size.');
if ((await this.members.count(guildId)) !== members.length)
throw new Error('members.count(guildId) is not of the expected amount');
for (const member of members) {
const cache = await this.members.raw(member.user.id, guildId);
if (!cache) throw new Error(`members.raw(${member.user.id}, ${guildId}) has returned undefined.`);
if (cache.roles[0] !== member.roles[0])
throw new Error(
`members.raw(${member.user.id}, ${guildId}).roles[0] is not the expected value: ${member.roles[0]} (cache: ${cache.roles[0]})`,
);
if (cache.user.username !== member.user.username)
throw new Error(
`members.raw(${member.user.id}, ${guildId}).user.username is not the expected value!!!!!! (cache (${cache.user.username})) (expected value: (${member.user.username}))`,
);
if (cache.user.id !== member.user.id)
throw new Error(
`members.raw(${member.user.id}, ${guildId}).user.id is not the expected value!!!!!! (cache (${cache.user.id})) (expected value: (${member.user.id}))`,
);
}
}
if ((await this.members.values('*')).length !== Object.values(guildMembers).flat().length)
throw new Error('members.values(*) is not of the expected size');
if ((await this.members.count('*')) !== Object.values(guildMembers).flat().length)
throw new Error('the global amount of members.count(*) is not the expected amount');
this.__logger__!.info('the member cache seems to be alright.');
}
private async testChannelsAndOverwrites() {
if (!this.channels) throw new Error('Channels cache disabled, you should enable it for this.');
if (!this.overwrites) throw new Error('Overwrites cache disabled, you should enable it for this.');
function createChannel(name: string): APITextChannel {
return {
id: `${Math.random()}`.slice(2),
name,
type: ChannelType.GuildText,
position: Math.random() > 0.5 ? 1 : 0,
};
}
function createOverwrites(name: string): (APIOverwrite & { channel_id: string })[] {
const channel_id = `${Math.random()}`.slice(2);
return [
{
id: name,
allow: '8',
deny: '2',
type: OverwriteType.Role,
channel_id,
},
{
id: `${name}-2`,
allow: '8',
deny: '2',
type: OverwriteType.Role,
channel_id,
},
];
}
const guildChannels: Record<string, APIChannel[]> = {
'852531635252494346': [
createChannel("witherking_'s channel"),
createChannel("vanecia's channel"),
createChannel("nobody's channel"),
],
'1003825077969764412': [
createChannel("free's channel"),
createChannel("socram's channel"),
createChannel("marcrock's channel"),
createChannel("justevil's channel"),
createChannel("vyrek's channel"),
],
'876711213126520882': [
createChannel("aaron's channel"),
createChannel("simxnet's channel"),
createChannel("yuzu's channel"),
],
};
for (const guildId in guildChannels) {
const channels = guildChannels[guildId];
for (const channel of channels) {
await this.channels.set(channel.id, guildId, channel);
}
if ((await this.channels.values(guildId)).length !== channels.length)
throw new Error('channels.values(guildId) is not of the expected size');
if ((await this.channels.count(guildId)) !== channels.length)
throw new Error('channels.count(guildId) is not of the expected amount');
for (const channel of channels) {
const cache = await this.channels.raw(channel.id);
if (!cache) throw new Error(`channels.raw(${channel.id}) has returned undefined!!!!!!`);
if (cache.type !== ChannelType.GuildText)
throw new Error(
`channels.raw(${channel.id}).type is not of the expected type: ${channel.type}!!!!!!!! (mismatched type: ${cache.type})`,
);
if (cache.name !== channel.name)
throw new Error(
`channels.raw(${channel.id}).name is not the expected value!!!!!! (cache (${cache.name})) (expected value: (${channel.name}))`,
);
if (cache.id !== channel.id)
throw new Error(
`channels.raw(${channel.id}).id is not the expected value!!!!!! (cache (${cache.id})) (expected value: (${channel.id}))`,
);
}
}
if ((await this.channels.values('*')).length !== Object.values(guildChannels).flat().length)
throw new Error('channels.values(*) is not of the expected size');
if ((await this.channels.count('*')) !== Object.values(guildChannels).flat().length)
throw new Error('channels.count(*) is not of the expected amount');
this.__logger__!.info('the channel cache seems to be alright');
const guildOverwrites: Record<string, ReturnType<typeof createOverwrites>[]> = {
'852531635252494346': [
createOverwrites("witherking_'s channel"),
createOverwrites("vanecia's channel"),
createOverwrites("nobody's channel"),
],
'1003825077969764412': [
createOverwrites("free's channel"),
createOverwrites("socram's channel"),
createOverwrites("marcrock's channel"),
createOverwrites("justevil's channel"),
createOverwrites("vyrek's channel"),
],
'876711213126520882': [
createOverwrites("aaron's channel"),
createOverwrites("simxnet's channel"),
createOverwrites("yuzu's channel"),
],
};
for (const guildId in guildOverwrites) {
const bulkOverwrites = guildOverwrites[guildId];
for (const overwrites of bulkOverwrites) {
await this.overwrites.set(overwrites[0].channel_id, guildId, overwrites);
}
if ((await this.overwrites.values(guildId)).length !== bulkOverwrites.length)
throw new Error('overwrites.values(channelId) is not of the expected size');
if ((await this.overwrites.count(guildId)) !== bulkOverwrites.length)
throw new Error('overwrites.count(channelId) is not of the expected amount');
for (const overwrites of bulkOverwrites) {
const cache = await this.overwrites.raw(overwrites[0].channel_id);
if (!cache) throw new Error(`overwrites.raw(${overwrites[0].channel_id}) has returned undefined!!!!!!`);
if (cache.length !== overwrites.length)
throw new Error(
`overwrites.raw(${overwrites[0].channel_id}).length is not of the expected length!!!!!! (cache (${cache.length})) (expected value: (${overwrites.length}))`,
);
for (const overwrite of overwrites) {
if (
!cache.some(x => {
return (
x.allow === overwrite.allow &&
x.deny === overwrite.deny &&
x.guild_id === guildId &&
x.id === overwrite.id &&
x.type === overwrite.type
);
})
)
throw new Error("cache wasn't found in the overwrites cache");
}
}
}
this.__logger__!.info('the overwrites cache seems to be alright.');
}
}

View File

@ -1,9 +1,9 @@
import type { APIBan } from 'discord-api-types/v10';
import type { APIBan, GatewayGuildBanModifyDispatchData } from 'discord-api-types/v10';
import type { ReturnCache } from '../..';
import { fakePromise } from '../../common';
import { GuildBasedResource } from './default/guild-based';
import { type GuildBanStructure, Transformers } from '../../client/transformers';
export class Bans extends GuildBasedResource {
export class Bans extends GuildBasedResource<any, GatewayGuildBanModifyDispatchData | APIBan> {
namespace = 'ban';
//@ts-expect-error

View File

@ -5,7 +5,7 @@ import channelFrom from '../../structures/channels';
import type { ReturnCache } from '../index';
import { GuildRelatedResource } from './default/guild-related';
export class Channels extends GuildRelatedResource {
export class Channels extends GuildRelatedResource<any, APIChannel> {
namespace = 'channel';
parse(data: APIChannel, id: string, guild_id: string) {

View File

@ -3,7 +3,7 @@ import type { UsingClient } from '../../../commands';
import { fakePromise } from '../../../common';
import type { Cache, ReturnCache } from '../../index';
export class BaseResource<T = any> {
export class BaseResource<T = any, S = any> {
client!: UsingClient;
namespace = 'base';
@ -37,7 +37,7 @@ export class BaseResource<T = any> {
return;
}
setIfNI(intent: keyof typeof GatewayIntentBits, id: string, data: any) {
setIfNI(intent: keyof typeof GatewayIntentBits, id: string, data: S) {
if (!this.cache.hasIntent(intent)) {
return this.set(id, data);
}
@ -51,12 +51,12 @@ export class BaseResource<T = any> {
return fakePromise(this.adapter.bulkGet(ids.map(id => this.hashId(id)))).then(x => x.filter(y => y));
}
set(id: string, data: any) {
set(id: string, data: S) {
if (!this.filter(data, id)) return;
return fakePromise(this.addToRelationship(id)).then(() => this.adapter.set(this.hashId(id), data));
}
patch(id: string, data: any) {
patch(id: string, data: S) {
if (!this.filter(data, id)) return;
return fakePromise(this.addToRelationship(id)).then(() => this.adapter.patch(false, this.hashId(id), data));
}
@ -73,12 +73,12 @@ export class BaseResource<T = any> {
return this.adapter.values(this.namespace) as T[];
}
count() {
return this.adapter.count(this.namespace);
count(): ReturnCache<number> {
return this.adapter.count(this.namespace) as number;
}
contains(id: string) {
return this.adapter.contains(this.namespace, id);
contains(id: string): ReturnCache<boolean> {
return this.adapter.contains(this.namespace, id) as boolean;
}
getToRelationship() {
@ -94,6 +94,6 @@ export class BaseResource<T = any> {
}
hashId(id: string) {
return `${this.namespace}.${id}`;
return id.startsWith(this.namespace) ? id : `${this.namespace}.${id}`;
}
}

View File

@ -3,7 +3,7 @@ import type { UsingClient } from '../../../commands';
import { fakePromise } from '../../../common';
import type { Cache, ReturnCache } from '../../index';
export class GuildBasedResource<T = any> {
export class GuildBasedResource<T = any, S = any> {
client!: UsingClient;
namespace = 'base';
@ -43,7 +43,7 @@ export class GuildBasedResource<T = any> {
return;
}
setIfNI(intent: keyof typeof GatewayIntentBits, id: string, guildId: string, data: any) {
setIfNI(intent: keyof typeof GatewayIntentBits, id: string, guildId: string, data: S) {
if (!this.cache.hasIntent(intent)) {
return this.set(id, guildId, data);
}
@ -57,13 +57,12 @@ export class GuildBasedResource<T = any> {
return fakePromise(this.adapter.bulkGet(ids.map(id => this.hashGuildId(guild, id)))).then(x => x.filter(y => y));
}
set(__keys: string, guild: string, data: any): ReturnCache<void>;
set(__keys: [string, any][], guild: string): ReturnCache<void>;
set(__keys: string | [string, any][], guild: string, data?: any): ReturnCache<void> {
const keys = (Array.isArray(__keys) ? __keys : [[__keys, data]]).filter(x => this.filter(x[1], x[0], guild)) as [
string,
any,
][];
set(__keys: string, guild: string, data: S): ReturnCache<void>;
set(__keys: [string, S][], guild: string): ReturnCache<void>;
set(__keys: string | [string, S][], guild: string, data?: S): ReturnCache<void> {
const keys = (Array.isArray(__keys) ? __keys : [[__keys, data]]).filter(x =>
this.filter(x[1], x[0] as string, guild),
) as [string, any][];
return fakePromise(
this.addToRelationship(
@ -79,7 +78,7 @@ export class GuildBasedResource<T = any> {
) as void;
}
patch(__keys: string, guild: string, data: any): ReturnCache<void>;
patch(__keys: string, guild: string, data: S): ReturnCache<void>;
patch(__keys: [string, any][], guild: string): ReturnCache<void>;
patch(__keys: string | [string, any][], guild: string, data?: any): ReturnCache<void> {
const keys = (Array.isArray(__keys) ? __keys : [[__keys, data]]).filter(x => this.filter(x[1], x[0], guild)) as [
@ -144,10 +143,10 @@ export class GuildBasedResource<T = any> {
}
hashId(id: string) {
return `${this.namespace}.${id}`;
return id.startsWith(this.namespace) ? id : `${this.namespace}.${id}`;
}
hashGuildId(guild: string, id: string) {
return `${this.namespace}.${guild}.${id}`;
return id.startsWith(this.namespace) ? id : `${this.namespace}.${guild}.${id}`;
}
}

View File

@ -4,7 +4,7 @@ import type { UsingClient } from '../../../commands';
import { fakePromise } from '../../../common';
import type { Cache, ReturnCache } from '../../index';
export class GuildRelatedResource<T = any> {
export class GuildRelatedResource<T = any, S = any> {
client!: BaseClient;
namespace = 'base';
@ -43,7 +43,7 @@ export class GuildRelatedResource<T = any> {
}
}
setIfNI(intent: keyof typeof GatewayIntentBits, id: string, guildId: string, data: any) {
setIfNI(intent: keyof typeof GatewayIntentBits, id: string, guildId: string, data: S) {
if (!this.cache.hasIntent(intent)) {
return this.set(id, guildId, data);
}
@ -57,13 +57,12 @@ export class GuildRelatedResource<T = any> {
return fakePromise(this.adapter.bulkGet(ids.map(x => this.hashId(x)))).then(x => x.filter(y => y));
}
set(__keys: string, guild: string, data: any): ReturnCache<void>;
set(__keys: [string, any][], guild: string): ReturnCache<void>;
set(__keys: string | [string, any][], guild: string, data?: any): ReturnCache<void> {
const keys = (Array.isArray(__keys) ? __keys : [[__keys, data]]).filter(x => this.filter(x[1], x[0], guild)) as [
string,
any,
][];
set(__keys: string, guild: string, data: S): ReturnCache<void>;
set(__keys: [string, S][], guild: string): ReturnCache<void>;
set(__keys: string | [string, S][], guild: string, data?: S): ReturnCache<void> {
const keys = (Array.isArray(__keys) ? __keys : [[__keys, data]]).filter(x =>
this.filter(x[1], x[0] as string, guild),
) as [string, any][];
return fakePromise(
this.addToRelationship(
@ -137,12 +136,14 @@ export class GuildRelatedResource<T = any> {
) as (T & { guild_id: string })[]);
}
count(to: string) {
return to === '*' ? fakePromise(this.keys(to)).then(x => x.length) : this.adapter.count(this.hashId(to));
count(to: string): ReturnCache<number> {
return to === '*'
? fakePromise(this.keys(to)).then(x => x.length)
: (this.adapter.count(this.hashId(to)) as number);
}
contains(id: string, guild: string) {
return this.adapter.contains(this.hashId(guild), id);
contains(id: string, guild: string): ReturnCache<boolean> {
return this.adapter.contains(this.hashId(guild), id) as boolean;
}
getToRelationship(guild: string) {
@ -162,6 +163,6 @@ export class GuildRelatedResource<T = any> {
}
hashId(id: string) {
return `${this.namespace}.${id}`;
return id.startsWith(this.namespace) ? id : `${this.namespace}.${id}`;
}
}

View File

@ -4,7 +4,7 @@ import { fakePromise } from '../../common';
import { GuildRelatedResource } from './default/guild-related';
import { type GuildEmojiStructure, Transformers } from '../../client/transformers';
export class Emojis extends GuildRelatedResource {
export class Emojis extends GuildRelatedResource<any, APIEmoji> {
namespace = 'emoji';
//@ts-expect-error

View File

@ -1,10 +1,10 @@
import type { APIGuild } from 'discord-api-types/v10';
import type { APIGuild, GatewayGuildCreateDispatchData } from 'discord-api-types/v10';
import type { Cache, ReturnCache } from '..';
import { fakePromise } from '../../common';
import { BaseResource } from './default/base';
import { type GuildStructure, Transformers } from '../../client/transformers';
export class Guilds extends BaseResource {
export class Guilds extends BaseResource<any, APIGuild | GatewayGuildCreateDispatchData> {
namespace = 'guild';
//@ts-expect-error
@ -35,22 +35,34 @@ export class Guilds extends BaseResource {
}
override async remove(id: string) {
const keysChannels = this.cache.channels?.keys(id) ?? [];
await this.cache.adapter.bulkRemove(
(
await Promise.all([
this.cache.members?.keys(id) ?? [],
this.cache.roles?.keys(id) ?? [],
this.cache.channels?.keys(id) ?? [],
keysChannels,
this.cache.emojis?.keys(id) ?? [],
this.cache.stickers?.keys(id) ?? [],
this.cache.voiceStates?.keys(id) ?? [],
this.cache.presences?.keys(id) ?? [],
this.cache.threads?.keys(id) ?? [],
this.cache.stageInstances?.keys(id) ?? [],
this.cache.bans?.keys(id) ?? [],
])
).flat(),
);
if (this.cache.messages && this.cache.channels) {
const keysMessages: string[] = [];
for (const i of keysChannels) {
const channelId = i.slice(this.cache.channels.namespace.length + 1);
const messages = await this.cache.messages.keys(channelId);
keysMessages.push(...messages);
}
if (keysMessages.length) await this.cache.adapter.bulkRemove(keysMessages);
}
await this.cache.adapter.removeRelationship(
[
this.cache.members?.hashId(id),

View File

@ -3,7 +3,7 @@ import type { ReturnCache } from '../..';
import { fakePromise } from '../../common';
import { GuildBasedResource } from './default/guild-based';
import { type GuildMemberStructure, Transformers } from '../../client/transformers';
export class Members extends GuildBasedResource {
export class Members extends GuildBasedResource<any, APIGuildMember> {
namespace = 'member';
//@ts-expect-error

View File

@ -4,7 +4,7 @@ import type { MessageData, ReturnCache } from '../..';
import { fakePromise } from '../../common';
import { type MessageStructure, Transformers } from '../../client/transformers';
export class Messages extends GuildRelatedResource {
export class Messages extends GuildRelatedResource<any, APIMessage> {
namespace = 'message';
//@ts-expect-error
@ -48,8 +48,8 @@ export class Messages extends GuildRelatedResource {
);
}
override values(guild: string): ReturnCache<MessageStructure[]> {
return fakePromise(super.values(guild) as APIMessageResource[]).then(messages => {
override values(channel: string): ReturnCache<MessageStructure[]> {
return fakePromise(super.values(channel) as APIMessageResource[]).then(messages => {
const hashes: (string | undefined)[] = this.cache.users
? messages.map(x => (x.user_id ? this.cache.users!.hashId(x.user_id) : undefined))
: [];
@ -63,6 +63,10 @@ export class Messages extends GuildRelatedResource {
});
});
}
keys(channel: string) {
return super.keys(channel);
}
}
export type APIMessageResource = Omit<APIMessage, 'author'> & { user_id?: string };

View File

@ -4,7 +4,7 @@ import { fakePromise } from '../../common/it/utils';
import { PermissionsBitField } from '../../structures/extra/Permissions';
import { GuildRelatedResource } from './default/guild-related';
export class Overwrites extends GuildRelatedResource {
export class Overwrites extends GuildRelatedResource<any, APIOverwrite[]> {
namespace = 'overwrite';
//@ts-expect-error
@ -19,6 +19,10 @@ export class Overwrites extends GuildRelatedResource {
return data;
}
raw(id: string): ReturnCache<(APIOverwrite & { guild_id: string })[]> {
return super.get(id);
}
override get(
id: string,
): ReturnCache<

View File

@ -1,7 +1,7 @@
import type { GatewayPresenceUpdate } from 'discord-api-types/v10';
import { GuildRelatedResource } from './default/guild-related';
export class Presences extends GuildRelatedResource<PresenceResource> {
export class Presences extends GuildRelatedResource<PresenceResource, GatewayPresenceUpdate> {
namespace = 'presence';
//@ts-expect-error
@ -17,4 +17,4 @@ export class Presences extends GuildRelatedResource<PresenceResource> {
}
}
export type PresenceResource = Omit<GatewayPresenceUpdate, 'user'> & { id: string };
export type PresenceResource = Omit<GatewayPresenceUpdate, 'user'> & { id: string; user_id: string };

View File

@ -4,7 +4,7 @@ import { fakePromise } from '../../common';
import { GuildRelatedResource } from './default/guild-related';
import { type GuildRoleStructure, Transformers } from '../../client/transformers';
export class Roles extends GuildRelatedResource {
export class Roles extends GuildRelatedResource<any, APIRole> {
namespace = 'role';
//@ts-expect-error

View File

@ -1,7 +1,7 @@
import type { APIStageInstance } from 'discord-api-types/v10';
import { GuildRelatedResource } from './default/guild-related';
export class StageInstances extends GuildRelatedResource<APIStageInstance> {
export class StageInstances extends GuildRelatedResource<APIStageInstance, APIStageInstance> {
namespace = 'stage_instance';
//@ts-expect-error

View File

@ -4,7 +4,7 @@ import { fakePromise } from '../../common';
import { GuildRelatedResource } from './default/guild-related';
import { type StickerStructure, Transformers } from '../../client/transformers';
export class Stickers extends GuildRelatedResource {
export class Stickers extends GuildRelatedResource<any, APISticker> {
namespace = 'sticker';
//@ts-expect-error

View File

@ -4,7 +4,7 @@ import { fakePromise } from '../../common';
import { GuildRelatedResource } from './default/guild-related';
import { type ThreadChannelStructure, Transformers } from '../../client/transformers';
export class Threads extends GuildRelatedResource {
export class Threads extends GuildRelatedResource<any, APIThreadChannel> {
namespace = 'thread';
//@ts-expect-error

View File

@ -4,7 +4,7 @@ import { fakePromise } from '../../common';
import { BaseResource } from './default/base';
import { Transformers, type UserStructure } from '../../client/transformers';
export class Users extends BaseResource {
export class Users extends BaseResource<any, APIUser> {
namespace = 'user';
//@ts-expect-error

View File

@ -4,7 +4,7 @@ import { fakePromise } from '../../common';
import { GuildBasedResource } from './default/guild-based';
import { Transformers, type VoiceStateStructure } from '../../client/transformers';
export class VoiceStates extends GuildBasedResource {
export class VoiceStates extends GuildBasedResource<any, GatewayVoiceState> {
namespace = 'voice_state';
//@ts-expect-error

View File

@ -2,9 +2,9 @@ import type { GatewayDispatchPayload, GatewaySendPayload } from 'discord-api-typ
import { execSync } from 'node:child_process';
import { ApiHandler, Router } from '../../api';
import { BaseClient, type InternalRuntimeConfig } from '../../client/base';
import { ShardManager, type ShardManagerOptions } from '../../websocket';
import { ShardManager, type ShardManagerDefaults, type ShardManagerOptions } from '../../websocket';
import { Logger } from '../it/logger';
import type { MakeRequired } from '../types/util';
import type { MakePartial, MakeRequired } from '../types/util';
import { lazyLoadPackage } from '../it/utils';
/**
@ -17,7 +17,7 @@ export class Watcher extends ShardManager {
});
rest?: ApiHandler;
declare options: MakeRequired<WatcherOptions, 'intents' | 'token' | 'handlePayload' | 'info'>;
declare options: MakeRequired<WatcherOptions, 'token' | 'info' | keyof typeof ShardManagerDefaults>;
/**
* Initializes a new instance of the Watcher class.
@ -119,7 +119,19 @@ export class Watcher extends ShardManager {
}
}
export interface WatcherOptions extends Omit<ShardManager['options'], 'handlePayload' | 'info' | 'token' | 'intents'> {
export interface WatcherOptions
extends MakePartial<
Omit<ShardManager['options'], 'handlePayload' | 'info' | 'token' | 'intents'>,
| 'compress'
| 'presence'
| 'properties'
| 'shardEnd'
| 'shardStart'
| 'spawnShardDelay'
| 'totalShards'
| 'url'
| 'version'
> {
filePath: string;
transpileCommand: string;
srcPath: string;

View File

@ -12,6 +12,7 @@ import { PermissionsBitField } from '../../structures/extra/Permissions';
import { BaseShorter } from './base';
import { MergeOptions } from '../it/utils';
import { type MessageStructure, Transformers } from '../../client/transformers';
import type { MakeRequired } from '../types/util';
export class ChannelShorter extends BaseShorter {
/**
@ -61,14 +62,14 @@ export class ChannelShorter extends BaseShorter {
body: RESTPatchAPIChannelJSONBody,
optional: ChannelShorterOptionalParams = { guildId: '@me' },
): Promise<AllChannels> {
const options = MergeOptions<ChannelShorterOptionalParams>({ guildId: '@me' }, optional);
const options = MergeOptions<MakeRequired<ChannelShorterOptionalParams, 'guildId'>>({ guildId: '@me' }, optional);
const res = await this.client.proxy.channels(id).patch({ body, reason: options.reason });
await this.client.cache.channels?.setIfNI(BaseChannel.__intent__(options.guildId!), res.id, options.guildId!, res);
if (body.permission_overwrites && 'permission_overwrites' in res)
if (body.permission_overwrites && 'permission_overwrites' in res && res.permission_overwrites)
await this.client.cache.overwrites?.setIfNI(
BaseChannel.__intent__(options.guildId!),
BaseChannel.__intent__(options.guildId),
res.id,
options.guildId!,
options.guildId,
res.permission_overwrites,
);
return channelFrom(res, this.client);