diff --git a/src/cache/index.ts b/src/cache/index.ts index aa1dfb3..e07cbd9 100644 --- a/src/cache/index.ts +++ b/src/cache/index.ts @@ -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 = { + '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 = { + '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[]> = { + '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.'); + } } diff --git a/src/cache/resources/bans.ts b/src/cache/resources/bans.ts index d5c7b66..1bbed63 100644 --- a/src/cache/resources/bans.ts +++ b/src/cache/resources/bans.ts @@ -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 { namespace = 'ban'; //@ts-expect-error diff --git a/src/cache/resources/channels.ts b/src/cache/resources/channels.ts index b5e6b68..51aee77 100644 --- a/src/cache/resources/channels.ts +++ b/src/cache/resources/channels.ts @@ -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 { namespace = 'channel'; parse(data: APIChannel, id: string, guild_id: string) { diff --git a/src/cache/resources/default/base.ts b/src/cache/resources/default/base.ts index 94f03e1..4622f1a 100644 --- a/src/cache/resources/default/base.ts +++ b/src/cache/resources/default/base.ts @@ -3,7 +3,7 @@ import type { UsingClient } from '../../../commands'; import { fakePromise } from '../../../common'; import type { Cache, ReturnCache } from '../../index'; -export class BaseResource { +export class BaseResource { client!: UsingClient; namespace = 'base'; @@ -37,7 +37,7 @@ export class BaseResource { 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 { 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 { return this.adapter.values(this.namespace) as T[]; } - count() { - return this.adapter.count(this.namespace); + count(): ReturnCache { + return this.adapter.count(this.namespace) as number; } - contains(id: string) { - return this.adapter.contains(this.namespace, id); + contains(id: string): ReturnCache { + return this.adapter.contains(this.namespace, id) as boolean; } getToRelationship() { @@ -94,6 +94,6 @@ export class BaseResource { } hashId(id: string) { - return `${this.namespace}.${id}`; + return id.startsWith(this.namespace) ? id : `${this.namespace}.${id}`; } } diff --git a/src/cache/resources/default/guild-based.ts b/src/cache/resources/default/guild-based.ts index c92c650..a7804a1 100644 --- a/src/cache/resources/default/guild-based.ts +++ b/src/cache/resources/default/guild-based.ts @@ -3,7 +3,7 @@ import type { UsingClient } from '../../../commands'; import { fakePromise } from '../../../common'; import type { Cache, ReturnCache } from '../../index'; -export class GuildBasedResource { +export class GuildBasedResource { client!: UsingClient; namespace = 'base'; @@ -43,7 +43,7 @@ export class GuildBasedResource { 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 { 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; - set(__keys: [string, any][], guild: string): ReturnCache; - set(__keys: string | [string, any][], guild: string, data?: any): ReturnCache { - 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; + set(__keys: [string, S][], guild: string): ReturnCache; + set(__keys: string | [string, S][], guild: string, data?: S): ReturnCache { + 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 { ) as void; } - patch(__keys: string, guild: string, data: any): ReturnCache; + patch(__keys: string, guild: string, data: S): ReturnCache; patch(__keys: [string, any][], guild: string): ReturnCache; patch(__keys: string | [string, any][], guild: string, data?: any): ReturnCache { 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 { } 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}`; } } diff --git a/src/cache/resources/default/guild-related.ts b/src/cache/resources/default/guild-related.ts index ea21c30..cc696ea 100644 --- a/src/cache/resources/default/guild-related.ts +++ b/src/cache/resources/default/guild-related.ts @@ -4,7 +4,7 @@ import type { UsingClient } from '../../../commands'; import { fakePromise } from '../../../common'; import type { Cache, ReturnCache } from '../../index'; -export class GuildRelatedResource { +export class GuildRelatedResource { client!: BaseClient; namespace = 'base'; @@ -43,7 +43,7 @@ export class GuildRelatedResource { } } - 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 { 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; - set(__keys: [string, any][], guild: string): ReturnCache; - set(__keys: string | [string, any][], guild: string, data?: any): ReturnCache { - 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; + set(__keys: [string, S][], guild: string): ReturnCache; + set(__keys: string | [string, S][], guild: string, data?: S): ReturnCache { + 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 { ) 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 { + 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 { + return this.adapter.contains(this.hashId(guild), id) as boolean; } getToRelationship(guild: string) { @@ -162,6 +163,6 @@ export class GuildRelatedResource { } hashId(id: string) { - return `${this.namespace}.${id}`; + return id.startsWith(this.namespace) ? id : `${this.namespace}.${id}`; } } diff --git a/src/cache/resources/emojis.ts b/src/cache/resources/emojis.ts index 9d3981a..0a446af 100644 --- a/src/cache/resources/emojis.ts +++ b/src/cache/resources/emojis.ts @@ -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 { namespace = 'emoji'; //@ts-expect-error diff --git a/src/cache/resources/guilds.ts b/src/cache/resources/guilds.ts index 7141485..7c74d4d 100644 --- a/src/cache/resources/guilds.ts +++ b/src/cache/resources/guilds.ts @@ -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 { 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), diff --git a/src/cache/resources/members.ts b/src/cache/resources/members.ts index 112ca5a..40cc464 100644 --- a/src/cache/resources/members.ts +++ b/src/cache/resources/members.ts @@ -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 { namespace = 'member'; //@ts-expect-error diff --git a/src/cache/resources/messages.ts b/src/cache/resources/messages.ts index e83a5e2..4f707ae 100644 --- a/src/cache/resources/messages.ts +++ b/src/cache/resources/messages.ts @@ -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 { namespace = 'message'; //@ts-expect-error @@ -48,8 +48,8 @@ export class Messages extends GuildRelatedResource { ); } - override values(guild: string): ReturnCache { - return fakePromise(super.values(guild) as APIMessageResource[]).then(messages => { + override values(channel: string): ReturnCache { + 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 & { user_id?: string }; diff --git a/src/cache/resources/overwrites.ts b/src/cache/resources/overwrites.ts index 7d1987c..31d62b4 100644 --- a/src/cache/resources/overwrites.ts +++ b/src/cache/resources/overwrites.ts @@ -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 { 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< diff --git a/src/cache/resources/presence.ts b/src/cache/resources/presence.ts index fa65868..02fef95 100644 --- a/src/cache/resources/presence.ts +++ b/src/cache/resources/presence.ts @@ -1,7 +1,7 @@ import type { GatewayPresenceUpdate } from 'discord-api-types/v10'; import { GuildRelatedResource } from './default/guild-related'; -export class Presences extends GuildRelatedResource { +export class Presences extends GuildRelatedResource { namespace = 'presence'; //@ts-expect-error @@ -17,4 +17,4 @@ export class Presences extends GuildRelatedResource { } } -export type PresenceResource = Omit & { id: string }; +export type PresenceResource = Omit & { id: string; user_id: string }; diff --git a/src/cache/resources/roles.ts b/src/cache/resources/roles.ts index 9bec29e..a96aa5f 100644 --- a/src/cache/resources/roles.ts +++ b/src/cache/resources/roles.ts @@ -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 { namespace = 'role'; //@ts-expect-error diff --git a/src/cache/resources/stage-instances.ts b/src/cache/resources/stage-instances.ts index 30c4e13..71eda10 100644 --- a/src/cache/resources/stage-instances.ts +++ b/src/cache/resources/stage-instances.ts @@ -1,7 +1,7 @@ import type { APIStageInstance } from 'discord-api-types/v10'; import { GuildRelatedResource } from './default/guild-related'; -export class StageInstances extends GuildRelatedResource { +export class StageInstances extends GuildRelatedResource { namespace = 'stage_instance'; //@ts-expect-error diff --git a/src/cache/resources/stickers.ts b/src/cache/resources/stickers.ts index aee0186..0449842 100644 --- a/src/cache/resources/stickers.ts +++ b/src/cache/resources/stickers.ts @@ -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 { namespace = 'sticker'; //@ts-expect-error diff --git a/src/cache/resources/threads.ts b/src/cache/resources/threads.ts index b45d509..29a9a26 100644 --- a/src/cache/resources/threads.ts +++ b/src/cache/resources/threads.ts @@ -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 { namespace = 'thread'; //@ts-expect-error diff --git a/src/cache/resources/users.ts b/src/cache/resources/users.ts index 7fc44ea..03b2b89 100644 --- a/src/cache/resources/users.ts +++ b/src/cache/resources/users.ts @@ -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 { namespace = 'user'; //@ts-expect-error diff --git a/src/cache/resources/voice-states.ts b/src/cache/resources/voice-states.ts index 1ede0b3..5bace4a 100644 --- a/src/cache/resources/voice-states.ts +++ b/src/cache/resources/voice-states.ts @@ -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 { namespace = 'voice_state'; //@ts-expect-error diff --git a/src/common/bot/watcher.ts b/src/common/bot/watcher.ts index 9e52a10..6746602 100644 --- a/src/common/bot/watcher.ts +++ b/src/common/bot/watcher.ts @@ -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; + declare options: MakeRequired; /** * Initializes a new instance of the Watcher class. @@ -119,7 +119,19 @@ export class Watcher extends ShardManager { } } -export interface WatcherOptions extends Omit { +export interface WatcherOptions + extends MakePartial< + Omit, + | 'compress' + | 'presence' + | 'properties' + | 'shardEnd' + | 'shardStart' + | 'spawnShardDelay' + | 'totalShards' + | 'url' + | 'version' + > { filePath: string; transpileCommand: string; srcPath: string; diff --git a/src/common/shorters/channels.ts b/src/common/shorters/channels.ts index b0445be..b2cee8f 100644 --- a/src/common/shorters/channels.ts +++ b/src/common/shorters/channels.ts @@ -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 { - const options = MergeOptions({ guildId: '@me' }, optional); + const options = MergeOptions>({ 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);