diff --git a/src/bot.ts b/src/bot.ts index f740aa0f9..e324c61b6 100644 --- a/src/bot.ts +++ b/src/bot.ts @@ -12,6 +12,7 @@ import { DiscordGatewayIntents } from "./types/gateway/gateway_intents.ts"; import { GetGatewayBot } from "./types/gateway/get_gateway_bot.ts"; import { dispatchRequirements } from "./util/dispatch_requirements.ts"; import { processQueue } from "./rest/process_queue.ts"; +import { snowflakeToBigint } from "./util/bigint.ts"; export async function createBot(options: CreateBotOptions) { return { @@ -118,8 +119,19 @@ export type CreatedBot = UnPromise>; export type Bot = CreatedBot & { rest: RestManager; gateway: GatewayManager; + transformers: Transformers; }; +export interface Transformers { + snowflake: typeof snowflakeToBigint, +} + +export function createTransformers(options: Partial) { + return { + snowflake: options.snowflake || snowflakeToBigint, + } +} + export type RestManager = ReturnType; export interface GatewayManager {} diff --git a/src/structures/role.ts b/src/structures/role.ts deleted file mode 100644 index d6d256887..000000000 --- a/src/structures/role.ts +++ /dev/null @@ -1,189 +0,0 @@ -import { eventHandlers } from "../bot.ts"; -import { cache } from "../cache.ts"; -import { deleteRole } from "../helpers/roles/delete_role.ts"; -import { editRole } from "../helpers/roles/edit_role.ts"; -import { CreateGuildRole } from "../types/guilds/create_guild_role.ts"; -import { Errors } from "../types/discordeno/errors.ts"; -import type { Role } from "../types/permissions/role.ts"; -import { snowflakeToBigint } from "../util/bigint.ts"; -import { Collection } from "../util/collection.ts"; -import { highestRole } from "../util/permissions.ts"; -import { createNewProp } from "../util/utils.ts"; -import { DiscordenoGuild } from "./guild.ts"; -import { DiscordenoMember } from "./member.ts"; - -const ROLE_SNOWFLAKES = ["id", "botId", "integrationId", "guildId"]; - -const roleToggles = { - /** If this role is showed seperately in the user listing */ - hoist: 1n, - /** Whether this role is managed by an integration */ - managed: 2n, - /** Whether this role is mentionable */ - mentionable: 4n, - /** If this role is the nitro boost role. */ - isNitroBoostRole: 8n, -}; - -const baseRole: Partial = { - get guild() { - return cache.guilds.get(this.guildId!); - }, - get hexColor() { - return this.color!.toString(16); - }, - get members() { - return cache.members.filter((m) => m.guilds.some((g) => g.roles.includes(this.id!))); - }, - get mention() { - return `<@&${this.id}>`; - }, - - // METHODS - delete() { - return deleteRole(this.guildId!, this.id!); - }, - edit(options) { - return editRole(this.guildId!, this.id!, options); - }, - higherThanRole(roleId: bigint, position?: number) { - // If no position try and find one from cache - if (!position) position = this.guild?.roles.get(roleId)?.position; - // If still none error out. - if (!position) { - throw new Error( - "role.higherThanRoleId() did not have a position provided and the role or guild was not found in cache. Please provide a position like role.higherThanRoleId(roleId, position)" - ); - } - - // Rare edge case handling - if (this.position === position) { - return this.id! < roleId; - } - - return this.position! > position; - }, - async higherThanMember(memberId: bigint) { - const guild = this.guild; - if (!guild) throw new Error(Errors.GUILD_NOT_FOUND); - - if (guild.ownerId === memberId) return false; - - const memberHighestRole = await highestRole(guild, memberId); - return this.higherThanRole!(memberHighestRole.id, memberHighestRole.position); - }, - get hoist() { - return Boolean(this.bitfield! & roleToggles.hoist); - }, - get managed() { - return Boolean(this.bitfield! & roleToggles.managed); - }, - get mentionable() { - return Boolean(this.bitfield! & roleToggles.mentionable); - }, - get isNitroBoostRole() { - return Boolean(this.bitfield! & roleToggles.isNitroBoostRole); - }, - toJSON() { - return { - guildId: this.guildId?.toString(), - id: this.id?.toString(), - name: this.name, - color: this.color, - hoist: this.hoist, - position: this.position, - permissions: this.permissions?.toString(), - managed: this.managed, - mentionable: this.mentionable, - tags: { - botId: this.botId?.toString(), - integrationId: this.integrationId?.toString(), - premiumSubscriber: this.isNitroBoostRole, - }, - } as Role & { guildId: string }; - }, -}; - -// deno-lint-ignore require-await -export async function createDiscordenoRole( - data: { role: Role } & { - guildId: bigint; - } -) { - const { tags = {}, ...rest } = { guildId: data.guildId, ...data.role }; - - let bitfield = 0n; - - const props: Record> = {}; - for (const key of Object.keys(rest) as (keyof typeof rest)[]) { - eventHandlers.debug?.("loop", `Running for of loop in createDiscordenoRole function.`); - - const toggleBits = roleToggles[key as keyof typeof roleToggles]; - if (toggleBits) { - bitfield |= rest[key] ? toggleBits : 0n; - continue; - } - - props[key] = createNewProp( - ROLE_SNOWFLAKES.includes(key) ? (rest[key] ? snowflakeToBigint(rest[key] as string) : undefined) : rest[key] - ); - } - - if (!cache.requiredStructureProperties.roles.size || cache.requiredStructureProperties.roles.has("permissions")) - props.permissions = createNewProp(BigInt(rest.permissions)); - - if (!cache.requiredStructureProperties.roles.size || cache.requiredStructureProperties.roles.has("botId")) - props.botId = createNewProp(tags.botId ? snowflakeToBigint(tags.botId) : undefined); - - if (!cache.requiredStructureProperties.roles.size || cache.requiredStructureProperties.roles.has("isNitroBoostRole")) - props.isNitroBoostRole = createNewProp("premiumSubscriber" in tags); - - if (!cache.requiredStructureProperties.roles.size || cache.requiredStructureProperties.roles.has("integrationId")) - props.integrationId = createNewProp(tags.integrationId ? snowflakeToBigint(tags.integrationId) : undefined); - - if (!cache.requiredStructureProperties.roles.size || cache.requiredStructureProperties.roles.has("bitfield")) - props.bitfield = createNewProp(bitfield); - - return Object.create(baseRole, props) as DiscordenoRole; -} - -export interface DiscordenoRole extends Omit { - /** The role id */ - id: bigint; - /** The bot id that is associated with this role. */ - botId?: bigint; - /** If this role is the nitro boost role. */ - isNitroBoostRole: boolean; - /** The integration id that is associated with this role */ - integrationId: bigint; - /** The roles guildId */ - guildId: bigint; - /** Permission bit set */ - permissions: bigint; - /** Holds all the boolean toggles. */ - bitfield: bigint; - - // GETTERS - - /** The guild where this role is. If undefined, the guild is not cached */ - guild?: DiscordenoGuild; - /** The hex color for this role. */ - hexColor: string; - /** The cached members that have this role */ - members: Collection; - /** The @ mention of the role in a string. */ - mention: string; - - // METHODS - - /** Delete the role */ - delete(): ReturnType; - /** Edits the role */ - edit(options: CreateGuildRole): ReturnType; - /** Checks if this role is higher than another role. */ - higherThanRole(roleId: bigint, position?: number): boolean; - /** Checks if the role has a higher position than the given member */ - higherThanMember(memberId: bigint): Promise; - /** Convert to json friendly role with guild id */ - toJSON(): Role & { guildId: string }; -} diff --git a/src/structures/channel.ts b/src/transformers/channel.ts similarity index 100% rename from src/structures/channel.ts rename to src/transformers/channel.ts diff --git a/src/structures/guild.ts b/src/transformers/guild.ts similarity index 100% rename from src/structures/guild.ts rename to src/transformers/guild.ts diff --git a/src/structures/member.ts b/src/transformers/member.ts similarity index 100% rename from src/structures/member.ts rename to src/transformers/member.ts diff --git a/src/structures/message.ts b/src/transformers/message.ts similarity index 100% rename from src/structures/message.ts rename to src/transformers/message.ts diff --git a/src/structures/mod.ts b/src/transformers/mod.ts similarity index 100% rename from src/structures/mod.ts rename to src/transformers/mod.ts diff --git a/src/transformers/role.ts b/src/transformers/role.ts new file mode 100644 index 000000000..8b03e09be --- /dev/null +++ b/src/transformers/role.ts @@ -0,0 +1,203 @@ +// import { eventHandlers } from "../bot.ts"; +// import { cache } from "../cache.ts"; +// import { deleteRole } from "../helpers/roles/delete_role.ts"; +// import { editRole } from "../helpers/roles/edit_role.ts"; +// import { CreateGuildRole } from "../types/guilds/create_guild_role.ts"; +// import { Errors } from "../types/discordeno/errors.ts"; +// import type { Role } from "../types/permissions/role.ts"; +// import { snowflakeToBigint } from "../util/bigint.ts"; +// import { Collection } from "../util/collection.ts"; +// import { highestRole } from "../util/permissions.ts"; +// import { createNewProp } from "../util/utils.ts"; +// import { DiscordenoGuild } from "./guild.ts"; +// import { DiscordenoMember } from "./member.ts"; + +import { Bot } from "../bot.ts"; +import { Role } from "../types/mod.ts"; + +// const ROLE_SNOWFLAKES = ["id", "botId", "integrationId", "guildId"]; + +// const roleToggles = { +// /** If this role is showed seperately in the user listing */ +// hoist: 1n, +// /** Whether this role is managed by an integration */ +// managed: 2n, +// /** Whether this role is mentionable */ +// mentionable: 4n, +// /** If this role is the nitro boost role. */ +// isNitroBoostRole: 8n, +// }; + +// const baseRole: Partial = { +// get guild() { +// return cache.guilds.get(this.guildId!); +// }, +// get hexColor() { +// return this.color!.toString(16); +// }, +// get members() { +// return cache.members.filter((m) => m.guilds.some((g) => g.roles.includes(this.id!))); +// }, +// get mention() { +// return `<@&${this.id}>`; +// }, + +// // METHODS +// delete() { +// return deleteRole(this.guildId!, this.id!); +// }, +// edit(options) { +// return editRole(this.guildId!, this.id!, options); +// }, +// higherThanRole(roleId: bigint, position?: number) { +// // If no position try and find one from cache +// if (!position) position = this.guild?.roles.get(roleId)?.position; +// // If still none error out. +// if (!position) { +// throw new Error( +// "role.higherThanRoleId() did not have a position provided and the role or guild was not found in cache. Please provide a position like role.higherThanRoleId(roleId, position)" +// ); +// } + +// // Rare edge case handling +// if (this.position === position) { +// return this.id! < roleId; +// } + +// return this.position! > position; +// }, +// async higherThanMember(memberId: bigint) { +// const guild = this.guild; +// if (!guild) throw new Error(Errors.GUILD_NOT_FOUND); + +// if (guild.ownerId === memberId) return false; + +// const memberHighestRole = await highestRole(guild, memberId); +// return this.higherThanRole!(memberHighestRole.id, memberHighestRole.position); +// }, +// get hoist() { +// return Boolean(this.bitfield! & roleToggles.hoist); +// }, +// get managed() { +// return Boolean(this.bitfield! & roleToggles.managed); +// }, +// get mentionable() { +// return Boolean(this.bitfield! & roleToggles.mentionable); +// }, +// get isNitroBoostRole() { +// return Boolean(this.bitfield! & roleToggles.isNitroBoostRole); +// }, +// toJSON() { +// return { +// guildId: this.guildId?.toString(), +// id: this.id?.toString(), +// name: this.name, +// color: this.color, +// hoist: this.hoist, +// position: this.position, +// permissions: this.permissions?.toString(), +// managed: this.managed, +// mentionable: this.mentionable, +// tags: { +// botId: this.botId?.toString(), +// integrationId: this.integrationId?.toString(), +// premiumSubscriber: this.isNitroBoostRole, +// }, +// } as Role & { guildId: string }; +// }, +// }; + +// // deno-lint-ignore require-await +// export async function createDiscordenoRole( +// data: { role: Role } & { +// guildId: bigint; +// } +// ) { +// const { tags = {}, ...rest } = { guildId: data.guildId, ...data.role }; + +// let bitfield = 0n; + +// const props: Record> = {}; +// for (const key of Object.keys(rest) as (keyof typeof rest)[]) { +// eventHandlers.debug?.("loop", `Running for of loop in createDiscordenoRole function.`); + +// const toggleBits = roleToggles[key as keyof typeof roleToggles]; +// if (toggleBits) { +// bitfield |= rest[key] ? toggleBits : 0n; +// continue; +// } + +// props[key] = createNewProp( +// ROLE_SNOWFLAKES.includes(key) ? (rest[key] ? snowflakeToBigint(rest[key] as string) : undefined) : rest[key] +// ); +// } + +// if (!cache.requiredStructureProperties.roles.size || cache.requiredStructureProperties.roles.has("permissions")) +// props.permissions = createNewProp(BigInt(rest.permissions)); + +// if (!cache.requiredStructureProperties.roles.size || cache.requiredStructureProperties.roles.has("botId")) +// props.botId = createNewProp(tags.botId ? snowflakeToBigint(tags.botId) : undefined); + +// if (!cache.requiredStructureProperties.roles.size || cache.requiredStructureProperties.roles.has("isNitroBoostRole")) +// props.isNitroBoostRole = createNewProp("premiumSubscriber" in tags); + +// if (!cache.requiredStructureProperties.roles.size || cache.requiredStructureProperties.roles.has("integrationId")) +// props.integrationId = createNewProp(tags.integrationId ? snowflakeToBigint(tags.integrationId) : undefined); + +// if (!cache.requiredStructureProperties.roles.size || cache.requiredStructureProperties.roles.has("bitfield")) +// props.bitfield = createNewProp(bitfield); + +// return Object.create(baseRole, props) as DiscordenoRole; +// } + +export function transformRole(bot: Bot, payload: { role: Role } & { + guildId: bigint; + }) { + return { + // TODO: decide if its better to spread like this or do manually + ...payload, + id: bot.transformers.snowflake(payload.role.id), + botId: payload.role.tags?.botId ? bot.transformers.snowflake(payload.role.tags?.botId) : undefined, + } +} + +export interface DiscordenoRole extends Omit { + /** The role id */ + id: bigint; + /** The bot id that is associated with this role. */ + botId?: bigint; + /** If this role is the nitro boost role. */ + isNitroBoostRole: boolean; + /** The integration id that is associated with this role */ + integrationId: bigint; + /** The roles guildId */ + guildId: bigint; + /** Permission bit set */ + permissions: bigint; + /** Holds all the boolean toggles. */ + bitfield: bigint; + + // GETTERS + + /** The guild where this role is. If undefined, the guild is not cached */ + guild?: DiscordenoGuild; + /** The hex color for this role. */ + hexColor: string; + /** The cached members that have this role */ + members: Collection; + /** The @ mention of the role in a string. */ + mention: string; + + // METHODS + + /** Delete the role */ + delete(): ReturnType; + /** Edits the role */ + edit(options: CreateGuildRole): ReturnType; + /** Checks if this role is higher than another role. */ + higherThanRole(roleId: bigint, position?: number): boolean; + /** Checks if the role has a higher position than the given member */ + higherThanMember(memberId: bigint): Promise; + /** Convert to json friendly role with guild id */ + toJSON(): Role & { guildId: string }; +} diff --git a/src/structures/voice_state.ts b/src/transformers/voice_state.ts similarity index 100% rename from src/structures/voice_state.ts rename to src/transformers/voice_state.ts