diff --git a/packages/biscuit/Util.ts b/packages/biscuit/Util.ts index 37c865d..a0e019a 100644 --- a/packages/biscuit/Util.ts +++ b/packages/biscuit/Util.ts @@ -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 */ diff --git a/packages/biscuit/mod.ts b/packages/biscuit/mod.ts index 5d8d4de..bc196b1 100644 --- a/packages/biscuit/mod.ts +++ b/packages/biscuit/mod.ts @@ -1,4 +1,7 @@ // structures +import { Session } from "./Session.ts"; +export default Session; + export * from "./structures/Attachment.ts"; export * from "./structures/Base.ts"; export * from "./structures/Embed.ts"; @@ -48,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"; diff --git a/packages/biscuit/structures/Message.ts b/packages/biscuit/structures/Message.ts index e933364..ea07beb 100644 --- a/packages/biscuit/structures/Message.ts +++ b/packages/biscuit/structures/Message.ts @@ -361,6 +361,18 @@ export class Message implements Model { return new Message(this.session, message); } + async fetch() { + const message = await this.session.rest.runMethod( + this.session.rest, + "GET", + Routes.CHANNEL_MESSAGE(this.channelId, this.message), + ); + + if (!message?.id) return; + + return new Message(this.session, message); + } + /* * alias of Message.crosspost * */ diff --git a/packages/biscuit/structures/channels.ts b/packages/biscuit/structures/channels.ts index 8c29c20..e93dd14 100644 --- a/packages/biscuit/structures/channels.ts +++ b/packages/biscuit/structures/channels.ts @@ -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; + /** * Mixin */ diff --git a/packages/biscuit/structures/guilds/Guild.ts b/packages/biscuit/structures/guilds/Guild.ts index 53ea0a6..86a60f4 100644 --- a/packages/biscuit/structures/guilds/Guild.ts +++ b/packages/biscuit/structures/guilds/Guild.ts @@ -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; + roles: Map; + emojis: Map; + channels: Map; /** * 'null' would reset the nickname diff --git a/packages/cache/deps.ts b/packages/cache/deps.ts new file mode 100644 index 0000000..dc3c536 --- /dev/null +++ b/packages/cache/deps.ts @@ -0,0 +1,2 @@ +export * from "../biscuit/mod.ts"; +export * from "../discordeno/mod.ts"; diff --git a/packages/cache/mod.ts b/packages/cache/mod.ts new file mode 100644 index 0000000..f1f6316 --- /dev/null +++ b/packages/cache/mod.ts @@ -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; + users: StructCache; + dms: StructCache; + emojis: StructCache; + session: Session, +} + +export default function (session: Session): SessionCache { + return { + guilds: new StructCache(session), + users: new StructCache(session), + dms: new StructCache(session), + emojis: new StructCache(session), + cache: cache_sym, + session, + }; +} + +export class StructCache extends Map { + constructor(session: Session, entries?: Iterable) { + 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)); +}