feat: cache

This commit is contained in:
Yuzu 2022-07-10 19:22:14 -05:00
parent a90e55080a
commit 0219f63d2d
11 changed files with 100 additions and 98 deletions

View File

@ -2,6 +2,13 @@ import type { ButtonBuilder, InputTextBuilder, SelectMenuBuilder } from "./mod.t
import type { Permissions } from "./structures/Permissions.ts";
import type { Snowflake } from "./Snowflake.ts";
/*
* Represents a session's cache
* */
export interface SymCache {
readonly cache: symbol;
}
/*
* @link https://discord.com/developers/docs/resources/channel#message-object-message-flags
*/

View File

@ -51,6 +51,9 @@ export * from "./structures/interactions/InteractionFactory.ts";
export * from "./structures/interactions/ModalSubmitInteraction.ts";
export * from "./structures/interactions/PingInteraction.ts";
// etc
export * from "./Snowflake.ts";
// session
export * from "./Session.ts";

View File

@ -130,6 +130,8 @@ export class TextChannel {
if (data.last_pin_timestamp) {
this.lastPinTimestamp = data.last_pin_timestamp;
}
this.messages = new Map();
}
readonly session: Session;
@ -141,6 +143,9 @@ export class TextChannel {
rateLimitPerUser: number;
nsfw: boolean;
/** Meant to be used with cache */
messages: Map<Snowflake, Message>;
/**
* Mixin
*/

View File

@ -22,7 +22,7 @@ import {
VerificationLevels,
} from "../../../discordeno/mod.ts";
import { encode as _encode, urlToBase64 } from "../../util/urlToBase64.ts";
import { ThreadChannel } from "../channels.ts";
import { GuildChannel, ThreadChannel } from "../channels.ts";
import Util from "../../Util.ts";
import Member from "../Member.ts";
import BaseGuild from "./BaseGuild.ts";
@ -208,10 +208,22 @@ export class Guild extends BaseGuild implements Model {
this.vefificationLevel = data.verification_level;
this.defaultMessageNotificationLevel = data.default_message_notifications;
this.explicitContentFilterLevel = data.explicit_content_filter;
this.members = data.members?.map((member) => new Member(session, { ...member, user: member.user! }, data.id)) ??
[];
this.roles = data.roles.map((role) => new Role(session, role, data.id));
this.emojis = data.emojis.map((guildEmoji) => new GuildEmoji(session, guildEmoji, data.id));
this.members = new Map(
data.members?.map((member) => [data.id, new Member(session, { ...member, user: member.user! }, data.id)])
);
this.roles = new Map(
data.roles.map((role) => [data.id, new Role(session, role, data.id)])
);
this.emojis = new Map(
data.emojis.map((guildEmoji) => [guildEmoji.id!, new GuildEmoji(session, guildEmoji, data.id)])
);
this.channels = new Map(
data.channels?.map((guildChannel) => [guildChannel.id, new GuildChannel(session, guildChannel, data.id)])
);
}
splashHash?: bigint;
@ -222,9 +234,10 @@ export class Guild extends BaseGuild implements Model {
vefificationLevel: VerificationLevels;
defaultMessageNotificationLevel: DefaultMessageNotificationLevels;
explicitContentFilterLevel: ExplicitContentFilterLevels;
members: Member[];
roles: Role[];
emojis: GuildEmoji[];
members: Map<Snowflake, Member>;
roles: Map<Snowflake, Role>;
emojis: Map<Snowflake, GuildEmoji>;
channels: Map<Snowflake, GuildChannel>;
/**
* 'null' would reset the nickname

View File

View File

@ -1,14 +0,0 @@
import type { Session } from "./deps.ts";
export class Collection<K, V> extends Map<K, V> {
constructor(session: Session, entries: Iterable<readonly [K, V]>) {
super(entries);
this.session = session;
}
/** Reference to a session */
readonly session: Session;
}
export default Collection;

View File

View File

View File

@ -1,43 +0,0 @@
import type { DiscordMessage, Session } from "./deps.ts";
import { Message } from "./deps.ts";
import { Collection } from "./Collection.ts";
export class CachedMessage extends Message {
constructor(session: Session, data: DiscordMessage) {
super(session, data);
CachedMessage.from(this);
}
_id!: bigint;
static from(message: Message): CachedMessage {
const target: CachedMessage = Object.assign(message, { _id: BigInt(message.id) });
Object.defineProperty(target, "id", {
get(this: CachedMessage) {
return String(this._id);
}
});
return target;
}
}
export class MessageCache extends Collection<bigint, CachedMessage> {
constructor(session: Session, entries: Iterable<readonly [bigint, Message]>) {
super(session, entries);
}
async fetch(channelId: bigint, id: bigint) {
const message = this.get(id) ?? await Message.prototype.fetch.call({
session: this.session,
channelId: String(channelId),
id: String(id)
});
return CachedMessage.from(message);
}
}
export default MessageCache;

View File

@ -1,33 +0,0 @@
import type { DiscordUser, Session } from "./deps.ts";
import { User } from "./deps.ts";
import { Collection } from "./Collection.ts";
export class CachedUser extends User {
constructor(session: Session, data: DiscordUser) {
super(session, data);
CachedUser.from(this);
}
_id!: bigint;
static from(user: User): CachedUser {
const target: CachedUser = Object.assign(user, { _id: BigInt(user.id) });
Object.defineProperty(target, "id", {
get(this: CachedUser) {
return String(this._id);
}
});
return target;
}
}
export class UserCache extends Collection<bigint, CachedUser> {
constructor(session: Session, entries: Iterable<readonly [bigint, User]>) {
super(session, entries);
}
}
export default UserCache;

64
packages/cache/mod.ts vendored
View File

@ -0,0 +1,64 @@
import type {
SymCache,
Session,
Snowflake,
DiscordGuild,
DiscordEmoji,
DiscordUser,
DiscordChannel,
} from "./deps.ts";
import {
Guild,
User,
DMChannel,
GuildEmoji,
} from "./deps.ts";
export const cache_sym = Symbol("@cache");
export interface SessionCache extends SymCache {
guilds: StructCache<Guild>;
users: StructCache<User>;
dms: StructCache<DMChannel>;
emojis: StructCache<GuildEmoji>;
session: Session,
}
export default function (session: Session): SessionCache {
return {
guilds: new StructCache<Guild>(session),
users: new StructCache<User>(session),
dms: new StructCache<DMChannel>(session),
emojis: new StructCache<GuildEmoji>(session),
cache: cache_sym,
session,
};
}
export class StructCache<T> extends Map<Snowflake, T> {
constructor(session: Session, entries?: Iterable<readonly [Snowflake, T]>) {
super(entries);
this.session = session;
}
readonly session: Session;
}
export function userBootstrapper(cache: SessionCache, user: DiscordUser) {
cache.users.set(user.id, new User(cache.session, user));
}
export function emojiBootstrapper(cache: SessionCache, emoji: DiscordEmoji, guildId: Snowflake) {
if (!emoji.id) return;
cache.emojis.set(emoji.id, new GuildEmoji(cache.session, emoji, guildId));
}
export function DMChannelBootstrapper(cache: SessionCache, channel: DiscordChannel) {
cache.dms.set(channel.id, new DMChannel(cache.session, channel));
}
export function guildBootstrapper(guild: DiscordGuild, cache: SessionCache) {
// TODO: optimizee this garbage
cache.guilds.set(guild.id, new Guild(cache.session, guild));
}