diff --git a/framework/src/client/mod.ts b/framework/src/client/mod.ts index e883ce5d..d67f9080 100644 --- a/framework/src/client/mod.ts +++ b/framework/src/client/mod.ts @@ -10,6 +10,7 @@ import { ChannelsManager } from "../managers/mod.ts"; import { GuildsManager } from "../managers/guilds.ts"; import { UsersManager } from "../managers/users.ts"; import { RolesManager } from "../managers/roles.ts"; +import { EmojisManager } from "../managers/emojis.ts"; export interface ClientOptions extends APIManagerOptions { intents?: number; @@ -23,6 +24,7 @@ export class Client extends EventEmitter { guilds = new GuildsManager(this); users = new UsersManager(this); roles = new RolesManager(this); + emojis = new EmojisManager(this); constructor(token: string, options: ClientOptions = {}) { super(); diff --git a/framework/src/managers/emojis.ts b/framework/src/managers/emojis.ts new file mode 100644 index 00000000..a0f30d69 --- /dev/null +++ b/framework/src/managers/emojis.ts @@ -0,0 +1,72 @@ +import type { EmojiPayload } from "../../../types/mod.ts"; +import type { EmojiPayloadWithGuildID } from "../../types/emoji.ts"; +import { Emoji } from "../structures/emojis/mod.ts"; +import { BaseManager } from "./base.ts"; + +export class EmojisManager extends BaseManager { + _fill(emojis: EmojiPayloadWithGuildID[]) { + for (const emoji of emojis) { + this.set(emoji.id!, emoji); + } + } + + async _fetch( + guildID: string, + id: string, + ): Promise { + try { + const resp: EmojiPayload | undefined = await this.client.rest.get( + `/guilds/${guildID}/emojis/${id}`, + ); + if (!resp) return; + const result = { + ...resp, + guild_id: guildID, + }; + this.set(id, result); + return result; + } catch (_err) { + return; + } + } + async _fetchAll( + guildID: string, + ): Promise { + try { + const resp: EmojiPayload[] | undefined = await this.client.rest.get( + `/guilds/${guildID}/emojis`, + ); + if (!resp) return; + return resp.map((emoji) => { + const withGuildID = { + ...emoji, + guild_id: guildID, + }; + this.set(emoji.id!, withGuildID); + return withGuildID; + }); + } catch (_err) { + return; + } + } + + get( + id: string, + ) { + const cached = this._get(id); + if (!cached) return; + return new Emoji(this.client, cached, cached.guild_id); + } + async fetch( + guildID: string, + id: string, + ) { + try { + const payload = await this._fetch(guildID, id); + if (!payload) return; + return new Emoji(this.client, payload, payload.guild_id); + } catch (_err) { + return; + } + } +} diff --git a/framework/src/managers/guildEmojis.ts b/framework/src/managers/guildEmojis.ts new file mode 100644 index 00000000..3e33de14 --- /dev/null +++ b/framework/src/managers/guildEmojis.ts @@ -0,0 +1,95 @@ +import type { EmojiPayload } from "../../../types/mod.ts"; +import type { EmojiPayloadWithGuildID } from "../../types/emoji.ts"; +import type { Client } from "../client/mod.ts"; +import { Emoji } from "../structures/emojis/mod.ts"; +import { BaseChildManager } from "./baseChild.ts"; +import type { EmojisManager } from "./emojis.ts"; + +export class GuildEmojisManager + extends BaseChildManager { + guildID: string; + + constructor(client: Client, parent: EmojisManager, guildID: string) { + super(client, parent); + this.guildID = guildID; + } + + _fill(payloads: EmojiPayload[]) { + for (const payload of payloads) { + this.set(payload.id!, { + ...payload, + guild_id: this.guildID, + }); + } + } + + _get(key: string): EmojiPayloadWithGuildID | undefined { + const emoji = this.parent._get(key); + if (!emoji) return; + if (emoji.guild_id !== this.guildID) return; + return emoji; + } + + async _fetchAll(): Promise { + try { + const resp: EmojiPayload[] | undefined = await this.client.rest + .get( + `/guilds/${this.guildID}/emojis`, + ); + if (!resp) return; + const emojis = resp.map((r) => ({ ...r, guild_id: this.guildID })); + this._fill(emojis); + return emojis; + } catch (_err) { + return; + } + } + + async _fetch(id: string): Promise { + try { + const resp: EmojiPayload | undefined = await this.client.rest + .get( + `/guilds/${this.guildID}/emojis/${id}`, + ); + if (!resp) return; + const emoji = { + ...resp, + guild_id: this.guildID, + }; + this.set(id, emoji); + return emoji; + } catch (_err) { + return; + } + } + + get( + id: string, + ) { + const cached = this._get(id); + if (!cached) return; + return new Emoji(this.client, cached, cached.guild_id); + } + + async fetchAll(): Promise { + try { + const emojis = await this._fetchAll(); + if (!emojis) return; + return emojis.map((r) => new Emoji(this.client, r, this.guildID)); + } catch (_err) { + return; + } + } + + async fetch( + id: string, + ) { + try { + const payload = await this._fetch(id); + if (!payload) return; + return new Emoji(this.client, payload, this.guildID); + } catch (_err) { + return; + } + } +} diff --git a/framework/src/managers/guildRoles.ts b/framework/src/managers/guildRoles.ts index 9fef3f7c..28153d06 100644 --- a/framework/src/managers/guildRoles.ts +++ b/framework/src/managers/guildRoles.ts @@ -1,15 +1,16 @@ -import { RolePayload } from "../../../types/mod.ts"; +import type { RolePayload } from "../../../types/mod.ts"; import type { RolePayloadWithGuildID } from "../../types/role.ts"; import type { Client } from "../client/mod.ts"; import { Role } from "../structures/guilds/role.ts"; import { BaseChildManager } from "./baseChild.ts"; +import type { RolesManager } from "./roles.ts"; export class GuildRolesManager extends BaseChildManager { guildID: string; - constructor(client: Client, guildID: string) { - super(client, client.roles); + constructor(client: Client, parent: RolesManager, guildID: string) { + super(client, parent); this.guildID = guildID; } diff --git a/framework/src/structures/channels/guildForumChannel.ts b/framework/src/structures/channels/guildForumChannel.ts index dc4c1476..84ac5b4b 100644 --- a/framework/src/structures/channels/guildForumChannel.ts +++ b/framework/src/structures/channels/guildForumChannel.ts @@ -1,6 +1,7 @@ import type { GuildForumChannelPayload } from "../../../../types/mod.ts"; import { Mixin } from "../../../deps.ts"; import type { GuildForumTag } from "../../../types/forum.ts"; +import { Emoji } from "../emojis/mod.ts"; import { GuildTextBasedChannel } from "./guildTextBasedChannel.ts"; import { GuildThreadAvailableChannel } from "./guildThreadAvailableChannel.ts"; @@ -8,9 +9,21 @@ export class GuildForumChannel extends Mixin( GuildThreadAvailableChannel, GuildTextBasedChannel, ) { - // get defaultReactionEmoji(): Emoji { - // TODO: add emoji - // } + get defaultReactionEmoji(): Emoji | undefined { + if (this.payload.default_reaction_emoji) { + if (this.payload.default_reaction_emoji.emoji_id !== null) { + return this.client.emojis.get( + this.payload.default_reaction_emoji.emoji_id, + ); + } else if (this.payload.default_reaction_emoji.emoji_name !== null) { + return new Emoji(this.client, { + id: null, + name: this.payload.default_reaction_emoji.emoji_name, + }); + } + } + return undefined; + } get defaultSortOrder() { return this.payload.default_auto_archive_duration; } @@ -18,11 +31,24 @@ export class GuildForumChannel extends Mixin( return this.payload.default_auto_archive_duration; } get availableTags(): GuildForumTag { + let result: Emoji; + + if (this.payload.available_tags.emoji_id !== null) { + result = this.client.emojis.get( + this.payload.available_tags.emoji_id, + )!; + } else if (this.payload.available_tags.emoji_name !== null) { + result = new Emoji(this.client, { + id: null, + name: this.payload.available_tags.emoji_name, + }); + } + return { id: this.payload.available_tags.id, name: this.payload.available_tags.name, moderated: this.payload.available_tags.moderated, - // TODO: add emoji + emoji: result!, }; } } diff --git a/framework/src/structures/channels/mod.ts b/framework/src/structures/channels/mod.ts index c64c15d8..331ac653 100644 --- a/framework/src/structures/channels/mod.ts +++ b/framework/src/structures/channels/mod.ts @@ -1,6 +1,15 @@ export * from "./channel.ts"; +export * from "./DMBasedChannel.ts"; +export * from "./DMChannel.ts"; +export * from "./groupDMChannel.ts"; +export * from "./guildAnnouncementChannel.ts"; +export * from "./guildCategory.ts"; export * from "./guildChannel.ts"; +export * from "./guildForumChannel.ts"; +export * from "./guildStageChannel.ts"; export * from "./guildTextBasedChannel.ts"; export * from "./guildTextChannel.ts"; export * from "./guildThreadAvailableChannel.ts"; +export * from "./guildVoiceBasedChannel.ts"; +export * from "./guildVoiceChannel.ts"; export * from "./textChannel.ts"; diff --git a/framework/src/structures/emojis/mod.ts b/framework/src/structures/emojis/mod.ts new file mode 100644 index 00000000..d3edf2d2 --- /dev/null +++ b/framework/src/structures/emojis/mod.ts @@ -0,0 +1,42 @@ +import { EmojiPayload } from "../../../../types/mod.ts"; +import type { Client } from "../../client/mod.ts"; +import { User } from "../users/mod.ts"; + +export class Emoji { + client: Client; + payload: EmojiPayload; + guildID?: string; + + constructor(client: Client, payload: EmojiPayload, guildID?: string) { + this.client = client; + this.payload = payload; + this.guildID = guildID; + } + + get id() { + return this.payload.id; + } + get name() { + return this.payload.name; + } + get roles() { + return this.payload.roles?.map((id) => this.client.roles.get(id)); + } + get user() { + return this.payload.user !== undefined + ? new User(this.client, this.payload.user) + : undefined; + } + get requireColons() { + return this.payload.require_colons; + } + get managed() { + return this.payload.managed; + } + get animated() { + return this.payload.animated; + } + get available() { + return this.payload.available; + } +} diff --git a/framework/src/structures/guilds/guild.ts b/framework/src/structures/guilds/guild.ts index c76ad636..0fccdfad 100644 --- a/framework/src/structures/guilds/guild.ts +++ b/framework/src/structures/guilds/guild.ts @@ -6,15 +6,20 @@ import type { VerificationLevel, } from "../../../../types/mod.ts"; import { Client } from "../../client/mod.ts"; +import { GuildEmojisManager } from "../../managers/guildEmojis.ts"; import { GuildRolesManager } from "../../managers/guildRoles.ts"; import { UnavailableGuild } from "./unavaliable.ts"; export class Guild extends UnavailableGuild { roles: GuildRolesManager; + emojis: GuildEmojisManager; constructor(client: Client, payload: GuildPayload) { + // TODO: think about fill methods super(client, payload); - this.roles = new GuildRolesManager(client, payload.id); - this.roles._fill(payload.roles); + this.roles = new GuildRolesManager(client, client.roles, payload.id); + // this.roles._fill(payload.roles); + this.emojis = new GuildEmojisManager(client, client.emojis, payload.id); + // this.emojis._fill(payload.emojis); } get name(): string { @@ -65,9 +70,6 @@ export class Guild extends UnavailableGuild { get explicitContentFilter(): ExplicitContentFilterLevel { return this.payload.explicit_content_filter; } - get emojis(): string[] { - return this.payload.emojis; - } get features(): string[] { return this.payload.features; } diff --git a/framework/types/emoji.ts b/framework/types/emoji.ts new file mode 100644 index 00000000..373054eb --- /dev/null +++ b/framework/types/emoji.ts @@ -0,0 +1,5 @@ +import type { EmojiPayload } from "../../types/mod.ts"; + +export interface EmojiPayloadWithGuildID extends EmojiPayload { + guild_id: string; +} diff --git a/framework/types/forum.ts b/framework/types/forum.ts index 3d13de00..5c3e3410 100644 --- a/framework/types/forum.ts +++ b/framework/types/forum.ts @@ -1,8 +1,8 @@ -// TODO: uncomment Emoji import when it's ready +import type { Emoji } from "../src/structures/emojis/mod.ts"; export interface GuildForumTag { id: string; name: string; moderated: boolean; - // emoji: Emoji + emoji: Emoji; }