From cffbadee61a61a58f6841af31119022cc2cf29d5 Mon Sep 17 00:00:00 2001 From: MARCROCK22 <57925328+MARCROCK22@users.noreply.github.com> Date: Sat, 20 Apr 2024 23:36:06 -0400 Subject: [PATCH] feat: messages cache --- src/cache/adapters/limited.ts | 1 + src/cache/index.ts | 26 ++++++++++++-- src/cache/resources/messages.ts | 60 +++++++++++++++++++++++++++++++++ src/common/shorters/channels.ts | 17 ++++++++-- 4 files changed, 100 insertions(+), 4 deletions(-) create mode 100644 src/cache/resources/messages.ts diff --git a/src/cache/adapters/limited.ts b/src/cache/adapters/limited.ts index 638a672..4f985e2 100644 --- a/src/cache/adapters/limited.ts +++ b/src/cache/adapters/limited.ts @@ -111,6 +111,7 @@ export class LimitedMemoryAdapter implements Adapter { case 'sticker': case 'thread': case 'overwrite': + case 'message': self.removeToRelationship(namespace, k.split('.')[1]); break; } diff --git a/src/cache/index.ts b/src/cache/index.ts index ea2be36..df53c45 100644 --- a/src/cache/index.ts +++ b/src/cache/index.ts @@ -18,6 +18,7 @@ import { VoiceStates } from './resources/voice-states'; import { ChannelType, GatewayIntentBits, type GatewayDispatchPayload } from 'discord-api-types/v10'; import type { InternalOptions, UsingClient } from '../commands'; import { Overwrites } from './resources/overwrites'; +import { Messages } from './resources/messages'; export type InferAsyncCache = InternalOptions extends { asyncCache: infer P } ? P : false; export type ReturnCache = If, T>; @@ -34,7 +35,8 @@ export type GuildRelated = | 'stickers' | 'presences' | 'stageInstances' - | 'overwrites'; + | 'overwrites' + | 'messages'; // ClientBased export type NonGuildBased = 'users' | 'guilds'; @@ -90,6 +92,7 @@ export class Cache { stickers?: Stickers; presences?: Presences; stageInstances?: StageInstances; + messages?: Messages; constructor( public intents: number, @@ -138,6 +141,9 @@ export class Cache { if (!this.disabledCache.includes('stageInstances')) { this.stageInstances = new StageInstances(this, client); } + if (!this.disabledCache.includes('messages')) { + this.messages = new Messages(this, client); + } } /** @internal */ @@ -156,6 +162,7 @@ export class Cache { this.presences?.__setClient(client); this.threads?.__setClient(client); this.stageInstances?.__setClient(client); + this.messages?.__setClient(client); } flush(): ReturnCache { @@ -239,6 +246,7 @@ export class Cache { case 'users': case 'guilds': case 'overwrites': + case 'messages': { if (!allData[type]) { allData[type] = []; @@ -305,6 +313,7 @@ export class Cache { case 'stageInstances': case 'emojis': case 'overwrites': + case 'messages': { if (!this[type]?.filter(data, id, guildId)) continue; const hashId = this[type]?.hashId(guildId!); @@ -395,6 +404,7 @@ export class Cache { case 'stageInstances': case 'emojis': case 'overwrites': + case 'messages': { if (!this[type]?.filter(data, id, guildId)) continue; const hashId = this[type]?.hashId(guildId!); @@ -500,7 +510,7 @@ export class Cache { 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]), + event.d.stickers.map(x => [x.id, x] as const), event.d.guild_id, ); break; @@ -548,6 +558,18 @@ export class Cache { case 'STAGE_INSTANCE_DELETE': await this.stageInstances?.remove(event.d.id, event.d.guild_id); break; + case 'MESSAGE_CREATE': + await this.messages?.set(event.d.id, event.d.channel_id, event.d); + break; + case 'MESSAGE_UPDATE': + await this.messages?.patch(event.d.id, event.d.channel_id, event.d); + break; + case 'MESSAGE_DELETE': + await this.messages?.remove(event.d.id, event.d.channel_id); + break; + case 'MESSAGE_DELETE_BULK': + await this.messages?.remove(event.d.ids, event.d.channel_id); + break; } } } diff --git a/src/cache/resources/messages.ts b/src/cache/resources/messages.ts new file mode 100644 index 0000000..68eb28a --- /dev/null +++ b/src/cache/resources/messages.ts @@ -0,0 +1,60 @@ +import type { APIMessage, APIUser } from 'discord-api-types/v10'; +import { GuildRelatedResource } from './default/guild-related'; +import type { MessageData, ReturnCache } from '../..'; +import { fakePromise } from '../../common'; +import { Message } from '../../structures'; + +export class Messages extends GuildRelatedResource { + namespace = 'message'; + + //@ts-expect-error + filter(data: MessageData, id: string, channel_id?: string) { + return true; + } + + override parse(data: any, _key: string, _channel_id: string) { + const { author, member, ...rest } = data; + rest.user_id = author.id; + + return rest; + } + + override get(id: string): ReturnCache { + return fakePromise(super.get(id) as APIMessageResource).then(rawMessage => { + const user = this.cache.users + ? (this.cache.adapter.get(this.cache.users.hashId(rawMessage.user_id)) as APIUser | undefined) + : undefined; + return user ? new Message(this.client, { ...rawMessage, author: user }) : undefined; + }); + } + + override bulk(ids: string[]): ReturnCache { + return fakePromise(super.bulk(ids) as APIMessageResource[]).then( + messages => + messages + .map(rawMessage => { + const user = this.cache.users + ? (this.cache.adapter.get(this.cache.users.hashId(rawMessage.user_id)) as APIUser | undefined) + : undefined; + return user ? new Message(this.client, { ...rawMessage, author: user }) : undefined; + }) + .filter(Boolean) as Message[], + ); + } + + override values(guild: string): ReturnCache { + return fakePromise(super.values(guild) as APIMessageResource[]).then(messages => { + const hashes: string[] = this.cache.users ? messages.map(x => this.cache.users!.hashId(x.user_id)) : []; + return fakePromise(this.cache.adapter.get(hashes) as APIUser[]).then(users => { + return messages + .map(message => { + const user = users.find(user => user.id === message.user_id); + return user ? new Message(this.client, { ...message, author: user }) : undefined; + }) + .filter(Boolean) as Message[]; + }); + }); + } +} + +export type APIMessageResource = Omit & { user_id: string }; diff --git a/src/common/shorters/channels.ts b/src/common/shorters/channels.ts index 481eca3..9aca93b 100644 --- a/src/common/shorters/channels.ts +++ b/src/common/shorters/channels.ts @@ -79,6 +79,12 @@ export class ChannelShorter extends BaseShorter { async pins(channelId: string): Promise { const messages = await this.client.proxy.channels(channelId).pins.get(); + await this.client.cache.messages?.patch( + messages.map(x => { + return [x.id, x]; + }) satisfies [string, any][], + channelId, + ); return messages.map(message => new Message(this.client, message)); } @@ -178,10 +184,17 @@ export class ChannelShorter extends BaseShorter { return permissions; } - fetchMessages(channelId: string, query?: RESTGetAPIChannelMessagesQuery) { - return this.client.proxy.channels(channelId).messages.get({ + async fetchMessages(channelId: string, query?: RESTGetAPIChannelMessagesQuery) { + const result = await this.client.proxy.channels(channelId).messages.get({ query, }); + await this.client.cache.messages?.patch( + result.map(x => { + return [x.id, x]; + }) satisfies [string, any][], + channelId, + ); + return result.map(message => new Message(this.client, message)); } setVoiceStatus(channelId: string, status: string | null = null) {