feat: messages cache

This commit is contained in:
MARCROCK22 2024-04-20 23:36:06 -04:00
parent 5470516e3d
commit cffbadee61
4 changed files with 100 additions and 4 deletions

View File

@ -111,6 +111,7 @@ export class LimitedMemoryAdapter implements Adapter {
case 'sticker':
case 'thread':
case 'overwrite':
case 'message':
self.removeToRelationship(namespace, k.split('.')[1]);
break;
}

26
src/cache/index.ts vendored
View File

@ -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<T> = If<InferAsyncCache, Promise<T>, 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<void> {
@ -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;
}
}
}

60
src/cache/resources/messages.ts vendored Normal file
View File

@ -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<Message | undefined> {
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<Message[]> {
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<Message[]> {
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<APIMessage, 'author'> & { user_id: string };

View File

@ -79,6 +79,12 @@ export class ChannelShorter extends BaseShorter {
async pins(channelId: string): Promise<Message[]> {
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) {