diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 42ad9a86c..609f329d2 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -1,7 +1,7 @@ # Contributing - Read the [style guide](#style-guide). -- Ask for help on the [official Discord server](https:) +- Ask for help on the [official Discord server](https://discord.gg/5vBgXk3UcZ) - If you are going to work on an issue, mention so in the issue comments before you start working on the issue. - If you are going to work on a new feature, create an issue and discuss with @@ -38,10 +38,9 @@ ## Types Guide -- Must use snake case (according to Discord API). +- Must use camel case (same property name as in the docs just in camel case). - Each field or property must be accompanied with a reasonable JSDoc comment right above its type definition. -- The name of the type must be prefixed with `Discord`. - Must be placed inside of the types module (in `src/types` directory). Example: @@ -61,6 +60,4 @@ export interface User { flags?: number; premiumType?: number; } - -export type DiscordUser = SnakeCasedPropertiesDeep; ``` diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1483334c6..3f5f034af 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -18,8 +18,10 @@ jobs: if: ${{ github.actor == 'Skillz4Killz' || github.actor == 'itohatweb' }} run: deno test --unstable --coverage=coverage -A tests/mod.ts - name: Create coverage report + if: github.ref == 'refs/heads/main' run: deno --unstable coverage ./coverage --lcov > coverage.lcov - name: Collect and upload the coverage report + if: github.ref == 'refs/heads/main' uses: codecov/codecov-action@v1.0.10 with: file: ./coverage.lcov diff --git a/README.md b/README.md index 66aac30ef..5d456f74f 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ import { startBot } from "https://deno.land/x/discordeno/mod.ts"; startBot({ token: "BOT TOKEN", - intents: ["GUILDS", "GUILD_MESSAGES"], + intents: ["Guilds", "GuildMessages"], eventHandlers: { ready() { console.log("Successfully connected to gateway"); diff --git a/src/bot.ts b/src/bot.ts index f23043674..ae0dc92ff 100644 --- a/src/bot.ts +++ b/src/bot.ts @@ -1,6 +1,6 @@ import { getGatewayBot } from "./helpers/misc/get_gateway_bot.ts"; import { rest } from "./rest/rest.ts"; -import { EventHandlers } from "./types/discordeno/eventHandlers.ts"; +import type { EventHandlers } from "./types/discordeno/eventHandlers.ts"; import { DiscordGatewayIntents } from "./types/gateway/gateway_intents.ts"; import { snowflakeToBigint } from "./util/bigint.ts"; import { baseEndpoints, GATEWAY_VERSION } from "./util/constants.ts"; diff --git a/src/cache.ts b/src/cache.ts index 3beadbb7b..3abdab3c9 100644 --- a/src/cache.ts +++ b/src/cache.ts @@ -1,10 +1,10 @@ // deno-lint-ignore-file require-await no-explicit-any prefer-const -import { DiscordenoChannel } from "./structures/channel.ts"; -import { DiscordenoGuild } from "./structures/guild.ts"; -import { DiscordenoMember } from "./structures/member.ts"; -import { DiscordenoMessage } from "./structures/message.ts"; -import { Emoji } from "./types/emojis/emoji.ts"; -import { PresenceUpdate } from "./types/misc/presence_update.ts"; +import type { DiscordenoChannel } from "./structures/channel.ts"; +import type { DiscordenoGuild } from "./structures/guild.ts"; +import type { DiscordenoMember } from "./structures/member.ts"; +import type { DiscordenoMessage } from "./structures/message.ts"; +import type { PresenceUpdate } from "./types/activity/presence_update.ts"; +import type { Emoji } from "./types/emojis/emoji.ts"; import { Collection } from "./util/collection.ts"; export const cache = { diff --git a/src/handlers/channels/CHANNEL_CREATE.ts b/src/handlers/channels/CHANNEL_CREATE.ts index 135dbc0d9..679241f19 100644 --- a/src/handlers/channels/CHANNEL_CREATE.ts +++ b/src/handlers/channels/CHANNEL_CREATE.ts @@ -1,8 +1,8 @@ import { eventHandlers } from "../../bot.ts"; import { cacheHandlers } from "../../cache.ts"; import { structures } from "../../structures/mod.ts"; -import { Channel } from "../../types/channels/channel.ts"; -import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; +import type { Channel } from "../../types/channels/channel.ts"; +import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; export async function handleChannelCreate(data: DiscordGatewayPayload) { const payload = data.d as Channel; diff --git a/src/handlers/channels/CHANNEL_DELETE.ts b/src/handlers/channels/CHANNEL_DELETE.ts index 1b226370b..a2e07b828 100644 --- a/src/handlers/channels/CHANNEL_DELETE.ts +++ b/src/handlers/channels/CHANNEL_DELETE.ts @@ -1,8 +1,8 @@ import { eventHandlers } from "../../bot.ts"; import { cacheHandlers } from "../../cache.ts"; -import { Channel } from "../../types/channels/channel.ts"; +import type { Channel } from "../../types/channels/channel.ts"; import { DiscordChannelTypes } from "../../types/channels/channel_types.ts"; -import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; +import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; import { snowflakeToBigint } from "../../util/bigint.ts"; export async function handleChannelDelete(data: DiscordGatewayPayload) { @@ -15,7 +15,7 @@ export async function handleChannelDelete(data: DiscordGatewayPayload) { if (!cachedChannel) return; if ( - cachedChannel.type === DiscordChannelTypes.GUILD_VOICE && payload.guildId + cachedChannel.type === DiscordChannelTypes.GuildVoice && payload.guildId ) { const guild = await cacheHandlers.get("guilds", cachedChannel.guildId); @@ -34,15 +34,27 @@ export async function handleChannelDelete(data: DiscordGatewayPayload) { } } + if ( + [ + DiscordChannelTypes.GuildText, + DiscordChannelTypes.DM, + DiscordChannelTypes.GroupDm, + DiscordChannelTypes.GuildNews, + ].includes(payload.type) + ) { + await cacheHandlers.delete("channels", snowflakeToBigint(payload.id)); + cacheHandlers.forEach("messages", (message) => { + eventHandlers.debug?.( + "loop", + `Running forEach messages loop in CHANNEL_DELTE file.`, + ); + if (message.channelId === snowflakeToBigint(payload.id)) { + cacheHandlers.delete("messages", message.id); + } + }); + } + await cacheHandlers.delete("channels", snowflakeToBigint(payload.id)); - cacheHandlers.forEach("messages", (message) => { - eventHandlers.debug?.( - "loop", - `Running forEach messages loop in CHANNEL_DELTE file.`, - ); - if (message.channelId === snowflakeToBigint(payload.id)) { - cacheHandlers.delete("messages", message.id); - } - }); + eventHandlers.channelDelete?.(cachedChannel); } diff --git a/src/handlers/channels/CHANNEL_PINS_UPDATE.ts b/src/handlers/channels/CHANNEL_PINS_UPDATE.ts index b5570bc2e..529e33195 100644 --- a/src/handlers/channels/CHANNEL_PINS_UPDATE.ts +++ b/src/handlers/channels/CHANNEL_PINS_UPDATE.ts @@ -1,7 +1,7 @@ import { eventHandlers } from "../../bot.ts"; import { cacheHandlers } from "../../cache.ts"; -import { ChannelPinsUpdate } from "../../types/channels/channel_pins_update.ts"; -import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; +import type { ChannelPinsUpdate } from "../../types/channels/channel_pins_update.ts"; +import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; import { snowflakeToBigint } from "../../util/bigint.ts"; export async function handleChannelPinsUpdate(data: DiscordGatewayPayload) { diff --git a/src/handlers/channels/CHANNEL_UPDATE.ts b/src/handlers/channels/CHANNEL_UPDATE.ts index 624eaaf70..59a0d8693 100644 --- a/src/handlers/channels/CHANNEL_UPDATE.ts +++ b/src/handlers/channels/CHANNEL_UPDATE.ts @@ -1,8 +1,8 @@ import { eventHandlers } from "../../bot.ts"; import { cacheHandlers } from "../../cache.ts"; import { structures } from "../../structures/mod.ts"; -import { Channel } from "../../types/channels/channel.ts"; -import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; +import type { Channel } from "../../types/channels/channel.ts"; +import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; import { snowflakeToBigint } from "../../util/bigint.ts"; export async function handleChannelUpdate(data: DiscordGatewayPayload) { @@ -11,11 +11,10 @@ export async function handleChannelUpdate(data: DiscordGatewayPayload) { "channels", snowflakeToBigint(payload.id), ); + if (!cachedChannel) return; const discordenoChannel = await structures.createDiscordenoChannel(payload); await cacheHandlers.set("channels", discordenoChannel.id, discordenoChannel); - if (!cachedChannel) return; - eventHandlers.channelUpdate?.(discordenoChannel, cachedChannel); } diff --git a/src/handlers/channels/THREAD_CREATE.ts b/src/handlers/channels/THREAD_CREATE.ts new file mode 100644 index 000000000..ac24436b5 --- /dev/null +++ b/src/handlers/channels/THREAD_CREATE.ts @@ -0,0 +1,14 @@ +import { eventHandlers } from "../../bot.ts"; +import { cacheHandlers } from "../../cache.ts"; +import { structures } from "../../structures/mod.ts"; +import { Channel } from "../../types/channels/channel.ts"; +import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; + +export async function handleThreadCreate(data: DiscordGatewayPayload) { + const payload = data.d as Channel; + + const discordenoChannel = await structures.createDiscordenoChannel(payload); + await cacheHandlers.set("channels", discordenoChannel.id, discordenoChannel); + + eventHandlers.threadCreate?.(discordenoChannel); +} diff --git a/src/handlers/channels/THREAD_DELETE.ts b/src/handlers/channels/THREAD_DELETE.ts new file mode 100644 index 000000000..e4c2b4d87 --- /dev/null +++ b/src/handlers/channels/THREAD_DELETE.ts @@ -0,0 +1,28 @@ +import { eventHandlers } from "../../bot.ts"; +import { cacheHandlers } from "../../cache.ts"; +import { Channel } from "../../types/channels/channel.ts"; +import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; +import { snowflakeToBigint } from "../../util/bigint.ts"; + +export async function handleThreadDelete(data: DiscordGatewayPayload) { + const payload = data.d as Channel; + + const cachedChannel = await cacheHandlers.get( + "channels", + snowflakeToBigint(payload.id), + ); + if (!cachedChannel) return; + + await cacheHandlers.delete("channels", snowflakeToBigint(payload.id)); + cacheHandlers.forEach("messages", (message) => { + eventHandlers.debug?.( + "loop", + `Running forEach messages loop in CHANNEL_DELTE file.`, + ); + if (message.channelId === snowflakeToBigint(payload.id)) { + cacheHandlers.delete("messages", message.id); + } + }); + + eventHandlers.threadDelete?.(cachedChannel); +} diff --git a/src/handlers/channels/THREAD_LIST_SYNC.ts b/src/handlers/channels/THREAD_LIST_SYNC.ts new file mode 100644 index 000000000..aedcab173 --- /dev/null +++ b/src/handlers/channels/THREAD_LIST_SYNC.ts @@ -0,0 +1,39 @@ +import { eventHandlers } from "../../bot.ts"; +import { cacheHandlers } from "../../cache.ts"; +import { DiscordenoChannel } from "../../structures/channel.ts"; +import { structures } from "../../structures/mod.ts"; +import { ThreadListSync } from "../../types/channels/threads/thread_list_sync.ts"; +import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; +import { snowflakeToBigint } from "../../util/bigint.ts"; +import { Collection } from "../../util/collection.ts"; + +export async function handleThreadListSync(data: DiscordGatewayPayload) { + const payload = data.d as ThreadListSync; + + const discordenoChannels = await Promise.all( + payload.threads.map(async (thread) => { + const discordenoChannel = await structures.createDiscordenoChannel( + thread, + snowflakeToBigint(payload.guildId), + ); + + await cacheHandlers.set( + "channels", + discordenoChannel.id, + discordenoChannel, + ); + + return discordenoChannel; + }), + ); + + const threads = new Collection( + discordenoChannels.map((t) => [t.id, t]), + ); + + eventHandlers.threadListSync?.( + threads, + payload.members, + snowflakeToBigint(payload.guildId), + ); +} diff --git a/src/handlers/channels/THREAD_MEMBERS_UPDATE.ts b/src/handlers/channels/THREAD_MEMBERS_UPDATE.ts new file mode 100644 index 000000000..b614f143e --- /dev/null +++ b/src/handlers/channels/THREAD_MEMBERS_UPDATE.ts @@ -0,0 +1,19 @@ +import { eventHandlers } from "../../bot.ts"; +import { cacheHandlers } from "../../cache.ts"; +import { ThreadMembersUpdate } from "../../types/channels/threads/thread_members_update.ts"; +import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; +import { snowflakeToBigint } from "../../util/bigint.ts"; + +export async function handleThreadMembersUpdate(data: DiscordGatewayPayload) { + const payload = data.d as ThreadMembersUpdate; + const thread = await cacheHandlers.get( + "channels", + snowflakeToBigint(payload.id), + ); + if (!thread) return; + + thread.memberCount = payload.memberCount; + await cacheHandlers.set("channels", thread.id, thread); + + eventHandlers.threadMembersUpdate?.(payload); +} diff --git a/src/handlers/channels/THREAD_MEMBER_UPDATE.ts b/src/handlers/channels/THREAD_MEMBER_UPDATE.ts new file mode 100644 index 000000000..a25490523 --- /dev/null +++ b/src/handlers/channels/THREAD_MEMBER_UPDATE.ts @@ -0,0 +1,20 @@ +import { eventHandlers } from "../../bot.ts"; +import { cacheHandlers } from "../../cache.ts"; +import { ThreadMember } from "../../types/channels/threads/thread_member.ts"; +import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; +import { snowflakeToBigint } from "../../util/bigint.ts"; + +export async function handleThreadMemberUpdate(data: DiscordGatewayPayload) { + const payload = data.d as ThreadMember; + const thread = await cacheHandlers.get( + "channels", + snowflakeToBigint(payload.id), + ); + if (!thread) return; + + thread.member = payload; + + await cacheHandlers.set("channels", thread.id, thread); + + eventHandlers.threadMemberUpdate?.(payload); +} diff --git a/src/handlers/channels/THREAD_UPDATE.ts b/src/handlers/channels/THREAD_UPDATE.ts new file mode 100644 index 000000000..1e3ae12d0 --- /dev/null +++ b/src/handlers/channels/THREAD_UPDATE.ts @@ -0,0 +1,20 @@ +import { eventHandlers } from "../../bot.ts"; +import { cacheHandlers } from "../../cache.ts"; +import { structures } from "../../structures/mod.ts"; +import { Channel } from "../../types/channels/channel.ts"; +import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; +import { snowflakeToBigint } from "../../util/bigint.ts"; + +export async function handleThreadUpdate(data: DiscordGatewayPayload) { + const payload = data.d as Channel; + const oldChannel = await cacheHandlers.get( + "channels", + snowflakeToBigint(payload.id), + ); + if (!oldChannel) return; + + const discordenoChannel = await structures.createDiscordenoChannel(payload); + await cacheHandlers.set("channels", discordenoChannel.id, discordenoChannel); + + eventHandlers.threadUpdate?.(discordenoChannel, oldChannel); +} diff --git a/src/handlers/commands/APPLICATION_COMMAND_CREATE.ts b/src/handlers/commands/APPLICATION_COMMAND_CREATE.ts index 2ceae936b..bcfa4270e 100644 --- a/src/handlers/commands/APPLICATION_COMMAND_CREATE.ts +++ b/src/handlers/commands/APPLICATION_COMMAND_CREATE.ts @@ -1,8 +1,8 @@ import { eventHandlers } from "../../bot.ts"; -import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; -import { +import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; +import type { ApplicationCommandCreateUpdateDelete, -} from "../../types/interactions/application_command_create_update_delete.ts"; +} from "../../types/interactions/commands/application_command_create_update_delete.ts"; export function handleApplicationCommandCreate( data: DiscordGatewayPayload, diff --git a/src/handlers/commands/APPLICATION_COMMAND_DELETE.ts b/src/handlers/commands/APPLICATION_COMMAND_DELETE.ts index 63d96b23e..5a9fe3e23 100644 --- a/src/handlers/commands/APPLICATION_COMMAND_DELETE.ts +++ b/src/handlers/commands/APPLICATION_COMMAND_DELETE.ts @@ -1,8 +1,8 @@ import { eventHandlers } from "../../bot.ts"; -import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; -import { +import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; +import type { ApplicationCommandCreateUpdateDelete, -} from "../../types/interactions/application_command_create_update_delete.ts"; +} from "../../types/interactions/commands/application_command_create_update_delete.ts"; export function handleApplicationCommandDelete(data: DiscordGatewayPayload) { eventHandlers.applicationCommandDelete?.( diff --git a/src/handlers/commands/APPLICATION_COMMAND_UPDATE.ts b/src/handlers/commands/APPLICATION_COMMAND_UPDATE.ts index ad9ffde28..b1940c91c 100644 --- a/src/handlers/commands/APPLICATION_COMMAND_UPDATE.ts +++ b/src/handlers/commands/APPLICATION_COMMAND_UPDATE.ts @@ -1,8 +1,8 @@ import { eventHandlers } from "../../bot.ts"; -import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; -import { +import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; +import type { ApplicationCommandCreateUpdateDelete, -} from "../../types/interactions/application_command_create_update_delete.ts"; +} from "../../types/interactions/commands/application_command_create_update_delete.ts"; export function handleApplicationCommandUpdate(data: DiscordGatewayPayload) { eventHandlers.applicationCommandUpdate?.( diff --git a/src/handlers/emojis/GUILD_EMOJIS_UPDATE.ts b/src/handlers/emojis/GUILD_EMOJIS_UPDATE.ts index bbb1c817d..04dba3335 100644 --- a/src/handlers/emojis/GUILD_EMOJIS_UPDATE.ts +++ b/src/handlers/emojis/GUILD_EMOJIS_UPDATE.ts @@ -1,7 +1,7 @@ import { eventHandlers } from "../../bot.ts"; import { cacheHandlers } from "../../cache.ts"; -import { GuildEmojisUpdate } from "../../types/emojis/guild_emojis_update.ts"; -import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; +import type { GuildEmojisUpdate } from "../../types/emojis/guild_emojis_update.ts"; +import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; import { snowflakeToBigint } from "../../util/bigint.ts"; import { Collection } from "../../util/collection.ts"; diff --git a/src/handlers/guilds/GUILD_BAN_ADD.ts b/src/handlers/guilds/GUILD_BAN_ADD.ts index 70d233ff0..584369503 100644 --- a/src/handlers/guilds/GUILD_BAN_ADD.ts +++ b/src/handlers/guilds/GUILD_BAN_ADD.ts @@ -1,7 +1,7 @@ import { eventHandlers } from "../../bot.ts"; import { cacheHandlers } from "../../cache.ts"; -import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; -import { GuildBanAddRemove } from "../../types/guilds/guild_ban_add_remove.ts"; +import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; +import type { GuildBanAddRemove } from "../../types/guilds/guild_ban_add_remove.ts"; import { snowflakeToBigint } from "../../util/bigint.ts"; export async function handleGuildBanAdd(data: DiscordGatewayPayload) { diff --git a/src/handlers/guilds/GUILD_BAN_REMOVE.ts b/src/handlers/guilds/GUILD_BAN_REMOVE.ts index eb588bd2c..8e7805fbe 100644 --- a/src/handlers/guilds/GUILD_BAN_REMOVE.ts +++ b/src/handlers/guilds/GUILD_BAN_REMOVE.ts @@ -1,7 +1,7 @@ import { eventHandlers } from "../../bot.ts"; import { cacheHandlers } from "../../cache.ts"; -import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; -import { GuildBanAddRemove } from "../../types/guilds/guild_ban_add_remove.ts"; +import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; +import type { GuildBanAddRemove } from "../../types/guilds/guild_ban_add_remove.ts"; import { snowflakeToBigint } from "../../util/bigint.ts"; export async function handleGuildBanRemove(data: DiscordGatewayPayload) { diff --git a/src/handlers/guilds/GUILD_CREATE.ts b/src/handlers/guilds/GUILD_CREATE.ts index a9cc05791..3c62e57ea 100644 --- a/src/handlers/guilds/GUILD_CREATE.ts +++ b/src/handlers/guilds/GUILD_CREATE.ts @@ -1,8 +1,8 @@ import { eventHandlers } from "../../bot.ts"; import { cache, cacheHandlers } from "../../cache.ts"; import { structures } from "../../structures/mod.ts"; -import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; -import { Guild } from "../../types/guilds/guild.ts"; +import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; +import type { Guild } from "../../types/guilds/guild.ts"; import { snowflakeToBigint } from "../../util/bigint.ts"; import { ws } from "../../ws/ws.ts"; diff --git a/src/handlers/guilds/GUILD_DELETE.ts b/src/handlers/guilds/GUILD_DELETE.ts index 5b32388e8..ea30c220b 100644 --- a/src/handlers/guilds/GUILD_DELETE.ts +++ b/src/handlers/guilds/GUILD_DELETE.ts @@ -1,7 +1,7 @@ import { eventHandlers } from "../../bot.ts"; import { cacheHandlers } from "../../cache.ts"; -import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; -import { UnavailableGuild } from "../../types/guilds/unavailable_guild.ts"; +import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; +import type { UnavailableGuild } from "../../types/guilds/unavailable_guild.ts"; import { snowflakeToBigint } from "../../util/bigint.ts"; import { ws } from "../../ws/ws.ts"; diff --git a/src/handlers/guilds/GUILD_INTEGRATIONS_UPDATE.ts b/src/handlers/guilds/GUILD_INTEGRATIONS_UPDATE.ts index 36b013ec6..0175c6843 100644 --- a/src/handlers/guilds/GUILD_INTEGRATIONS_UPDATE.ts +++ b/src/handlers/guilds/GUILD_INTEGRATIONS_UPDATE.ts @@ -1,7 +1,7 @@ import { eventHandlers } from "../../bot.ts"; import { cacheHandlers } from "../../cache.ts"; -import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; -import { GuildIntegrationsUpdate } from "../../types/integration/guild_integrations_update.ts"; +import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; +import type { GuildIntegrationsUpdate } from "../../types/integrations/guild_integrations_update.ts"; import { snowflakeToBigint } from "../../util/bigint.ts"; export async function handleGuildIntegrationsUpdate( diff --git a/src/handlers/guilds/GUILD_UPDATE.ts b/src/handlers/guilds/GUILD_UPDATE.ts index 9504e9df0..173337717 100644 --- a/src/handlers/guilds/GUILD_UPDATE.ts +++ b/src/handlers/guilds/GUILD_UPDATE.ts @@ -1,8 +1,8 @@ import { eventHandlers } from "../../bot.ts"; import { cacheHandlers } from "../../cache.ts"; -import { GuildUpdateChange } from "../../types/discordeno/guild_update_change.ts"; -import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; -import { Guild } from "../../types/guilds/guild.ts"; +import type { GuildUpdateChange } from "../../types/discordeno/guild_update_change.ts"; +import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; +import type { Guild } from "../../types/guilds/guild.ts"; import { snowflakeToBigint } from "../../util/bigint.ts"; export async function handleGuildUpdate(data: DiscordGatewayPayload) { diff --git a/src/handlers/integrations/INTEGRATION_CREATE.ts b/src/handlers/integrations/INTEGRATION_CREATE.ts index 1f6aede60..7b6f31937 100644 --- a/src/handlers/integrations/INTEGRATION_CREATE.ts +++ b/src/handlers/integrations/INTEGRATION_CREATE.ts @@ -1,8 +1,8 @@ import { eventHandlers } from "../../bot.ts"; -import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; -import { +import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; +import type { IntegrationCreateUpdate, -} from "../../types/integration/integration_create_update.ts"; +} from "../../types/integrations/integration_create_update.ts"; export function handleIntegrationCreate( data: DiscordGatewayPayload, diff --git a/src/handlers/integrations/INTEGRATION_DELETE.ts b/src/handlers/integrations/INTEGRATION_DELETE.ts index 1718d2a3c..207bf339a 100644 --- a/src/handlers/integrations/INTEGRATION_DELETE.ts +++ b/src/handlers/integrations/INTEGRATION_DELETE.ts @@ -1,6 +1,6 @@ import { eventHandlers } from "../../bot.ts"; -import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; -import { IntegrationDelete } from "../../types/integration/integration_delete.ts"; +import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; +import type { IntegrationDelete } from "../../types/integrations/integration_delete.ts"; export function handleIntegrationDelete(data: DiscordGatewayPayload) { eventHandlers.integrationDelete?.( diff --git a/src/handlers/integrations/INTEGRATION_UPDATE.ts b/src/handlers/integrations/INTEGRATION_UPDATE.ts index c756ee2b3..d9953a982 100644 --- a/src/handlers/integrations/INTEGRATION_UPDATE.ts +++ b/src/handlers/integrations/INTEGRATION_UPDATE.ts @@ -1,8 +1,8 @@ import { eventHandlers } from "../../bot.ts"; -import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; -import { +import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; +import type { IntegrationCreateUpdate, -} from "../../types/integration/integration_create_update.ts"; +} from "../../types/integrations/integration_create_update.ts"; export function handleIntegrationUpdate(data: DiscordGatewayPayload) { eventHandlers.integrationUpdate?.( diff --git a/src/handlers/interactions/INTERACTION_CREATE.ts b/src/handlers/interactions/INTERACTION_CREATE.ts index 026af104c..6ce6996ec 100644 --- a/src/handlers/interactions/INTERACTION_CREATE.ts +++ b/src/handlers/interactions/INTERACTION_CREATE.ts @@ -1,9 +1,9 @@ import { eventHandlers } from "../../bot.ts"; import { cacheHandlers } from "../../cache.ts"; import { structures } from "../../structures/mod.ts"; -import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; -import { GuildMemberWithUser } from "../../types/guilds/guild_member.ts"; -import { Interaction } from "../../types/interactions/interaction.ts"; +import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; +import type { Interaction } from "../../types/interactions/interaction.ts"; +import type { GuildMemberWithUser } from "../../types/members/guild_member.ts"; import { snowflakeToBigint } from "../../util/bigint.ts"; export async function handleInteractionCreate(data: DiscordGatewayPayload) { diff --git a/src/handlers/invites/INVITE_CREATE.ts b/src/handlers/invites/INVITE_CREATE.ts index bb5a4d8c7..44ffec43f 100644 --- a/src/handlers/invites/INVITE_CREATE.ts +++ b/src/handlers/invites/INVITE_CREATE.ts @@ -1,6 +1,6 @@ import { eventHandlers } from "../../bot.ts"; -import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; -import { InviteCreate } from "../../types/invites/invite_create.ts"; +import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; +import type { InviteCreate } from "../../types/invites/invite_create.ts"; export function handleInviteCreate(data: DiscordGatewayPayload) { eventHandlers.inviteCreate?.( diff --git a/src/handlers/invites/INVITE_DELETE.ts b/src/handlers/invites/INVITE_DELETE.ts index 6c7b137a8..2f09e6f52 100644 --- a/src/handlers/invites/INVITE_DELETE.ts +++ b/src/handlers/invites/INVITE_DELETE.ts @@ -1,6 +1,6 @@ import { eventHandlers } from "../../bot.ts"; -import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; -import { InviteDelete } from "../../types/invites/invite_delete.ts"; +import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; +import type { InviteDelete } from "../../types/invites/invite_delete.ts"; export function handleInviteDelete(data: DiscordGatewayPayload) { eventHandlers.inviteDelete?.( diff --git a/src/handlers/members/GUILD_MEMBERS_CHUNK.ts b/src/handlers/members/GUILD_MEMBERS_CHUNK.ts index f1b76e556..65d1eeb76 100644 --- a/src/handlers/members/GUILD_MEMBERS_CHUNK.ts +++ b/src/handlers/members/GUILD_MEMBERS_CHUNK.ts @@ -1,7 +1,7 @@ import { cache, cacheHandlers } from "../../cache.ts"; import { structures } from "../../structures/mod.ts"; -import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; -import { GuildMembersChunk } from "../../types/members/guild_members_chunk.ts"; +import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; +import type { GuildMembersChunk } from "../../types/members/guild_members_chunk.ts"; import { snowflakeToBigint } from "../../util/bigint.ts"; import { Collection } from "../../util/collection.ts"; diff --git a/src/handlers/members/GUILD_MEMBER_ADD.ts b/src/handlers/members/GUILD_MEMBER_ADD.ts index 7743d3d75..8e6e597de 100644 --- a/src/handlers/members/GUILD_MEMBER_ADD.ts +++ b/src/handlers/members/GUILD_MEMBER_ADD.ts @@ -1,8 +1,8 @@ import { eventHandlers } from "../../bot.ts"; import { cacheHandlers } from "../../cache.ts"; import { structures } from "../../structures/mod.ts"; -import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; -import { GuildMemberAdd } from "../../types/members/guild_member_add.ts"; +import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; +import type { GuildMemberAdd } from "../../types/members/guild_member_add.ts"; import { snowflakeToBigint } from "../../util/bigint.ts"; export async function handleGuildMemberAdd(data: DiscordGatewayPayload) { diff --git a/src/handlers/members/GUILD_MEMBER_REMOVE.ts b/src/handlers/members/GUILD_MEMBER_REMOVE.ts index 9a18461f0..dfc051200 100644 --- a/src/handlers/members/GUILD_MEMBER_REMOVE.ts +++ b/src/handlers/members/GUILD_MEMBER_REMOVE.ts @@ -1,7 +1,7 @@ import { eventHandlers } from "../../bot.ts"; import { cacheHandlers } from "../../cache.ts"; -import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; -import { GuildMemberRemove } from "../../types/members/guild_member_remove.ts"; +import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; +import type { GuildMemberRemove } from "../../types/members/guild_member_remove.ts"; import { snowflakeToBigint } from "../../util/bigint.ts"; export async function handleGuildMemberRemove(data: DiscordGatewayPayload) { diff --git a/src/handlers/members/GUILD_MEMBER_UPDATE.ts b/src/handlers/members/GUILD_MEMBER_UPDATE.ts index 05c4f5a38..72185ddb8 100644 --- a/src/handlers/members/GUILD_MEMBER_UPDATE.ts +++ b/src/handlers/members/GUILD_MEMBER_UPDATE.ts @@ -1,8 +1,8 @@ import { eventHandlers } from "../../bot.ts"; import { cacheHandlers } from "../../cache.ts"; import { structures } from "../../structures/mod.ts"; -import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; -import { GuildMemberUpdate } from "../../types/members/guild_member_update.ts"; +import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; +import type { GuildMemberUpdate } from "../../types/members/guild_member_update.ts"; import { bigintToSnowflake, snowflakeToBigint } from "../../util/bigint.ts"; export async function handleGuildMemberUpdate(data: DiscordGatewayPayload) { diff --git a/src/handlers/messages/MESSAGE_CREATE.ts b/src/handlers/messages/MESSAGE_CREATE.ts index 51d6856cc..2f9dbfb8a 100644 --- a/src/handlers/messages/MESSAGE_CREATE.ts +++ b/src/handlers/messages/MESSAGE_CREATE.ts @@ -1,9 +1,9 @@ import { eventHandlers } from "../../bot.ts"; import { cacheHandlers } from "../../cache.ts"; import { structures } from "../../structures/mod.ts"; -import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; -import { GuildMemberWithUser } from "../../types/guilds/guild_member.ts"; -import { Message } from "../../types/messages/message.ts"; +import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; +import type { GuildMemberWithUser } from "../../types/members/guild_member.ts"; +import type { Message } from "../../types/messages/message.ts"; import { snowflakeToBigint } from "../../util/bigint.ts"; export async function handleMessageCreate(data: DiscordGatewayPayload) { diff --git a/src/handlers/messages/MESSAGE_DELETE.ts b/src/handlers/messages/MESSAGE_DELETE.ts index 078d6cfb2..89430f202 100644 --- a/src/handlers/messages/MESSAGE_DELETE.ts +++ b/src/handlers/messages/MESSAGE_DELETE.ts @@ -1,7 +1,7 @@ import { eventHandlers } from "../../bot.ts"; import { cacheHandlers } from "../../cache.ts"; -import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; -import { MessageDelete } from "../../types/messages/message_delete.ts"; +import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; +import type { MessageDelete } from "../../types/messages/message_delete.ts"; import { snowflakeToBigint } from "../../util/bigint.ts"; export async function handleMessageDelete(data: DiscordGatewayPayload) { diff --git a/src/handlers/messages/MESSAGE_DELETE_BULK.ts b/src/handlers/messages/MESSAGE_DELETE_BULK.ts index f5b5ad680..2b585d338 100644 --- a/src/handlers/messages/MESSAGE_DELETE_BULK.ts +++ b/src/handlers/messages/MESSAGE_DELETE_BULK.ts @@ -1,7 +1,7 @@ import { eventHandlers } from "../../bot.ts"; import { cacheHandlers } from "../../cache.ts"; -import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; -import { MessageDeleteBulk } from "../../types/messages/message_delete_bulk.ts"; +import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; +import type { MessageDeleteBulk } from "../../types/messages/message_delete_bulk.ts"; import { snowflakeToBigint } from "../../util/bigint.ts"; export async function handleMessageDeleteBulk(data: DiscordGatewayPayload) { diff --git a/src/handlers/messages/MESSAGE_REACTION_ADD.ts b/src/handlers/messages/MESSAGE_REACTION_ADD.ts index ec6871a73..8dc959bae 100644 --- a/src/handlers/messages/MESSAGE_REACTION_ADD.ts +++ b/src/handlers/messages/MESSAGE_REACTION_ADD.ts @@ -1,12 +1,11 @@ import { botId, eventHandlers } from "../../bot.ts"; import { cacheHandlers } from "../../cache.ts"; import { structures } from "../../structures/mod.ts"; -import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; -import { +import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; +import type { MessageReactionAdd, } from "../../types/messages/message_reaction_add.ts"; import { snowflakeToBigint } from "../../util/bigint.ts"; -import { snakeKeysToCamelCase } from "../../util/utils.ts"; export async function handleMessageReactionAdd(data: DiscordGatewayPayload) { const payload = data.d as MessageReactionAdd; @@ -56,7 +55,7 @@ export async function handleMessageReactionAdd(data: DiscordGatewayPayload) { } eventHandlers.reactionAdd?.( - snakeKeysToCamelCase(payload), + payload, message, ); } diff --git a/src/handlers/messages/MESSAGE_REACTION_REMOVE.ts b/src/handlers/messages/MESSAGE_REACTION_REMOVE.ts index 652baa592..59c5d77ef 100644 --- a/src/handlers/messages/MESSAGE_REACTION_REMOVE.ts +++ b/src/handlers/messages/MESSAGE_REACTION_REMOVE.ts @@ -1,7 +1,7 @@ import { eventHandlers } from "../../bot.ts"; import { cacheHandlers } from "../../cache.ts"; -import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; -import { +import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; +import type { MessageReactionRemove, } from "../../types/messages/message_reaction_remove.ts"; import { snowflakeToBigint } from "../../util/bigint.ts"; diff --git a/src/handlers/messages/MESSAGE_REACTION_REMOVE_ALL.ts b/src/handlers/messages/MESSAGE_REACTION_REMOVE_ALL.ts index 0cb0088ed..81b365241 100644 --- a/src/handlers/messages/MESSAGE_REACTION_REMOVE_ALL.ts +++ b/src/handlers/messages/MESSAGE_REACTION_REMOVE_ALL.ts @@ -1,7 +1,7 @@ import { eventHandlers } from "../../bot.ts"; import { cacheHandlers } from "../../cache.ts"; -import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; -import { +import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; +import type { MessageReactionRemoveAll, } from "../../types/messages/message_reaction_remove_all.ts"; import { snowflakeToBigint } from "../../util/bigint.ts"; diff --git a/src/handlers/messages/MESSAGE_REACTION_REMOVE_EMOJI.ts b/src/handlers/messages/MESSAGE_REACTION_REMOVE_EMOJI.ts index 43ca252ef..4241e718e 100644 --- a/src/handlers/messages/MESSAGE_REACTION_REMOVE_EMOJI.ts +++ b/src/handlers/messages/MESSAGE_REACTION_REMOVE_EMOJI.ts @@ -1,7 +1,7 @@ import { eventHandlers } from "../../bot.ts"; import { cacheHandlers } from "../../cache.ts"; -import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; -import { MessageReactionRemoveEmoji } from "../../types/messages/message_reaction_remove_emoji.ts"; +import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; +import type { MessageReactionRemoveEmoji } from "../../types/messages/message_reaction_remove_emoji.ts"; import { snowflakeToBigint } from "../../util/bigint.ts"; export async function handleMessageReactionRemoveEmoji( diff --git a/src/handlers/messages/MESSAGE_UPDATE.ts b/src/handlers/messages/MESSAGE_UPDATE.ts index 648aeec06..61383517e 100644 --- a/src/handlers/messages/MESSAGE_UPDATE.ts +++ b/src/handlers/messages/MESSAGE_UPDATE.ts @@ -1,8 +1,8 @@ import { eventHandlers } from "../../bot.ts"; import { cacheHandlers } from "../../cache.ts"; import { structures } from "../../structures/mod.ts"; -import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; -import { Message } from "../../types/messages/message.ts"; +import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; +import type { Message } from "../../types/messages/message.ts"; import { snowflakeToBigint } from "../../util/bigint.ts"; export async function handleMessageUpdate(data: DiscordGatewayPayload) { diff --git a/src/handlers/misc/PRESENCE_UPDATE.ts b/src/handlers/misc/PRESENCE_UPDATE.ts index c770dc8b4..c54f2db1c 100644 --- a/src/handlers/misc/PRESENCE_UPDATE.ts +++ b/src/handlers/misc/PRESENCE_UPDATE.ts @@ -1,7 +1,7 @@ import { eventHandlers } from "../../bot.ts"; import { cacheHandlers } from "../../cache.ts"; -import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; -import { PresenceUpdate } from "../../types/misc/presence_update.ts"; +import type { PresenceUpdate } from "../../types/activity/presence_update.ts"; +import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; import { snowflakeToBigint } from "../../util/bigint.ts"; export async function handlePresenceUpdate(data: DiscordGatewayPayload) { diff --git a/src/handlers/misc/READY.ts b/src/handlers/misc/READY.ts index 782e88f29..56188fdd7 100644 --- a/src/handlers/misc/READY.ts +++ b/src/handlers/misc/READY.ts @@ -1,10 +1,7 @@ import { eventHandlers, setApplicationId, setBotId } from "../../bot.ts"; -import { cache, cacheHandlers } from "../../cache.ts"; -import { initialMemberLoadQueue } from "../../structures/guild.ts"; -import { structures } from "../../structures/mod.ts"; -import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; -import { Ready } from "../../types/gateway/ready.ts"; -import { GuildMemberWithUser } from "../../types/mod.ts"; +import { cache } from "../../cache.ts"; +import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; +import type { Ready } from "../../types/gateway/ready.ts"; import { snowflakeToBigint } from "../../util/bigint.ts"; import { ws } from "../../ws/ws.ts"; @@ -35,18 +32,18 @@ export function handleReady( ); // Start ready check in 2 seconds - setTimeout(async () => { + setTimeout(() => { eventHandlers.debug?.( "loop", `1. Running setTimeout in READY file.`, ); - await checkReady(payload, shardId, now); + checkReady(payload, shardId, now); }, 2000); } // Don't pass the shard itself because unavailableGuilds won't be updated by the GUILD_CREATE event /** This function checks if the shard is fully loaded */ -async function checkReady(payload: Ready, shardId: number, now: number) { +function checkReady(payload: Ready, shardId: number, now: number) { const shard = ws.shards.get(shardId); if (!shard) return; @@ -55,24 +52,24 @@ async function checkReady(payload: Ready, shardId: number, now: number) { if (Date.now() - now > 10000) { eventHandlers.shardFailedToLoad?.(shardId, shard.unavailableGuildIds); // Force execute the loaded function to prevent infinite loop - await loaded(shardId); + loaded(shardId); } else { // Not all guilds were loaded but 10 seconds haven't passed so check again - setTimeout(async () => { + setTimeout(() => { eventHandlers.debug?.( "loop", `2. Running setTimeout in READY file.`, ); - await checkReady(payload, shardId, now); + checkReady(payload, shardId, now); }, 2000); } } else { // All guilds were loaded - await loaded(shardId); + loaded(shardId); } } -async function loaded(shardId: number) { +function loaded(shardId: number) { const shard = ws.shards.get(shardId); if (!shard) return; @@ -82,38 +79,16 @@ async function loaded(shardId: number) { if (shardId === ws.lastShardId - 1) { // Still some shards are loading so wait another 2 seconds for them if (ws.shards.some((shard) => !shard.ready)) { - setTimeout(async () => { + setTimeout(() => { eventHandlers.debug?.( "loop", - `3. Running setTimeout in CHANNEL_DELTE file.`, + `3. Running setTimeout in READY file.`, ); - await loaded(shardId); + loaded(shardId); }, 2000); } else { cache.isReady = true; eventHandlers.ready?.(); - - // All the members that came in on guild creates should now be processed 1 by 1 - for (const [guildId, members] of initialMemberLoadQueue.entries()) { - eventHandlers.debug?.( - "loop", - "Running for of loop in READY file for loading members.", - ); - await Promise.allSettled( - members.map(async (member) => { - const discordenoMember = await structures.createDiscordenoMember( - member as GuildMemberWithUser, - guildId, - ); - - return cacheHandlers.set( - "members", - discordenoMember.id, - discordenoMember, - ); - }), - ); - } } } } diff --git a/src/handlers/misc/TYPING_START.ts b/src/handlers/misc/TYPING_START.ts index 1cfde4296..707edfc4f 100644 --- a/src/handlers/misc/TYPING_START.ts +++ b/src/handlers/misc/TYPING_START.ts @@ -1,6 +1,6 @@ import { eventHandlers } from "../../bot.ts"; -import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; -import { TypingStart } from "../../types/misc/typing_start.ts"; +import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; +import type { TypingStart } from "../../types/misc/typing_start.ts"; export function handleTypingStart(data: DiscordGatewayPayload) { eventHandlers.typingStart?.( diff --git a/src/handlers/misc/USER_UPDATE.ts b/src/handlers/misc/USER_UPDATE.ts index 02297cce9..fbe68ff70 100644 --- a/src/handlers/misc/USER_UPDATE.ts +++ b/src/handlers/misc/USER_UPDATE.ts @@ -1,7 +1,7 @@ import { eventHandlers } from "../../bot.ts"; import { cacheHandlers } from "../../cache.ts"; -import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; -import { User } from "../../types/users/user.ts"; +import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; +import type { User } from "../../types/users/user.ts"; import { snowflakeToBigint } from "../../util/bigint.ts"; export async function handleUserUpdate(data: DiscordGatewayPayload) { diff --git a/src/handlers/mod.ts b/src/handlers/mod.ts index 2eda4a9c7..169e79d21 100644 --- a/src/handlers/mod.ts +++ b/src/handlers/mod.ts @@ -2,6 +2,12 @@ import { handleChannelCreate } from "./channels/CHANNEL_CREATE.ts"; import { handleChannelDelete } from "./channels/CHANNEL_DELETE.ts"; import { handleChannelPinsUpdate } from "./channels/CHANNEL_PINS_UPDATE.ts"; import { handleChannelUpdate } from "./channels/CHANNEL_UPDATE.ts"; +import { handleThreadCreate } from "./channels/THREAD_CREATE.ts"; +import { handleThreadDelete } from "./channels/THREAD_DELETE.ts"; +import { handleThreadListSync } from "./channels/THREAD_LIST_SYNC.ts"; +import { handleThreadMembersUpdate } from "./channels/THREAD_MEMBERS_UPDATE.ts"; +import { handleThreadMemberUpdate } from "./channels/THREAD_MEMBER_UPDATE.ts"; +import { handleThreadUpdate } from "./channels/THREAD_UPDATE.ts"; import { handleApplicationCommandCreate } from "./commands/APPLICATION_COMMAND_CREATE.ts"; import { handleApplicationCommandDelete } from "./commands/APPLICATION_COMMAND_DELETE.ts"; import { handleApplicationCommandUpdate } from "./commands/APPLICATION_COMMAND_UPDATE.ts"; @@ -77,6 +83,12 @@ export { handleMessageUpdate, handlePresenceUpdate, handleReady, + handleThreadCreate, + handleThreadDelete, + handleThreadListSync, + handleThreadMembersUpdate, + handleThreadMemberUpdate, + handleThreadUpdate, handleTypingStart, handleUserUpdate, handleVoiceServerUpdate, @@ -92,6 +104,12 @@ export let handlers = { CHANNEL_DELETE: handleChannelDelete, CHANNEL_PINS_UPDATE: handleChannelPinsUpdate, CHANNEL_UPDATE: handleChannelUpdate, + THREAD_CREATE: handleThreadCreate, + THREAD_UPDATE: handleThreadUpdate, + THREAD_DELETE: handleThreadDelete, + THREAD_LIST_SYNC: handleThreadListSync, + THREAD_MEMBER_UPDATE: handleThreadMemberUpdate, + THREAD_MEMBERS_UPDATE: handleThreadMembersUpdate, // commands APPLICATION_COMMAND_CREATE: handleApplicationCommandCreate, APPLICATION_COMMAND_DELETE: handleApplicationCommandDelete, diff --git a/src/handlers/roles/GUILD_ROLE_CREATE.ts b/src/handlers/roles/GUILD_ROLE_CREATE.ts index acdc40c0b..c8801e2ce 100644 --- a/src/handlers/roles/GUILD_ROLE_CREATE.ts +++ b/src/handlers/roles/GUILD_ROLE_CREATE.ts @@ -1,8 +1,8 @@ import { eventHandlers } from "../../bot.ts"; import { cacheHandlers } from "../../cache.ts"; import { structures } from "../../structures/mod.ts"; -import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; -import { GuildRoleCreate } from "../../types/mod.ts"; +import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; +import type { GuildRoleCreate } from "../../types/mod.ts"; import { snowflakeToBigint } from "../../util/bigint.ts"; export async function handleGuildRoleCreate(data: DiscordGatewayPayload) { diff --git a/src/handlers/roles/GUILD_ROLE_DELETE.ts b/src/handlers/roles/GUILD_ROLE_DELETE.ts index 8fd35f5e1..bed41d946 100644 --- a/src/handlers/roles/GUILD_ROLE_DELETE.ts +++ b/src/handlers/roles/GUILD_ROLE_DELETE.ts @@ -1,7 +1,7 @@ import { eventHandlers } from "../../bot.ts"; import { cacheHandlers } from "../../cache.ts"; -import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; -import { GuildRoleDelete } from "../../types/guilds/guild_role_delete.ts"; +import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; +import type { GuildRoleDelete } from "../../types/guilds/guild_role_delete.ts"; import { snowflakeToBigint } from "../../util/bigint.ts"; export async function handleGuildRoleDelete(data: DiscordGatewayPayload) { diff --git a/src/handlers/roles/GUILD_ROLE_UPDATE.ts b/src/handlers/roles/GUILD_ROLE_UPDATE.ts index ae9c6e6d1..e3c1b445f 100644 --- a/src/handlers/roles/GUILD_ROLE_UPDATE.ts +++ b/src/handlers/roles/GUILD_ROLE_UPDATE.ts @@ -1,8 +1,8 @@ import { eventHandlers } from "../../bot.ts"; import { cacheHandlers } from "../../cache.ts"; import { structures } from "../../structures/mod.ts"; -import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; -import { GuildRoleUpdate } from "../../types/mod.ts"; +import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; +import type { GuildRoleUpdate } from "../../types/mod.ts"; import { snowflakeToBigint } from "../../util/bigint.ts"; export async function handleGuildRoleUpdate(data: DiscordGatewayPayload) { diff --git a/src/handlers/voice/VOICE_SERVER_UPDATE.ts b/src/handlers/voice/VOICE_SERVER_UPDATE.ts index 3f6128a52..8150f7f01 100644 --- a/src/handlers/voice/VOICE_SERVER_UPDATE.ts +++ b/src/handlers/voice/VOICE_SERVER_UPDATE.ts @@ -1,7 +1,7 @@ import { eventHandlers } from "../../bot.ts"; import { cacheHandlers } from "../../cache.ts"; -import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; -import { VoiceServerUpdate } from "../../types/voice/voice_server_update.ts"; +import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; +import type { VoiceServerUpdate } from "../../types/voice/voice_server_update.ts"; import { snowflakeToBigint } from "../../util/bigint.ts"; export async function handleVoiceServerUpdate(data: DiscordGatewayPayload) { diff --git a/src/handlers/voice/VOICE_STATE_UPDATE.ts b/src/handlers/voice/VOICE_STATE_UPDATE.ts index e358eb3b6..7c9b93751 100644 --- a/src/handlers/voice/VOICE_STATE_UPDATE.ts +++ b/src/handlers/voice/VOICE_STATE_UPDATE.ts @@ -1,8 +1,8 @@ import { eventHandlers } from "../../bot.ts"; import { cacheHandlers } from "../../cache.ts"; import { structures } from "../../structures/mod.ts"; -import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; -import { VoiceState } from "../../types/voice/voice_state.ts"; +import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; +import type { VoiceState } from "../../types/voice/voice_state.ts"; import { snowflakeToBigint } from "../../util/bigint.ts"; export async function handleVoiceStateUpdate(data: DiscordGatewayPayload) { diff --git a/src/handlers/webhooks/WEBHOOKS_UPDATE.ts b/src/handlers/webhooks/WEBHOOKS_UPDATE.ts index 110a6761d..9512aa58f 100644 --- a/src/handlers/webhooks/WEBHOOKS_UPDATE.ts +++ b/src/handlers/webhooks/WEBHOOKS_UPDATE.ts @@ -1,6 +1,6 @@ import { eventHandlers } from "../../bot.ts"; -import { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; -import { WebhookUpdate } from "../../types/webhooks/webhooks_update.ts"; +import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; +import type { WebhookUpdate } from "../../types/webhooks/webhooks_update.ts"; import { snowflakeToBigint } from "../../util/bigint.ts"; export function handleWebhooksUpdate(data: DiscordGatewayPayload) { diff --git a/src/helpers/channels/channel_overwrite_has_permission.ts b/src/helpers/channels/channel_overwrite_has_permission.ts index bcf6b3407..2b0adcd12 100644 --- a/src/helpers/channels/channel_overwrite_has_permission.ts +++ b/src/helpers/channels/channel_overwrite_has_permission.ts @@ -1,6 +1,6 @@ -import { DiscordOverwrite } from "../../types/channels/overwrite.ts"; +import type { DiscordOverwrite } from "../../types/channels/overwrite.ts"; import { DiscordBitwisePermissionFlags } from "../../types/permissions/bitwise_permission_flags.ts"; -import { PermissionStrings } from "../../types/permissions/permission_strings.ts"; +import type { PermissionStrings } from "../../types/permissions/permission_strings.ts"; /** Checks if a channel overwrite for a user id or a role id has permission in this channel */ export function channelOverwriteHasPermission( diff --git a/src/helpers/channels/clone_channel.ts b/src/helpers/channels/clone_channel.ts index 200189a32..c2864a2c9 100644 --- a/src/helpers/channels/clone_channel.ts +++ b/src/helpers/channels/clone_channel.ts @@ -1,7 +1,7 @@ import { cacheHandlers } from "../../cache.ts"; import { DiscordChannelTypes } from "../../types/channels/channel_types.ts"; -import { CreateGuildChannel } from "../../types/guilds/create_guild_channel.ts"; -import { Errors } from "../../types/misc/errors.ts"; +import type { CreateGuildChannel } from "../../types/guilds/create_guild_channel.ts"; +import { Errors } from "../../types/discordeno/errors.ts"; import { bigintToSnowflake } from "../../util/bigint.ts"; import { calculatePermissions } from "../../util/permissions.ts"; import { createChannel } from "./create_channel.ts"; @@ -15,7 +15,7 @@ export async function cloneChannel(channelId: bigint, reason?: string) { //Check for DM channel if ( channelToClone.type === DiscordChannelTypes.DM || - channelToClone.type === DiscordChannelTypes.GROUP_DM + channelToClone.type === DiscordChannelTypes.GroupDm ) { throw new Error(Errors.CHANNEL_NOT_IN_GUILD); } diff --git a/src/helpers/channels/create_channel.ts b/src/helpers/channels/create_channel.ts index 316362399..83aad09d5 100644 --- a/src/helpers/channels/create_channel.ts +++ b/src/helpers/channels/create_channel.ts @@ -1,20 +1,18 @@ -import { eventHandlers } from "../../bot.ts"; import { cacheHandlers } from "../../cache.ts"; import { rest } from "../../rest/rest.ts"; import { structures } from "../../structures/mod.ts"; -import { Channel } from "../../types/channels/channel.ts"; +import type { Channel } from "../../types/channels/channel.ts"; import { DiscordChannelTypes } from "../../types/channels/channel_types.ts"; -import { +import type { CreateGuildChannel, DiscordCreateGuildChannel, } from "../../types/guilds/create_guild_channel.ts"; -import { PermissionStrings } from "../../types/permissions/permission_strings.ts"; import { endpoints } from "../../util/constants.ts"; import { calculateBits, - requireBotGuildPermissions, + requireOverwritePermissions, } from "../../util/permissions.ts"; -import { camelKeysToSnakeCase } from "../../util/utils.ts"; +import { snakelize } from "../../util/utils.ts"; /** Create a channel in your server. Bot needs MANAGE_CHANNEL permissions in the server. */ export async function createChannel( @@ -22,18 +20,12 @@ export async function createChannel( options?: CreateGuildChannel, reason?: string, ) { - const requiredPerms: Set = new Set(["MANAGE_CHANNELS"]); - - options?.permissionOverwrites?.forEach((overwrite) => { - eventHandlers.debug?.( - "loop", - `Running forEach loop in create_channel file.`, + if (options?.permissionOverwrites) { + await requireOverwritePermissions( + guildId, + options.permissionOverwrites, ); - overwrite.allow.forEach(requiredPerms.add, requiredPerms); - overwrite.deny.forEach(requiredPerms.add, requiredPerms); - }); - - await requireBotGuildPermissions(guildId, [...requiredPerms]); + } // BITRATES ARE IN THOUSANDS SO IF USER PROVIDES 32 WE CONVERT TO 32000 if (options?.bitrate && options.bitrate < 1000) options.bitrate *= 1000; @@ -42,13 +34,13 @@ export async function createChannel( "post", endpoints.GUILD_CHANNELS(guildId), { - ...camelKeysToSnakeCase(options ?? {}), + ...snakelize(options ?? {}), permission_overwrites: options?.permissionOverwrites?.map((perm) => ({ ...perm, allow: calculateBits(perm.allow), deny: calculateBits(perm.deny), })), - type: options?.type || DiscordChannelTypes.GUILD_TEXT, + type: options?.type || DiscordChannelTypes.GuildText, reason, }, ); diff --git a/src/helpers/channels/delete_channel.ts b/src/helpers/channels/delete_channel.ts index b8588c7b0..ed443c78a 100644 --- a/src/helpers/channels/delete_channel.ts +++ b/src/helpers/channels/delete_channel.ts @@ -1,26 +1,39 @@ import { cacheHandlers } from "../../cache.ts"; import { rest } from "../../rest/rest.ts"; -import { Errors } from "../../types/misc/errors.ts"; +import { Errors } from "../../types/discordeno/errors.ts"; +import { ChannelTypes } from "../../types/mod.ts"; import { endpoints } from "../../util/constants.ts"; import { requireBotGuildPermissions } from "../../util/permissions.ts"; /** Delete a channel in your server. Bot needs MANAGE_CHANNEL permissions in the server. */ export async function deleteChannel( - guildId: bigint, channelId: bigint, reason?: string, -): Promise { - await requireBotGuildPermissions(guildId, ["MANAGE_CHANNELS"]); +) { + const channel = await cacheHandlers.get("channels", channelId); - const guild = await cacheHandlers.get("guilds", guildId); - if (!guild) throw new Error(Errors.GUILD_NOT_FOUND); + if (channel?.guildId) { + const guild = await cacheHandlers.get("guilds", channel.guildId); + if (!guild) throw new Error(Errors.GUILD_NOT_FOUND); - if (guild?.rulesChannelId === channelId) { - throw new Error(Errors.RULES_CHANNEL_CANNOT_BE_DELETED); - } + // TODO(threads): check if this requires guild perms or channel is enough + await requireBotGuildPermissions( + guild, + [ + ChannelTypes.GuildNewsThread, + ChannelTypes.GuildPivateThread, + ChannelTypes.GuildPublicThread, + ].includes(channel.type) + ? ["MANAGE_THREADS"] + : ["MANAGE_CHANNELS"], + ); + if (guild.rulesChannelId === channelId) { + throw new Error(Errors.RULES_CHANNEL_CANNOT_BE_DELETED); + } - if (guild?.publicUpdatesChannelId === channelId) { - throw new Error(Errors.UPDATES_CHANNEL_CANNOT_BE_DELETED); + if (guild.publicUpdatesChannelId === channelId) { + throw new Error(Errors.UPDATES_CHANNEL_CANNOT_BE_DELETED); + } } return await rest.runMethod( diff --git a/src/helpers/channels/edit_channel.ts b/src/helpers/channels/edit_channel.ts index 26a40fdfa..b0c4247db 100644 --- a/src/helpers/channels/edit_channel.ts +++ b/src/helpers/channels/edit_channel.ts @@ -1,22 +1,68 @@ import { eventHandlers } from "../../bot.ts"; +import { cacheHandlers } from "../../cache.ts"; import { rest } from "../../rest/rest.ts"; -import { ModifyChannel } from "../../types/channels/modify_channel.ts"; -import { Channel } from "../../types/mod.ts"; +import type { Channel } from "../../types/channels/channel.ts"; +import { DiscordChannelTypes } from "../../types/channels/channel_types.ts"; +import type { ModifyChannel } from "../../types/channels/modify_channel.ts"; +import type { ModifyThread } from "../../types/channels/threads/modify_thread.ts"; +import type { PermissionStrings } from "../../types/permissions/permission_strings.ts"; import { endpoints } from "../../util/constants.ts"; import { calculateBits, requireBotChannelPermissions, + requireOverwritePermissions, } from "../../util/permissions.ts"; +import { hasOwnProperty, snakelize } from "../../util/utils.ts"; +//TODO: implement DM group channel edit +//TODO(threads): check thread perms /** Update a channel's settings. Requires the `MANAGE_CHANNELS` permission for the guild. */ export async function editChannel( channelId: bigint, - options: ModifyChannel, + options: ModifyChannel | ModifyThread, reason?: string, ) { - await requireBotChannelPermissions(channelId, ["MANAGE_CHANNELS"]); + const channel = await cacheHandlers.get("channels", channelId); - if (options.name || options.topic) { + if (channel) { + if ( + [ + DiscordChannelTypes.GuildNewsThread, + DiscordChannelTypes.GuildPivateThread, + DiscordChannelTypes.GuildPublicThread, + ].includes(channel.type) + ) { + const permissions = new Set(); + + if (hasOwnProperty(options, "archive") && options.archive === false) { + permissions.add("SEND_MESSAGES"); + } + + // TODO(threads): change this to a better check + // hacky way of checking if more is being modified + if (Object.keys(options).length > 1) { + permissions.add("MANAGE_THREADS"); + } + + await requireBotChannelPermissions(channel.parentId ?? 0n, [ + ...permissions, + ]); + } + + if ( + hasOwnProperty( + options, + "permissionOverwrites", + ) && Array.isArray(options.permissionOverwrites) + ) { + await requireOverwritePermissions( + channel.guildId, + options.permissionOverwrites, + ); + } + } + + if (options.name || (options as ModifyChannel).topic) { const request = editChannelNameTopicQueue.get(channelId); if (!request) { // If this hasnt been done before simply add 1 for it @@ -42,21 +88,18 @@ export async function editChannel( } const payload = { - ...options, + ...snakelize>(options), // deno-lint-ignore camelcase - rate_limit_per_user: options.rateLimitPerUser, - // deno-lint-ignore camelcase - parent_id: options.parentId, - // deno-lint-ignore camelcase - user_limit: options.userLimit, - // deno-lint-ignore camelcase - permission_overwrites: options.permissionOverwrites?.map((overwrite) => { - return { - ...overwrite, - allow: calculateBits(overwrite.allow), - deny: calculateBits(overwrite.deny), - }; - }), + permission_overwrites: + hasOwnProperty(options, "permissionOverwrites") + ? options.permissionOverwrites?.map((overwrite) => { + return { + ...overwrite, + allow: calculateBits(overwrite.allow), + deny: calculateBits(overwrite.deny), + }; + }) + : undefined, }; return await rest.runMethod( diff --git a/src/helpers/channels/edit_channel_overwrite.ts b/src/helpers/channels/edit_channel_overwrite.ts index 056cd6fc4..179bddbd1 100644 --- a/src/helpers/channels/edit_channel_overwrite.ts +++ b/src/helpers/channels/edit_channel_overwrite.ts @@ -1,5 +1,5 @@ import { rest } from "../../rest/rest.ts"; -import { Overwrite } from "../../types/channels/overwrite.ts"; +import type { Overwrite } from "../../types/channels/overwrite.ts"; import { endpoints } from "../../util/constants.ts"; import { calculateBits, diff --git a/src/helpers/channels/follow_channel.ts b/src/helpers/channels/follow_channel.ts index 6ef4ed0e7..ede74126e 100644 --- a/src/helpers/channels/follow_channel.ts +++ b/src/helpers/channels/follow_channel.ts @@ -1,5 +1,5 @@ import { rest } from "../../rest/rest.ts"; -import { FollowedChannel } from "../../types/channels/followed_channel.ts"; +import type { FollowedChannel } from "../../types/channels/followed_channel.ts"; import { endpoints } from "../../util/constants.ts"; import { requireBotChannelPermissions } from "../../util/permissions.ts"; diff --git a/src/helpers/channels/get_channel.ts b/src/helpers/channels/get_channel.ts index 122f075c8..4818bba41 100644 --- a/src/helpers/channels/get_channel.ts +++ b/src/helpers/channels/get_channel.ts @@ -1,7 +1,7 @@ import { cacheHandlers } from "../../cache.ts"; import { rest } from "../../rest/rest.ts"; import { structures } from "../../structures/mod.ts"; -import { Channel } from "../../types/channels/channel.ts"; +import type { Channel } from "../../types/channels/channel.ts"; import { snowflakeToBigint } from "../../util/bigint.ts"; import { endpoints } from "../../util/constants.ts"; diff --git a/src/helpers/channels/get_channel_webhooks.ts b/src/helpers/channels/get_channel_webhooks.ts index d3752ff97..9f4110c43 100644 --- a/src/helpers/channels/get_channel_webhooks.ts +++ b/src/helpers/channels/get_channel_webhooks.ts @@ -1,5 +1,5 @@ import { rest } from "../../rest/rest.ts"; -import { Webhook } from "../../types/webhooks/webhook.ts"; +import type { Webhook } from "../../types/webhooks/webhook.ts"; import { Collection } from "../../util/collection.ts"; import { endpoints } from "../../util/constants.ts"; import { requireBotChannelPermissions } from "../../util/permissions.ts"; diff --git a/src/helpers/channels/get_channels.ts b/src/helpers/channels/get_channels.ts index 681601cd1..53d72529d 100644 --- a/src/helpers/channels/get_channels.ts +++ b/src/helpers/channels/get_channels.ts @@ -1,7 +1,7 @@ import { cacheHandlers } from "../../cache.ts"; import { rest } from "../../rest/rest.ts"; import { structures } from "../../structures/mod.ts"; -import { Channel } from "../../types/channels/channel.ts"; +import type { Channel } from "../../types/channels/channel.ts"; import { Collection } from "../../util/collection.ts"; import { endpoints } from "../../util/constants.ts"; diff --git a/src/helpers/channels/get_pins.ts b/src/helpers/channels/get_pins.ts index dd4d26954..63c2090f4 100644 --- a/src/helpers/channels/get_pins.ts +++ b/src/helpers/channels/get_pins.ts @@ -1,6 +1,6 @@ import { rest } from "../../rest/rest.ts"; import { structures } from "../../structures/mod.ts"; -import { Message } from "../../types/messages/message.ts"; +import type { Message } from "../../types/messages/message.ts"; import { endpoints } from "../../util/constants.ts"; /** Get pinned messages in this channel. */ diff --git a/src/helpers/channels/start_typing.ts b/src/helpers/channels/start_typing.ts index 91ef100f9..486253f08 100644 --- a/src/helpers/channels/start_typing.ts +++ b/src/helpers/channels/start_typing.ts @@ -1,7 +1,7 @@ import { cacheHandlers } from "../../cache.ts"; import { rest } from "../../rest/rest.ts"; import { DiscordChannelTypes } from "../../types/channels/channel_types.ts"; -import { Errors } from "../../types/misc/errors.ts"; +import { Errors } from "../../types/discordeno/errors.ts"; import { endpoints } from "../../util/constants.ts"; import { botHasChannelPermissions } from "../../util/permissions.ts"; @@ -17,8 +17,11 @@ export async function startTyping(channelId: bigint) { if ( ![ DiscordChannelTypes.DM, - DiscordChannelTypes.GUILD_NEWS, - DiscordChannelTypes.GUILD_TEXT, + DiscordChannelTypes.GuildNews, + DiscordChannelTypes.GuildText, + DiscordChannelTypes.GuildNewsThread, + DiscordChannelTypes.GuildPivateThread, + DiscordChannelTypes.GuildPublicThread, ].includes(channel.type) ) { throw new Error(Errors.CHANNEL_NOT_TEXT_BASED); diff --git a/src/helpers/channels/swap_channels.ts b/src/helpers/channels/swap_channels.ts index 21dddd139..a3b3135f5 100644 --- a/src/helpers/channels/swap_channels.ts +++ b/src/helpers/channels/swap_channels.ts @@ -1,5 +1,5 @@ import { rest } from "../../rest/rest.ts"; -import { ModifyGuildChannelPositions } from "../../types/guilds/modify_guild_channel_position.ts"; +import type { ModifyGuildChannelPositions } from "../../types/guilds/modify_guild_channel_position.ts"; import { endpoints } from "../../util/constants.ts"; /** Modify the positions of channels on the guild. Requires MANAGE_CHANNELS permisison. */ diff --git a/src/helpers/channels/threads/add_to_thread.ts b/src/helpers/channels/threads/add_to_thread.ts new file mode 100644 index 000000000..1fd913b5f --- /dev/null +++ b/src/helpers/channels/threads/add_to_thread.ts @@ -0,0 +1,35 @@ +import { cacheHandlers } from "../../../cache.ts"; +import { rest } from "../../../rest/rest.ts"; +import { ChannelTypes, Errors } from "../../../types/mod.ts"; +import { endpoints } from "../../../util/constants.ts"; +//TODO(threads): this does not work rn +/** Adds the current user to a thread. Returns a 204 empty response on success. Also requires the thread is not archived. Fires a Thread Members Update Gateway event.Adds another user to a thread. Requires the ability to send messages in the thread. Also requires the thread is not archived. Returns a 204 empty response on success. Fires a Thread Members Update Gateway event. + * @param userId the user to add to the thread defaults to bot + */ +export async function addToThread(channelId: bigint, userId?: bigint) { + // TODO(threads): perm check + const channel = await cacheHandlers.get("channels", channelId); + if (channel) { + if ( + ![ + ChannelTypes.GuildNewsThread, + ChannelTypes.GuildPivateThread, + ChannelTypes.GuildPublicThread, + ].includes(channel.type) + ) { + throw new Error(Errors.NOT_A_THREAD_CHANNEL); + } + } + console.log( + "put", + userId + ? endpoints.THREAD_USER(channelId, userId) + : endpoints.THREAD_ME(channelId), + ); + return await rest.runMethod( + "put", + userId + ? endpoints.THREAD_USER(channelId, userId) + : endpoints.THREAD_ME(channelId), + ); +} diff --git a/src/helpers/channels/threads/get_active_threads.ts b/src/helpers/channels/threads/get_active_threads.ts new file mode 100644 index 000000000..2ed30691d --- /dev/null +++ b/src/helpers/channels/threads/get_active_threads.ts @@ -0,0 +1,12 @@ +import { rest } from "../../../rest/rest.ts"; +import { endpoints } from "../../../util/constants.ts"; + +/** Returns all active threads in the channel, including public and private threads. Threads are ordered by their id, in descending order. Requires the READ_MESSAGE_HISTORY permission. */ +export async function getActiveThreads(channelId: bigint) { + // TODO(threads): perm check + // TODO(threads): test if it works + return await rest.runMethod( + "get", + endpoints.THREAD_ACTIVE(channelId), + ); +} diff --git a/src/helpers/channels/threads/get_archived_threads.ts b/src/helpers/channels/threads/get_archived_threads.ts new file mode 100644 index 000000000..afff32710 --- /dev/null +++ b/src/helpers/channels/threads/get_archived_threads.ts @@ -0,0 +1,24 @@ +import { rest } from "../../../rest/rest.ts"; +import { ListPublicArchivedThreads } from "../../../types/channels/threads/list_public_archived_threads.ts"; +import { endpoints } from "../../../util/constants.ts"; +import { snakelize } from "../../../util/utils.ts"; + +export async function getArchivedThreads( + channelId: bigint, + options?: ListPublicArchivedThreads & { + type?: "public" | "private" | "privateJoinedThreads"; + }, +) { + // TODO(threads): perm check + // TODO(threads): check if this works + + return await rest.runMethod( + "get", + options?.type === "privateJoinedThreads" + ? endpoints.THREAD_ARCHIVED_PRIVATE_JOINED(channelId) + : options?.type === "private" + ? endpoints.THREAD_ARCHIVED_PRIVATE(channelId) + : endpoints.THREAD_ARCHIVED_PUBLIC(channelId), + snakelize(options ?? {}), + ); +} diff --git a/src/helpers/channels/threads/get_thread_members.ts b/src/helpers/channels/threads/get_thread_members.ts new file mode 100644 index 000000000..89fe6a2ed --- /dev/null +++ b/src/helpers/channels/threads/get_thread_members.ts @@ -0,0 +1,26 @@ +import { cacheHandlers } from "../../../cache.ts"; +import { rest } from "../../../rest/rest.ts"; +import { ChannelTypes } from "../../../types/channels/channel_types.ts"; +import { Errors } from "../../../types/discordeno/errors.ts"; +import { endpoints } from "../../../util/constants.ts"; + +// TODO(threads): it seems like the documented return type is wrong +/** Returns array of thread members objects that are members of the thread. */ +export async function getThreadMembers(channelId: bigint) { + // TODO(threads): perm check + // TODO(threads): intents check + const channel = await cacheHandlers.get("channels", channelId); + if (channel) { + if ( + ![ + ChannelTypes.GuildNewsThread, + ChannelTypes.GuildPivateThread, + ChannelTypes.GuildPublicThread, + ].includes(channel.type) + ) { + throw new Error(Errors.NOT_A_THREAD_CHANNEL); + } + } + + return await rest.runMethod("get", endpoints.THREAD_MEMBERS(channelId)); +} diff --git a/src/helpers/channels/threads/remove_from_thread.ts b/src/helpers/channels/threads/remove_from_thread.ts new file mode 100644 index 000000000..917c36000 --- /dev/null +++ b/src/helpers/channels/threads/remove_from_thread.ts @@ -0,0 +1,29 @@ +import { cacheHandlers } from "../../../cache.ts"; +import { rest } from "../../../rest/rest.ts"; +import { ChannelTypes } from "../../../types/channels/channel_types.ts"; +import { Errors } from "../../../types/discordeno/errors.ts"; +import { endpoints } from "../../../util/constants.ts"; + +/** Removes another user from a thread. Requires the MANAGE_THREADS permission or that you are the creator of the thread. Also requires the thread is not archived. Returns a 204 empty response on success. Fires a Thread Members Update Gateway event. */ +export async function removeFromThread(channelId: bigint, userId?: bigint) { + // TODO(threads): perm check + const channel = await cacheHandlers.get("channels", channelId); + if (channel) { + if ( + ![ + ChannelTypes.GuildNewsThread, + ChannelTypes.GuildPivateThread, + ChannelTypes.GuildPublicThread, + ].includes(channel.type) + ) { + throw new Error(Errors.NOT_A_THREAD_CHANNEL); + } + } + + return await rest.runMethod( + "delete", + userId + ? endpoints.THREAD_USER(channelId, userId) + : endpoints.THREAD_ME(channelId), + ); +} diff --git a/src/helpers/channels/threads/start_thread.ts b/src/helpers/channels/threads/start_thread.ts new file mode 100644 index 000000000..0a6f90e2e --- /dev/null +++ b/src/helpers/channels/threads/start_thread.ts @@ -0,0 +1,38 @@ +import { cacheHandlers } from "../../../cache.ts"; +import { rest } from "../../../rest/rest.ts"; +import { ChannelTypes } from "../../../types/channels/channel_types.ts"; +import { StartThread } from "../../../types/channels/threads/start_thread.ts"; +import { Errors } from "../../../types/discordeno/errors.ts"; +import { endpoints } from "../../../util/constants.ts"; +import { snakelize } from "../../../util/utils.ts"; + +/** + * Creates a new public thread from an existing message. Returns a channel on success, and a 400 BAD REQUEST on invalid parameters. Fires a Thread Create Gateway event. + * @param messageId when provided the thread will be public + */ +export async function startThread( + channelId: bigint, + options: StartThread & { messageId?: bigint }, +) { + const channel = await cacheHandlers.get("channels", channelId); + if (channel) { + // TODO(threads): perm check + if ( + ![ChannelTypes.GuildText, ChannelTypes.GuildNews].includes(channel.type) + ) { + throw new Error(Errors.INVALID_THREAD_PARENT_CHANNEL_TYPE); + } + + if (!options.messageId && channel.type === ChannelTypes.GuildNews) { + throw new Error(Errors.GUILD_NEWS_CHANNEL_ONLY_SUPPORT_PUBLIC_THREADS); + } + } + + return rest.runMethod( + "post", + options?.messageId + ? endpoints.THREAD_START_PUBLIC(channelId, options.messageId) + : endpoints.THREAD_START_PRIVATE(channelId), + snakelize(options), + ); +} diff --git a/src/helpers/channels/update_voice_state.ts b/src/helpers/channels/update_voice_state.ts new file mode 100644 index 000000000..17ead3140 --- /dev/null +++ b/src/helpers/channels/update_voice_state.ts @@ -0,0 +1,32 @@ +import { rest } from "../../rest/rest.ts"; +import { UpdateOthersVoiceState } from "../../types/guilds/update_others_voice_state.ts"; +import type { + UpdateSelfVoiceState, +} from "../../types/guilds/update_self_voice_state.ts"; +import { endpoints } from "../../util/constants.ts"; +import { hasOwnProperty, snakelize } from "../../util/utils.ts"; + +/** + * Updates the a user's voice state, defaults to the current user + * Caveats: + * - `channel_id` must currently point to a stage channel. + * - User must already have joined `channel_id`. + * - You must have the `MUTE_MEMBERS` permission. But can always suppress yourself. + * - When unsuppressed, non-bot users will have their `request_to_speak_timestamp` set to the current time. Bot users will not. + * - You must have the `REQUEST_TO_SPEAK` permission to request to speak. You can always clear your own request to speak. + * - You are able to set `request_to_speak_timestamp` to any present or future time. + * - When suppressed, the user will have their `request_to_speak_timestamp` removed. + */ +export async function updateBotVoiceState( + guildId: bigint, + options: UpdateSelfVoiceState | { userId: bigint } & UpdateOthersVoiceState, +) { + return await rest.runMethod( + "patch", + endpoints.UPDATE_VOICE_STATE( + guildId, + hasOwnProperty(options, "userId") ? options.userId : undefined, + ), + snakelize(options), + ); +} diff --git a/src/helpers/commands/edit_slash_command_permissions.ts b/src/helpers/commands/edit_slash_command_permissions.ts deleted file mode 100644 index 743780b45..000000000 --- a/src/helpers/commands/edit_slash_command_permissions.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { applicationId } from "../../bot.ts"; -import { rest } from "../../rest/rest.ts"; -import { ApplicationCommandPermissions } from "../../types/interactions/application_command_permissions.ts"; -import { endpoints } from "../../util/constants.ts"; -import { camelKeysToSnakeCase } from "../../util/utils.ts"; - -/** Edits command permissions for a specific command for your application in a guild. */ -export async function editSlashCommandPermissions( - guildId: bigint, - commandId: bigint, - options: ApplicationCommandPermissions[], -) { - return await rest.runMethod( - "put", - endpoints.COMMANDS_PERMISSION(applicationId, guildId, commandId), - { permissions: camelKeysToSnakeCase(options) }, - ); -} diff --git a/src/helpers/discovery/add_discovery_subcategory.ts b/src/helpers/discovery/add_discovery_subcategory.ts index 3341f394c..4061925cd 100644 --- a/src/helpers/discovery/add_discovery_subcategory.ts +++ b/src/helpers/discovery/add_discovery_subcategory.ts @@ -1,5 +1,5 @@ import { rest } from "../../rest/rest.ts"; -import { +import type { AddGuildDiscoverySubcategory, } from "../../types/discovery/add_guild_discovery_subcategory.ts"; import { endpoints } from "../../util/constants.ts"; diff --git a/src/helpers/discovery/edit_discovery.ts b/src/helpers/discovery/edit_discovery.ts index e94c7a60b..e4b48f6f2 100644 --- a/src/helpers/discovery/edit_discovery.ts +++ b/src/helpers/discovery/edit_discovery.ts @@ -1,9 +1,9 @@ import { rest } from "../../rest/rest.ts"; -import { DiscoveryMetadata } from "../../types/discovery/discovery_metadata.ts"; -import { ModifyGuildDiscoveryMetadata } from "../../types/discovery/modify_guild_discovery_metadata.ts"; +import type { DiscoveryMetadata } from "../../types/discovery/discovery_metadata.ts"; +import type { ModifyGuildDiscoveryMetadata } from "../../types/discovery/modify_guild_discovery_metadata.ts"; import { endpoints } from "../../util/constants.ts"; import { requireBotGuildPermissions } from "../../util/permissions.ts"; -import { camelKeysToSnakeCase } from "../../util/utils.ts"; +import { snakelize } from "../../util/utils.ts"; /** Modify the discovery metadata for the guild. Requires the MANAGE_GUILD permission. Returns the updated discovery metadata object on success. */ export async function editDiscovery( @@ -15,6 +15,6 @@ export async function editDiscovery( return await rest.runMethod( "patch", endpoints.DISCOVERY_MODIFY(guildId), - camelKeysToSnakeCase(data), + snakelize(data), ); } diff --git a/src/helpers/discovery/get_discovery_categories.ts b/src/helpers/discovery/get_discovery_categories.ts index 8ec9858f5..0ac60d848 100644 --- a/src/helpers/discovery/get_discovery_categories.ts +++ b/src/helpers/discovery/get_discovery_categories.ts @@ -1,5 +1,5 @@ import { rest } from "../../rest/rest.ts"; -import { DiscoveryCategory } from "../../types/discovery/discovery_category.ts"; +import type { DiscoveryCategory } from "../../types/discovery/discovery_category.ts"; import { Collection } from "../../util/collection.ts"; import { endpoints } from "../../util/constants.ts"; diff --git a/src/helpers/discovery/valid_discovery_term.ts b/src/helpers/discovery/valid_discovery_term.ts index 5a96016af..b41a60742 100644 --- a/src/helpers/discovery/valid_discovery_term.ts +++ b/src/helpers/discovery/valid_discovery_term.ts @@ -1,5 +1,5 @@ import { rest } from "../../rest/rest.ts"; -import { ValidateDiscoverySearchTerm } from "../../types/discovery/validate_discovery_search_term.ts"; +import type { ValidateDiscoverySearchTerm } from "../../types/discovery/validate_discovery_search_term.ts"; import { endpoints } from "../../util/constants.ts"; export async function validDiscoveryTerm(term: string) { diff --git a/src/helpers/emojis/create_emoji.ts b/src/helpers/emojis/create_emoji.ts index 504bdd299..432885fc0 100644 --- a/src/helpers/emojis/create_emoji.ts +++ b/src/helpers/emojis/create_emoji.ts @@ -1,6 +1,6 @@ import { rest } from "../../rest/rest.ts"; import { CreateGuildEmoji } from "../../types/emojis/create_guild_emoji.ts"; -import { Emoji } from "../../types/emojis/emoji.ts"; +import type { Emoji } from "../../types/emojis/emoji.ts"; import { snowflakeToBigint } from "../../util/bigint.ts"; import { endpoints } from "../../util/constants.ts"; import { requireBotGuildPermissions } from "../../util/permissions.ts"; diff --git a/src/helpers/emojis/edit_emoji.ts b/src/helpers/emojis/edit_emoji.ts index 5d2a0f8ed..87264c5f6 100644 --- a/src/helpers/emojis/edit_emoji.ts +++ b/src/helpers/emojis/edit_emoji.ts @@ -1,6 +1,6 @@ import { rest } from "../../rest/rest.ts"; -import { ModifyGuildEmoji } from "../../types/emojis/modify_guild_emoji.ts"; -import { Emoji } from "../../types/mod.ts"; +import type { Emoji } from "../../types/emojis/emoji.ts"; +import type { ModifyGuildEmoji } from "../../types/emojis/modify_guild_emoji.ts"; import { endpoints } from "../../util/constants.ts"; import { requireBotGuildPermissions } from "../../util/permissions.ts"; diff --git a/src/helpers/emojis/get_emoji.ts b/src/helpers/emojis/get_emoji.ts index d66ac2aa1..ceba22536 100644 --- a/src/helpers/emojis/get_emoji.ts +++ b/src/helpers/emojis/get_emoji.ts @@ -1,7 +1,7 @@ import { cacheHandlers } from "../../cache.ts"; import { rest } from "../../rest/rest.ts"; -import { Emoji } from "../../types/emojis/emoji.ts"; -import { Errors } from "../../types/misc/errors.ts"; +import type { Emoji } from "../../types/emojis/emoji.ts"; +import { Errors } from "../../types/discordeno/errors.ts"; import { endpoints } from "../../util/constants.ts"; /** diff --git a/src/helpers/emojis/get_emojis.ts b/src/helpers/emojis/get_emojis.ts index c0e56b65f..049f2a809 100644 --- a/src/helpers/emojis/get_emojis.ts +++ b/src/helpers/emojis/get_emojis.ts @@ -1,8 +1,8 @@ import { eventHandlers } from "../../bot.ts"; import { cacheHandlers } from "../../cache.ts"; import { rest } from "../../rest/rest.ts"; -import { Emoji } from "../../types/emojis/emoji.ts"; -import { Errors } from "../../types/misc/errors.ts"; +import type { Emoji } from "../../types/emojis/emoji.ts"; +import { Errors } from "../../types/discordeno/errors.ts"; import { snowflakeToBigint } from "../../util/bigint.ts"; import { Collection } from "../../util/collection.ts"; import { endpoints } from "../../util/constants.ts"; diff --git a/src/helpers/guilds/create_guild.ts b/src/helpers/guilds/create_guild.ts index 40c28f3fa..517a0f63c 100644 --- a/src/helpers/guilds/create_guild.ts +++ b/src/helpers/guilds/create_guild.ts @@ -2,8 +2,8 @@ import { botId } from "../../bot.ts"; import { cacheHandlers } from "../../cache.ts"; import { rest } from "../../rest/rest.ts"; import { structures } from "../../structures/mod.ts"; -import { CreateGuild } from "../../types/guilds/create_guild.ts"; -import { Guild } from "../../types/guilds/guild.ts"; +import type { CreateGuild } from "../../types/guilds/create_guild.ts"; +import type { Guild } from "../../types/guilds/guild.ts"; import { endpoints } from "../../util/constants.ts"; import { getMember } from "../members/get_member.ts"; diff --git a/src/helpers/guilds/edit_guild.ts b/src/helpers/guilds/edit_guild.ts index 212419486..278597312 100644 --- a/src/helpers/guilds/edit_guild.ts +++ b/src/helpers/guilds/edit_guild.ts @@ -1,8 +1,8 @@ import { cacheHandlers } from "../../cache.ts"; import { rest } from "../../rest/rest.ts"; import { structures } from "../../structures/mod.ts"; -import { Guild } from "../../types/guilds/guild.ts"; -import { ModifyGuild } from "../../types/guilds/modify_guild.ts"; +import type { Guild } from "../../types/guilds/guild.ts"; +import type { ModifyGuild } from "../../types/guilds/modify_guild.ts"; import { endpoints } from "../../util/constants.ts"; import { requireBotGuildPermissions } from "../../util/permissions.ts"; import { urlToBase64 } from "../../util/utils.ts"; diff --git a/src/helpers/guilds/edit_welcome_screen.ts b/src/helpers/guilds/edit_welcome_screen.ts index 284f1fb96..07034cef5 100644 --- a/src/helpers/guilds/edit_welcome_screen.ts +++ b/src/helpers/guilds/edit_welcome_screen.ts @@ -1,8 +1,8 @@ import { rest } from "../../rest/rest.ts"; -import { ModifyGuildWelcomeScreen } from "../../types/guilds/modify_guild_welcome_screen.ts"; -import { WelcomeScreen } from "../../types/mod.ts"; +import type { ModifyGuildWelcomeScreen } from "../../types/guilds/modify_guild_welcome_screen.ts"; +import type { WelcomeScreen } from "../../types/guilds/welcome_screen.ts"; import { endpoints } from "../../util/constants.ts"; -import { camelKeysToSnakeCase } from "../../util/utils.ts"; +import { snakelize } from "../../util/utils.ts"; export async function editWelcomeScreen( guildId: bigint, @@ -11,6 +11,6 @@ export async function editWelcomeScreen( return await rest.runMethod( "patch", endpoints.GUILD_WELCOME_SCREEN(guildId), - camelKeysToSnakeCase(options), + snakelize(options), ); } diff --git a/src/helpers/guilds/edit_widget.ts b/src/helpers/guilds/edit_widget.ts index 8a27129b3..9cc0ccd69 100644 --- a/src/helpers/guilds/edit_widget.ts +++ b/src/helpers/guilds/edit_widget.ts @@ -1,5 +1,5 @@ import { rest } from "../../rest/rest.ts"; -import { GuildWidget } from "../../types/guilds/guild_widget.ts"; +import type { GuildWidget } from "../../types/guilds/guild_widget.ts"; import { endpoints } from "../../util/constants.ts"; import { requireBotGuildPermissions } from "../../util/permissions.ts"; diff --git a/src/helpers/guilds/get_audit_logs.ts b/src/helpers/guilds/get_audit_logs.ts index babcc0354..a82cce811 100644 --- a/src/helpers/guilds/get_audit_logs.ts +++ b/src/helpers/guilds/get_audit_logs.ts @@ -1,9 +1,9 @@ import { rest } from "../../rest/rest.ts"; -import { AuditLog } from "../../types/audit_log/audit_log.ts"; -import { GetGuildAuditLog } from "../../types/audit_log/get_guild_audit_log.ts"; +import type { AuditLog } from "../../types/audit_log/audit_log.ts"; +import type { GetGuildAuditLog } from "../../types/audit_log/get_guild_audit_log.ts"; import { endpoints } from "../../util/constants.ts"; import { requireBotGuildPermissions } from "../../util/permissions.ts"; -import { camelKeysToSnakeCase } from "../../util/utils.ts"; +import { snakelize } from "../../util/utils.ts"; /** Returns the audit logs for the guild. Requires VIEW AUDIT LOGS permission */ export async function getAuditLogs( @@ -15,7 +15,7 @@ export async function getAuditLogs( return await rest.runMethod( "get", endpoints.GUILD_AUDIT_LOGS(guildId), - camelKeysToSnakeCase({ + snakelize({ ...options, limit: options.limit && options.limit >= 1 && options.limit <= 100 ? options.limit diff --git a/src/helpers/guilds/get_available_voice_regions.ts b/src/helpers/guilds/get_available_voice_regions.ts index 5570e4916..2111f6a3d 100644 --- a/src/helpers/guilds/get_available_voice_regions.ts +++ b/src/helpers/guilds/get_available_voice_regions.ts @@ -1,5 +1,5 @@ import { rest } from "../../rest/rest.ts"; -import { VoiceRegion } from "../../types/voice/voice_region.ts"; +import type { VoiceRegion } from "../../types/voice/voice_region.ts"; import { endpoints } from "../../util/constants.ts"; /** Returns an array of voice regions that can be used when creating servers. */ diff --git a/src/helpers/guilds/get_ban.ts b/src/helpers/guilds/get_ban.ts index db70fc796..c6f73a22a 100644 --- a/src/helpers/guilds/get_ban.ts +++ b/src/helpers/guilds/get_ban.ts @@ -1,5 +1,5 @@ import { rest } from "../../rest/rest.ts"; -import { Ban } from "../../types/guilds/ban.ts"; +import type { Ban } from "../../types/guilds/ban.ts"; import { endpoints } from "../../util/constants.ts"; import { requireBotGuildPermissions } from "../../util/permissions.ts"; diff --git a/src/helpers/guilds/get_bans.ts b/src/helpers/guilds/get_bans.ts index ba939dfb8..f2a09617d 100644 --- a/src/helpers/guilds/get_bans.ts +++ b/src/helpers/guilds/get_bans.ts @@ -1,5 +1,5 @@ import { rest } from "../../rest/rest.ts"; -import { Ban } from "../../types/guilds/ban.ts"; +import type { Ban } from "../../types/guilds/ban.ts"; import { snowflakeToBigint } from "../../util/bigint.ts"; import { Collection } from "../../util/collection.ts"; import { endpoints } from "../../util/constants.ts"; diff --git a/src/helpers/guilds/get_guild.ts b/src/helpers/guilds/get_guild.ts index 0a809bbf2..3b13a74dc 100644 --- a/src/helpers/guilds/get_guild.ts +++ b/src/helpers/guilds/get_guild.ts @@ -1,7 +1,7 @@ import { cacheHandlers } from "../../cache.ts"; import { rest } from "../../rest/rest.ts"; import { structures } from "../../structures/mod.ts"; -import { Guild } from "../../types/guilds/guild.ts"; +import type { Guild } from "../../types/guilds/guild.ts"; import { endpoints } from "../../util/constants.ts"; import { ws } from "../../ws/ws.ts"; diff --git a/src/helpers/guilds/get_guild_preview.ts b/src/helpers/guilds/get_guild_preview.ts index b5024f2b8..a62379a6d 100644 --- a/src/helpers/guilds/get_guild_preview.ts +++ b/src/helpers/guilds/get_guild_preview.ts @@ -1,5 +1,5 @@ import { rest } from "../../rest/rest.ts"; -import { GuildPreview } from "../../types/guilds/guild_preview.ts"; +import type { GuildPreview } from "../../types/guilds/guild_preview.ts"; import { endpoints } from "../../util/constants.ts"; /** Returns the guild preview object for the given id. If the bot is not in the guild, then the guild must be Discoverable. */ diff --git a/src/helpers/guilds/get_prune_count.ts b/src/helpers/guilds/get_prune_count.ts index 27f1691cc..327516a5d 100644 --- a/src/helpers/guilds/get_prune_count.ts +++ b/src/helpers/guilds/get_prune_count.ts @@ -1,9 +1,9 @@ import { rest } from "../../rest/rest.ts"; -import { GetGuildPruneCountQuery } from "../../types/guilds/get_guild_prune_count.ts"; -import { Errors } from "../../types/misc/errors.ts"; +import { Errors } from "../../types/discordeno/errors.ts"; +import type { GetGuildPruneCountQuery } from "../../types/guilds/get_guild_prune_count.ts"; import { endpoints } from "../../util/constants.ts"; import { requireBotGuildPermissions } from "../../util/permissions.ts"; -import { camelKeysToSnakeCase } from "../../util/utils.ts"; +import { snakelize } from "../../util/utils.ts"; /** Check how many members would be removed from the server in a prune operation. Requires the KICK_MEMBERS permission */ export async function getPruneCount( @@ -20,7 +20,7 @@ export async function getPruneCount( const result = await rest.runMethod( "get", endpoints.GUILD_PRUNE(guildId), - camelKeysToSnakeCase(options ?? {}), + snakelize(options ?? {}), ); return result.pruned as number; diff --git a/src/helpers/guilds/get_vainty_url.ts b/src/helpers/guilds/get_vainty_url.ts index c14719b30..9554b2b04 100644 --- a/src/helpers/guilds/get_vainty_url.ts +++ b/src/helpers/guilds/get_vainty_url.ts @@ -1,5 +1,5 @@ import { rest } from "../../rest/rest.ts"; -import { InviteMetadata } from "../../types/invites/invite_metadata.ts"; +import type { InviteMetadata } from "../../types/invites/invite_metadata.ts"; import { endpoints } from "../../util/constants.ts"; /** Returns the code and uses of the vanity url for this server if it is enabled else `code` will be null. Requires the `MANAGE_GUILD` permission. */ diff --git a/src/helpers/guilds/get_voice_regions.ts b/src/helpers/guilds/get_voice_regions.ts index ad1598ce5..966867d82 100644 --- a/src/helpers/guilds/get_voice_regions.ts +++ b/src/helpers/guilds/get_voice_regions.ts @@ -1,5 +1,5 @@ import { rest } from "../../rest/rest.ts"; -import { VoiceRegion } from "../../types/voice/voice_region.ts"; +import type { VoiceRegion } from "../../types/voice/voice_region.ts"; import { Collection } from "../../util/collection.ts"; import { endpoints } from "../../util/constants.ts"; diff --git a/src/helpers/guilds/get_welcome_screen.ts b/src/helpers/guilds/get_welcome_screen.ts index f30b8e9c7..2b20e2826 100644 --- a/src/helpers/guilds/get_welcome_screen.ts +++ b/src/helpers/guilds/get_welcome_screen.ts @@ -1,5 +1,5 @@ import { rest } from "../../rest/rest.ts"; -import { WelcomeScreen } from "../../types/mod.ts"; +import type { WelcomeScreen } from "../../types/mod.ts"; import { endpoints } from "../../util/constants.ts"; export async function getWelcomeScreen(guildId: bigint) { diff --git a/src/helpers/guilds/get_widget.ts b/src/helpers/guilds/get_widget.ts index 0be0e4991..58659bacb 100644 --- a/src/helpers/guilds/get_widget.ts +++ b/src/helpers/guilds/get_widget.ts @@ -1,7 +1,7 @@ import { cacheHandlers } from "../../cache.ts"; import { rest } from "../../rest/rest.ts"; -import { GuildWidgetDetails } from "../../types/guilds/guild_widget_details.ts"; -import { Errors } from "../../types/misc/errors.ts"; +import type { GuildWidgetDetails } from "../../types/guilds/guild_widget_details.ts"; +import { Errors } from "../../types/discordeno/errors.ts"; import { endpoints } from "../../util/constants.ts"; /** Returns the widget for the guild. */ diff --git a/src/helpers/guilds/get_widget_image_url.ts b/src/helpers/guilds/get_widget_image_url.ts index ede9e97ff..d33413872 100644 --- a/src/helpers/guilds/get_widget_image_url.ts +++ b/src/helpers/guilds/get_widget_image_url.ts @@ -1,6 +1,6 @@ import { cacheHandlers } from "../../cache.ts"; -import { GetGuildWidgetImageQuery } from "../../types/guilds/get_guild_widget_image.ts"; -import { Errors } from "../../types/misc/errors.ts"; +import type { GetGuildWidgetImageQuery } from "../../types/guilds/get_guild_widget_image.ts"; +import { Errors } from "../../types/discordeno/errors.ts"; import { endpoints } from "../../util/constants.ts"; /** Returns the widget image URL for the guild. */ diff --git a/src/helpers/guilds/get_widget_settings.ts b/src/helpers/guilds/get_widget_settings.ts index e8a106816..622199621 100644 --- a/src/helpers/guilds/get_widget_settings.ts +++ b/src/helpers/guilds/get_widget_settings.ts @@ -1,5 +1,5 @@ import { rest } from "../../rest/rest.ts"; -import { GuildWidget } from "../../types/guilds/guild_widget.ts"; +import type { GuildWidget } from "../../types/guilds/guild_widget.ts"; import { endpoints } from "../../util/constants.ts"; import { requireBotGuildPermissions } from "../../util/permissions.ts"; diff --git a/src/helpers/guilds/guild_banner_url.ts b/src/helpers/guilds/guild_banner_url.ts index 030d2cab6..b539b27be 100644 --- a/src/helpers/guilds/guild_banner_url.ts +++ b/src/helpers/guilds/guild_banner_url.ts @@ -1,5 +1,5 @@ -import { DiscordImageFormat } from "../../types/misc/image_format.ts"; -import { DiscordImageSize } from "../../types/misc/image_size.ts"; +import type { DiscordImageFormat } from "../../types/misc/image_format.ts"; +import type { DiscordImageSize } from "../../types/misc/image_size.ts"; import { endpoints } from "../../util/constants.ts"; import { formatImageURL } from "../../util/utils.ts"; diff --git a/src/helpers/guilds/guild_icon_url.ts b/src/helpers/guilds/guild_icon_url.ts index 09982fec3..5a4c2104a 100644 --- a/src/helpers/guilds/guild_icon_url.ts +++ b/src/helpers/guilds/guild_icon_url.ts @@ -1,5 +1,5 @@ -import { DiscordImageFormat } from "../../types/misc/image_format.ts"; -import { DiscordImageSize } from "../../types/misc/image_size.ts"; +import type { DiscordImageFormat } from "../../types/misc/image_format.ts"; +import type { DiscordImageSize } from "../../types/misc/image_size.ts"; import { endpoints } from "../../util/constants.ts"; import { formatImageURL } from "../../util/utils.ts"; diff --git a/src/helpers/guilds/guild_splash_url.ts b/src/helpers/guilds/guild_splash_url.ts index 83d734a07..b8aef6d56 100644 --- a/src/helpers/guilds/guild_splash_url.ts +++ b/src/helpers/guilds/guild_splash_url.ts @@ -1,5 +1,5 @@ -import { DiscordImageFormat } from "../../types/misc/image_format.ts"; -import { DiscordImageSize } from "../../types/misc/image_size.ts"; +import type { DiscordImageFormat } from "../../types/misc/image_format.ts"; +import type { DiscordImageSize } from "../../types/misc/image_size.ts"; import { endpoints } from "../../util/constants.ts"; import { formatImageURL } from "../../util/utils.ts"; diff --git a/src/helpers/guilds/update_bot_voice_state.ts b/src/helpers/guilds/update_bot_voice_state.ts deleted file mode 100644 index e75d5ce9c..000000000 --- a/src/helpers/guilds/update_bot_voice_state.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { RequestManager } from "../../rest/request_manager.ts"; -import { - DiscordUpdateSelfVoiceState, - UpdateSelfVoiceState, -} from "../../types/guilds/update_self_voice_state.ts"; -import { endpoints } from "../../util/constants.ts"; -import { camelKeysToSnakeCase } from "../../util/utils.ts"; - -/** - * Updates the current user's voice state. - * Caveats: - * - `channel_id` must currently point to a stage channel. - * - current user must already have joined `channel_id`. - * - You must have the `MUTE_MEMBERS` permission to unsuppress yourself. You can always suppress yourself. - * - You must have the `REQUEST_TO_SPEAK` permission to request to speak. You can always clear your own request to speak. - * - You are able to set `request_to_speak_timestamp` to any present or future time. - */ -export function updateBotVoiceState( - guildId: bigint, - data: UpdateSelfVoiceState, -) { - const payload = camelKeysToSnakeCase(data); - - return RequestManager.patch( - endpoints.UPDATE_VOICE_STATE(guildId), - payload, - ); -} diff --git a/src/helpers/guilds/update_user_voice_state.ts b/src/helpers/guilds/update_user_voice_state.ts deleted file mode 100644 index 88708ad10..000000000 --- a/src/helpers/guilds/update_user_voice_state.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { RequestManager } from "../../rest/request_manager.ts"; -import { - DiscordUpdateOthersVoiceState, - UpdateOthersVoiceState, -} from "../../types/guilds/update_others_voice_state.ts"; -import { endpoints } from "../../util/constants.ts"; -import { camelKeysToSnakeCase } from "../../util/utils.ts"; - -/** - * Updates another user's voice state. - * Caveats: - * - `channel_id` must currently point to a stage channel. - * - User must already have joined `channel_id`. - * - You must have the `MUTE_MEMBERS` permission. (Since suppression is the only thing that is available currently.) - * - When unsuppressed, non-bot users will have their `request_to_speak_timestamp` set to the current time. Bot users will not. - * - When suppressed, the user will have their `request_to_speak_timestamp` removed. - */ -export function updateVoiceState( - guildId: bigint, - userId: bigint, - data: UpdateOthersVoiceState, -) { - const payload = camelKeysToSnakeCase(data); - - return RequestManager.patch( - endpoints.UPDATE_VOICE_STATE(guildId, userId), - payload, - ); -} diff --git a/src/helpers/integrations/get_integrations.ts b/src/helpers/integrations/get_integrations.ts index 96fd2110c..340bf8421 100644 --- a/src/helpers/integrations/get_integrations.ts +++ b/src/helpers/integrations/get_integrations.ts @@ -1,5 +1,5 @@ import { rest } from "../../rest/rest.ts"; -import { Integration } from "../../types/mod.ts"; +import type { Integration } from "../../types/integrations/integration.ts"; import { endpoints } from "../../util/constants.ts"; import { requireBotGuildPermissions } from "../../util/permissions.ts"; diff --git a/src/helpers/commands/batch_edit_slash_command_permissions.ts b/src/helpers/interactions/commands/batch_edit_slash_command_permissions.ts similarity index 54% rename from src/helpers/commands/batch_edit_slash_command_permissions.ts rename to src/helpers/interactions/commands/batch_edit_slash_command_permissions.ts index 139ee5981..f8b957019 100644 --- a/src/helpers/commands/batch_edit_slash_command_permissions.ts +++ b/src/helpers/interactions/commands/batch_edit_slash_command_permissions.ts @@ -1,8 +1,8 @@ -import { applicationId } from "../../bot.ts"; -import { rest } from "../../rest/rest.ts"; -import { ApplicationCommandPermissions } from "../../types/interactions/application_command_permissions.ts"; -import { endpoints } from "../../util/constants.ts"; -import { camelKeysToSnakeCase } from "../../util/utils.ts"; +import { applicationId } from "../../../bot.ts"; +import { rest } from "../../../rest/rest.ts"; +import type { ApplicationCommandPermissions } from "../../../types/interactions/commands/application_command_permissions.ts"; +import { endpoints } from "../../../util/constants.ts"; +import { snakelize } from "../../../util/utils.ts"; /** Batch edits permissions for all commands in a guild. Takes an array of partial GuildApplicationCommandPermissions objects including `id` and `permissions`. */ export async function batchEditSlashCommandPermissions( @@ -12,6 +12,6 @@ export async function batchEditSlashCommandPermissions( return await rest.runMethod( "put", endpoints.COMMANDS_PERMISSIONS(applicationId, guildId), - camelKeysToSnakeCase(options), + snakelize(options), ); } diff --git a/src/helpers/commands/create_slash_command.ts b/src/helpers/interactions/commands/create_slash_command.ts similarity index 72% rename from src/helpers/commands/create_slash_command.ts rename to src/helpers/interactions/commands/create_slash_command.ts index 9a6f1f36d..2d9c1ebf6 100644 --- a/src/helpers/commands/create_slash_command.ts +++ b/src/helpers/interactions/commands/create_slash_command.ts @@ -1,12 +1,9 @@ -import { applicationId } from "../../bot.ts"; -import { rest } from "../../rest/rest.ts"; -import { CreateGlobalApplicationCommand } from "../../types/interactions/create_global_application_command.ts"; -import { ApplicationCommand } from "../../types/mod.ts"; -import { endpoints } from "../../util/constants.ts"; -import { - camelKeysToSnakeCase, - validateSlashCommands, -} from "../../util/utils.ts"; +import { applicationId } from "../../../bot.ts"; +import { rest } from "../../../rest/rest.ts"; +import type { ApplicationCommand } from "../../../types/interactions/commands/application_command.ts"; +import type { CreateGlobalApplicationCommand } from "../../../types/interactions/commands/create_global_application_command.ts"; +import { endpoints } from "../../../util/constants.ts"; +import { snakelize, validateSlashCommands } from "../../../util/utils.ts"; /** * There are two kinds of Slash Commands: global commands and guild commands. Global commands are available for every guild that adds your app; guild commands are specific to the guild you specify when making them. Command names are unique per application within each scope (global and guild). That means: @@ -30,6 +27,6 @@ export async function createSlashCommand( guildId ? endpoints.COMMANDS_GUILD(applicationId, guildId) : endpoints.COMMANDS(applicationId), - camelKeysToSnakeCase(options), + snakelize(options), ); } diff --git a/src/helpers/commands/delete_slash_command.ts b/src/helpers/interactions/commands/delete_slash_command.ts similarity index 66% rename from src/helpers/commands/delete_slash_command.ts rename to src/helpers/interactions/commands/delete_slash_command.ts index 0468ad3e5..d7fd746cb 100644 --- a/src/helpers/commands/delete_slash_command.ts +++ b/src/helpers/interactions/commands/delete_slash_command.ts @@ -1,6 +1,6 @@ -import { applicationId } from "../../bot.ts"; -import { rest } from "../../rest/rest.ts"; -import { endpoints } from "../../util/constants.ts"; +import { applicationId } from "../../../bot.ts"; +import { rest } from "../../../rest/rest.ts"; +import { endpoints } from "../../../util/constants.ts"; /** Deletes a slash command. */ export async function deleteSlashCommand( diff --git a/src/helpers/commands/delete_slash_response.ts b/src/helpers/interactions/commands/delete_slash_response.ts similarity index 76% rename from src/helpers/commands/delete_slash_response.ts rename to src/helpers/interactions/commands/delete_slash_response.ts index 7e6d7d991..d772f6e64 100644 --- a/src/helpers/commands/delete_slash_response.ts +++ b/src/helpers/interactions/commands/delete_slash_response.ts @@ -1,6 +1,6 @@ -import { applicationId } from "../../bot.ts"; -import { rest } from "../../rest/rest.ts"; -import { endpoints } from "../../util/constants.ts"; +import { applicationId } from "../../../bot.ts"; +import { rest } from "../../../rest/rest.ts"; +import { endpoints } from "../../../util/constants.ts"; /** To delete your response to a slash command. If a message id is not provided, it will default to deleting the original response. */ export async function deleteSlashResponse( diff --git a/src/helpers/interactions/commands/edit_slash_command_permissions.ts b/src/helpers/interactions/commands/edit_slash_command_permissions.ts new file mode 100644 index 000000000..6bbe374a7 --- /dev/null +++ b/src/helpers/interactions/commands/edit_slash_command_permissions.ts @@ -0,0 +1,18 @@ +import { applicationId } from "../../../bot.ts"; +import { rest } from "../../../rest/rest.ts"; +import type { ApplicationCommandPermissions } from "../../../types/interactions/commands/application_command_permissions.ts"; +import { endpoints } from "../../../util/constants.ts"; +import { snakelize } from "../../../util/utils.ts"; + +/** Edits command permissions for a specific command for your application in a guild. */ +export async function editSlashCommandPermissions( + guildId: bigint, + commandId: bigint, + options: ApplicationCommandPermissions[], +) { + return await rest.runMethod( + "put", + endpoints.COMMANDS_PERMISSION(applicationId, guildId, commandId), + { permissions: snakelize(options) }, + ); +} diff --git a/src/helpers/commands/edit_slash_response.ts b/src/helpers/interactions/commands/edit_slash_response.ts similarity index 80% rename from src/helpers/commands/edit_slash_response.ts rename to src/helpers/interactions/commands/edit_slash_response.ts index 2c458f047..13ea278a7 100644 --- a/src/helpers/commands/edit_slash_response.ts +++ b/src/helpers/interactions/commands/edit_slash_response.ts @@ -1,10 +1,10 @@ -import { applicationId } from "../../bot.ts"; -import { rest } from "../../rest/rest.ts"; -import { structures } from "../../structures/mod.ts"; -import { DiscordenoEditWebhookMessage } from "../../types/discordeno/edit_webhook_message.ts"; -import { DiscordAllowedMentionsTypes } from "../../types/messages/allowed_mentions_types.ts"; -import { Errors } from "../../types/misc/errors.ts"; -import { endpoints } from "../../util/constants.ts"; +import { applicationId } from "../../../bot.ts"; +import { rest } from "../../../rest/rest.ts"; +import { structures } from "../../../structures/mod.ts"; +import type { DiscordenoEditWebhookMessage } from "../../../types/discordeno/edit_webhook_message.ts"; +import { Errors } from "../../../types/discordeno/errors.ts"; +import { DiscordAllowedMentionsTypes } from "../../../types/messages/allowed_mentions_types.ts"; +import { endpoints } from "../../../util/constants.ts"; /** To edit your response to a slash command. If a messageId is not provided it will default to editing the original response. */ export async function editSlashResponse( diff --git a/src/helpers/commands/get_slash_command.ts b/src/helpers/interactions/commands/get_slash_command.ts similarity index 61% rename from src/helpers/commands/get_slash_command.ts rename to src/helpers/interactions/commands/get_slash_command.ts index 2c0f9be01..65bebb020 100644 --- a/src/helpers/commands/get_slash_command.ts +++ b/src/helpers/interactions/commands/get_slash_command.ts @@ -1,7 +1,7 @@ -import { applicationId } from "../../bot.ts"; -import { rest } from "../../rest/rest.ts"; -import { ApplicationCommand } from "../../types/interactions/application_command.ts"; -import { endpoints } from "../../util/constants.ts"; +import { applicationId } from "../../../bot.ts"; +import { rest } from "../../../rest/rest.ts"; +import type { ApplicationCommand } from "../../../types/interactions/commands/application_command.ts"; +import { endpoints } from "../../../util/constants.ts"; /** Fetchs the global command for the given Id. If a guildId is provided, the guild command will be fetched. */ export async function getSlashCommand(commandId: bigint, guildId?: bigint) { diff --git a/src/helpers/commands/get_slash_command_permission.ts b/src/helpers/interactions/commands/get_slash_command_permission.ts similarity index 57% rename from src/helpers/commands/get_slash_command_permission.ts rename to src/helpers/interactions/commands/get_slash_command_permission.ts index ead639b36..0c3391d39 100644 --- a/src/helpers/commands/get_slash_command_permission.ts +++ b/src/helpers/interactions/commands/get_slash_command_permission.ts @@ -1,7 +1,7 @@ -import { applicationId } from "../../bot.ts"; -import { rest } from "../../rest/rest.ts"; -import { GuildApplicationCommandPermissions } from "../../types/interactions/guild_application_command_permissions.ts"; -import { endpoints } from "../../util/constants.ts"; +import { applicationId } from "../../../bot.ts"; +import { rest } from "../../../rest/rest.ts"; +import type { GuildApplicationCommandPermissions } from "../../../types/interactions/commands/guild_application_command_permissions.ts"; +import { endpoints } from "../../../util/constants.ts"; /** Fetches command permissions for a specific command for your application in a guild. Returns a GuildApplicationCommandPermissions object. */ export async function getSlashCommandPermission( diff --git a/src/helpers/commands/get_slash_command_permissions.ts b/src/helpers/interactions/commands/get_slash_command_permissions.ts similarity index 55% rename from src/helpers/commands/get_slash_command_permissions.ts rename to src/helpers/interactions/commands/get_slash_command_permissions.ts index 821642c8d..f40dd9576 100644 --- a/src/helpers/commands/get_slash_command_permissions.ts +++ b/src/helpers/interactions/commands/get_slash_command_permissions.ts @@ -1,7 +1,7 @@ -import { applicationId } from "../../bot.ts"; -import { rest } from "../../rest/rest.ts"; -import { GuildApplicationCommandPermissions } from "../../types/interactions/guild_application_command_permissions.ts"; -import { endpoints } from "../../util/constants.ts"; +import { applicationId } from "../../../bot.ts"; +import { rest } from "../../../rest/rest.ts"; +import type { GuildApplicationCommandPermissions } from "../../../types/interactions/commands/guild_application_command_permissions.ts"; +import { endpoints } from "../../../util/constants.ts"; /** Fetches command permissions for all commands for your application in a guild. Returns an array of GuildApplicationCommandPermissions objects. */ export async function getSlashCommandPermissions(guildId: bigint) { diff --git a/src/helpers/commands/get_slash_commands.ts b/src/helpers/interactions/commands/get_slash_commands.ts similarity index 55% rename from src/helpers/commands/get_slash_commands.ts rename to src/helpers/interactions/commands/get_slash_commands.ts index bdac9a9bc..15163ad88 100644 --- a/src/helpers/commands/get_slash_commands.ts +++ b/src/helpers/interactions/commands/get_slash_commands.ts @@ -1,8 +1,8 @@ -import { applicationId } from "../../bot.ts"; -import { rest } from "../../rest/rest.ts"; -import { ApplicationCommand } from "../../types/interactions/application_command.ts"; -import { Collection } from "../../util/collection.ts"; -import { endpoints } from "../../util/constants.ts"; +import { applicationId } from "../../../bot.ts"; +import { rest } from "../../../rest/rest.ts"; +import type { ApplicationCommand } from "../../../types/interactions/commands/application_command.ts"; +import { Collection } from "../../../util/collection.ts"; +import { endpoints } from "../../../util/constants.ts"; /** Fetch all of the global commands for your application. */ export async function getSlashCommands(guildId?: bigint) { diff --git a/src/helpers/commands/upsert_slash_command.ts b/src/helpers/interactions/commands/upsert_slash_command.ts similarity index 52% rename from src/helpers/commands/upsert_slash_command.ts rename to src/helpers/interactions/commands/upsert_slash_command.ts index d0211400d..b6eea60e8 100644 --- a/src/helpers/commands/upsert_slash_command.ts +++ b/src/helpers/interactions/commands/upsert_slash_command.ts @@ -1,9 +1,9 @@ -import { applicationId } from "../../bot.ts"; -import { rest } from "../../rest/rest.ts"; -import { EditGlobalApplicationCommand } from "../../types/interactions/edit_global_application_command.ts"; -import { ApplicationCommand } from "../../types/mod.ts"; -import { endpoints } from "../../util/constants.ts"; -import { validateSlashCommands } from "../../util/utils.ts"; +import { applicationId } from "../../../bot.ts"; +import { rest } from "../../../rest/rest.ts"; +import type { ApplicationCommand } from "../../../types/interactions/commands/application_command.ts"; +import type { EditGlobalApplicationCommand } from "../../../types/interactions/commands/edit_global_application_command.ts"; +import { endpoints } from "../../../util/constants.ts"; +import { validateSlashCommands } from "../../../util/utils.ts"; /** * Edit an existing slash command. If this command did not exist, it will create it. diff --git a/src/helpers/commands/upsert_slash_commands.ts b/src/helpers/interactions/commands/upsert_slash_commands.ts similarity index 58% rename from src/helpers/commands/upsert_slash_commands.ts rename to src/helpers/interactions/commands/upsert_slash_commands.ts index 3be28f765..6598910f7 100644 --- a/src/helpers/commands/upsert_slash_commands.ts +++ b/src/helpers/interactions/commands/upsert_slash_commands.ts @@ -1,9 +1,9 @@ -import { applicationId } from "../../bot.ts"; -import { rest } from "../../rest/rest.ts"; -import { EditGlobalApplicationCommand } from "../../types/interactions/edit_global_application_command.ts"; -import { ApplicationCommand } from "../../types/mod.ts"; -import { endpoints } from "../../util/constants.ts"; -import { validateSlashCommands } from "../../util/utils.ts"; +import { applicationId } from "../../../bot.ts"; +import { rest } from "../../../rest/rest.ts"; +import type { ApplicationCommand } from "../../../types/interactions/commands/application_command.ts"; +import type { EditGlobalApplicationCommand } from "../../../types/interactions/commands/edit_global_application_command.ts"; +import { endpoints } from "../../../util/constants.ts"; +import { validateSlashCommands } from "../../../util/utils.ts"; /** * Bulk edit existing slash commands. If a command does not exist, it will create it. diff --git a/src/helpers/interactions/get_original_interaction_response.ts b/src/helpers/interactions/get_original_interaction_response.ts new file mode 100644 index 000000000..b6009c94f --- /dev/null +++ b/src/helpers/interactions/get_original_interaction_response.ts @@ -0,0 +1,15 @@ +import { applicationId } from "../../bot.ts"; +import { rest } from "../../rest/rest.ts"; +import { structures } from "../../structures/mod.ts"; +import type { Message } from "../../types/messages/message.ts"; +import { endpoints } from "../../util/constants.ts"; + +/** Returns the initial Interactio response. Functions the same as Get Webhook Message */ +export async function getOriginalInteractionResponse(token: string) { + const result = await rest.runMethod( + "get", + endpoints.INTERACTION_ORIGINAL_ID_TOKEN(applicationId, token), + ); + + return await structures.createDiscordenoMessage(result); +} diff --git a/src/helpers/commands/send_interaction_response.ts b/src/helpers/interactions/send_interaction_response.ts similarity index 94% rename from src/helpers/commands/send_interaction_response.ts rename to src/helpers/interactions/send_interaction_response.ts index 6200c6641..dae5c23bd 100644 --- a/src/helpers/commands/send_interaction_response.ts +++ b/src/helpers/interactions/send_interaction_response.ts @@ -1,7 +1,7 @@ import { applicationId, eventHandlers } from "../../bot.ts"; import { cache } from "../../cache.ts"; import { rest } from "../../rest/rest.ts"; -import { DiscordenoInteractionResponse } from "../../types/discordeno/interaction_response.ts"; +import type { DiscordenoInteractionResponse } from "../../types/discordeno/interaction_response.ts"; import { endpoints } from "../../util/constants.ts"; /** diff --git a/src/helpers/invites/create_invite.ts b/src/helpers/invites/create_invite.ts index 6761d9048..8266d1271 100644 --- a/src/helpers/invites/create_invite.ts +++ b/src/helpers/invites/create_invite.ts @@ -1,7 +1,7 @@ import { rest } from "../../rest/rest.ts"; -import { CreateChannelInvite } from "../../types/invites/create_channel_invite.ts"; -import { Invite } from "../../types/invites/invite.ts"; -import { Errors } from "../../types/misc/errors.ts"; +import type { CreateChannelInvite } from "../../types/invites/create_channel_invite.ts"; +import type { Invite } from "../../types/invites/invite.ts"; +import { Errors } from "../../types/discordeno/errors.ts"; import { endpoints } from "../../util/constants.ts"; import { requireBotChannelPermissions } from "../../util/permissions.ts"; diff --git a/src/helpers/invites/delete_invite.ts b/src/helpers/invites/delete_invite.ts index 130cd2488..ba88f94c5 100644 --- a/src/helpers/invites/delete_invite.ts +++ b/src/helpers/invites/delete_invite.ts @@ -1,7 +1,7 @@ import { cacheHandlers } from "../../cache.ts"; import { rest } from "../../rest/rest.ts"; -import { Invite } from "../../types/invites/invite.ts"; -import { Errors } from "../../types/misc/errors.ts"; +import type { Invite } from "../../types/invites/invite.ts"; +import { Errors } from "../../types/discordeno/errors.ts"; import { endpoints } from "../../util/constants.ts"; import { botHasChannelPermissions, diff --git a/src/helpers/invites/get_channel_invites.ts b/src/helpers/invites/get_channel_invites.ts index ecd27a6d5..42fa1e9d9 100644 --- a/src/helpers/invites/get_channel_invites.ts +++ b/src/helpers/invites/get_channel_invites.ts @@ -1,5 +1,5 @@ import { rest } from "../../rest/rest.ts"; -import { Invite } from "../../types/invites/invite.ts"; +import type { Invite } from "../../types/invites/invite.ts"; import { Collection } from "../../util/collection.ts"; import { endpoints } from "../../util/constants.ts"; import { requireBotChannelPermissions } from "../../util/permissions.ts"; diff --git a/src/helpers/invites/get_invite.ts b/src/helpers/invites/get_invite.ts index de91249fe..5d916264c 100644 --- a/src/helpers/invites/get_invite.ts +++ b/src/helpers/invites/get_invite.ts @@ -1,11 +1,14 @@ import { rest } from "../../rest/rest.ts"; -import { Invite } from "../../types/invites/invite.ts"; +import { GetInvite } from "../../types/invites/get_invite.ts"; +import type { Invite } from "../../types/invites/invite.ts"; import { endpoints } from "../../util/constants.ts"; +import { snakelize } from "../../util/utils.ts"; /** Returns an invite for the given code or throws an error if the invite doesn't exists. */ -export async function getInvite(inviteCode: string) { +export async function getInvite(inviteCode: string, options?: GetInvite) { return await rest.runMethod( "get", endpoints.INVITE(inviteCode), + snakelize(options ?? {}), ); } diff --git a/src/helpers/invites/get_invites.ts b/src/helpers/invites/get_invites.ts index 0ad0fda87..f2d1a732f 100644 --- a/src/helpers/invites/get_invites.ts +++ b/src/helpers/invites/get_invites.ts @@ -1,5 +1,5 @@ import { rest } from "../../rest/rest.ts"; -import { Invite } from "../../types/invites/invite.ts"; +import type { Invite } from "../../types/invites/invite.ts"; import { Collection } from "../../util/collection.ts"; import { endpoints } from "../../util/constants.ts"; import { requireBotGuildPermissions } from "../../util/permissions.ts"; diff --git a/src/helpers/members/avatar_url.ts b/src/helpers/members/avatar_url.ts index 64a136370..0f9ad36da 100644 --- a/src/helpers/members/avatar_url.ts +++ b/src/helpers/members/avatar_url.ts @@ -1,5 +1,5 @@ -import { DiscordImageFormat } from "../../types/misc/image_format.ts"; -import { DiscordImageSize } from "../../types/misc/image_size.ts"; +import type { DiscordImageFormat } from "../../types/misc/image_format.ts"; +import type { DiscordImageSize } from "../../types/misc/image_size.ts"; import { endpoints } from "../../util/constants.ts"; import { formatImageURL } from "../../util/utils.ts"; diff --git a/src/helpers/members/ban_member.ts b/src/helpers/members/ban_member.ts index 57215ba59..52424f5ff 100644 --- a/src/helpers/members/ban_member.ts +++ b/src/helpers/members/ban_member.ts @@ -1,8 +1,8 @@ import { rest } from "../../rest/rest.ts"; -import { CreateGuildBan } from "../../types/guilds/create_guild_ban.ts"; +import type { CreateGuildBan } from "../../types/guilds/create_guild_ban.ts"; import { endpoints } from "../../util/constants.ts"; import { requireBotGuildPermissions } from "../../util/permissions.ts"; -import { camelKeysToSnakeCase } from "../../util/utils.ts"; +import { snakelize } from "../../util/utils.ts"; /** Ban a user from the guild and optionally delete previous messages sent by the user. Requires the BAN_MEMBERS permission. */ export async function ban( @@ -15,7 +15,7 @@ export async function ban( return await rest.runMethod( "put", endpoints.GUILD_BAN(guildId, id), - camelKeysToSnakeCase(options), + snakelize(options), ); } diff --git a/src/helpers/members/edit_member.ts b/src/helpers/members/edit_member.ts index b9ad4efea..efeca3ebd 100644 --- a/src/helpers/members/edit_member.ts +++ b/src/helpers/members/edit_member.ts @@ -1,17 +1,17 @@ import { cacheHandlers } from "../../cache.ts"; import { rest } from "../../rest/rest.ts"; import { structures } from "../../structures/mod.ts"; -import { GuildMemberWithUser } from "../../types/guilds/guild_member.ts"; -import { Errors } from "../../types/misc/errors.ts"; -import { ModifyGuildMember } from "../../types/mod.ts"; -import { PermissionStrings } from "../../types/permissions/permission_strings.ts"; +import { Errors } from "../../types/discordeno/errors.ts"; +import type { ModifyGuildMember } from "../../types/guilds/modify_guild_member.ts"; +import type { GuildMemberWithUser } from "../../types/members/guild_member.ts"; +import type { PermissionStrings } from "../../types/permissions/permission_strings.ts"; import { bigintToSnowflake } from "../../util/bigint.ts"; import { endpoints } from "../../util/constants.ts"; import { requireBotChannelPermissions, requireBotGuildPermissions, } from "../../util/permissions.ts"; -import { camelKeysToSnakeCase } from "../../util/utils.ts"; +import { snakelize } from "../../util/utils.ts"; /** Edit the member */ export async function editMember( @@ -73,7 +73,7 @@ export async function editMember( const result = await rest.runMethod( "patch", endpoints.GUILD_MEMBER(guildId, memberId), - camelKeysToSnakeCase({ + snakelize({ ...options, channelId: options.channelId ? bigintToSnowflake(options.channelId) diff --git a/src/helpers/members/fetch_members.ts b/src/helpers/members/fetch_members.ts index eca4c7720..5f02762dd 100644 --- a/src/helpers/members/fetch_members.ts +++ b/src/helpers/members/fetch_members.ts @@ -1,9 +1,9 @@ import { cache } from "../../cache.ts"; import { DiscordenoMember } from "../../structures/member.ts"; import { DiscordGatewayOpcodes } from "../../types/codes/gateway_opcodes.ts"; +import { Errors } from "../../types/discordeno/errors.ts"; import { DiscordGatewayIntents } from "../../types/gateway/gateway_intents.ts"; -import type { RequestGuildMembers } from "../../types/guilds/request_guild_members.ts"; -import { Errors } from "../../types/misc/errors.ts"; +import type { RequestGuildMembers } from "../../types/members/request_guild_members.ts"; import { Collection } from "../../util/collection.ts"; import { sendShardMessage } from "../../ws/send_shard_message.ts"; import { ws } from "../../ws/ws.ts"; @@ -24,7 +24,7 @@ export function fetchMembers( // You can request 1 member without the intent if ( (!options?.limit || options.limit > 1) && - !(ws.identifyPayload.intents & DiscordGatewayIntents.GUILD_MEMBERS) + !(ws.identifyPayload.intents & DiscordGatewayIntents.GuildMembers) ) { throw new Error(Errors.MISSING_INTENT_GUILD_MEMBERS); } diff --git a/src/helpers/members/get_member.ts b/src/helpers/members/get_member.ts index 4949f3165..e7887bc65 100644 --- a/src/helpers/members/get_member.ts +++ b/src/helpers/members/get_member.ts @@ -1,7 +1,7 @@ import { cacheHandlers } from "../../cache.ts"; import { rest } from "../../rest/rest.ts"; import { structures } from "../../structures/mod.ts"; -import { GuildMemberWithUser } from "../../types/guilds/guild_member.ts"; +import type { GuildMemberWithUser } from "../../types/members/guild_member.ts"; import { endpoints } from "../../util/constants.ts"; /** Returns a guild member object for the specified user. diff --git a/src/helpers/members/get_members.ts b/src/helpers/members/get_members.ts index 9e0b10a02..602657df5 100644 --- a/src/helpers/members/get_members.ts +++ b/src/helpers/members/get_members.ts @@ -3,10 +3,10 @@ import { cacheHandlers } from "../../cache.ts"; import { rest } from "../../rest/rest.ts"; import { DiscordenoMember } from "../../structures/member.ts"; import { structures } from "../../structures/mod.ts"; +import { Errors } from "../../types/discordeno/errors.ts"; import { DiscordGatewayIntents } from "../../types/gateway/gateway_intents.ts"; -import { GuildMemberWithUser } from "../../types/guilds/guild_member.ts"; -import { ListGuildMembers } from "../../types/guilds/list_guild_members.ts"; -import { Errors } from "../../types/misc/errors.ts"; +import type { GuildMemberWithUser } from "../../types/members/guild_member.ts"; +import type { ListGuildMembers } from "../../types/members/list_guild_members.ts"; import { bigintToSnowflake } from "../../util/bigint.ts"; import { Collection } from "../../util/collection.ts"; import { endpoints } from "../../util/constants.ts"; @@ -24,7 +24,7 @@ export async function getMembers( guildId: bigint, options?: ListGuildMembers & { addToCache?: boolean }, ) { - if (!(ws.identifyPayload.intents && DiscordGatewayIntents.GUILD_MEMBERS)) { + if (!(ws.identifyPayload.intents && DiscordGatewayIntents.GuildMembers)) { throw new Error(Errors.MISSING_INTENT_GUILD_MEMBERS); } diff --git a/src/helpers/members/kick_member.ts b/src/helpers/members/kick_member.ts index 4b1151574..421cd9b5a 100644 --- a/src/helpers/members/kick_member.ts +++ b/src/helpers/members/kick_member.ts @@ -1,6 +1,6 @@ import { botId } from "../../bot.ts"; import { rest } from "../../rest/rest.ts"; -import { Errors } from "../../types/misc/errors.ts"; +import { Errors } from "../../types/discordeno/errors.ts"; import { endpoints } from "../../util/constants.ts"; import { highestRole, diff --git a/src/helpers/members/prune_members.ts b/src/helpers/members/prune_members.ts index 0ee5010fb..523daa2c1 100644 --- a/src/helpers/members/prune_members.ts +++ b/src/helpers/members/prune_members.ts @@ -1,9 +1,9 @@ import { rest } from "../../rest/rest.ts"; -import { BeginGuildPrune } from "../../types/guilds/begin_guild_prune.ts"; -import { Errors } from "../../types/misc/errors.ts"; +import { Errors } from "../../types/discordeno/errors.ts"; +import type { BeginGuildPrune } from "../../types/guilds/begin_guild_prune.ts"; import { endpoints } from "../../util/constants.ts"; import { requireBotGuildPermissions } from "../../util/permissions.ts"; -import { camelKeysToSnakeCase } from "../../util/utils.ts"; +import { snakelize } from "../../util/utils.ts"; /** * Begin a prune operation. Requires the KICK_MEMBERS permission. Returns an object with one 'pruned' key indicating the number of members that were removed in the prune operation. For large guilds it's recommended to set the computePruneCount option to false, forcing 'pruned' to null. Fires multiple Guild Member Remove Gateway events. @@ -22,7 +22,7 @@ export async function pruneMembers( const result = await rest.runMethod<{ pruned: number }>( "post", endpoints.GUILD_PRUNE(guildId), - camelKeysToSnakeCase(options), + snakelize(options), ); return result.pruned; diff --git a/src/helpers/members/search_members.ts b/src/helpers/members/search_members.ts index b57745f1d..0c27f884a 100644 --- a/src/helpers/members/search_members.ts +++ b/src/helpers/members/search_members.ts @@ -2,9 +2,9 @@ import { cacheHandlers } from "../../cache.ts"; import { rest } from "../../rest/rest.ts"; import { DiscordenoMember } from "../../structures/member.ts"; import { structures } from "../../structures/mod.ts"; -import { GuildMemberWithUser } from "../../types/guilds/guild_member.ts"; -import { SearchGuildMembers } from "../../types/members/search_guild_members.ts"; -import { Errors } from "../../types/misc/errors.ts"; +import { Errors } from "../../types/discordeno/errors.ts"; +import type { GuildMemberWithUser } from "../../types/members/guild_member.ts"; +import type { SearchGuildMembers } from "../../types/members/search_guild_members.ts"; import { Collection } from "../../util/collection.ts"; import { endpoints } from "../../util/constants.ts"; diff --git a/src/helpers/members/send_direct_message.ts b/src/helpers/members/send_direct_message.ts index 4aae8e391..710994a62 100644 --- a/src/helpers/members/send_direct_message.ts +++ b/src/helpers/members/send_direct_message.ts @@ -1,8 +1,8 @@ import { cacheHandlers } from "../../cache.ts"; import { rest } from "../../rest/rest.ts"; import { structures } from "../../structures/mod.ts"; -import { Channel } from "../../types/channels/channel.ts"; -import { CreateMessage } from "../../types/messages/create_message.ts"; +import type { Channel } from "../../types/channels/channel.ts"; +import type { CreateMessage } from "../../types/messages/create_message.ts"; import { endpoints } from "../../util/constants.ts"; import { sendMessage } from "../messages/send_message.ts"; diff --git a/src/helpers/messages/delete_messages.ts b/src/helpers/messages/delete_messages.ts index b8b3683a8..afed2cc95 100644 --- a/src/helpers/messages/delete_messages.ts +++ b/src/helpers/messages/delete_messages.ts @@ -1,5 +1,5 @@ import { rest } from "../../rest/rest.ts"; -import { Errors } from "../../types/misc/errors.ts"; +import { Errors } from "../../types/discordeno/errors.ts"; import { endpoints } from "../../util/constants.ts"; import { requireBotChannelPermissions } from "../../util/permissions.ts"; diff --git a/src/helpers/messages/edit_message.ts b/src/helpers/messages/edit_message.ts index e45bc4577..637133b08 100644 --- a/src/helpers/messages/edit_message.ts +++ b/src/helpers/messages/edit_message.ts @@ -3,9 +3,9 @@ import { rest } from "../../rest/rest.ts"; import { DiscordenoMessage } from "../../structures/message.ts"; import { structures } from "../../structures/mod.ts"; import { EditMessage } from "../../types/messages/edit_message.ts"; -import { Message } from "../../types/messages/message.ts"; -import { Errors } from "../../types/misc/errors.ts"; -import { PermissionStrings } from "../../types/permissions/permission_strings.ts"; +import type { Message } from "../../types/messages/message.ts"; +import { Errors } from "../../types/discordeno/errors.ts"; +import type { PermissionStrings } from "../../types/permissions/permission_strings.ts"; import { endpoints } from "../../util/constants.ts"; import { requireBotChannelPermissions } from "../../util/permissions.ts"; diff --git a/src/helpers/messages/get_message.ts b/src/helpers/messages/get_message.ts index 7779a9d67..863eb07e0 100644 --- a/src/helpers/messages/get_message.ts +++ b/src/helpers/messages/get_message.ts @@ -1,7 +1,7 @@ import { cacheHandlers } from "../../cache.ts"; import { rest } from "../../rest/rest.ts"; import { structures } from "../../structures/mod.ts"; -import { Message } from "../../types/messages/message.ts"; +import type { Message } from "../../types/messages/message.ts"; import { endpoints } from "../../util/constants.ts"; import { requireBotChannelPermissions } from "../../util/permissions.ts"; diff --git a/src/helpers/messages/get_messages.ts b/src/helpers/messages/get_messages.ts index f12e4eb0c..79b29d238 100644 --- a/src/helpers/messages/get_messages.ts +++ b/src/helpers/messages/get_messages.ts @@ -6,7 +6,7 @@ import { GetMessagesBefore, GetMessagesLimit, } from "../../types/messages/get_messages.ts"; -import { Message } from "../../types/messages/message.ts"; +import type { Message } from "../../types/messages/message.ts"; import { endpoints } from "../../util/constants.ts"; import { requireBotChannelPermissions } from "../../util/permissions.ts"; diff --git a/src/helpers/messages/get_reactions.ts b/src/helpers/messages/get_reactions.ts index 04ee9806e..b06dd5709 100644 --- a/src/helpers/messages/get_reactions.ts +++ b/src/helpers/messages/get_reactions.ts @@ -1,6 +1,6 @@ import { rest } from "../../rest/rest.ts"; -import { GetReactions } from "../../types/messages/message_get_reactions.ts"; -import { User } from "../../types/users/user.ts"; +import type { GetReactions } from "../../types/messages/message_get_reactions.ts"; +import type { User } from "../../types/users/user.ts"; import { Collection } from "../../util/collection.ts"; import { endpoints } from "../../util/constants.ts"; diff --git a/src/helpers/messages/publish_message.ts b/src/helpers/messages/publish_message.ts index 5c60a38bf..877d7c32d 100644 --- a/src/helpers/messages/publish_message.ts +++ b/src/helpers/messages/publish_message.ts @@ -1,6 +1,6 @@ import { rest } from "../../rest/rest.ts"; import { structures } from "../../structures/mod.ts"; -import { Message } from "../../types/messages/message.ts"; +import type { Message } from "../../types/messages/message.ts"; import { endpoints } from "../../util/constants.ts"; /** Crosspost a message in a News Channel to following channels. */ diff --git a/src/helpers/messages/send_message.ts b/src/helpers/messages/send_message.ts index 0dd952d6e..6f21f6912 100644 --- a/src/helpers/messages/send_message.ts +++ b/src/helpers/messages/send_message.ts @@ -2,15 +2,15 @@ import { cacheHandlers } from "../../cache.ts"; import { rest } from "../../rest/rest.ts"; import { structures } from "../../structures/mod.ts"; import { DiscordChannelTypes } from "../../types/channels/channel_types.ts"; +import { Errors } from "../../types/discordeno/errors.ts"; import { DiscordAllowedMentionsTypes } from "../../types/messages/allowed_mentions_types.ts"; import { ButtonStyles } from "../../types/messages/components/button_styles.ts"; -import { CreateMessage } from "../../types/messages/create_message.ts"; -import { Message } from "../../types/messages/message.ts"; -import { Errors } from "../../types/misc/errors.ts"; -import { PermissionStrings } from "../../types/permissions/permission_strings.ts"; +import type { CreateMessage } from "../../types/messages/create_message.ts"; +import type { Message } from "../../types/messages/message.ts"; +import type { PermissionStrings } from "../../types/permissions/permission_strings.ts"; import { endpoints } from "../../util/constants.ts"; import { requireBotChannelPermissions } from "../../util/permissions.ts"; -import { camelKeysToSnakeCase } from "../../util/utils.ts"; +import { snakelize } from "../../util/utils.ts"; import { validateLength } from "../../util/validate_length.ts"; import { isActionRow } from "../type_guards/is_action_row.ts"; import { isButton } from "../type_guards/is_button.ts"; @@ -27,8 +27,11 @@ export async function sendMessage( if ( ![ DiscordChannelTypes.DM, - DiscordChannelTypes.GUILD_NEWS, - DiscordChannelTypes.GUILD_TEXT, + DiscordChannelTypes.GuildNews, + DiscordChannelTypes.GuildText, + DiscordChannelTypes.GuildPublicThread, + DiscordChannelTypes.GuildPivateThread, + DiscordChannelTypes.GuildNewsThread, ].includes(channel.type) ) { throw new Error(Errors.CHANNEL_NOT_TEXT_BASED); @@ -142,17 +145,10 @@ export async function sendMessage( } } - if ( - content.nonce && - !validateLength(content.nonce.toString(), { max: 25 }) - ) { - throw new Error(Errors.NONCE_TOO_LONG); - } - const result = await rest.runMethod( "post", endpoints.CHANNEL_MESSAGES(channelId), - camelKeysToSnakeCase({ + snakelize({ ...content, ...(content.messageReference?.messageId ? { diff --git a/src/helpers/members/edit_bot_profile.ts b/src/helpers/misc/edit_bot_profile.ts similarity index 90% rename from src/helpers/members/edit_bot_profile.ts rename to src/helpers/misc/edit_bot_profile.ts index 2e4fd6c7c..11efed089 100644 --- a/src/helpers/members/edit_bot_profile.ts +++ b/src/helpers/misc/edit_bot_profile.ts @@ -1,6 +1,6 @@ import { rest } from "../../rest/rest.ts"; -import { Errors } from "../../types/misc/errors.ts"; -import { User } from "../../types/mod.ts"; +import { Errors } from "../../types/discordeno/errors.ts"; +import type { User } from "../../types/users/user.ts"; import { endpoints } from "../../util/constants.ts"; import { urlToBase64 } from "../../util/utils.ts"; diff --git a/src/helpers/misc/get_gateway_bot.ts b/src/helpers/misc/get_gateway_bot.ts index d765780be..ac7594177 100644 --- a/src/helpers/misc/get_gateway_bot.ts +++ b/src/helpers/misc/get_gateway_bot.ts @@ -1,5 +1,5 @@ import { rest } from "../../rest/rest.ts"; -import { GetGatewayBot } from "../../types/gateway/get_gateway_bot.ts"; +import type { GetGatewayBot } from "../../types/gateway/get_gateway_bot.ts"; import { endpoints } from "../../util/constants.ts"; /** Get the bots Gateway metadata that can help during the operation of large or sharded bots. */ diff --git a/src/helpers/misc/get_user.ts b/src/helpers/misc/get_user.ts index 0c1517c91..f4632beb5 100644 --- a/src/helpers/misc/get_user.ts +++ b/src/helpers/misc/get_user.ts @@ -1,5 +1,5 @@ import { rest } from "../../rest/rest.ts"; -import { User } from "../../types/users/user.ts"; +import type { User } from "../../types/users/user.ts"; import { endpoints } from "../../util/constants.ts"; /** This function will return the raw user payload in the rare cases you need to fetch a user directly from the API. */ diff --git a/src/helpers/mod.ts b/src/helpers/mod.ts index 44bb6a467..356938908 100644 --- a/src/helpers/mod.ts +++ b/src/helpers/mod.ts @@ -13,19 +13,7 @@ import { getPins } from "./channels/get_pins.ts"; import { isChannelSynced } from "./channels/is_channel_synced.ts"; import { startTyping } from "./channels/start_typing.ts"; import { swapChannels } from "./channels/swap_channels.ts"; -import { batchEditSlashCommandPermissions } from "./commands/batch_edit_slash_command_permissions.ts"; -import { createSlashCommand } from "./commands/create_slash_command.ts"; -import { deleteSlashCommand } from "./commands/delete_slash_command.ts"; -import { deleteSlashResponse } from "./commands/delete_slash_response.ts"; -import { editSlashCommandPermissions } from "./commands/edit_slash_command_permissions.ts"; -import { editSlashResponse } from "./commands/edit_slash_response.ts"; -import { getSlashCommand } from "./commands/get_slash_command.ts"; -import { getSlashCommands } from "./commands/get_slash_commands.ts"; -import { getSlashCommandPermission } from "./commands/get_slash_command_permission.ts"; -import { getSlashCommandPermissions } from "./commands/get_slash_command_permissions.ts"; -import { sendInteractionResponse } from "./commands/send_interaction_response.ts"; -import { upsertSlashCommand } from "./commands/upsert_slash_command.ts"; -import { upsertSlashCommands } from "./commands/upsert_slash_commands.ts"; +import { updateBotVoiceState } from "./channels/update_voice_state.ts"; import { addDiscoverySubcategory } from "./discovery/add_discovery_subcategory.ts"; import { editDiscovery } from "./discovery/edit_discovery.ts"; import { getDiscoveryCategories } from "./discovery/get_discovery_categories.ts"; @@ -61,6 +49,20 @@ import { guildSplashURL } from "./guilds/guild_splash_url.ts"; import { leaveGuild } from "./guilds/leave_guild.ts"; import { deleteIntegration } from "./integrations/delete_integration.ts"; import { getIntegrations } from "./integrations/get_integrations.ts"; +import { batchEditSlashCommandPermissions } from "./interactions/commands/batch_edit_slash_command_permissions.ts"; +import { createSlashCommand } from "./interactions/commands/create_slash_command.ts"; +import { deleteSlashCommand } from "./interactions/commands/delete_slash_command.ts"; +import { deleteSlashResponse } from "./interactions/commands/delete_slash_response.ts"; +import { editSlashCommandPermissions } from "./interactions/commands/edit_slash_command_permissions.ts"; +import { editSlashResponse } from "./interactions/commands/edit_slash_response.ts"; +import { getSlashCommand } from "./interactions/commands/get_slash_command.ts"; +import { getSlashCommands } from "./interactions/commands/get_slash_commands.ts"; +import { getSlashCommandPermission } from "./interactions/commands/get_slash_command_permission.ts"; +import { getSlashCommandPermissions } from "./interactions/commands/get_slash_command_permissions.ts"; +import { upsertSlashCommand } from "./interactions/commands/upsert_slash_command.ts"; +import { upsertSlashCommands } from "./interactions/commands/upsert_slash_commands.ts"; +import { getOriginalInteractionResponse } from "./interactions/get_original_interaction_response.ts"; +import { sendInteractionResponse } from "./interactions/send_interaction_response.ts"; import { createInvite } from "./invites/create_invite.ts"; import { deleteInvite } from "./invites/delete_invite.ts"; import { getChannelInvites } from "./invites/get_channel_invites.ts"; @@ -70,7 +72,6 @@ import { avatarURL } from "./members/avatar_url.ts"; import { ban, banMember } from "./members/ban_member.ts"; import { disconnectMember } from "./members/disconnect_member.ts"; import { editBotNickname } from "./members/edit_bot_nickname.ts"; -import { editBotProfile } from "./members/edit_bot_profile.ts"; import { editMember } from "./members/edit_member.ts"; import { fetchMembers } from "./members/fetch_members.ts"; import { getMember } from "./members/get_member.ts"; @@ -95,6 +96,7 @@ import { removeReaction } from "./messages/remove_reaction.ts"; import { removeReactionEmoji } from "./messages/remove_reaction_emoji.ts"; import { sendMessage } from "./messages/send_message.ts"; import { unpin, unpinMessage } from "./messages/unpin_message.ts"; +import { editBotProfile } from "./misc/edit_bot_profile.ts"; import { editBotStatus } from "./misc/edit_bot_status.ts"; import { getGatewayBot } from "./misc/get_gateway_bot.ts"; import { getUser } from "./misc/get_user.ts"; @@ -111,6 +113,9 @@ import { editGuildTemplate } from "./templates/edit_guild_template.ts"; import { getGuildTemplates } from "./templates/get_guild_templates.ts"; import { getTemplate } from "./templates/get_template.ts"; import { syncGuildTemplate } from "./templates/sync_guild_template.ts"; +// Type Guards +import { isActionRow } from "./type_guards/is_action_row.ts"; +import { isButton } from "./type_guards/is_button.ts"; import { createWebhook } from "./webhooks/create_webhook.ts"; import { deleteWebhook } from "./webhooks/delete_webhook.ts"; import { deleteWebhookMessage } from "./webhooks/delete_webhook_message.ts"; @@ -118,13 +123,11 @@ import { deleteWebhookWithToken } from "./webhooks/delete_webhook_with_token.ts" import { editWebhook } from "./webhooks/edit_webhook.ts"; import { editWebhookMessage } from "./webhooks/edit_webhook_message.ts"; import { editWebhookWithToken } from "./webhooks/edit_webhook_with_token.ts"; -import { executeWebhook } from "./webhooks/execute_webhook.ts"; import { getWebhook } from "./webhooks/get_webhook.ts"; import { getWebhooks } from "./webhooks/get_webhooks.ts"; +import { getWebhookMessage } from "./webhooks/get_webhook_message.ts"; import { getWebhookWithToken } from "./webhooks/get_webhook_with_token.ts"; -// Type Guards -import { isActionRow } from "./type_guards/is_action_row.ts"; -import { isButton } from "./type_guards/is_button.ts"; +import { sendWebhook } from "./webhooks/send_webhook.ts"; export { addDiscoverySubcategory, @@ -181,7 +184,6 @@ export { editWelcomeScreen, editWidget, emojiURL, - executeWebhook, fetchMembers, followChannel, getAuditLogs, @@ -206,6 +208,7 @@ export { getMembers, getMessage, getMessages, + getOriginalInteractionResponse, getPins, getPruneCount, getReactions, @@ -219,6 +222,7 @@ export { getVanityURL, getVoiceRegions, getWebhook, + getWebhookMessage, getWebhooks, getWebhookWithToken, getWelcomeScreen, @@ -247,6 +251,7 @@ export { sendDirectMessage, sendInteractionResponse, sendMessage, + sendWebhook, startTyping, swapChannels, syncGuildTemplate, @@ -254,6 +259,7 @@ export { unbanMember, unpin, unpinMessage, + updateBotVoiceState, upsertSlashCommand, upsertSlashCommands, validDiscoveryTerm, @@ -275,6 +281,7 @@ export let helpers = { isChannelSynced, startTyping, swapChannels, + updateBotVoiceState, // commands createSlashCommand, deleteSlashCommand, @@ -289,6 +296,7 @@ export let helpers = { getSlashCommands, upsertSlashCommand, upsertSlashCommands, + getOriginalInteractionResponse, // emojis createEmoji, deleteEmoji, @@ -392,10 +400,11 @@ export let helpers = { editWebhookMessage, editWebhookWithToken, editWebhook, - executeWebhook, + sendWebhook, getWebhookWithToken, getWebhook, getWebhooks, + getWebhookMessage, }; export type Helpers = typeof helpers; diff --git a/src/helpers/roles/add_role.ts b/src/helpers/roles/add_role.ts index b207ad9c8..a080f01ba 100644 --- a/src/helpers/roles/add_role.ts +++ b/src/helpers/roles/add_role.ts @@ -1,6 +1,6 @@ import { botId } from "../../bot.ts"; import { rest } from "../../rest/rest.ts"; -import { Errors } from "../../types/misc/errors.ts"; +import { Errors } from "../../types/discordeno/errors.ts"; import { endpoints } from "../../util/constants.ts"; import { isHigherPosition, diff --git a/src/helpers/roles/create_role.ts b/src/helpers/roles/create_role.ts index 363809489..89d4f3bc0 100644 --- a/src/helpers/roles/create_role.ts +++ b/src/helpers/roles/create_role.ts @@ -2,7 +2,7 @@ import { cacheHandlers } from "../../cache.ts"; import { rest } from "../../rest/rest.ts"; import { structures } from "../../structures/mod.ts"; import { CreateGuildRole } from "../../types/guilds/create_guild_role.ts"; -import { Role } from "../../types/permissions/role.ts"; +import type { Role } from "../../types/permissions/role.ts"; import { endpoints } from "../../util/constants.ts"; import { calculateBits, @@ -31,9 +31,13 @@ export async function createRole( role: result, guildId, }); - const guild = await cacheHandlers.get("guilds", guildId); - guild?.roles.set(role.id, role); - // TODO: ADD TO CACHE? + const guild = await cacheHandlers.get("guilds", guildId); + if (guild) { + guild.roles.set(role.id, role); + + await cacheHandlers.set("guilds", guildId, guild); + } + return role; } diff --git a/src/helpers/roles/edit_role.ts b/src/helpers/roles/edit_role.ts index ad178d063..3b0595913 100644 --- a/src/helpers/roles/edit_role.ts +++ b/src/helpers/roles/edit_role.ts @@ -1,6 +1,7 @@ import { rest } from "../../rest/rest.ts"; import { structures } from "../../structures/mod.ts"; -import { CreateGuildRole, Role } from "../../types/mod.ts"; +import type { CreateGuildRole } from "../../types/guilds/create_guild_role.ts"; +import type { Role } from "../../types/permissions/role.ts"; import { endpoints } from "../../util/constants.ts"; import { calculateBits, diff --git a/src/helpers/roles/get_roles.ts b/src/helpers/roles/get_roles.ts index b65dbf882..a4529e507 100644 --- a/src/helpers/roles/get_roles.ts +++ b/src/helpers/roles/get_roles.ts @@ -1,5 +1,7 @@ +import { cacheHandlers } from "../../cache.ts"; import { rest } from "../../rest/rest.ts"; -import { Role } from "../../types/permissions/role.ts"; +import { structures } from "../../structures/mod.ts"; +import type { Role } from "../../types/permissions/role.ts"; import { Collection } from "../../util/collection.ts"; import { endpoints } from "../../util/constants.ts"; import { requireBotGuildPermissions } from "../../util/permissions.ts"; @@ -8,7 +10,7 @@ import { requireBotGuildPermissions } from "../../util/permissions.ts"; * * ⚠️ **If you need this, you are probably doing something wrong. This is not intended for use. Your roles will be cached in your guild.** */ -export async function getRoles(guildId: bigint) { +export async function getRoles(guildId: bigint, addToCache = true) { await requireBotGuildPermissions(guildId, ["MANAGE_ROLES"]); const result = await rest.runMethod( @@ -16,9 +18,23 @@ export async function getRoles(guildId: bigint) { endpoints.GUILD_ROLES(guildId), ); - // TODO: addToCache - - return new Collection( - result.map((role) => [role.id, role]), + const roleStructures = await Promise.all( + result.map(async (role) => + await structures.createDiscordenoRole({ role, guildId }) + ), ); + + const roles = new Collection( + roleStructures.map((role) => [role.id, role]), + ); + + if (addToCache) { + const guild = await cacheHandlers.get("guilds", guildId); + if (guild) { + guild.roles = roles; + await cacheHandlers.set("guilds", guild.id, guild); + } + } + + return roleStructures; } diff --git a/src/helpers/roles/remove_role.ts b/src/helpers/roles/remove_role.ts index 645cd990f..feb3c923b 100644 --- a/src/helpers/roles/remove_role.ts +++ b/src/helpers/roles/remove_role.ts @@ -1,6 +1,6 @@ import { botId } from "../../bot.ts"; import { rest } from "../../rest/rest.ts"; -import { Errors } from "../../types/misc/errors.ts"; +import { Errors } from "../../types/discordeno/errors.ts"; import { endpoints } from "../../util/constants.ts"; import { isHigherPosition, diff --git a/src/helpers/templates/create_guild_from_template.ts b/src/helpers/templates/create_guild_from_template.ts index 770f71299..9c17dd0aa 100644 --- a/src/helpers/templates/create_guild_from_template.ts +++ b/src/helpers/templates/create_guild_from_template.ts @@ -1,9 +1,11 @@ import { cacheHandlers } from "../../cache.ts"; import { rest } from "../../rest/rest.ts"; -import { Guild } from "../../types/guilds/guild.ts"; -import { CreateGuildFromTemplate } from "../../types/templates/create_guild_from_template.ts"; +import { structures } from "../../structures/mod.ts"; +import type { Guild } from "../../types/guilds/guild.ts"; +import type { CreateGuildFromTemplate } from "../../types/templates/create_guild_from_template.ts"; import { endpoints } from "../../util/constants.ts"; import { urlToBase64 } from "../../util/utils.ts"; +import { ws } from "../../ws/ws.ts"; /** * Create a new guild based on a template @@ -23,11 +25,17 @@ export async function createGuildFromTemplate( data.icon = await urlToBase64(data.icon); } - // TODO: discordeno guild? - - return await rest.runMethod( + const createdGuild = await rest.runMethod( "post", endpoints.GUILD_TEMPLATE(templateCode), data, ); + + return await structures.createDiscordenoGuild( + createdGuild, + Number( + (BigInt(createdGuild.id) >> 22n % BigInt(ws.botGatewayData.shards)) + .toString(), + ), + ); } diff --git a/src/helpers/templates/create_guild_template.ts b/src/helpers/templates/create_guild_template.ts index b6d54feed..c8f3d5dfb 100644 --- a/src/helpers/templates/create_guild_template.ts +++ b/src/helpers/templates/create_guild_template.ts @@ -1,5 +1,5 @@ import { rest } from "../../rest/rest.ts"; -import { Template } from "../../types/templates/template.ts"; +import type { Template } from "../../types/templates/template.ts"; import { endpoints } from "../../util/constants.ts"; import { requireBotGuildPermissions } from "../../util/permissions.ts"; diff --git a/src/helpers/templates/delete_guild_template.ts b/src/helpers/templates/delete_guild_template.ts index 4cacb22e7..253a39b4e 100644 --- a/src/helpers/templates/delete_guild_template.ts +++ b/src/helpers/templates/delete_guild_template.ts @@ -1,5 +1,5 @@ import { rest } from "../../rest/rest.ts"; -import { Template } from "../../types/templates/template.ts"; +import type { Template } from "../../types/templates/template.ts"; import { endpoints } from "../../util/constants.ts"; import { requireBotGuildPermissions } from "../../util/permissions.ts"; diff --git a/src/helpers/templates/edit_guild_template.ts b/src/helpers/templates/edit_guild_template.ts index d35779cbd..d4aee54df 100644 --- a/src/helpers/templates/edit_guild_template.ts +++ b/src/helpers/templates/edit_guild_template.ts @@ -1,6 +1,6 @@ import { rest } from "../../rest/rest.ts"; -import { ModifyGuildTemplate } from "../../types/templates/modify_guild_template.ts"; -import { Template } from "../../types/templates/template.ts"; +import type { ModifyGuildTemplate } from "../../types/templates/modify_guild_template.ts"; +import type { Template } from "../../types/templates/template.ts"; import { endpoints } from "../../util/constants.ts"; import { requireBotGuildPermissions } from "../../util/permissions.ts"; diff --git a/src/helpers/templates/get_guild_templates.ts b/src/helpers/templates/get_guild_templates.ts index 30ba5be5f..c2a3d8521 100644 --- a/src/helpers/templates/get_guild_templates.ts +++ b/src/helpers/templates/get_guild_templates.ts @@ -1,5 +1,5 @@ import { rest } from "../../rest/rest.ts"; -import { Template } from "../../types/templates/template.ts"; +import type { Template } from "../../types/templates/template.ts"; import { Collection } from "../../util/collection.ts"; import { endpoints } from "../../util/constants.ts"; import { requireBotGuildPermissions } from "../../util/permissions.ts"; diff --git a/src/helpers/templates/get_template.ts b/src/helpers/templates/get_template.ts index 41213e967..f67d9ffe0 100644 --- a/src/helpers/templates/get_template.ts +++ b/src/helpers/templates/get_template.ts @@ -1,5 +1,5 @@ import { rest } from "../../rest/rest.ts"; -import { Template } from "../../types/templates/template.ts"; +import type { Template } from "../../types/templates/template.ts"; import { endpoints } from "../../util/constants.ts"; /** Returns the guild template if it exists */ diff --git a/src/helpers/templates/sync_guild_template.ts b/src/helpers/templates/sync_guild_template.ts index 235952321..24fe0fc05 100644 --- a/src/helpers/templates/sync_guild_template.ts +++ b/src/helpers/templates/sync_guild_template.ts @@ -1,5 +1,5 @@ import { rest } from "../../rest/rest.ts"; -import { Template } from "../../types/templates/template.ts"; +import type { Template } from "../../types/templates/template.ts"; import { endpoints } from "../../util/constants.ts"; import { requireBotGuildPermissions } from "../../util/permissions.ts"; diff --git a/src/helpers/type_guards/is_action_row.ts b/src/helpers/type_guards/is_action_row.ts index c64fc8a6d..2dec9aafe 100644 --- a/src/helpers/type_guards/is_action_row.ts +++ b/src/helpers/type_guards/is_action_row.ts @@ -1,5 +1,5 @@ -import { ActionRow } from "../../types/messages/components/action_row.ts"; -import { MessageComponent } from "../../types/messages/components/message_components.ts"; +import type { ActionRow } from "../../types/messages/components/action_row.ts"; +import type { MessageComponent } from "../../types/messages/components/message_components.ts"; import { MessageComponentTypes } from "../../types/messages/components/message_component_types.ts"; /** A type guard function to tell if it is a action row component */ diff --git a/src/helpers/type_guards/is_button.ts b/src/helpers/type_guards/is_button.ts index dfe2b92cd..acc99645b 100644 --- a/src/helpers/type_guards/is_button.ts +++ b/src/helpers/type_guards/is_button.ts @@ -1,5 +1,5 @@ -import { ButtonComponent } from "../../types/messages/components/button_component.ts"; -import { MessageComponent } from "../../types/messages/components/message_components.ts"; +import type { ButtonComponent } from "../../types/messages/components/button_component.ts"; +import type { MessageComponent } from "../../types/messages/components/message_components.ts"; import { MessageComponentTypes } from "../../types/messages/components/message_component_types.ts"; /** A type guard function to tell if it is a button component */ diff --git a/src/helpers/webhooks/create_webhook.ts b/src/helpers/webhooks/create_webhook.ts index dd169d286..14055633d 100644 --- a/src/helpers/webhooks/create_webhook.ts +++ b/src/helpers/webhooks/create_webhook.ts @@ -1,7 +1,7 @@ import { rest } from "../../rest/rest.ts"; -import { Errors } from "../../types/misc/errors.ts"; -import { CreateWebhook } from "../../types/webhooks/create_webhook.ts"; -import { Webhook } from "../../types/webhooks/webhook.ts"; +import { Errors } from "../../types/discordeno/errors.ts"; +import type { CreateWebhook } from "../../types/webhooks/create_webhook.ts"; +import type { Webhook } from "../../types/webhooks/webhook.ts"; import { endpoints } from "../../util/constants.ts"; import { requireBotChannelPermissions } from "../../util/permissions.ts"; import { urlToBase64 } from "../../util/utils.ts"; diff --git a/src/helpers/webhooks/edit_webhook.ts b/src/helpers/webhooks/edit_webhook.ts index 28dc6b11a..244bd129e 100644 --- a/src/helpers/webhooks/edit_webhook.ts +++ b/src/helpers/webhooks/edit_webhook.ts @@ -1,6 +1,6 @@ import { rest } from "../../rest/rest.ts"; -import { ModifyWebhook } from "../../types/webhooks/modify_webhook.ts"; -import { Webhook } from "../../types/webhooks/webhook.ts"; +import type { ModifyWebhook } from "../../types/webhooks/modify_webhook.ts"; +import type { Webhook } from "../../types/webhooks/webhook.ts"; import { endpoints } from "../../util/constants.ts"; import { requireBotChannelPermissions } from "../../util/permissions.ts"; diff --git a/src/helpers/webhooks/edit_webhook_message.ts b/src/helpers/webhooks/edit_webhook_message.ts index d1193a885..c066d2933 100644 --- a/src/helpers/webhooks/edit_webhook_message.ts +++ b/src/helpers/webhooks/edit_webhook_message.ts @@ -1,16 +1,15 @@ import { rest } from "../../rest/rest.ts"; import { structures } from "../../structures/mod.ts"; import { DiscordAllowedMentionsTypes } from "../../types/messages/allowed_mentions_types.ts"; -import { Message } from "../../types/messages/message.ts"; -import { Errors } from "../../types/misc/errors.ts"; -import { EditWebhookMessage } from "../../types/webhooks/edit_webhook_message.ts"; +import type { Message } from "../../types/messages/message.ts"; +import { Errors } from "../../types/discordeno/errors.ts"; +import type { EditWebhookMessage } from "../../types/webhooks/edit_webhook_message.ts"; import { endpoints } from "../../util/constants.ts"; export async function editWebhookMessage( webhookId: bigint, webhookToken: string, - messageId: bigint, - options: EditWebhookMessage, + options: EditWebhookMessage & { messageId?: bigint }, ) { if (options.content && options.content.length > 2000) { throw Error(Errors.MESSAGE_MAX_LENGTH); @@ -62,7 +61,9 @@ export async function editWebhookMessage( const result = await rest.runMethod( "patch", - endpoints.WEBHOOK_MESSAGE(webhookId, webhookToken, messageId), + options.messageId + ? endpoints.WEBHOOK_MESSAGE(webhookId, webhookToken, options.messageId) + : endpoints.WEBHOOK_MESSAGE_ORIGINAL(webhookId, webhookToken), { ...options, allowedMentions: options.allowedMentions }, ); diff --git a/src/helpers/webhooks/edit_webhook_with_token.ts b/src/helpers/webhooks/edit_webhook_with_token.ts index 0d35ead16..3332a1d13 100644 --- a/src/helpers/webhooks/edit_webhook_with_token.ts +++ b/src/helpers/webhooks/edit_webhook_with_token.ts @@ -1,6 +1,6 @@ import { rest } from "../../rest/rest.ts"; -import { ModifyWebhook } from "../../types/webhooks/modify_webhook.ts"; -import { Webhook } from "../../types/webhooks/webhook.ts"; +import type { ModifyWebhook } from "../../types/webhooks/modify_webhook.ts"; +import type { Webhook } from "../../types/webhooks/webhook.ts"; import { endpoints } from "../../util/constants.ts"; /** Edit a webhook. Returns the updated webhook object on success. */ diff --git a/src/helpers/webhooks/get_webhook.ts b/src/helpers/webhooks/get_webhook.ts index 6dd2e655d..86f40ab5e 100644 --- a/src/helpers/webhooks/get_webhook.ts +++ b/src/helpers/webhooks/get_webhook.ts @@ -1,5 +1,5 @@ import { rest } from "../../rest/rest.ts"; -import { Webhook } from "../../types/webhooks/webhook.ts"; +import type { Webhook } from "../../types/webhooks/webhook.ts"; import { endpoints } from "../../util/constants.ts"; /** Returns the new webhook object for the given id. */ diff --git a/src/helpers/webhooks/get_webhook_message.ts b/src/helpers/webhooks/get_webhook_message.ts new file mode 100644 index 000000000..d59fc02a7 --- /dev/null +++ b/src/helpers/webhooks/get_webhook_message.ts @@ -0,0 +1,18 @@ +import { rest } from "../../rest/rest.ts"; +import { structures } from "../../structures/mod.ts"; +import type { Message } from "../../types/messages/message.ts"; +import { endpoints } from "../../util/constants.ts"; + +/** Returns a previousy-sent webhook message from the same token. Returns a message object on success. */ +export async function getWebhookMessage( + webhookId: bigint, + webhookToken: string, + messageId: bigint, +) { + const result = await rest.runMethod( + "get", + endpoints.WEBHOOK_MESSAGE(webhookId, webhookToken, messageId), + ); + + return await structures.createDiscordenoMessage(result); +} diff --git a/src/helpers/webhooks/get_webhook_with_token.ts b/src/helpers/webhooks/get_webhook_with_token.ts index 665011c84..d4085b1c1 100644 --- a/src/helpers/webhooks/get_webhook_with_token.ts +++ b/src/helpers/webhooks/get_webhook_with_token.ts @@ -1,5 +1,5 @@ import { rest } from "../../rest/rest.ts"; -import { Webhook } from "../../types/webhooks/webhook.ts"; +import type { Webhook } from "../../types/webhooks/webhook.ts"; import { endpoints } from "../../util/constants.ts"; /** Returns the new webhook object for the given id, this call does not require authentication and returns no user in the webhook object. */ diff --git a/src/helpers/webhooks/get_webhooks.ts b/src/helpers/webhooks/get_webhooks.ts index c05c1a3cb..a9e90873d 100644 --- a/src/helpers/webhooks/get_webhooks.ts +++ b/src/helpers/webhooks/get_webhooks.ts @@ -1,5 +1,5 @@ import { rest } from "../../rest/rest.ts"; -import { Webhook } from "../../types/webhooks/webhook.ts"; +import type { Webhook } from "../../types/webhooks/webhook.ts"; import { Collection } from "../../util/collection.ts"; import { endpoints } from "../../util/constants.ts"; import { requireBotGuildPermissions } from "../../util/permissions.ts"; diff --git a/src/helpers/webhooks/execute_webhook.ts b/src/helpers/webhooks/send_webhook.ts similarity index 81% rename from src/helpers/webhooks/execute_webhook.ts rename to src/helpers/webhooks/send_webhook.ts index 2a03e3ebb..ab96626df 100644 --- a/src/helpers/webhooks/execute_webhook.ts +++ b/src/helpers/webhooks/send_webhook.ts @@ -1,13 +1,13 @@ import { rest } from "../../rest/rest.ts"; import { structures } from "../../structures/mod.ts"; import { DiscordAllowedMentionsTypes } from "../../types/messages/allowed_mentions_types.ts"; -import { Message } from "../../types/messages/message.ts"; -import { Errors } from "../../types/misc/errors.ts"; -import { ExecuteWebhook } from "../../types/webhooks/execute_webhook.ts"; +import type { Message } from "../../types/messages/message.ts"; +import { Errors } from "../../types/discordeno/errors.ts"; +import type { ExecuteWebhook } from "../../types/webhooks/execute_webhook.ts"; import { endpoints } from "../../util/constants.ts"; -/** Execute a webhook with webhook Id and webhook token */ -export async function executeWebhook( +/** Send a webhook with webhook Id and webhook token */ +export async function sendWebhook( webhookId: bigint, webhookToken: string, options: ExecuteWebhook, @@ -66,8 +66,8 @@ export async function executeWebhook( const result = await rest.runMethod( "post", - `${endpoints.WEBHOOK(webhookId, webhookToken)}${ - options.wait ? "?wait=true" : "" + `${endpoints.WEBHOOK(webhookId, webhookToken)}?wait=${options.wait}${ + options.threadId ? `&thread_id=${options.threadId}` : "" }`, { ...options, @@ -75,7 +75,6 @@ export async function executeWebhook( avatar_url: options.avatarUrl, }, ); - // TODO: not sure if (!options.wait) return; return structures.createDiscordenoMessage(result); diff --git a/src/rest/create_request_body.ts b/src/rest/create_request_body.ts index 3ab79d995..595ada4a3 100644 --- a/src/rest/create_request_body.ts +++ b/src/rest/create_request_body.ts @@ -1,4 +1,4 @@ -import { FileContent } from "../types/misc/file_content.ts"; +import type { FileContent } from "../types/discordeno/file_content.ts"; import { USER_AGENT } from "../util/constants.ts"; import { rest, RestPayload, RestRequest } from "./rest.ts"; diff --git a/src/rest/rest.ts b/src/rest/rest.ts index 2f7997780..91aa47f6c 100644 --- a/src/rest/rest.ts +++ b/src/rest/rest.ts @@ -14,7 +14,7 @@ export const rest = { token: "", /** The maximum amount of retries allowed */ maxRetryCount: 10, - apiVersion: "8", + apiVersion: "9", /** The secret authorization key to confirm that this was a request made by you and not a DDOS attack. */ authorization: "discordeno_best_lib_ever", pathQueues: new Map< diff --git a/src/rest/run_method.ts b/src/rest/run_method.ts index 53ff1f34b..5593b89d5 100644 --- a/src/rest/run_method.ts +++ b/src/rest/run_method.ts @@ -1,6 +1,6 @@ import { API_VERSION, BASE_URL, IMAGE_BASE_URL } from "../util/constants.ts"; import { loopObject } from "../util/loop_object.ts"; -import { snakeKeysToCamelCase } from "../util/utils.ts"; +import { camelize } from "../util/utils.ts"; import { rest } from "./rest.ts"; // deno-lint-ignore no-explicit-any @@ -62,7 +62,7 @@ export async function runMethod( method, reject, respond: (data: { status: number; body?: string }) => - resolve(snakeKeysToCamelCase(JSON.parse(data.body || "{}"))), + resolve(camelize(JSON.parse(data.body || "{}"))), }, { bucketId, diff --git a/src/structures/channel.ts b/src/structures/channel.ts index 3a84ba831..d9e81b357 100644 --- a/src/structures/channel.ts +++ b/src/structures/channel.ts @@ -8,11 +8,14 @@ import { editChannel } from "../helpers/channels/edit_channel.ts"; import { editChannelOverwrite } from "../helpers/channels/edit_channel_overwrite.ts"; import { sendMessage } from "../helpers/messages/send_message.ts"; import { disconnectMember } from "../helpers/mod.ts"; -import { Channel } from "../types/channels/channel.ts"; -import { ModifyChannel } from "../types/channels/modify_channel.ts"; -import { DiscordOverwrite, Overwrite } from "../types/channels/overwrite.ts"; -import { CreateMessage } from "../types/messages/create_message.ts"; -import { PermissionStrings } from "../types/permissions/permission_strings.ts"; +import type { Channel } from "../types/channels/channel.ts"; +import type { ModifyChannel } from "../types/channels/modify_channel.ts"; +import type { + DiscordOverwrite, + Overwrite, +} from "../types/channels/overwrite.ts"; +import type { CreateMessage } from "../types/messages/create_message.ts"; +import type { PermissionStrings } from "../types/permissions/permission_strings.ts"; import { snowflakeToBigint } from "../util/bigint.ts"; import { Collection } from "../util/collection.ts"; import { createNewProp } from "../util/utils.ts"; @@ -59,8 +62,8 @@ const baseChannel: Partial = { disconnect(memberId) { return disconnectMember(this.guildId!, memberId); }, - delete() { - return deleteChannel(this.guildId!, this.id!); + delete(reason) { + return deleteChannel(this.id!, reason); }, editOverwrite(id, options) { return editChannelOverwrite( @@ -201,7 +204,7 @@ export interface DiscordenoChannel extends /** Disconnect a member from a voice channel. Requires MOVE_MEMBERS permission. */ disconnect(memberId: bigint): ReturnType; /** Delete the channel */ - delete(): ReturnType; + delete(reason?: string): ReturnType; /** Edit a channel Overwrite */ editOverwrite( overwriteId: bigint, diff --git a/src/structures/guild.ts b/src/structures/guild.ts index 87f6dccc1..75bc4a09b 100644 --- a/src/structures/guild.ts +++ b/src/structures/guild.ts @@ -12,20 +12,21 @@ import { leaveGuild } from "../helpers/guilds/leave_guild.ts"; import { getInvites } from "../helpers/invites/get_invites.ts"; import { banMember } from "../helpers/members/ban_member.ts"; import { unbanMember } from "../helpers/members/unban_member.ts"; +import type { PresenceUpdate } from "../types/activity/presence_update.ts"; import { GetGuildAuditLog } from "../types/audit_log/get_guild_audit_log.ts"; -import { Emoji } from "../types/emojis/emoji.ts"; -import { CreateGuildBan } from "../types/guilds/create_guild_ban.ts"; -import { Guild } from "../types/guilds/guild.ts"; +import type { Emoji } from "../types/emojis/emoji.ts"; +import type { CreateGuildBan } from "../types/guilds/create_guild_ban.ts"; +import type { Guild } from "../types/guilds/guild.ts"; import { DiscordGuildFeatures } from "../types/guilds/guild_features.ts"; -import { +import type { ModifyGuild } from "../types/guilds/modify_guild.ts"; +import type { GuildMember, GuildMemberWithUser, -} from "../types/guilds/guild_member.ts"; -import { ModifyGuild } from "../types/guilds/modify_guild.ts"; -import { DiscordImageFormat } from "../types/misc/image_format.ts"; -import { DiscordImageSize } from "../types/misc/image_size.ts"; -import { PresenceUpdate } from "../types/misc/presence_update.ts"; +} from "../types/members/guild_member.ts"; +import type { DiscordImageFormat } from "../types/misc/image_format.ts"; +import type { DiscordImageSize } from "../types/misc/image_size.ts"; import { snowflakeToBigint } from "../util/bigint.ts"; +import { cacheMembers } from "../util/cache_members.ts"; import { Collection } from "../util/collection.ts"; import { createNewProp } from "../util/utils.ts"; import { DiscordenoChannel } from "./channel.ts"; @@ -34,7 +35,6 @@ import { structures } from "./mod.ts"; import { DiscordenoRole } from "./role.ts"; import { DiscordenoVoiceState } from "./voice_state.ts"; -export const initialMemberLoadQueue = new Map(); const GUILD_SNOWFLAKES = [ "id", "ownerId", @@ -47,6 +47,19 @@ const GUILD_SNOWFLAKES = [ "publicUpdatesChannelId", ]; +export const guildToggles = { + /** Whether this user is owner of this guild */ + owner: 1n, + /** Whether the guild widget is enabled */ + widgetEnabled: 2n, + /** Whether this is a large guild */ + large: 4n, + /** Whether this guild is unavailable due to an outage */ + unavailable: 8n, + /** Whether this server is an nsfw guild */ + nsfw: 16n, +}; + const baseGuild: Partial = { get members() { return cache.members.filter((member) => member.guilds.has(this.id!)); @@ -79,10 +92,10 @@ const baseGuild: Partial = { return cache.members.get(this.ownerId!); }, get partnered() { - return Boolean(this.features?.includes(DiscordGuildFeatures.PARTNERED)); + return Boolean(this.features?.includes(DiscordGuildFeatures.Partnered)); }, get verified() { - return Boolean(this.features?.includes(DiscordGuildFeatures.VERIFIED)); + return Boolean(this.features?.includes(DiscordGuildFeatures.Verified)); }, bannerURL(size, format) { return guildBannerURL(this.id!, this.banner!, size, format); @@ -120,6 +133,21 @@ const baseGuild: Partial = { leave() { return leaveGuild(this.id!); }, + get isOwner() { + return Boolean(this.bitfield! & guildToggles.owner); + }, + get widgetEnabled() { + return Boolean(this.bitfield! & guildToggles.widgetEnabled); + }, + get large() { + return Boolean(this.bitfield! & guildToggles.large); + }, + get unavailable() { + return Boolean(this.bitfield! & guildToggles.unavailable); + }, + get nsfw() { + return Boolean(this.bitfield! & guildToggles.nsfw); + }, }; export async function createDiscordenoGuild( @@ -130,6 +158,7 @@ export async function createDiscordenoGuild( memberCount = 0, voiceStates = [], channels = [], + threads = [], presences = [], joinedAt = "", emojis, @@ -137,6 +166,7 @@ export async function createDiscordenoGuild( ...rest } = data; + let bitfield = 0n; const guildId = snowflakeToBigint(rest.id); const roles = await Promise.all( @@ -152,7 +182,7 @@ export async function createDiscordenoGuild( voiceStates.map((vs) => structures.createDiscordenoVoiceState(guildId, vs)), ); - await Promise.all(channels.map(async (channel) => { + await Promise.all([...channels, ...threads].map(async (channel) => { const discordenoChannel = await structures.createDiscordenoChannel( channel, guildId, @@ -172,6 +202,12 @@ export async function createDiscordenoGuild( `Running for of loop in createDiscordenoGuild function.`, ); + const toggleBits = guildToggles[key as keyof typeof guildToggles]; + if (toggleBits) { + bitfield |= value ? toggleBits : 0n; + continue; + } + props[key] = createNewProp( GUILD_SNOWFLAKES.includes(key) ? value ? snowflakeToBigint(value) : undefined @@ -202,27 +238,10 @@ export async function createDiscordenoGuild( voiceStates: createNewProp( new Collection(voiceStateStructs.map((vs) => [vs.userId, vs])), ), + bitfield: createNewProp(bitfield), }); - // ONLY ADD TO QUEUE WHEN BOT IS NOT FULLY ONLINE - if (!cache.isReady) initialMemberLoadQueue.set(guild.id, members); - // BOT IS ONLINE, JUST DIRECTLY ADD MEMBERS - else { - await Promise.allSettled( - members.map(async (member) => { - const discordenoMember = await structures.createDiscordenoMember( - member as GuildMemberWithUser, - guild.id, - ); - - return cacheHandlers.set( - "members", - discordenoMember.id, - discordenoMember, - ); - }), - ); - } + await cacheMembers(guild.id, members as GuildMemberWithUser[]); return guild; } @@ -278,6 +297,10 @@ export interface DiscordenoGuild extends voiceStates: Collection; /** Custom guild emojis */ emojis: Collection; + /** Whether the bot is the owner of this guild */ + isOwner: boolean; + /** Holds all the boolean toggles. */ + bitfield: bigint; // GETTERS /** Members in this guild. */ diff --git a/src/structures/member.ts b/src/structures/member.ts index a250cb15f..3ee3ff30d 100644 --- a/src/structures/member.ts +++ b/src/structures/member.ts @@ -7,27 +7,37 @@ import { kickMember } from "../helpers/members/kick_member.ts"; import { sendDirectMessage } from "../helpers/members/send_direct_message.ts"; import { addRole } from "../helpers/roles/add_role.ts"; import { removeRole } from "../helpers/roles/remove_role.ts"; -import { CreateGuildBan } from "../types/guilds/create_guild_ban.ts"; -import { +import type { CreateGuildBan } from "../types/guilds/create_guild_ban.ts"; +import type { ModifyGuildMember } from "../types/guilds/modify_guild_member.ts"; +import type { GuildMember, GuildMemberWithUser, -} from "../types/guilds/guild_member.ts"; -import { ModifyGuildMember } from "../types/guilds/modify_guild_member.ts"; -import { CreateMessage } from "../types/messages/create_message.ts"; -import { DiscordImageFormat } from "../types/misc/image_format.ts"; -import { DiscordImageSize } from "../types/misc/image_size.ts"; -import { User } from "../types/users/user.ts"; +} from "../types/members/guild_member.ts"; +import type { CreateMessage } from "../types/messages/create_message.ts"; +import type { DiscordImageFormat } from "../types/misc/image_format.ts"; +import type { DiscordImageSize } from "../types/misc/image_size.ts"; +import type { User } from "../types/users/user.ts"; import { snowflakeToBigint } from "../util/bigint.ts"; import { Collection } from "../util/collection.ts"; import { createNewProp } from "../util/utils.ts"; import { DiscordenoGuild } from "./guild.ts"; const MEMBER_SNOWFLAKES = [ - "roles", "id", "discriminator", ]; +export const memberToggles = { + /** Whether the user belongs to an OAuth2 application */ + bot: 1n, + /** Whether the user is an Official Discord System user (part of the urgent message system) */ + system: 2n, + /** Whether the user has two factor enabled on their account */ + mfaEnabled: 4n, + /** Whether the email on this account has been verified */ + verified: 8n, +}; + const baseMember: Partial = { get avatarURL() { return avatarURL(this.id!, this.discriminator!, this.avatar!); @@ -76,6 +86,18 @@ const baseMember: Partial = { removeRole(guildId, roleId, reason) { return removeRole(guildId, this.id!, roleId, reason); }, + get bot() { + return Boolean(this.bitfield! & memberToggles.bot); + }, + get system() { + return Boolean(this.bitfield! & memberToggles.system); + }, + get mfaEnabled() { + return Boolean(this.bitfield! & memberToggles.mfaEnabled); + }, + get verified() { + return Boolean(this.bitfield! & memberToggles.verified); + }, }; export async function createDiscordenoMember( @@ -87,35 +109,23 @@ export async function createDiscordenoMember( user, joinedAt, premiumSince, - ...rest } = data; + let bitfield = 0n; const props: Record> = {}; - for (const [key, value] of Object.entries(rest)) { - eventHandlers.debug?.( - "loop", - `Running for of loop for Object.keys(rest) in DiscordenoMember function.`, - ); - - if (key === "roles") { - props[key] = value.map((id: string) => snowflakeToBigint(id)); - continue; - } - - props[key] = createNewProp( - MEMBER_SNOWFLAKES.includes(key) - ? value ? snowflakeToBigint(value) : undefined - : value, - ); - } - for (const [key, value] of Object.entries(user)) { eventHandlers.debug?.( "loop", `Running for of for Object.keys(user) loop in DiscordenoMember function.`, ); + const toggleBits = memberToggles[key as keyof typeof memberToggles]; + if (toggleBits) { + bitfield |= value ? toggleBits : 0n; + continue; + } + props[key] = createNewProp( MEMBER_SNOWFLAKES.includes(key) ? value ? snowflakeToBigint(value) : undefined @@ -127,6 +137,7 @@ export async function createDiscordenoMember( ...props, /** The guild related data mapped by guild id */ guilds: createNewProp(new Collection()), + bitfield: createNewProp(bitfield), }); const cached = await cacheHandlers.get("members", snowflakeToBigint(user.id)); @@ -142,29 +153,23 @@ export async function createDiscordenoMember( // User was never cached before member.guilds.set(guildId, { - nick: rest.nick, - roles: rest.roles.map((id) => snowflakeToBigint(id)), + nick: data.nick, + roles: data.roles.map((id) => snowflakeToBigint(id)), joinedAt: Date.parse(joinedAt), premiumSince: premiumSince ? Date.parse(premiumSince) : undefined, - deaf: rest.deaf, - mute: rest.mute, + deaf: data.deaf, + mute: data.mute, }); return member; } export interface DiscordenoMember extends - Omit< - GuildMember, - "roles" - >, Omit< User, | "discriminator" | "id" > { - /** Array of role object ids */ - roles: bigint[]; /** The user's id */ id: bigint; /** The user's 4-digit discord-tag */ @@ -178,6 +183,8 @@ export interface DiscordenoMember extends roles: bigint[]; } >; + /** Holds all the boolean toggles. */ + bitfield: bigint; // GETTERS /** The avatar url using the default format and size. */ diff --git a/src/structures/message.ts b/src/structures/message.ts index 47a798594..bec9d8e2d 100644 --- a/src/structures/message.ts +++ b/src/structures/message.ts @@ -10,10 +10,10 @@ import { removeAllReactions } from "../helpers/messages/remove_all_reactions.ts" import { removeReaction } from "../helpers/messages/remove_reaction.ts"; import { removeReactionEmoji } from "../helpers/messages/remove_reaction_emoji.ts"; import { sendMessage } from "../helpers/messages/send_message.ts"; -import { GuildMember } from "../types/guilds/guild_member.ts"; -import { CreateMessage } from "../types/messages/create_message.ts"; -import { EditMessage } from "../types/messages/edit_message.ts"; -import { Message } from "../types/messages/message.ts"; +import type { GuildMember } from "../types/members/guild_member.ts"; +import type { CreateMessage } from "../types/messages/create_message.ts"; +import type { EditMessage } from "../types/messages/edit_message.ts"; +import type { Message } from "../types/messages/message.ts"; import { bigintToSnowflake, snowflakeToBigint } from "../util/bigint.ts"; import { CHANNEL_MENTION_REGEX } from "../util/constants.ts"; import { createNewProp } from "../util/utils.ts"; @@ -29,6 +29,15 @@ const MESSAGE_SNOWFLAKES = [ "webhookId", ]; +const messageToggles = { + /** Whether this was a TTS message */ + tts: 1n, + /** Whether this message mentions everyone */ + mentionEveryone: 2n, + /** Whether this message is pinned */ + pinned: 4n, +}; + const baseMessage: Partial = { get channel() { if (this.guildId) return cache.channels.get(this.channelId!); @@ -132,6 +141,15 @@ const baseMessage: Partial = { removeReaction(reaction, userId) { return removeReaction(this.channelId!, this.id!, reaction, { userId }); }, + get tts() { + return Boolean(this.bitfield! & messageToggles.tts); + }, + get mentionEveryone() { + return Boolean(this.bitfield! & messageToggles.mentionEveryone); + }, + get pinned() { + return Boolean(this.bitfield! & messageToggles.pinned); + }, }; export async function createDiscordenoMessage(data: Message) { @@ -146,6 +164,8 @@ export async function createDiscordenoMessage(data: Message) { ...rest } = data; + let bitfield = 0n; + const props: Record> = {}; for (const [key, value] of Object.entries(rest)) { eventHandlers.debug?.( @@ -153,6 +173,12 @@ export async function createDiscordenoMessage(data: Message) { `Running for of loop in createDiscordenoMessage function.`, ); + const toggleBits = messageToggles[key as keyof typeof messageToggles]; + if (toggleBits) { + bitfield |= value ? toggleBits : 0n; + continue; + } + props[key] = createNewProp( MESSAGE_SNOWFLAKES.includes(key) ? value ? snowflakeToBigint(value) : undefined @@ -165,10 +191,10 @@ export async function createDiscordenoMessage(data: Message) { props.tag = createNewProp(`${author.username}#${author.discriminator}`); // Discord doesnt give guild id for getMessage() so this will fill it in - const guildIdFinal = guildId || + const guildIdFinal = snowflakeToBigint(guildId) || (await cacheHandlers.get("channels", snowflakeToBigint(data.channelId))) ?.guildId || - ""; + 0n; const message: DiscordenoMessage = Object.create(baseMessage, { ...props, @@ -208,6 +234,7 @@ export async function createDiscordenoMessage(data: Message) { } : undefined, ), + bitfield: createNewProp(bitfield), }); return message; @@ -226,12 +253,15 @@ export interface DiscordenoMessage extends | "author" > { id: bigint; - author: undefined; /** Whether or not this message was sent by a bot */ isBot: boolean; /** The username#discrimnator for the user who sent this message */ tag: string; + /** Holds all the boolean toggles. */ + bitfield: bigint; + // For better user experience + /** Id of the guild which the massage has been send in. "0n" if it a DM */ guildId: bigint; /** id of the channel the message was sent in */ @@ -252,6 +282,7 @@ export interface DiscordenoMessage extends timestamp: number; /** When this message was edited (or undefined if never) */ editedTimestamp?: number; + // GETTERS /** The channel where this message was sent. Can be undefined if uncached. */ diff --git a/src/structures/role.ts b/src/structures/role.ts index 783c20ce2..6af4de9d4 100644 --- a/src/structures/role.ts +++ b/src/structures/role.ts @@ -3,8 +3,8 @@ 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/misc/errors.ts"; -import { Role } from "../types/permissions/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"; @@ -19,6 +19,17 @@ const ROLE_SNOWFLAKES = [ "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!); @@ -71,6 +82,18 @@ const baseRole: Partial = { 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); + }, }; // deno-lint-ignore require-await @@ -84,6 +107,8 @@ export async function createDiscordenoRole( ...rest } = ({ guildId: data.guildId, ...data.role }); + let bitfield = 0n; + const props: Record> = {}; for (const [key, value] of Object.entries(rest)) { eventHandlers.debug?.( @@ -91,6 +116,12 @@ export async function createDiscordenoRole( `Running for of loop in createDiscordenoRole function.`, ); + const toggleBits = roleToggles[key as keyof typeof roleToggles]; + if (toggleBits) { + bitfield |= value ? toggleBits : 0n; + continue; + } + props[key] = createNewProp( ROLE_SNOWFLAKES.includes(key) ? value ? snowflakeToBigint(value) : undefined @@ -107,6 +138,7 @@ export async function createDiscordenoRole( integrationId: createNewProp( tags.integrationId ? snowflakeToBigint(tags.integrationId) : undefined, ), + bitfield: createNewProp(bitfield), }); return role; @@ -123,6 +155,8 @@ export interface DiscordenoRole extends Omit { integrationId: bigint; /** The roles guildId */ guildId: bigint; + /** Holds all the boolean toggles. */ + bitfield: bigint; // GETTERS diff --git a/src/structures/voice_state.ts b/src/structures/voice_state.ts index c5c846562..737b4e335 100644 --- a/src/structures/voice_state.ts +++ b/src/structures/voice_state.ts @@ -1,7 +1,7 @@ import { eventHandlers } from "../bot.ts"; import { cache } from "../cache.ts"; -import { GuildMember } from "../types/guilds/guild_member.ts"; -import { VoiceState } from "../types/voice/voice_state.ts"; +import type { GuildMember } from "../types/members/guild_member.ts"; +import type { VoiceState } from "../types/voice/voice_state.ts"; import { snowflakeToBigint } from "../util/bigint.ts"; import { createNewProp } from "../util/utils.ts"; import { DiscordenoGuild } from "./guild.ts"; @@ -82,7 +82,7 @@ export async function createDiscordenoVoiceState( const toggleBits = voiceStateToggles[key as keyof typeof voiceStateToggles]; if (toggleBits) { - bitfield |= toggleBits; + bitfield |= value ? toggleBits : 0n; continue; } diff --git a/src/types/misc/activity.ts b/src/types/activity/activity.ts similarity index 100% rename from src/types/misc/activity.ts rename to src/types/activity/activity.ts diff --git a/src/types/misc/activity_assets.ts b/src/types/activity/activity_assets.ts similarity index 100% rename from src/types/misc/activity_assets.ts rename to src/types/activity/activity_assets.ts diff --git a/src/types/misc/activity_button.ts b/src/types/activity/activity_button.ts similarity index 100% rename from src/types/misc/activity_button.ts rename to src/types/activity/activity_button.ts diff --git a/src/types/misc/activity_emoji.ts b/src/types/activity/activity_emoji.ts similarity index 100% rename from src/types/misc/activity_emoji.ts rename to src/types/activity/activity_emoji.ts diff --git a/src/types/misc/activity_flags.ts b/src/types/activity/activity_flags.ts similarity index 65% rename from src/types/misc/activity_flags.ts rename to src/types/activity/activity_flags.ts index 7b0abdd40..a51521231 100644 --- a/src/types/misc/activity_flags.ts +++ b/src/types/activity/activity_flags.ts @@ -1,11 +1,11 @@ /** https://discord.com/developers/docs/topics/gateway#activity-object-activity-flags */ export enum DiscordActivityFlags { - INSTANCE = 1 << 0, - JOIN = 1 << 1, - SPECTATE = 1 << 2, - JOIN_REQUEST = 1 << 3, - SYNC = 1 << 4, - PLAY = 1 << 5, + Instance = 1 << 0, + Join = 1 << 1, + Spectate = 1 << 2, + JoinRequest = 1 << 3, + Sync = 1 << 4, + Play = 1 << 5, } export type ActivityFlags = DiscordActivityFlags; diff --git a/src/types/misc/activity_party.ts b/src/types/activity/activity_party.ts similarity index 100% rename from src/types/misc/activity_party.ts rename to src/types/activity/activity_party.ts diff --git a/src/types/misc/activity_secrets.ts b/src/types/activity/activity_secrets.ts similarity index 100% rename from src/types/misc/activity_secrets.ts rename to src/types/activity/activity_secrets.ts diff --git a/src/types/misc/activity_timestamps.ts b/src/types/activity/activity_timestamps.ts similarity index 100% rename from src/types/misc/activity_timestamps.ts rename to src/types/activity/activity_timestamps.ts diff --git a/src/types/misc/activity_types.ts b/src/types/activity/activity_types.ts similarity index 100% rename from src/types/misc/activity_types.ts rename to src/types/activity/activity_types.ts diff --git a/src/types/misc/client_status.ts b/src/types/activity/client_status.ts similarity index 100% rename from src/types/misc/client_status.ts rename to src/types/activity/client_status.ts diff --git a/src/types/misc/presence_update.ts b/src/types/activity/presence_update.ts similarity index 100% rename from src/types/misc/presence_update.ts rename to src/types/activity/presence_update.ts diff --git a/src/types/audit_log/audit_log.ts b/src/types/audit_log/audit_log.ts index 41ccff42b..578a54d73 100644 --- a/src/types/audit_log/audit_log.ts +++ b/src/types/audit_log/audit_log.ts @@ -1,4 +1,4 @@ -import { Integration } from "../integration/integration.ts"; +import { Integration } from "../integrations/integration.ts"; import { User } from "../users/user.ts"; import { Webhook } from "../webhooks/webhook.ts"; import { AuditLogEntry } from "./audit_log_entry.ts"; diff --git a/src/types/audit_log/audit_log_events.ts b/src/types/audit_log/audit_log_events.ts index 0620c1465..88f35fa3f 100644 --- a/src/types/audit_log/audit_log_events.ts +++ b/src/types/audit_log/audit_log_events.ts @@ -1,40 +1,40 @@ /** https://discord.com/developers/docs/resources/audit-log#audit-log-entry-object-audit-log-events */ export enum DiscordAuditLogEvents { - GUILD_UPDATE = 1, - CHANNEL_CREATE = 10, - CHANNEL_UPDATE, - CHANNEL_DELETE, - CHANNEL_OVERWRITE_CREATE, - CHANNEL_OVERWRITE_UPDATE, - CHANNEL_OVERWRITE_DELETE, - MEMBER_KICK = 20, - MEMBER_PRUNE, - MEMBER_BAN_ADD, - MEMBER_BAN_REMOVE, - MEMBER_UPDATE, - MEMBER_ROLE_UPDATE, - MEMBER_MOVE, - MEMBER_DISCONNECT, - BOT_ADD, - ROLE_CREATE = 30, - ROLE_UPDATE, - ROLE_DELETE, - INVITE_CREATE = 40, - INVITE_UPDATE, - INVITE_DELETE, - WEBHOOK_CREATE = 50, - WEBHOOK_UPDATE, - WEBHOOK_DELETE, - EMOJI_CREATE = 60, - EMOJI_UPDATE, - EMOJI_DELETE, - MESSAGE_DELETE = 72, - MESSAGE_BULK_DELETE, - MESSAGE_PIN, - MESSAGE_UNPIN, - INTEGRATION_CREATE = 80, - INTEGRATION_UPDATE, - INTEGRATION_DELETE, + GuildUpdate = 1, + ChannelCreate = 10, + ChannelUpdate, + ChannelDelete, + ChannelOverwriteCreate, + ChannelOverwriteUpdate, + ChannelOverwriteDelete, + MemberKick = 20, + MemberPrune, + MemberBanAdd, + MemberBanRemove, + MemberUpdate, + MemberRoleUpdate, + MemberMove, + MemberDisconnect, + BotAdd, + RoleCreate = 30, + RoleUpdate, + RoleDelete, + InviteCreate = 40, + InviteUpdate, + InviteDelete, + WebhookCreate = 50, + WebhookUpdate, + WebhookDelete, + EmojiCreate = 60, + EmojiUpdate, + EmojiDelete, + MessageDelete = 72, + MessageBulkDelete, + MessagePin, + MessageUnpin, + IntegrationCreate = 80, + IntegrationUpdate, + IntegrationDelete, } export type AuditLogEvents = DiscordAuditLogEvents; diff --git a/src/types/channels/channel.ts b/src/types/channels/channel.ts index 7970c4f2c..ceda62144 100644 --- a/src/types/channels/channel.ts +++ b/src/types/channels/channel.ts @@ -1,6 +1,8 @@ import { User } from "../users/user.ts"; import { DiscordChannelTypes } from "./channel_types.ts"; import { DiscordOverwrite } from "./overwrite.ts"; +import { ThreadMember } from "./threads/thread_member.ts"; +import { ThreadMetadata } from "./threads/thread_metadata.ts"; import { DiscordVideoQualityModes } from "./video_quality_modes.ts"; /** https://discord.com/developers/docs/resources/channel#channel-object */ @@ -33,11 +35,11 @@ export interface Channel { recipients?: User[]; /** Icon hash */ icon?: string | null; - /** id of the DM creator */ + /** Id of the creator of the group DM or thread */ ownerId?: string; /** Application id of the group DM creator if it is bot-created */ applicationId?: string; - /** Id of the parent category for a channel (each parent category can contain up to 50 channels) */ + /** For guild channels: Id of the parent category for a channel (each parent category can contain up to 50 channels), for threads: id of the text channel this thread was created */ parentId?: string | null; /** When the last pinned message was pinned. This may be null in events such as GUILD_CREATE when a message is not pinned. */ lastPinTimestamp?: string | null; @@ -45,4 +47,13 @@ export interface Channel { rtcRegion?: string | null; /** The camera video quality mode of the voice channel, 1 when not present */ videoQualityMode?: DiscordVideoQualityModes; + // TODO(threads): consider a ThreadChannel object + /** An approximate count of messages in a thread, stops counting at 50 */ + messageCount?: number; + /** An approximate count of users in a thread, stops counting at 50 */ + memberCount?: number; + /** Thread-specifig fields not needed by other channels */ + threadMetadata?: ThreadMetadata; + /** Thread member object for the current user, if they have joined the thread, only included on certain API endpoints */ + member?: ThreadMember; } diff --git a/src/types/channels/channel_types.ts b/src/types/channels/channel_types.ts index 02d2c85b2..aec5aed04 100644 --- a/src/types/channels/channel_types.ts +++ b/src/types/channels/channel_types.ts @@ -1,21 +1,27 @@ /** https://discord.com/developers/docs/resources/channel#channel-object-channel-types */ export enum DiscordChannelTypes { /** A text channel within a server */ - GUILD_TEXT, + GuildText, /** A direct message between users */ DM, /** A voice channel within a server */ - GUILD_VOICE, + GuildVoice, /** A direct message between multiple users */ - GROUP_DM, + GroupDm, /** An organizational category that contains up to 50 channels */ - GUILD_CATEGORY, + GuildCategory, /** A channel that users can follow and crosspost into their own server */ - GUILD_NEWS, + GuildNews, /** A channel in which game developers can sell their game on Discord */ - GUILD_STORE, + GuildStore, + /** A temporary sub-channel within a GUILD_NEWS channel */ + GuildNewsThread = 10, + /** A temporary sub-channel within a GUILD_TEXT channel */ + GuildPublicThread, + /** A temporary sub-channel within a GUILD_TEXT channel that is only viewable by those invited and those with the MANAGE_THREADS permission */ + GuildPivateThread, /** A voice channel for hosting events with an audience */ - GUILD_STAGE_VOICE = 13, + GuildStageVoice = 13, } export type ChannelTypes = DiscordChannelTypes; diff --git a/src/types/channels/modify_channel.ts b/src/types/channels/modify_channel.ts index b6defe24b..09db31d89 100644 --- a/src/types/channels/modify_channel.ts +++ b/src/types/channels/modify_channel.ts @@ -35,7 +35,6 @@ export interface DiscordModifyChannel extends SnakeCasedPropertiesDeep< Omit > { + // deno-lint-ignore camelcase permission_overwrites?: DiscordOverwrite[]; } - -//TODO: check this diff --git a/src/types/channels/overwrite_types.ts b/src/types/channels/overwrite_types.ts index 5ee32e76d..9e4de3406 100644 --- a/src/types/channels/overwrite_types.ts +++ b/src/types/channels/overwrite_types.ts @@ -1,6 +1,6 @@ export enum DiscordOverwriteTypes { - ROLE, - MEMBER, + Role, + Member, } export type OverwriteTypes = DiscordOverwriteTypes; diff --git a/src/types/channels/threads/list_active_threads.ts b/src/types/channels/threads/list_active_threads.ts new file mode 100644 index 000000000..55753d444 --- /dev/null +++ b/src/types/channels/threads/list_active_threads.ts @@ -0,0 +1,12 @@ +import { Channel } from "../channel.ts"; +import { ThreadMember } from "./thread_member.ts"; + +// TODO: add docs link +export interface ListActiveThreads { + /** The active threads */ + threads: Channel[]; + /** A thread member object for each returned thread the current user has joined */ + members: ThreadMember[]; + /** Whether there are potentially additional threads that could be returned on subsequent call */ + hasMore: boolean; +} diff --git a/src/types/channels/threads/list_public_archived_threads.ts b/src/types/channels/threads/list_public_archived_threads.ts new file mode 100644 index 000000000..95a7a2a0a --- /dev/null +++ b/src/types/channels/threads/list_public_archived_threads.ts @@ -0,0 +1,8 @@ +// TODO: add docs link +export interface ListPublicArchivedThreads { + // TODO: convert unix to ISO9601 timestamp + /** Returns threads before this timestamp. UNIX or ISO8601 timestamp */ + before?: number | string; + /** Optional maximum number of threads to return */ + limit?: number; +} diff --git a/src/types/channels/threads/modify_thread.ts b/src/types/channels/threads/modify_thread.ts new file mode 100644 index 000000000..d261cab1d --- /dev/null +++ b/src/types/channels/threads/modify_thread.ts @@ -0,0 +1,13 @@ +// TODO: add docs link +export interface ModifyThread { + /** 2-100 character thread name */ + name?: string; + /** Whether the thread is archived */ + archived?: boolean; + /** Duration in minutes to automatically archive the thread after recent activity */ + autoArchiveDuration?: 60 | 1440 | 4320 | 10080; + /** When a thread is locked, only users with `MANAGE_THREADS` can unarchive it */ + locked?: boolean; + /** Amount of seconds a user has to wait before sending another message (0-21600); bots, as well as users with the permission `MANAGE_MESSAGES`, `MANAGE_THREAD` or `MANAGE_CHANNEL` are unaffected */ + rateLimitPerUser?: number; +} diff --git a/src/types/channels/threads/start_thread.ts b/src/types/channels/threads/start_thread.ts new file mode 100644 index 000000000..10a5c0b02 --- /dev/null +++ b/src/types/channels/threads/start_thread.ts @@ -0,0 +1,7 @@ +// TODO: add docs link +export interface StartThread { + /** 2-100 character thread name */ + name: string; + /** Duration in minutes to automatically archive the thread after recent activity */ + autoArchiveDuration: 60 | 1440 | 4320 | 10080; +} diff --git a/src/types/channels/threads/thread_list_sync.ts b/src/types/channels/threads/thread_list_sync.ts new file mode 100644 index 000000000..2c905a907 --- /dev/null +++ b/src/types/channels/threads/thread_list_sync.ts @@ -0,0 +1,15 @@ +import { Channel } from "../channel.ts"; +import { ThreadMember } from "./thread_member.ts"; + +// TODO: add docs link +export interface ThreadListSync { + /** The id of the guild */ + guildId: string; + /** The parent channel ids whose threads are being synced. If omitted, then threads were synced for the entire guild. This array may contain channelIds that have no active threads as well, so you know to clear that data */ + channelIds?: string[]; + // TODO: check if need to omit + /** All active threads in the given channels that the current user can access */ + threads: Channel[]; + /** All thread member objects from the synced threads for the current user, indicating which threads the current user has been added to */ + members: ThreadMember[]; +} diff --git a/src/types/channels/threads/thread_member.ts b/src/types/channels/threads/thread_member.ts new file mode 100644 index 000000000..2b3d1b54a --- /dev/null +++ b/src/types/channels/threads/thread_member.ts @@ -0,0 +1,10 @@ +export interface ThreadMember { + /** The id of the thread */ + id: string; + /** The id of the user */ + userId: string; + /** The time the current user last joined the thread */ + joinTimestamp: string; + /** Any user-thread settings, currently only used for notifications */ + flags: number; +} diff --git a/src/types/channels/threads/thread_members_update.ts b/src/types/channels/threads/thread_members_update.ts new file mode 100644 index 000000000..2190f6297 --- /dev/null +++ b/src/types/channels/threads/thread_members_update.ts @@ -0,0 +1,15 @@ +import { ThreadMember } from "./thread_member.ts"; + +// TODO: add docs link +export interface ThreadMembersUpdate { + /** The id of the thread */ + id: string; + /** The id of the guild */ + guildId: string; + /** The approximate number of members in the thread, capped at 50 */ + memberCount: number; + /** The users who were added to the thread */ + addedMembers?: ThreadMember[]; + /** The id of the users who were removed from the thread */ + removedMemberIds?: string[]; +} diff --git a/src/types/channels/threads/thread_metadata.ts b/src/types/channels/threads/thread_metadata.ts new file mode 100644 index 000000000..ea67fd966 --- /dev/null +++ b/src/types/channels/threads/thread_metadata.ts @@ -0,0 +1,13 @@ +export interface ThreadMetadata { + /** Whether the thread is archived */ + archived: boolean; + /** Id of the user that last archived or unarchived the thread */ + archiverId?: string; + /** Duration in minutes to automatically archive the thread after recent activity */ + autoArchiveDuration: 60 | 1440 | 4320 | 10080; + // TODO(threads): channel struct should convert this to a unixx + /** Timestamp when the thread's archive status was last changed, used for calculating recent activity */ + archiveTimestamp: string; + /** When a thread is locked, only users with `MANAGE_THREADS` can unarchive it */ + locked?: boolean; +} diff --git a/src/types/codes/json_error_codes.ts b/src/types/codes/json_error_codes.ts index 1d05ebb74..d26fa3133 100644 --- a/src/types/codes/json_error_codes.ts +++ b/src/types/codes/json_error_codes.ts @@ -80,6 +80,11 @@ export enum DiscordJsonErrorCodes { InvalidApiVersionProvided = 50041, CannotDeleteAChannelRequiredForCommunityGuilds = 50074, InvalidStickerSent = 50081, + TriedToPerformAnOperationOnAnArchivedThreadSuchAsEditingAMessageOrAddingAUserToTheThread = + 50083, + InvalidThreadNotificationSettings, + BeforeValueIsEarlierThanTheThreadCreationDate, + TwoFactorIsRequiredForThisOperation = 60003, ReqctionWasBlocked = 90001, ApiResourceIsCurrentlyOverloadedTryAgainALittleLater = 130000, } diff --git a/src/types/discordeno/create_slash_command.ts b/src/types/discordeno/create_slash_command.ts index 969ac33fc..b0008fca1 100644 --- a/src/types/discordeno/create_slash_command.ts +++ b/src/types/discordeno/create_slash_command.ts @@ -1,4 +1,4 @@ -import { CreateGlobalApplicationCommand } from "../interactions/create_global_application_command.ts"; +import { CreateGlobalApplicationCommand } from "../interactions/commands/create_global_application_command.ts"; export interface DiscordenoCreateApplicationCommand extends CreateGlobalApplicationCommand { diff --git a/src/types/misc/errors.ts b/src/types/discordeno/errors.ts similarity index 94% rename from src/types/misc/errors.ts rename to src/types/discordeno/errors.ts index ee55755c0..34c50ccea 100644 --- a/src/types/misc/errors.ts +++ b/src/types/discordeno/errors.ts @@ -18,6 +18,11 @@ export enum Errors { MEMBER_SEARCH_LIMIT_TOO_LOW = "MEMBER_SEARCH_LIMIT_TOO_LOW", PRUNE_MAX_DAYS = "PRUNE_MAX_DAYS", ROLE_NOT_FOUND = "ROLE_NOT_FOUND", + // Thread errors + INVALID_THREAD_PARENT_CHANNEL_TYPE = "INVALID_THREAD_PARENT_CHANNEL_TYPE", + GUILD_NEWS_CHANNEL_ONLY_SUPPORT_PUBLIC_THREADS = + "GUILD_NEWS_CHANNEL_ONLY_SUPPORT_PUBLIC_THREADS", + NOT_A_THREAD_CHANNEL = "NOT_A_THREAD_CHANNEL", // Message Delete Errors DELETE_MESSAGES_MIN = "DELETE_MESSAGES_MIN", PRUNE_MIN_DAYS = "PRUNE_MIN_DAYS", diff --git a/src/types/discordeno/eventHandlers.ts b/src/types/discordeno/eventHandlers.ts index 4c97cea77..c456c91ee 100644 --- a/src/types/discordeno/eventHandlers.ts +++ b/src/types/discordeno/eventHandlers.ts @@ -4,8 +4,10 @@ import { DiscordenoMember } from "../../structures/member.ts"; import { DiscordenoMessage } from "../../structures/message.ts"; import { DiscordenoRole } from "../../structures/role.ts"; import { Collection } from "../../util/collection.ts"; -import { IntegrationCreateUpdate } from "../integration/integration_create_update.ts"; -import { ApplicationCommandCreateUpdateDelete } from "../interactions/application_command_create_update_delete.ts"; +import { ThreadMember } from "../channels/threads/thread_member.ts"; +import { ThreadMembersUpdate } from "../channels/threads/thread_members_update.ts"; +import { IntegrationCreateUpdate } from "../integrations/integration_create_update.ts"; +import { ApplicationCommandCreateUpdateDelete } from "../interactions/commands/application_command_create_update_delete.ts"; import { DiscordGatewayPayload, Emoji, @@ -211,6 +213,25 @@ export interface EventHandlers { shardId: number, unavailableGuildIds: Set, ) => unknown; + /** Sent when a thread is created */ + threadCreate?: (channel: DiscordenoChannel) => unknown; + /** Sent when a thread is updated */ + threadUpdate?: ( + cahnnel: DiscordenoChannel, + oldChannel: DiscordenoChannel, + ) => unknown; + /** Sent when the bot gains access to threads */ + threadListSync?: ( + channels: Collection, + members: ThreadMember[], + guildId: bigint, + ) => unknown; + /** Sent when the current users thread member is updated */ + threadMemberUpdate?: (threadMember: ThreadMember) => unknown; + /** Sent when anyone is added to or removed from a thread */ + threadMembersUpdate?: (update: ThreadMembersUpdate) => unknown; + /** Sent when a thread is deleted */ + threadDelete?: (channel: DiscordenoChannel) => unknown; /** Sent when a user starts typing in a channel. */ typingStart?: (data: TypingStart) => unknown; /** Sent when a user joins a voice channel */ diff --git a/src/types/misc/file_content.ts b/src/types/discordeno/file_content.ts similarity index 100% rename from src/types/misc/file_content.ts rename to src/types/discordeno/file_content.ts diff --git a/src/types/gateway/gateway_intents.ts b/src/types/gateway/gateway_intents.ts index 533556a17..cb7f43944 100644 --- a/src/types/gateway/gateway_intents.ts +++ b/src/types/gateway/gateway_intents.ts @@ -11,63 +11,63 @@ export enum DiscordGatewayIntents { * - CHANNEL_DELETE * - CHANNEL_PINS_UPDATE */ - GUILDS = 1 << 0, + Guilds = 1 << 0, /** * - GUILD_MEMBER_ADD * - GUILD_MEMBER_UPDATE * - GUILD_MEMBER_REMOVE */ - GUILD_MEMBERS = 1 << 1, + GuildMembers = 1 << 1, /** * - GUILD_BAN_ADD * - GUILD_BAN_REMOVE */ - GUILD_BANS = 1 << 2, + GuildBans = 1 << 2, /** * - GUILD_EMOJIS_UPDATE */ - GUILD_EMOJIS = 1 << 3, + GuildEmojis = 1 << 3, /** * - GUILD_INTEGRATIONS_UPDATE * - INTEGRATION_CREATE * - INTEGRATION_UPDATE * - INTEGRATION_DELETE */ - GUILD_INTEGRATIONS = 1 << 4, + GuildIntegrations = 1 << 4, /** Enables the following events: * - WEBHOOKS_UPDATE */ - GUILD_WEBHOOKS = 1 << 5, + GuildWebhooks = 1 << 5, /** * - INVITE_CREATE * - INVITE_DELETE */ - GUILD_INVITES = 1 << 6, + GuildInvites = 1 << 6, /** * - VOICE_STATE_UPDATE */ - GUILD_VOICE_STATES = 1 << 7, + GuildVoiceStates = 1 << 7, /** * - PRESENCE_UPDATE */ - GUILD_PRESENCES = 1 << 8, + GuildPresences = 1 << 8, /** * - MESSAGE_CREATE * - MESSAGE_UPDATE * - MESSAGE_DELETE */ - GUILD_MESSAGES = 1 << 9, + GuildMessages = 1 << 9, /** * - MESSAGE_REACTION_ADD * - MESSAGE_REACTION_REMOVE * - MESSAGE_REACTION_REMOVE_ALL * - MESSAGE_REACTION_REMOVE_EMOJI */ - GUILD_MESSAGE_REACTIONS = 1 << 10, + GuildMessageReactions = 1 << 10, /** * - TYPING_START */ - GUILD_MESSAGE_TYPING = 1 << 11, + GuildMessageTyping = 1 << 11, /** * - CHANNEL_CREATE * - MESSAGE_CREATE @@ -75,18 +75,18 @@ export enum DiscordGatewayIntents { * - MESSAGE_DELETE * - CHANNEL_PINS_UPDATE */ - DIRECT_MESSAGES = 1 << 12, + DirectMessages = 1 << 12, /** * - MESSAGE_REACTION_ADD * - MESSAGE_REACTION_REMOVE * - MESSAGE_REACTION_REMOVE_ALL * - MESSAGE_REACTION_REMOVE_EMOJI */ - DIRECT_MESSAGE_REACTIONS = 1 << 13, + DirectMessageReactions = 1 << 13, /** * - TYPING_START */ - DIRECT_MESSAGE_TYPING = 1 << 14, + DirectMessageTyping = 1 << 14, } export type Intents = DiscordGatewayIntents; diff --git a/src/types/gateway/status_update.ts b/src/types/gateway/status_update.ts index 27f65b9ca..12092cbdd 100644 --- a/src/types/gateway/status_update.ts +++ b/src/types/gateway/status_update.ts @@ -1,4 +1,4 @@ -import { Activity } from "../misc/activity.ts"; +import { Activity } from "../activity/activity.ts"; import { DiscordStatusTypes } from "./status_types.ts"; /** https://discord.com/developers/docs/topics/gateway#update-status */ diff --git a/src/types/guilds/create_guild_channel.ts b/src/types/guilds/create_guild_channel.ts index d6fe506d0..38eb79102 100644 --- a/src/types/guilds/create_guild_channel.ts +++ b/src/types/guilds/create_guild_channel.ts @@ -30,6 +30,6 @@ export interface DiscordCreateGuildChannel extends SnakeCasedPropertiesDeep< Omit > { + // deno-lint-ignore camelcase permission_overwrites: DiscordOverwrite[]; } -// TODO: check this diff --git a/src/types/guilds/create_guild_role.ts b/src/types/guilds/create_guild_role.ts index 2183a0f7d..d1be99b30 100644 --- a/src/types/guilds/create_guild_role.ts +++ b/src/types/guilds/create_guild_role.ts @@ -18,4 +18,3 @@ export interface DiscordCreateGuildRole extends Omit { permissions?: string; } -// TODO: check this diff --git a/src/types/guilds/default_message_notification_levels.ts b/src/types/guilds/default_message_notification_levels.ts index 5c639ebde..8c3ced807 100644 --- a/src/types/guilds/default_message_notification_levels.ts +++ b/src/types/guilds/default_message_notification_levels.ts @@ -1,9 +1,9 @@ /** https://discord.com/developers/docs/resources/guild#guild-object-default-message-notification-level */ export enum DiscordDefaultMessageNotificationLevels { /** Members will receive notifications for all messages by default */ - ALL_MESSAGES, + AllMessages, /** Members will receive notifications only for messages that @mention them by default */ - ONLY_MENTIONS, + OnlyMentions, } export type DefaultMessageNotificationLevels = diff --git a/src/types/guilds/explicit_content_filter_levels.ts b/src/types/guilds/explicit_content_filter_levels.ts index 0fac226ed..583a2cdf4 100644 --- a/src/types/guilds/explicit_content_filter_levels.ts +++ b/src/types/guilds/explicit_content_filter_levels.ts @@ -1,11 +1,11 @@ /** https://discord.com/developers/docs/resources/guild#guild-object-explicit-content-filter-level */ export enum DiscordExplicitContentFilterLevels { /** Media content will not be scanned */ - DISABLED, + Disabled, /** Media content sent by members without roles will be scanned */ - MEMBERS_WITHOUT_ROLES, + MembersWithoutRoles, /** Media content sent by all members will be scanned */ - ALL_MEMBERS, + AllMembers, } export type ExplicitContentFilterLevels = DiscordExplicitContentFilterLevels; diff --git a/src/types/guilds/get_guild_widget_image_style_options.ts b/src/types/guilds/get_guild_widget_image_style_options.ts index b5c36c335..27aa6d044 100644 --- a/src/types/guilds/get_guild_widget_image_style_options.ts +++ b/src/types/guilds/get_guild_widget_image_style_options.ts @@ -1,15 +1,15 @@ /** https://discord.com/developers/docs/resources/guild#get-guild-widget-image-widget-style-options */ export enum DiscordGetGuildWidgetImageStyleOptions { /** Shield style widget with Discord icon and guild members online count */ - SHIELD = "shield", + Shield = "shield", /** Large image with guild icon, name and online count. "POWERED BY DISCORD" as the footer of the widget */ - BANNER_1 = "banner1", + Banner1 = "banner1", /** Smaller widget style with guild icon, name and online count. Split on the right with Discord logo */ - BANNER_2 = "banner2", + Banner2 = "banner2", /** Large image with guild icon, name and online count. In the footer, Discord logo on the left and "Chat Now" on the right */ - BANNER_3 = "banner3", + Banner3 = "banner3", /** Large Discord logo at the top of the widget. Guild icon, name and online count in the middle portion of the widget and a "JOIN MY SERVER" button at the bottom */ - BANNER_4 = "banner4", + Banner4 = "banner4", } export type GetGuildWidgetImageStyleOptions = diff --git a/src/types/guilds/guild.ts b/src/types/guilds/guild.ts index bcaa3dc9f..14e9676fe 100644 --- a/src/types/guilds/guild.ts +++ b/src/types/guilds/guild.ts @@ -1,12 +1,12 @@ +import { PresenceUpdate } from "../activity/presence_update.ts"; import { Channel } from "../channels/channel.ts"; import { Emoji } from "../emojis/emoji.ts"; -import { PresenceUpdate } from "../misc/presence_update.ts"; +import { GuildMember } from "../members/guild_member.ts"; import { Role } from "../permissions/role.ts"; import { VoiceState } from "../voice/voice_state.ts"; import { DiscordDefaultMessageNotificationLevels } from "./default_message_notification_levels.ts"; import { DiscordExplicitContentFilterLevels } from "./explicit_content_filter_levels.ts"; import { DiscordGuildFeatures } from "./guild_features.ts"; -import { GuildMember } from "./guild_member.ts"; import { DiscordMfaLevels } from "./mfa_levels.ts"; import { DiscordPremiumTiers } from "./premium_tiers.ts"; import { DiscordSystemChannelFlags } from "./system_channel_flags.ts"; @@ -79,6 +79,9 @@ export interface Guild { members?: GuildMember[]; /** Channels in the guild */ channels?: Channel[]; + // TODO: check if need to omit + /** All active threads in the guild that the current user has permission to view */ + threads?: Channel[]; /** Presences of the members in the guild, will only include non-offline members if the size is greater than large threshold */ presences?: Partial[]; /** The maximum number of presences for the guild (the default value, currently 25000, is in effect when null is returned) */ @@ -105,7 +108,7 @@ export interface Guild { approximateMemberCount?: number; /** Approximate number of non-offline members in this guild, returned from the GET /guilds/ endpoint when with_counts is true */ approximatePresenceCount?: number; - /** The welcome screen of a Community guild, shown to new members, returned when in the invite object */ + /** The welcome screen of a Community guild, shown to new members, returned in an Invite's guild object */ welcomeScreen?: WelcomeScreen; /** `true` if this guild is designated as NSFW */ nsfw: boolean; diff --git a/src/types/guilds/guild_features.ts b/src/types/guilds/guild_features.ts index c507bb5be..75582bb3f 100644 --- a/src/types/guilds/guild_features.ts +++ b/src/types/guilds/guild_features.ts @@ -1,37 +1,37 @@ /** https://discord.com/developers/docs/resources/guild#guild-object-guild-features */ export enum DiscordGuildFeatures { /** Guild has access to set an invite splash background */ - INVITE_SPLASH = "INVITE_SPLASH", + InviteSplash = "INVITE_SPLASH", /** Guild has access to set 384kbps bitrate in voice (previously VIP voice servers) */ - VIP_REGIONS = "VIP_REGIONS", + VipRegions = "VIP_REGIONS", /** Guild has access to set a vanity URL */ - VANITY_URL = "VANITY_URL", + VanityUrl = "VANITY_URL", /** Guild is verified */ - VERIFIED = "VERIFIED", + Verified = "VERIFIED", /** Guild is partnered */ - PARTNERED = "PARTNERED", + Partnered = "PARTNERED", /** Guild can enable welcome screen, Membership Screening, stage channels and discovery, and recives community updates */ - COMMUNITY = "COMMUNITY", + Community = "COMMUNITY", /** Guild has access to use commerce features (i.e. create store channels) */ - COMMERCE = "COMMERCE", + Commerce = "COMMERCE", /** Guild has access to create news channels */ - NEWS = "NEWS", + News = "NEWS", /** Guild is able to be discovered in the directory */ - DISCOVERABLE = "DISCOVERABLE", + Discoverable = "DISCOVERABLE", /** guild cannot be discoverable */ - DISCOVERABLE_DISABLED = "DISCOVERABLE_DISABLED", + DiscoverableDisabled = "DISCOVERABLE_DISABLED", /** Guild is able to be featured in the directory */ - FEATURABLE = "FEATURABLE", + Feature = "FEATURABLE", /** Guild has access to set an animated guild icon */ - ANIMATED_ICON = "ANIMATED_ICON", + AnimatedIcon = "ANIMATED_ICON", /** Guild has access to set a guild banner image */ - BANNER = "BANNER", + Banner = "BANNER", /** Guild has enabled the welcome screen */ - WELCOME_SCREEN_ENABLED = "WELCOME_SCREEN_ENABLED", + WelcomeScreenEnabled = "WELCOME_SCREEN_ENABLED", /** Guild has enabled [Membership Screening](https://discord.com/developers/docs/resources/guild#membership-screening-object) */ - MEMBER_VERIFICATION_GATE_ENABLED = "MEMBER_VERIFICATION_GATE_ENABLED", + MemberVerificationGateEnabled = "MEMBER_VERIFICATION_GATE_ENABLED", /** Guild can be previewed before joining via Membership Screening or the directory */ - PREVIEW_ENABLED = "PREVIEW_ENABLED", + PreviewEnabled = "PREVIEW_ENABLED", } export type GuildFeatures = DiscordGuildFeatures; diff --git a/src/types/guilds/mfa_levels.ts b/src/types/guilds/mfa_levels.ts index 12ef1ad7a..cb664b8ae 100644 --- a/src/types/guilds/mfa_levels.ts +++ b/src/types/guilds/mfa_levels.ts @@ -1,9 +1,9 @@ /** https://discord.com/developers/docs/resources/guild#guild-object-mfa-level */ export enum DiscordMfaLevels { /** Guild has no MFA/2FA requirement for moderation actions */ - NONE, + None, /** Guild has a 2FA requirement for moderation actions */ - ELEVATED, + Elevated, } export type MfaLevels = DiscordMfaLevels; diff --git a/src/types/guilds/modify_guild_channel_position.ts b/src/types/guilds/modify_guild_channel_position.ts index 646cce814..734786e9c 100644 --- a/src/types/guilds/modify_guild_channel_position.ts +++ b/src/types/guilds/modify_guild_channel_position.ts @@ -1,4 +1,3 @@ -// TODO: most likely it is but check if lockPositions and parentId really are optional /** https://discord.com/developers/docs/resources/guild#modify-guild-channel-positions */ export interface ModifyGuildChannelPositions { /** Channel id */ diff --git a/src/types/guilds/modify_guild_role.ts b/src/types/guilds/modify_guild_role.ts index cb5e09006..a23d92329 100644 --- a/src/types/guilds/modify_guild_role.ts +++ b/src/types/guilds/modify_guild_role.ts @@ -18,5 +18,3 @@ export interface DiscordModifyGuildRole extends Omit { permissions?: string | null; } - -// TODO: check this diff --git a/src/types/guilds/premium_tiers.ts b/src/types/guilds/premium_tiers.ts index 755c87e00..f6df334ec 100644 --- a/src/types/guilds/premium_tiers.ts +++ b/src/types/guilds/premium_tiers.ts @@ -1,13 +1,13 @@ /** https://discord.com/developers/docs/resources/guild#guild-object-premium-tier */ export enum DiscordPremiumTiers { /** Guild has not unlocked any Server Boost perks */ - NONE, + None, /** Guild has unlocked Server Boost level 1 perks */ - TIER_1, + Tier1, /** Guild has unlocked Server Boost level 2 perks */ - TIER_2, + Tier2, /** Guild has unlocked Server Boost level 3 perks */ - TIER_3, + Tier3, } export type PremiumTiers = DiscordPremiumTiers; diff --git a/src/types/guilds/system_channel_flags.ts b/src/types/guilds/system_channel_flags.ts index a2aebd752..81a5e2e79 100644 --- a/src/types/guilds/system_channel_flags.ts +++ b/src/types/guilds/system_channel_flags.ts @@ -1,11 +1,11 @@ /** https://discord.com/developers/docs/resources/guild#guild-object-system-channel-flags */ export enum DiscordSystemChannelFlags { /** Suppress member join notifications */ - SUPPRESS_JOIN_NOTIFICATIONS = 1 << 0, + SuppressJoinNotifications = 1 << 0, /** Suppress server boost notifications */ - SUPPRESS_PREMIUM_SUBSCRIPTIONS = 1 << 1, + SuppressPremiumSubscriptions = 1 << 1, /** Suppress server setup tips */ - SUPPRESS_GUILD_REMINDER_NOTIFICATIONS = 1 << 2, + SuppressGuildReminderNotifications = 1 << 2, } export type SystemChannelFlags = DiscordSystemChannelFlags; diff --git a/src/types/guilds/verification_levels.ts b/src/types/guilds/verification_levels.ts index 5e4e5f98e..5afa2f4d8 100644 --- a/src/types/guilds/verification_levels.ts +++ b/src/types/guilds/verification_levels.ts @@ -1,15 +1,15 @@ /** https://discord.com/developers/docs/resources/guild#guild-object-verification-level */ export enum DiscordVerificationLevels { /** Unrestricted */ - NONE, + None, /** Must have verified email on account */ - LOW, + Low, /** Must be registered on Discord for longer than 5 minutes */ - MEDIUM, + Medium, /** Must be a member of the server for longer than 10 minutes */ - HIGH, + High, /** Must have a verified phone number */ - VERY_HIGH, + VeryHigh, } export type VerificationLevels = DiscordVerificationLevels; diff --git a/src/types/integration/guild_integrations_update.ts b/src/types/integrations/guild_integrations_update.ts similarity index 100% rename from src/types/integration/guild_integrations_update.ts rename to src/types/integrations/guild_integrations_update.ts diff --git a/src/types/integration/integration.ts b/src/types/integrations/integration.ts similarity index 100% rename from src/types/integration/integration.ts rename to src/types/integrations/integration.ts diff --git a/src/types/integration/integration_account.ts b/src/types/integrations/integration_account.ts similarity index 100% rename from src/types/integration/integration_account.ts rename to src/types/integrations/integration_account.ts diff --git a/src/types/integration/integration_application.ts b/src/types/integrations/integration_application.ts similarity index 100% rename from src/types/integration/integration_application.ts rename to src/types/integrations/integration_application.ts diff --git a/src/types/integration/integration_create_update.ts b/src/types/integrations/integration_create_update.ts similarity index 100% rename from src/types/integration/integration_create_update.ts rename to src/types/integrations/integration_create_update.ts diff --git a/src/types/integration/integration_delete.ts b/src/types/integrations/integration_delete.ts similarity index 100% rename from src/types/integration/integration_delete.ts rename to src/types/integrations/integration_delete.ts diff --git a/src/types/integration/integration_expire_behaviors.ts b/src/types/integrations/integration_expire_behaviors.ts similarity index 100% rename from src/types/integration/integration_expire_behaviors.ts rename to src/types/integrations/integration_expire_behaviors.ts diff --git a/src/types/interactions/application_command_interaction_data_option.ts b/src/types/interactions/application_command_interaction_data_option.ts deleted file mode 100644 index 99421663d..000000000 --- a/src/types/interactions/application_command_interaction_data_option.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { DiscordApplicationCommandOptionTypes } from "./application_command_option_types.ts"; - -/** https://discord.com/developers/docs/interactions/slash-commands#interaction-applicationcommandinteractiondataoption */ -export interface ApplicationCommandInteractionDataOption { - /** The name of the parameter */ - name: string; - /** value of DiscordApplicationCommandOptionTypes */ - type: DiscordApplicationCommandOptionTypes; - /** The value of the pair */ - value?: DiscordApplicationCommandOptionTypes; - /** Present if this option is a group or subcommand */ - options?: ApplicationCommandInteractionDataOption[]; -} diff --git a/src/types/interactions/application_command.ts b/src/types/interactions/commands/application_command.ts similarity index 100% rename from src/types/interactions/application_command.ts rename to src/types/interactions/commands/application_command.ts diff --git a/src/types/interactions/application_command_callback_data.ts b/src/types/interactions/commands/application_command_callback_data.ts similarity index 80% rename from src/types/interactions/application_command_callback_data.ts rename to src/types/interactions/commands/application_command_callback_data.ts index 5844862d2..6857815af 100644 --- a/src/types/interactions/application_command_callback_data.ts +++ b/src/types/interactions/commands/application_command_callback_data.ts @@ -1,5 +1,5 @@ -import { Embed } from "../embeds/embed.ts"; -import { AllowedMentions } from "../messages/allowed_mentions.ts"; +import { Embed } from "../../embeds/embed.ts"; +import { AllowedMentions } from "../../messages/allowed_mentions.ts"; /** https://discord.com/developers/docs/interactions/slash-commands#interaction-response-interactionapplicationcommandcallbackdata */ export interface InteractionApplicationCommandCallbackData { diff --git a/src/types/interactions/application_command_create_update_delete.ts b/src/types/interactions/commands/application_command_create_update_delete.ts similarity index 100% rename from src/types/interactions/application_command_create_update_delete.ts rename to src/types/interactions/commands/application_command_create_update_delete.ts diff --git a/src/types/interactions/application_command_interaction_data.ts b/src/types/interactions/commands/application_command_interaction_data.ts similarity index 100% rename from src/types/interactions/application_command_interaction_data.ts rename to src/types/interactions/commands/application_command_interaction_data.ts diff --git a/src/types/interactions/commands/application_command_interaction_data_option.ts b/src/types/interactions/commands/application_command_interaction_data_option.ts new file mode 100644 index 000000000..67189716e --- /dev/null +++ b/src/types/interactions/commands/application_command_interaction_data_option.ts @@ -0,0 +1,85 @@ +import { DiscordApplicationCommandOptionTypes } from "./application_command_option_types.ts"; + +/** https://discord.com/developers/docs/interactions/slash-commands#interaction-applicationcommandinteractiondataoption */ +export type ApplicationCommandInteractionDataOption = + | ApplicationCommandInteractionDataOptionSubCommand + | ApplicationCommandInteractionDataOptionSubCommandGroup + | ApplicationCommandInteractionDataOptionString + | ApplicationCommandInteractionDataOptionInteger + | ApplicationCommandInteractionDataOptionBoolean + | ApplicationCommandInteractionDataOptionUser + | ApplicationCommandInteractionDataOptionChannel + | ApplicationCommandInteractionDataOptionRole + | ApplicationCommandInteractionDataOptionMentionable; + +interface ApplicationCommandInteractionDataOptionBase< + T extends DiscordApplicationCommandOptionTypes, + V = unknown, +> { + /** The name of the parameter */ + name: string; + /** Type of the option */ + type: T; + /** The value of the pair */ + value: V; +} + +export interface ApplicationCommandInteractionDataOptionSubCommand + extends + ApplicationCommandInteractionDataOptionBase< + DiscordApplicationCommandOptionTypes.SubCommand + > { + /** Present if this option is a group or subcommand */ + options?: ApplicationCommandInteractionDataOption[]; +} + +export interface ApplicationCommandInteractionDataOptionSubCommandGroup + extends + ApplicationCommandInteractionDataOptionBase< + DiscordApplicationCommandOptionTypes.SubCommandGroup + > { + /** Present if this option is a group or subcommand */ + options?: ApplicationCommandInteractionDataOption[]; +} + +export type ApplicationCommandInteractionDataOptionString = + ApplicationCommandInteractionDataOptionBase< + DiscordApplicationCommandOptionTypes.String, + string + >; + +export type ApplicationCommandInteractionDataOptionInteger = + ApplicationCommandInteractionDataOptionBase< + DiscordApplicationCommandOptionTypes.Integer, + number + >; + +export type ApplicationCommandInteractionDataOptionBoolean = + ApplicationCommandInteractionDataOptionBase< + DiscordApplicationCommandOptionTypes.Boolean, + boolean + >; + +export type ApplicationCommandInteractionDataOptionUser = + ApplicationCommandInteractionDataOptionBase< + DiscordApplicationCommandOptionTypes.User, + bigint + >; + +export type ApplicationCommandInteractionDataOptionChannel = + ApplicationCommandInteractionDataOptionBase< + DiscordApplicationCommandOptionTypes.Channel, + bigint + >; + +export type ApplicationCommandInteractionDataOptionRole = + ApplicationCommandInteractionDataOptionBase< + DiscordApplicationCommandOptionTypes.Role, + bigint + >; + +export type ApplicationCommandInteractionDataOptionMentionable = + ApplicationCommandInteractionDataOptionBase< + DiscordApplicationCommandOptionTypes.Mentionable, + bigint + >; diff --git a/src/types/interactions/application_command_interaction_data_resolved.ts b/src/types/interactions/commands/application_command_interaction_data_resolved.ts similarity index 68% rename from src/types/interactions/application_command_interaction_data_resolved.ts rename to src/types/interactions/commands/application_command_interaction_data_resolved.ts index db967bb97..976129ece 100644 --- a/src/types/interactions/application_command_interaction_data_resolved.ts +++ b/src/types/interactions/commands/application_command_interaction_data_resolved.ts @@ -1,7 +1,7 @@ -import { Channel } from "../channels/channel.ts"; -import { GuildMember } from "../guilds/guild_member.ts"; -import { Role } from "../permissions/role.ts"; -import { User } from "../users/user.ts"; +import { Channel } from "../../channels/channel.ts"; +import { GuildMember } from "../../members/guild_member.ts"; +import { Role } from "../../permissions/role.ts"; +import { User } from "../../users/user.ts"; export interface ApplicationCommandInteractionDataResolved { /** The Ids and User objects */ diff --git a/src/types/interactions/application_command_option.ts b/src/types/interactions/commands/application_command_option.ts similarity index 100% rename from src/types/interactions/application_command_option.ts rename to src/types/interactions/commands/application_command_option.ts diff --git a/src/types/interactions/application_command_option_choice.ts b/src/types/interactions/commands/application_command_option_choice.ts similarity index 100% rename from src/types/interactions/application_command_option_choice.ts rename to src/types/interactions/commands/application_command_option_choice.ts diff --git a/src/types/interactions/application_command_option_types.ts b/src/types/interactions/commands/application_command_option_types.ts similarity index 73% rename from src/types/interactions/application_command_option_types.ts rename to src/types/interactions/commands/application_command_option_types.ts index da0f2ed76..efae7bf80 100644 --- a/src/types/interactions/application_command_option_types.ts +++ b/src/types/interactions/commands/application_command_option_types.ts @@ -1,14 +1,14 @@ /** https://discord.com/developers/docs/interactions/slash-commands#applicationcommandoptiontype */ export enum DiscordApplicationCommandOptionTypes { - SUB_COMMAND = 1, - SUB_COMMAND_GROUP, - STRING, - INTEGER, - BOOLEAN, - USER, - CHANNEL, - ROLE, - MENTIONABLE, + SubCommand = 1, + SubCommandGroup, + String, + Integer, + Boolean, + User, + Channel, + Role, + Mentionable, } export type ApplicationCommandOptionTypes = diff --git a/src/types/interactions/application_command_permission_types.ts b/src/types/interactions/commands/application_command_permission_types.ts similarity index 100% rename from src/types/interactions/application_command_permission_types.ts rename to src/types/interactions/commands/application_command_permission_types.ts diff --git a/src/types/interactions/application_command_permissions.ts b/src/types/interactions/commands/application_command_permissions.ts similarity index 100% rename from src/types/interactions/application_command_permissions.ts rename to src/types/interactions/commands/application_command_permissions.ts diff --git a/src/types/interactions/create_global_application_command.ts b/src/types/interactions/commands/create_global_application_command.ts similarity index 100% rename from src/types/interactions/create_global_application_command.ts rename to src/types/interactions/commands/create_global_application_command.ts diff --git a/src/types/interactions/create_guild_application_command.ts b/src/types/interactions/commands/create_guild_application_command.ts similarity index 100% rename from src/types/interactions/create_guild_application_command.ts rename to src/types/interactions/commands/create_guild_application_command.ts diff --git a/src/types/interactions/edit_global_application_command.ts b/src/types/interactions/commands/edit_global_application_command.ts similarity index 100% rename from src/types/interactions/edit_global_application_command.ts rename to src/types/interactions/commands/edit_global_application_command.ts diff --git a/src/types/interactions/edit_guild_application_command.ts b/src/types/interactions/commands/edit_guild_application_command.ts similarity index 100% rename from src/types/interactions/edit_guild_application_command.ts rename to src/types/interactions/commands/edit_guild_application_command.ts diff --git a/src/types/interactions/guild_application_command_permissions.ts b/src/types/interactions/commands/guild_application_command_permissions.ts similarity index 100% rename from src/types/interactions/guild_application_command_permissions.ts rename to src/types/interactions/commands/guild_application_command_permissions.ts diff --git a/src/types/interactions/interaction.ts b/src/types/interactions/interaction.ts index 975238ac8..adf4ab521 100644 --- a/src/types/interactions/interaction.ts +++ b/src/types/interactions/interaction.ts @@ -1,7 +1,7 @@ -import { GuildMemberWithUser } from "../guilds/guild_member.ts"; +import { GuildMemberWithUser } from "../members/guild_member.ts"; import { Message } from "../messages/message.ts"; import { User } from "../users/user.ts"; -import { ApplicationCommandInteractionData } from "./application_command_interaction_data.ts"; +import { ApplicationCommandInteractionData } from "./commands/application_command_interaction_data.ts"; import { DiscordInteractionTypes } from "./interaction_types.ts"; /** https://discord.com/developers/docs/interactions/slash-commands#interaction */ diff --git a/src/types/interactions/interaction_guild_member.ts b/src/types/interactions/interaction_guild_member.ts index fb9cebc78..d7ab18d57 100644 --- a/src/types/interactions/interaction_guild_member.ts +++ b/src/types/interactions/interaction_guild_member.ts @@ -1,4 +1,4 @@ -import { GuildMember } from "../guilds/guild_member.ts"; +import { GuildMember } from "../members/guild_member.ts"; /** https://discord.com/developers/docs/resources/guild#guild-member-object */ export interface InteractionGuildMember extends GuildMember { diff --git a/src/types/interactions/interaction_response.ts b/src/types/interactions/interaction_response.ts index 5460cbb4e..4b0ac1b8c 100644 --- a/src/types/interactions/interaction_response.ts +++ b/src/types/interactions/interaction_response.ts @@ -1,4 +1,4 @@ -import { InteractionApplicationCommandCallbackData } from "./application_command_callback_data.ts"; +import { InteractionApplicationCommandCallbackData } from "./commands/application_command_callback_data.ts"; import { DiscordInteractionResponseTypes } from "./interaction_response_types.ts"; /** https://discord.com/developers/docs/interactions/slash-commands#interaction-response */ diff --git a/src/types/invites/target_types.ts b/src/types/invites/target_types.ts index c8f16d0ac..0d3153072 100644 --- a/src/types/invites/target_types.ts +++ b/src/types/invites/target_types.ts @@ -1,7 +1,7 @@ /** https://discord.com/developers/docs/resources/invite#invite-object-target-user-types */ export enum DiscordTargetTypes { - STREAM = 1, - EMBEDDED_APPLICATION, + Stream = 1, + EmbeddedApplication, } export type TargetTypes = DiscordTargetTypes; diff --git a/src/types/guilds/guild_member.ts b/src/types/members/guild_member.ts similarity index 100% rename from src/types/guilds/guild_member.ts rename to src/types/members/guild_member.ts diff --git a/src/types/members/guild_member_add.ts b/src/types/members/guild_member_add.ts index a39685228..f5b8bd9ee 100644 --- a/src/types/members/guild_member_add.ts +++ b/src/types/members/guild_member_add.ts @@ -1,4 +1,4 @@ -import { GuildMemberWithUser } from "../guilds/guild_member.ts"; +import { GuildMemberWithUser } from "../members/guild_member.ts"; /** https://discord.com/developers/docs/topics/gateway#guild-member-add */ export interface GuildMemberAdd extends GuildMemberWithUser { diff --git a/src/types/members/guild_members_chunk.ts b/src/types/members/guild_members_chunk.ts index a4b801f33..0e0cd7a32 100644 --- a/src/types/members/guild_members_chunk.ts +++ b/src/types/members/guild_members_chunk.ts @@ -1,5 +1,5 @@ -import { GuildMemberWithUser } from "../guilds/guild_member.ts"; -import { PresenceUpdate } from "../misc/presence_update.ts"; +import { PresenceUpdate } from "../activity/presence_update.ts"; +import { GuildMemberWithUser } from "../members/guild_member.ts"; /** https://discord.com/developers/docs/topics/gateway#guild-members-chunk */ export interface GuildMembersChunk { diff --git a/src/types/guilds/list_guild_members.ts b/src/types/members/list_guild_members.ts similarity index 100% rename from src/types/guilds/list_guild_members.ts rename to src/types/members/list_guild_members.ts diff --git a/src/types/guilds/modify_current_user_nick.ts b/src/types/members/modify_current_user_nick.ts similarity index 100% rename from src/types/guilds/modify_current_user_nick.ts rename to src/types/members/modify_current_user_nick.ts diff --git a/src/types/guilds/request_guild_members.ts b/src/types/members/request_guild_members.ts similarity index 100% rename from src/types/guilds/request_guild_members.ts rename to src/types/members/request_guild_members.ts diff --git a/src/types/messages/create_message.ts b/src/types/messages/create_message.ts index 836b0040c..5bee7b6ae 100644 --- a/src/types/messages/create_message.ts +++ b/src/types/messages/create_message.ts @@ -1,20 +1,18 @@ import { Embed } from "../embeds/embed.ts"; import { AllowedMentions } from "../messages/allowed_mentions.ts"; import { MessageReference } from "../messages/message_reference.ts"; -import { FileContent } from "../misc/file_content.ts"; +import { FileContent } from "../discordeno/file_content.ts"; import { SnakeCasedPropertiesDeep } from "../util.ts"; import { MessageComponents } from "./components/message_components.ts"; export interface CreateMessage { /** The message contents (up to 2000 characters) */ content?: string; - /** A nonce that can be used for optimistic message sending */ - nonce?: number | string; /** true if this is a TTS message */ tts?: boolean; /** Embedded `rich` content */ embed?: Embed; - /** Allowed mentions for a message */ + /** Allowed mentions for the message */ allowedMentions?: AllowedMentions; /** Include to make your message a reply */ messageReference?: MessageReference; @@ -28,5 +26,3 @@ export interface CreateMessage { export type DiscordCreateMessage = SnakeCasedPropertiesDeep< Omit >; - -// TODO: check this diff --git a/src/types/messages/edit_message.ts b/src/types/messages/edit_message.ts index 41169bc55..7009b9a1c 100644 --- a/src/types/messages/edit_message.ts +++ b/src/types/messages/edit_message.ts @@ -1,3 +1,4 @@ +import { FileContent } from "../discordeno/file_content.ts"; import { Embed } from "../embeds/embed.ts"; import { AllowedMentions } from "./allowed_mentions.ts"; import { Attachment } from "./attachment.ts"; @@ -10,6 +11,8 @@ export interface EditMessage { embed?: Embed | null; /** Edit the flags of the message (only `SUPRESS_EMBEDS` can currently be set/unset) */ flags?: 4 | null; + /** The contents of the file being sent/edited */ + file?: FileContent | FileContent[] | null; /** Allowed mentions for the message */ allowedMentions?: AllowedMentions | null; /** Attached files to keep */ diff --git a/src/types/messages/message.ts b/src/types/messages/message.ts index 3d373a69f..72934232f 100644 --- a/src/types/messages/message.ts +++ b/src/types/messages/message.ts @@ -1,7 +1,9 @@ +import { Channel } from "../channels/channel.ts"; import { ChannelMention } from "../channels/channel_mention.ts"; +import { ThreadMember } from "../channels/threads/thread_member.ts"; import { Embed } from "../embeds/embed.ts"; -import { GuildMember } from "../guilds/guild_member.ts"; import { MessageInteraction } from "../interactions/message_interaction.ts"; +import { GuildMember } from "../members/guild_member.ts"; import { Application } from "../oauth2/application.ts"; import { User } from "../users/user.ts"; import { Attachment } from "./attachment.ts"; @@ -83,6 +85,8 @@ export interface Message { referencedMessage?: Message; /** Sent if the message is a response to an Interaction */ interaction?: MessageInteraction; + /** The thread that was started from this message, includes thread member object */ + thread?: Omit & { member: ThreadMember }; /** The components related to this message */ components: MessageComponents; } diff --git a/src/types/messages/message_activity_types.ts b/src/types/messages/message_activity_types.ts index 5340111b9..91944ae0f 100644 --- a/src/types/messages/message_activity_types.ts +++ b/src/types/messages/message_activity_types.ts @@ -1,9 +1,9 @@ /** https://discord.com/developers/docs/resources/channel#message-object-message-activity-types */ export enum DiscordMessageActivityTypes { - JOIN = 1, - SPECTATE, - LISTEN, - JOIN_REQUEST, + Join = 1, + Spectate, + Listen, + JoinRequest, } export type MessageActivityTypes = DiscordMessageActivityTypes; diff --git a/src/types/messages/message_flags.ts b/src/types/messages/message_flags.ts index 57de222e1..76f4f422c 100644 --- a/src/types/messages/message_flags.ts +++ b/src/types/messages/message_flags.ts @@ -1,19 +1,21 @@ /** https://discord.com/developers/docs/resources/channel#message-object-message-flags */ export enum DiscordMessageFlags { /** This message has been published to subscribed channels (via Channel Following) */ - CROSSPOSTED = 1 << 0, + Crossposted = 1 << 0, /** This message originated from a message in another channel (via Channel Following) */ - IS_CROSSPOST = 1 << 1, + IsCrosspost = 1 << 1, /** Do not include any embeds when serializing this message */ - SUPPRESS_EMBEDS = 1 << 2, + SuppressEmbeeds = 1 << 2, /** The source message for this crosspost has been deleted (via Channel Following) */ - SOURCE_MESSAGE_DELETED = 1 << 3, + SourceMessageDeleted = 1 << 3, /** This message came from the urgent message system */ - URGENT = 1 << 4, + Urgent = 1 << 4, + /** This message has an associated thread, with the same id as the message */ + HasThread = 1 << 5, /** This message is only visible to the user who invoked the Interaction */ - EMPHERAL = 1 << 6, + Empheral = 1 << 6, /** This message is an Interaction Response and the bot is "thinking" */ - LOADING = 1 << 7, + Loading = 1 << 7, } export type MessageFlags = DiscordMessageFlags; diff --git a/src/types/messages/message_reaction_add.ts b/src/types/messages/message_reaction_add.ts index ef3709af3..c0846e858 100644 --- a/src/types/messages/message_reaction_add.ts +++ b/src/types/messages/message_reaction_add.ts @@ -1,5 +1,5 @@ import { Emoji } from "../emojis/emoji.ts"; -import { GuildMemberWithUser } from "../guilds/guild_member.ts"; +import { GuildMemberWithUser } from "../members/guild_member.ts"; /** https://discord.com/developers/docs/topics/gateway#message-reaction-add */ export interface MessageReactionAdd { diff --git a/src/types/messages/message_sticker_format_types.ts b/src/types/messages/message_sticker_format_types.ts index 3a2baa629..7193cb245 100644 --- a/src/types/messages/message_sticker_format_types.ts +++ b/src/types/messages/message_sticker_format_types.ts @@ -1,8 +1,8 @@ /** https://discord.com/developers/docs/resources/channel#message-object-message-sticker-format-types */ export enum DiscordMessageStickerFormatTypes { - PNG = 1, - APNG, - LOTTIE, + Png = 1, + Apng, + Lottie, } export type MessageStickerFormatTypes = DiscordMessageStickerFormatTypes; diff --git a/src/types/messages/message_types.ts b/src/types/messages/message_types.ts index 263c8851f..540359326 100644 --- a/src/types/messages/message_types.ts +++ b/src/types/messages/message_types.ts @@ -1,25 +1,26 @@ /** https://discord.com/developers/docs/resources/channel#message-object-message-types */ export enum DiscordMessageTypes { - DEFAULT, - RECIPIENT_ADD, - RECIPIENT_REMOVE, - CALL, - CHANNEL_NAME_CHANGE, - CHANNEL_ICON_CHANGE, - CHANNEL_PINNED_MESSAGE, - GUILD_MEMBER_JOIN, - USER_PREMIUM_GUILD_SUBSCRIPTION, - USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_1, - USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_2, - USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_3, - CHANNEL_FOLLOW_ADD, - GUILD_DISCOVERY_DISQUALIFIED = 14, - GUILD_DISCOVERY_REQUALIFIED, - GUILD_DISCOVERY_GRACE_PERIOD_INITIAL_WARNING, - GUILD_DISCOVERY_GRACE_PERIOD_FINAL_WARNING, - REPLY = 19, - APPLICATION_COMMAND, - GUILD_INVITE_REMINDER = 22, + Default, + RecipientAdd, + RecipientRemove, + Call, + ChannelNameChange, + ChannelIconChange, + ChannelPinnedMessage, + GuildMemberJoin, + UserPremiumGuildSubscription, + UserPremiumGuildSubscriptionTier1, + UserPremiumGuildSubscriptionTier2, + UserPremiumGuildSubscriptionTier3, + ChannelFollowAdd, + GuildDiscoveryDisqualified = 14, + GuildDiscoveryRequalified, + GuildDiscoveryGracePeriodInitialWarning, + GuildDiscoveryGracePeriodFinalWarning, + ThreadCreated, + Reply = 19, + ApplicationCommand, + GuildInviteReminder = 22, } export type MessageTypes = DiscordMessageTypes; diff --git a/src/types/misc/typing_start.ts b/src/types/misc/typing_start.ts index 4c23b7d2b..748de7b3f 100644 --- a/src/types/misc/typing_start.ts +++ b/src/types/misc/typing_start.ts @@ -1,4 +1,4 @@ -import { GuildMember } from "../guilds/guild_member.ts"; +import { GuildMember } from "../members/guild_member.ts"; /** https://discord.com/developers/docs/topics/gateway#typing-start */ export interface TypingStart { diff --git a/src/types/mod.ts b/src/types/mod.ts index bc4d06750..2bd4c0e92 100644 --- a/src/types/mod.ts +++ b/src/types/mod.ts @@ -1,3 +1,14 @@ +export * from "./activity/activity.ts"; +export * from "./activity/activity_assets.ts"; +export * from "./activity/activity_button.ts"; +export * from "./activity/activity_emoji.ts"; +export * from "./activity/activity_flags.ts"; +export * from "./activity/activity_party.ts"; +export * from "./activity/activity_secrets.ts"; +export * from "./activity/activity_timestamps.ts"; +export * from "./activity/activity_types.ts"; +export * from "./activity/client_status.ts"; +export * from "./activity/presence_update.ts"; export * from "./audit_log/audit_log.ts"; export * from "./audit_log/audit_log_change.ts"; export * from "./audit_log/audit_log_change_value.ts"; @@ -13,6 +24,14 @@ export * from "./channels/followed_channel.ts"; export * from "./channels/modify_channel.ts"; export * from "./channels/overwrite.ts"; export * from "./channels/overwrite_types.ts"; +export * from "./channels/threads/list_active_threads.ts"; +export * from "./channels/threads/list_public_archived_threads.ts"; +export * from "./channels/threads/modify_thread.ts"; +export * from "./channels/threads/start_thread.ts"; +export * from "./channels/threads/thread_list_sync.ts"; +export * from "./channels/threads/thread_member.ts"; +export * from "./channels/threads/thread_members_update.ts"; +export * from "./channels/threads/thread_metadata.ts"; export * from "./channels/video_quality_modes.ts"; export * from "./codes/gateway_close_event_codes.ts"; export * from "./codes/gateway_opcodes.ts"; @@ -25,10 +44,19 @@ export * from "./codes/voice_opcodes.ts"; export * from "./discordeno/create_slash_command.ts"; export * from "./discordeno/debug_arg.ts"; export * from "./discordeno/edit_webhook_message.ts"; +export * from "./discordeno/errors.ts"; export * from "./discordeno/eventHandlers.ts"; +export * from "./discordeno/file_content.ts"; export * from "./discordeno/guild_member.ts"; export * from "./discordeno/guild_update_change.ts"; export * from "./discordeno/interaction_response.ts"; +export * from "./discovery/add_guild_discovery_subcategory.ts"; +export * from "./discovery/discovery_category.ts"; +export * from "./discovery/discovery_metadata.ts"; +export * from "./discovery/discovery_name.ts"; +export * from "./discovery/modify_guild_discovery_metadata.ts"; +export * from "./discovery/validate_discovery_search_term.ts"; +export * from "./discovery/validate_discovery_search_term_params.ts"; export * from "./embeds/embed.ts"; export * from "./embeds/embed_author.ts"; export * from "./embeds/embed_field.ts"; @@ -70,15 +98,13 @@ export * from "./guilds/guild.ts"; export * from "./guilds/guild_ban_add_remove.ts"; export * from "./guilds/guild_ban_remove.ts"; export * from "./guilds/guild_features.ts"; -export * from "./guilds/guild_member.ts"; export * from "./guilds/guild_preview.ts"; export * from "./guilds/guild_role_create.ts"; export * from "./guilds/guild_role_delete.ts"; export * from "./guilds/guild_role_update.ts"; export * from "./guilds/guild_widget.ts"; -export * from "./guilds/list_guild_members.ts"; +export * from "./guilds/guild_widget_details.ts"; export * from "./guilds/mfa_levels.ts"; -export * from "./guilds/modify_current_user_nick.ts"; export * from "./guilds/modify_guild.ts"; export * from "./guilds/modify_guild_channel_position.ts"; export * from "./guilds/modify_guild_member.ts"; @@ -86,32 +112,36 @@ export * from "./guilds/modify_guild_role.ts"; export * from "./guilds/modify_guild_role_positions.ts"; export * from "./guilds/modify_guild_welcome_screen.ts"; export * from "./guilds/premium_tiers.ts"; -export * from "./guilds/request_guild_members.ts"; export * from "./guilds/system_channel_flags.ts"; export * from "./guilds/unavailable_guild.ts"; +export * from "./guilds/update_others_voice_state.ts"; +export * from "./guilds/update_self_voice_state.ts"; export * from "./guilds/verification_levels.ts"; export * from "./guilds/welcome_screen.ts"; export * from "./guilds/welcome_screen_channel.ts"; -export * from "./integration/guild_integrations_update.ts"; -export * from "./integration/integration.ts"; -export * from "./integration/integration_account.ts"; -export * from "./integration/integration_application.ts"; -export * from "./integration/integration_create_update.ts"; -export * from "./integration/integration_delete.ts"; -export * from "./integration/integration_expire_behaviors.ts"; -export * from "./interactions/application_command.ts"; -export * from "./interactions/application_command_callback_data.ts"; -export * from "./interactions/application_command_create_update_delete.ts"; -export * from "./interactions/application_command_interaction_data.ts"; -export * from "./interactions/application_command_interaction_data_option.ts"; -export * from "./interactions/application_command_interaction_data_resolved.ts"; -export * from "./interactions/application_command_option.ts"; -export * from "./interactions/application_command_option_choice.ts"; -export * from "./interactions/application_command_option_types.ts"; -export * from "./interactions/create_global_application_command.ts"; -export * from "./interactions/create_guild_application_command.ts"; -export * from "./interactions/edit_global_application_command.ts"; -export * from "./interactions/edit_guild_application_command.ts"; +export * from "./integrations/guild_integrations_update.ts"; +export * from "./integrations/integration.ts"; +export * from "./integrations/integration_account.ts"; +export * from "./integrations/integration_application.ts"; +export * from "./integrations/integration_create_update.ts"; +export * from "./integrations/integration_delete.ts"; +export * from "./integrations/integration_expire_behaviors.ts"; +export * from "./interactions/commands/application_command.ts"; +export * from "./interactions/commands/application_command_callback_data.ts"; +export * from "./interactions/commands/application_command_create_update_delete.ts"; +export * from "./interactions/commands/application_command_interaction_data.ts"; +export * from "./interactions/commands/application_command_interaction_data_option.ts"; +export * from "./interactions/commands/application_command_interaction_data_resolved.ts"; +export * from "./interactions/commands/application_command_option.ts"; +export * from "./interactions/commands/application_command_option_choice.ts"; +export * from "./interactions/commands/application_command_option_types.ts"; +export * from "./interactions/commands/application_command_permissions.ts"; +export * from "./interactions/commands/application_command_permission_types.ts"; +export * from "./interactions/commands/create_global_application_command.ts"; +export * from "./interactions/commands/create_guild_application_command.ts"; +export * from "./interactions/commands/edit_global_application_command.ts"; +export * from "./interactions/commands/edit_guild_application_command.ts"; +export * from "./interactions/commands/guild_application_command_permissions.ts"; export * from "./interactions/interaction.ts"; export * from "./interactions/interaction_guild_member.ts"; export * from "./interactions/interaction_response.ts"; @@ -126,19 +156,23 @@ export * from "./invites/invite_delete.ts"; export * from "./invites/invite_metadata.ts"; export * from "./invites/invite_target_types.ts"; export * from "./invites/target_types.ts"; +export * from "./members/guild_member.ts"; export * from "./members/guild_members_chunk.ts"; export * from "./members/guild_member_add.ts"; export * from "./members/guild_member_remove.ts"; export * from "./members/guild_member_update.ts"; +export * from "./members/list_guild_members.ts"; +export * from "./members/modify_current_user_nick.ts"; +export * from "./members/request_guild_members.ts"; export * from "./members/search_guild_members.ts"; -export * from "./messages/components/action_row.ts"; -export * from "./messages/components/button_component.ts"; -export * from "./messages/components/button_styles.ts"; -export * from "./messages/components/message_component_types.ts"; -export * from "./messages/components/message_components.ts"; export * from "./messages/allowed_mentions.ts"; export * from "./messages/allowed_mentions_types.ts"; export * from "./messages/attachment.ts"; +export * from "./messages/components/action_row.ts"; +export * from "./messages/components/button_component.ts"; +export * from "./messages/components/button_styles.ts"; +export * from "./messages/components/message_components.ts"; +export * from "./messages/components/message_component_types.ts"; export * from "./messages/create_message.ts"; export * from "./messages/edit_message.ts"; export * from "./messages/get_messages.ts"; @@ -158,21 +192,8 @@ export * from "./messages/message_sticker.ts"; export * from "./messages/message_sticker_format_types.ts"; export * from "./messages/message_types.ts"; export * from "./messages/reaction.ts"; -export * from "./misc/activity.ts"; -export * from "./misc/activity_assets.ts"; -export * from "./misc/activity_button.ts"; -export * from "./misc/activity_emoji.ts"; -export * from "./misc/activity_flags.ts"; -export * from "./misc/activity_party.ts"; -export * from "./misc/activity_secrets.ts"; -export * from "./misc/activity_timestamps.ts"; -export * from "./misc/activity_types.ts"; -export * from "./misc/client_status.ts"; -export * from "./misc/errors.ts"; -export * from "./misc/file_content.ts"; export * from "./misc/image_format.ts"; export * from "./misc/image_size.ts"; -export * from "./misc/presence_update.ts"; export * from "./misc/typing_start.ts"; export * from "./mod.ts"; export * from "./oauth2/application.ts"; diff --git a/src/types/oauth2/application_flags.ts b/src/types/oauth2/application_flags.ts index 5fe9538f2..d2ada528b 100644 --- a/src/types/oauth2/application_flags.ts +++ b/src/types/oauth2/application_flags.ts @@ -1,5 +1,4 @@ -// https://github.com/discord/discord-api-docs/pull/2624 -// TODO: add documentation link +/** https://discord.com/developers/docs/topics/oauth2#application-application-flags */ export enum DiscordApplicationFlags { GatewayPresence = 1 << 12, GatewayPresenceLimited = 1 << 13, diff --git a/src/types/permissions/bitwise_permission_flags.ts b/src/types/permissions/bitwise_permission_flags.ts index cd539e5d0..c76891e99 100644 --- a/src/types/permissions/bitwise_permission_flags.ts +++ b/src/types/permissions/bitwise_permission_flags.ts @@ -65,7 +65,13 @@ export enum DiscordBitwisePermissionFlags { /** Allows members to use slash commands in text channels */ USE_SLASH_COMMANDS = 0x80000000, /** Allows for requesting to speak in stage channels. */ - REQUEST_TO_SPEAK = 0x100000000, + REQUEST_TO_SPEAK = 0x100000001, + /** Allows for deleting and archiving threads, and viewing all private threads */ + MANAGE_THREADS = 0x0400000000, + /** Allows for creating and participating in threads */ + USE_PUBLIC_THREADS = 0x0800000000, + /** Allows for creating and participating in private threads */ + USE_PRIVATE_THREADS = 0x1000000000, } export type BitwisePermissions = DiscordBitwisePermissionFlags; diff --git a/src/types/teams/team_membership_states.ts b/src/types/teams/team_membership_states.ts index 151fb4868..b1bc70c8d 100644 --- a/src/types/teams/team_membership_states.ts +++ b/src/types/teams/team_membership_states.ts @@ -1,7 +1,7 @@ /** https://discord.com/developers/docs/topics/teams#data-models-membership-state-enum */ export enum DiscordTeamMembershipStates { - INVITED = 1, - ACCEPTED, + Invited = 1, + Accepted, } export type TeamMembershipStates = DiscordTeamMembershipStates; diff --git a/src/types/users/connection.ts b/src/types/users/connection.ts index 4d3f64f26..69e8de021 100644 --- a/src/types/users/connection.ts +++ b/src/types/users/connection.ts @@ -1,4 +1,4 @@ -import { Integration } from "../integration/integration.ts"; +import { Integration } from "../integrations/integration.ts"; import { DiscordVisibilityTypes } from "./visibility_types.ts"; /** https://discord.com/developers/docs/resources/user#connection-objecthttps://discord.com/developers/docs/resources/user#user-object-premium-types */ diff --git a/src/types/voice/voice_state.ts b/src/types/voice/voice_state.ts index 8aa38f68b..156e15ad4 100644 --- a/src/types/voice/voice_state.ts +++ b/src/types/voice/voice_state.ts @@ -1,4 +1,4 @@ -import { GuildMemberWithUser } from "../guilds/guild_member.ts"; +import { GuildMemberWithUser } from "../members/guild_member.ts"; /** https://discord.com/developers/docs/resources/voice#voice-state-object-voice-state-structure */ export interface VoiceState { diff --git a/src/types/webhooks/edit_webhook_message.ts b/src/types/webhooks/edit_webhook_message.ts index 6317c70fe..ea18f54a5 100644 --- a/src/types/webhooks/edit_webhook_message.ts +++ b/src/types/webhooks/edit_webhook_message.ts @@ -1,7 +1,7 @@ import { Embed } from "../embeds/embed.ts"; import { AllowedMentions } from "../messages/allowed_mentions.ts"; -import { FileContent } from "../misc/file_content.ts"; import { Attachment } from "../messages/attachment.ts"; +import { FileContent } from "../discordeno/file_content.ts"; /** https://discord.com/developers/docs/resources/webhook#edit-webhook-message-jsonform-params */ export interface EditWebhookMessage { @@ -10,7 +10,7 @@ export interface EditWebhookMessage { /** Embedded `rich` content */ embeds?: Embed[] | null; /** The contents of the file being sent/edited */ - file?: FileContent | FileContent[]; + file?: FileContent | FileContent[] | null; /** Allowed mentions for the message */ allowedMentions?: AllowedMentions | null; /** Attached files to keep */ diff --git a/src/types/webhooks/execute_webhook.ts b/src/types/webhooks/execute_webhook.ts index f668a0906..c8c47639d 100644 --- a/src/types/webhooks/execute_webhook.ts +++ b/src/types/webhooks/execute_webhook.ts @@ -1,12 +1,14 @@ import { Embed } from "../embeds/embed.ts"; import { AllowedMentions } from "../messages/allowed_mentions.ts"; -import { FileContent } from "../misc/file_content.ts"; +import { FileContent } from "../discordeno/file_content.ts"; import { SnakeCasedPropertiesDeep } from "../util.ts"; /** https://discord.com/developers/docs/resources/webhook#execute-webhook */ export interface ExecuteWebhook { /** Waits for server confirmation of message send before response, and returns the created message body (defaults to `false`; when `false` a message that is not saved does not return an error) */ wait?: boolean; + /** Send a message to the specified thread within a webhook's channel. The thread will automatically be unarchived. */ + threadId?: bigint; /** The message contents (up to 2000 characters) */ content?: string; /** Override the default username of the webhook */ @@ -26,4 +28,3 @@ export interface ExecuteWebhook { export type DiscordExecuteWebhook = SnakeCasedPropertiesDeep< Omit >; -//TODO: check this diff --git a/src/util/cache_members.ts b/src/util/cache_members.ts new file mode 100644 index 000000000..86e27d15a --- /dev/null +++ b/src/util/cache_members.ts @@ -0,0 +1,57 @@ +import { eventHandlers } from "../bot.ts"; +import { cacheHandlers } from "../cache.ts"; +import { structures } from "../structures/mod.ts"; +import { GuildMemberWithUser } from "../types/members/guild_member.ts"; + +const guildMemberQueue = new Map< + bigint, + { members: GuildMemberWithUser[]; resolve?: (value?: unknown) => void } +>(); +let processingQueue = false; + +/** Cache all guild members without need to worry about overwriting something. */ +// deno-lint-ignore require-await +export async function cacheMembers( + guildId: bigint, + members: GuildMemberWithUser[], +) { + return new Promise((resolve) => { + guildMemberQueue.set(guildId, { members, resolve }); + startQueue(); + }); +} + +async function startQueue() { + if (processingQueue) return; + + processingQueue = true; + + while (guildMemberQueue.size) { + eventHandlers.debug?.("loop", "Running whille loop in cache_members file."); + const [guildId, queue]: [ + bigint, + { members: GuildMemberWithUser[]; resolve: (value?: unknown) => void }, + ] = guildMemberQueue.entries().next().value; + + await Promise.allSettled([ + queue.members.map(async (member) => { + const discordenoMember = await structures.createDiscordenoMember( + member, + guildId, + ); + + await cacheHandlers.set( + "members", + discordenoMember.id, + discordenoMember, + ); + }), + ]); + + queue.resolve?.(); + + guildMemberQueue.delete(guildId); + } + + processingQueue = false; +} diff --git a/src/util/constants.ts b/src/util/constants.ts index 132f802f7..89b987d3a 100644 --- a/src/util/constants.ts +++ b/src/util/constants.ts @@ -2,13 +2,14 @@ export const BASE_URL = "https://discord.com/api"; /** https://discord.com/developers/docs/reference#api-versioning-api-versions */ -export const API_VERSION = 8; +export const API_VERSION = 9; /** https://discord.com/developers/docs/topics/gateway#gateways-gateway-versions */ -export const GATEWAY_VERSION = 8; +export const GATEWAY_VERSION = 9; +// TODO: update this version /** https://github.com/discordeno/discordeno/releases */ -export const DISCORDENO_VERSION = 11; +export const DISCORDENO_VERSION = "11.0.0"; /** https://discord.com/developers/docs/reference#user-agent */ export const USER_AGENT = @@ -77,6 +78,28 @@ export const endpoints = { // Bots SHALL NOT use this endpoint but they can CHANNEL_TYPING: (channelId: bigint) => `${CHANNEL_BASE(channelId)}/typing`, + // Thread Endpoints + THREAD_START_PUBLIC: (channelId: bigint, messageId: bigint) => + `${endpoints.CHANNEL_MESSAGE(channelId, messageId)}/threads`, + THREAD_START_PRIVATE: (channelId: bigint) => + `${CHANNEL_BASE(channelId)}/threads`, + THREAD_ACTIVE: (channelId: bigint) => + `${CHANNEL_BASE(channelId)}/threads/active`, + THREAD_MEMBERS: (channelId: bigint) => + `${CHANNEL_BASE(channelId)}/thread-members`, + THREAD_ME: (channelId: bigint) => + `${endpoints.THREAD_MEMBERS(channelId)}/@me`, + THREAD_USER: (channelId: bigint, userId: bigint) => + `${endpoints.THREAD_MEMBERS(channelId)}/${userId}`, + THREAD_ARCHIVED_BASE: (channelId: bigint) => + `${CHANNEL_BASE(channelId)}/threads/archived`, + THREAD_ARCHIVED_PUBLIC: (channelId: bigint) => + `${endpoints.THREAD_ARCHIVED_BASE(channelId)}/public`, + THREAD_ARCHIVED_PRIVATE: (channelId: bigint) => + `${endpoints.THREAD_ARCHIVED_BASE(channelId)}/private`, + THREAD_ARCHIVED_PRIVATE_JOINED: (channelId: bigint) => + `${CHANNEL_BASE(channelId)}/users/@me/threads/archived/private`, + // Guild Endpoints GUILDS: `${baseEndpoints.BASE_URL}/guilds`, GUILD_AUDIT_LOGS: (guildId: bigint) => `${GUILDS_BASE(guildId)}/audit-logs`, @@ -138,6 +161,8 @@ export const endpoints = { `${baseEndpoints.BASE_URL}/webhooks/${webhookId}`, WEBHOOK_MESSAGE: (webhookId: bigint, token: string, messageId: bigint) => `${baseEndpoints.BASE_URL}/webhooks/${webhookId}/${token}/messages/${messageId}`, + WEBHOOK_MESSAGE_ORIGINAL: (webhookId: bigint, token: string) => + `${baseEndpoints.BASE_URL}/webhooks/${webhookId}/${token}/messages/@original`, WEBHOOK_SLACK: (webhookId: bigint, token: string) => `${baseEndpoints.BASE_URL}/webhooks/${webhookId}/${token}/slack`, WEBHOOK_GITHUB: (webhookId: bigint, token: string) => diff --git a/src/util/mod.ts b/src/util/mod.ts index 9af7e2b53..5adeab630 100644 --- a/src/util/mod.ts +++ b/src/util/mod.ts @@ -1,4 +1,5 @@ export * from "./bigint.ts"; +export * from "./cache_members.ts"; export * from "./collection.ts"; export * from "./constants.ts"; export * from "./loop_object.ts"; diff --git a/src/util/permissions.ts b/src/util/permissions.ts index 86cb97ea0..b2f5c71f8 100644 --- a/src/util/permissions.ts +++ b/src/util/permissions.ts @@ -4,9 +4,10 @@ import { DiscordenoChannel } from "../structures/channel.ts"; import { DiscordenoGuild } from "../structures/guild.ts"; import { DiscordenoMember } from "../structures/member.ts"; import { DiscordenoRole } from "../structures/role.ts"; -import { Errors } from "../types/misc/errors.ts"; +import { Overwrite } from "../types/channels/overwrite.ts"; +import { Errors } from "../types/discordeno/errors.ts"; import { DiscordBitwisePermissionFlags } from "../types/permissions/bitwise_permission_flags.ts"; -import { PermissionStrings } from "../types/permissions/permission_strings.ts"; +import type { PermissionStrings } from "../types/permissions/permission_strings.ts"; async function getCached( table: "guilds", @@ -28,11 +29,6 @@ async function getCached( ? // @ts-ignore TS is wrong here await cacheHandlers.get(table, key) : key; - if (!cached || typeof cached === "bigint") { - throw new Error( - Errors[`${table.slice(0, -1).toUpperCase()}_NOT_FOUND` as Errors], - ); - } return typeof cached === "bigint" ? undefined : cached; } @@ -50,7 +46,7 @@ export async function calculateBasePermissions( let permissions = 0n; // Calculate the role permissions bits, @everyone role is not in memberRoleIds so we need to pass guildId manualy permissions |= [...(member.guilds.get(guild.id)?.roles || []), guild.id] - .map((id) => (guild as DiscordenoGuild).roles.get(id)?.permissions) + .map((id) => guild.roles.get(id)?.permissions) // Removes any edge case undefined .filter((perm) => perm) .reduce((bits, perms) => { @@ -76,7 +72,7 @@ export async function calculateChannelOverwrites( const member = await getCached("members", memberOrId); - if (!member) return "8"; + if (!channel || !member) return "8"; // Get all the role permissions this member already has let permissions = BigInt( @@ -84,8 +80,8 @@ export async function calculateChannelOverwrites( ); // First calculate @everyone overwrites since these have the lowest priority - const overwriteEveryone = channel?.permissionOverwrites?.find( - (overwrite) => overwrite.id === (channel as DiscordenoChannel).guildId, + const overwriteEveryone = channel.permissionOverwrites?.find( + (overwrite) => overwrite.id === channel.guildId, ); if (overwriteEveryone) { // First remove denied permissions since denied < allowed @@ -93,7 +89,7 @@ export async function calculateChannelOverwrites( permissions |= BigInt(overwriteEveryone.allow); } - const overwrites = channel?.permissionOverwrites; + const overwrites = channel.permissionOverwrites; // In order to calculate the role permissions correctly we need to temporarily save the allowed and denied permissions let allow = 0n; @@ -112,7 +108,7 @@ export async function calculateChannelOverwrites( // Third calculate member specific overwrites since these have the highest priority const overwriteMember = overwrites?.find( - (overwrite) => overwrite.id === (member as DiscordenoMember).id, + (overwrite) => overwrite.id === member.id, ); if (overwriteMember) { permissions &= ~BigInt(overwriteMember.deny); @@ -290,6 +286,26 @@ export function calculateBits(permissions: PermissionStrings[]) { .toString(); } +/** Internal function to check if the bot has the permissions to set these overwrites */ +export async function requireOverwritePermissions( + guildOrId: bigint | DiscordenoGuild, + overwrites: Overwrite[], +) { + let requiredPerms: Set = new Set(["MANAGE_CHANNELS"]); + + overwrites?.forEach((overwrite) => { + overwrite.allow.forEach(requiredPerms.add, requiredPerms); + overwrite.deny.forEach(requiredPerms.add, requiredPerms); + }); + + // MANAGE_ROLES permission can only be set by administrators + if (requiredPerms.has("MANAGE_ROLES")) { + requiredPerms = new Set(["ADMINISTRATOR"]); + } + + await requireGuildPermissions(guildOrId, botId, [...requiredPerms]); +} + /** Gets the highest role from the member in this guild */ export async function highestRole( guildOrId: bigint | DiscordenoGuild, diff --git a/src/util/utils.ts b/src/util/utils.ts index 6a2b9a240..d936d291b 100644 --- a/src/util/utils.ts +++ b/src/util/utils.ts @@ -1,13 +1,13 @@ import { encode } from "../../deps.ts"; import { eventHandlers } from "../bot.ts"; -import { ApplicationCommandOption } from "../types/interactions/application_command_option.ts"; -import { ApplicationCommandOptionChoice } from "../types/interactions/application_command_option_choice.ts"; -import { DiscordApplicationCommandOptionTypes } from "../types/interactions/application_command_option_types.ts"; -import { CreateGlobalApplicationCommand } from "../types/interactions/create_global_application_command.ts"; -import { Errors } from "../types/misc/errors.ts"; -import { DiscordImageFormat } from "../types/misc/image_format.ts"; -import { DiscordImageSize } from "../types/misc/image_size.ts"; -import { EditGlobalApplicationCommand } from "../types/mod.ts"; +import { Errors } from "../types/discordeno/errors.ts"; +import type { ApplicationCommandOption } from "../types/interactions/commands/application_command_option.ts"; +import type { ApplicationCommandOptionChoice } from "../types/interactions/commands/application_command_option_choice.ts"; +import { DiscordApplicationCommandOptionTypes } from "../types/interactions/commands/application_command_option_types.ts"; +import type { CreateGlobalApplicationCommand } from "../types/interactions/commands/create_global_application_command.ts"; +import type { EditGlobalApplicationCommand } from "../types/interactions/commands/edit_global_application_command.ts"; +import type { DiscordImageFormat } from "../types/misc/image_format.ts"; +import type { DiscordImageSize } from "../types/misc/image_size.ts"; import { SLASH_COMMANDS_NAME_REGEX } from "./constants.ts"; import { validateLength } from "./validate_length.ts"; @@ -61,7 +61,7 @@ function isConvertableObject(obj: unknown) { ); } -export function camelKeysToSnakeCase( +export function snakelize( // deno-lint-ignore no-explicit-any obj: Record | Record[], ): T { @@ -72,9 +72,9 @@ export function camelKeysToSnakeCase( Object.keys(obj).forEach((key) => { eventHandlers.debug?.( "loop", - `Running forEach loop in camelKeysToSnakeCase function.`, + `Running forEach loop in snakelize function.`, ); - convertedObject[camelToSnakeCase(key)] = camelKeysToSnakeCase( + convertedObject[camelToSnakeCase(key)] = snakelize( // deno-lint-ignore no-explicit-any (obj as Record)[key], ); @@ -82,13 +82,13 @@ export function camelKeysToSnakeCase( return convertedObject as T; } else if (Array.isArray(obj)) { - obj = obj.map((element) => camelKeysToSnakeCase(element)); + obj = obj.map((element) => snakelize(element)); } return obj as T; } -export function snakeKeysToCamelCase( +export function camelize( // deno-lint-ignore no-explicit-any obj: Record | Record[], ): T { @@ -99,9 +99,9 @@ export function snakeKeysToCamelCase( Object.keys(obj).forEach((key) => { eventHandlers.debug?.( "loop", - `Running forEach loop in snakeKeysToCamelCase function.`, + `Running forEach loop in camelize function.`, ); - convertedObject[snakeToCamelCase(key)] = snakeKeysToCamelCase( + convertedObject[snakeToCamelCase(key)] = camelize( // deno-lint-ignore no-explicit-any (obj as Record)[key], ); @@ -109,7 +109,7 @@ export function snakeKeysToCamelCase( return convertedObject as T; } else if (Array.isArray(obj)) { - obj = obj.map((element) => snakeKeysToCamelCase(element)); + obj = obj.map((element) => camelize(element)); } return obj as T; @@ -130,11 +130,11 @@ function validateSlashOptionChoices( } if ( - (optionType === DiscordApplicationCommandOptionTypes.STRING && + (optionType === DiscordApplicationCommandOptionTypes.String && (typeof choice.value !== "string" || choice.value.length < 1 || choice.value.length > 100)) || - (optionType === DiscordApplicationCommandOptionTypes.INTEGER && + (optionType === DiscordApplicationCommandOptionTypes.Integer && typeof choice.value !== "number") ) { throw new Error(Errors.INVALID_SLASH_OPTIONS_CHOICES); @@ -152,8 +152,8 @@ function validateSlashOptions(options: ApplicationCommandOption[]) { if ( option.choices?.length && (option.choices.length > 25 || - (option.type !== DiscordApplicationCommandOptionTypes.STRING && - option.type !== DiscordApplicationCommandOptionTypes.INTEGER)) + (option.type !== DiscordApplicationCommandOptionTypes.String && + option.type !== DiscordApplicationCommandOptionTypes.Integer)) ) { throw new Error(Errors.INVALID_SLASH_OPTIONS_CHOICES); } @@ -204,3 +204,15 @@ export function validateSlashCommands( } } } + +// Typescript is not so good as we developers so we need this little utility function to help it out +// Taken from https://fettblog.eu/typescript-hasownproperty/ +/** TS save way to check if a property exists in an object */ +// deno-lint-ignore ban-types +export function hasOwnProperty( + obj: T, + prop: Y, +): obj is T & Record { + // deno-lint-ignore no-prototype-builtins + return obj.hasOwnProperty(prop); +} diff --git a/src/ws/events.ts b/src/ws/events.ts index a64d7e474..1a9a03e6d 100644 --- a/src/ws/events.ts +++ b/src/ws/events.ts @@ -1,4 +1,4 @@ -import { DiscordGatewayPayload } from "../types/gateway/gateway_payload.ts"; +import type { DiscordGatewayPayload } from "../types/gateway/gateway_payload.ts"; import { DiscordenoShard } from "./ws.ts"; /** The handler for logging different actions happening inside the ws. User can override and put custom handling per event. */ diff --git a/src/ws/handle_discord_payload.ts b/src/ws/handle_discord_payload.ts index a1ba8ddb8..3a21169a1 100644 --- a/src/ws/handle_discord_payload.ts +++ b/src/ws/handle_discord_payload.ts @@ -1,4 +1,4 @@ -import { DiscordGatewayPayload } from "../types/gateway/gateway_payload.ts"; +import type { DiscordGatewayPayload } from "../types/gateway/gateway_payload.ts"; import { ws } from "./ws.ts"; /** Handler for processing all dispatch payloads that should be sent/forwarded to another server/vps/process. */ diff --git a/src/ws/handle_on_message.ts b/src/ws/handle_on_message.ts index 055b6e203..33335c8da 100644 --- a/src/ws/handle_on_message.ts +++ b/src/ws/handle_on_message.ts @@ -1,10 +1,10 @@ import { eventHandlers } from "../bot.ts"; import { handlers } from "../handlers/mod.ts"; import { DiscordGatewayOpcodes } from "../types/codes/gateway_opcodes.ts"; -import { DiscordGatewayPayload } from "../types/gateway/gateway_payload.ts"; -import { DiscordHello } from "../types/gateway/hello.ts"; -import { DiscordReady } from "../types/gateway/ready.ts"; -import { delay, snakeKeysToCamelCase } from "../util/utils.ts"; +import type { DiscordGatewayPayload } from "../types/gateway/gateway_payload.ts"; +import type { DiscordHello } from "../types/gateway/hello.ts"; +import type { DiscordReady } from "../types/gateway/ready.ts"; +import { camelize, delay } from "../util/utils.ts"; import { decompressWith } from "./deps.ts"; import { identify } from "./identify.ts"; import { resume } from "./resume.ts"; @@ -128,7 +128,7 @@ export async function handleOnMessage(message: any, shardId: number) { if (!messageData.t) return; return handlers[messageData.t]?.( - snakeKeysToCamelCase(messageData), + camelize(messageData), shardId, ); } diff --git a/src/ws/start_gateway.ts b/src/ws/start_gateway.ts index e057a91d8..281611bcd 100644 --- a/src/ws/start_gateway.ts +++ b/src/ws/start_gateway.ts @@ -1,6 +1,6 @@ import { DiscordGatewayIntents } from "../types/gateway/gateway_intents.ts"; -import { GetGatewayBot } from "../types/gateway/get_gateway_bot.ts"; -import { snakeKeysToCamelCase } from "../util/utils.ts"; +import type { GetGatewayBot } from "../types/gateway/get_gateway_bot.ts"; +import { camelize } from "../util/utils.ts"; import { StartGatewayOptions } from "./start_gateway_options.ts"; import { ws } from "./ws.ts"; @@ -33,7 +33,7 @@ export async function startGateway(options: StartGatewayOptions) { 0, ); - ws.botGatewayData = snakeKeysToCamelCase( + ws.botGatewayData = camelize( await fetch(`https://discord.com/api/gateway/bot`, { headers: { Authorization: ws.identifyPayload.token }, }).then((res) => res.json()), diff --git a/src/ws/ws.ts b/src/ws/ws.ts index a66e3f816..2ff84d92b 100644 --- a/src/ws/ws.ts +++ b/src/ws/ws.ts @@ -49,7 +49,7 @@ export const ws = { }, botGatewayData: { /** The WSS URL that can be used for connecting to the gateway. */ - url: "wss://gateway.discord.gg/?v=8&encoding=json", + url: "wss://gateway.discord.gg/?v=9&encoding=json", /** The recommended number of shards to use when connecting. */ shards: 1, /** Info on the current start limit. */ diff --git a/test.ts b/test.ts deleted file mode 100644 index 540dc8902..000000000 --- a/test.ts +++ /dev/null @@ -1,75 +0,0 @@ -const config = { - maxConcurrency: 16, - maxShards: 1120, - maxClusters: 140, - shardsPerCluster: 8, -}; - -function sleep(ms: number) { - return new Promise((resolve) => setTimeout(resolve, ms)); -} - -function organizeClusters() { - const clusters = new Map(); - const buckets = new Map(); - const shardClusters = new Map(); - let cluster = 0; - - for (let i = 0; i < config.maxShards; i++) { - const shards = clusters.get(cluster); - if (!shards) clusters.set(cluster, [i]); - else { - if (shards.length < config.shardsPerCluster) shards.push(i); - else { - cluster++; - clusters.set(cluster, [i]); - } - } - - shardClusters.set(i, cluster); - } - - for (let i = 0; i < config.maxShards; i++) { - const bucketID = i % config.maxConcurrency; - const bucket = buckets.get(bucketID); - if (!bucket) { - buckets.set(bucketID, [i]); - } else { - bucket.push(i); - } - } - - return { clusters, buckets }; -} - -function startup() { - const { clusters, buckets } = organizeClusters(); - - // SPREAD THIS OUT TO DIFFERENT CLUSTERS TO BEGIN STARTING UP - // FOREACH will have this concurrently - buckets.forEach(async (bucket, bucketID) => { - for (const queue of bucket) { - for (const shardID of queue) { - console.log( - `Bucket ID:`, - bucketID, - "Cluster ID:", - clusters.get(shardID), - "Shard ID:", - shardID, - ); - redis.publish( - "sharder", - JSON.stringify({ clusterID: clusters.get(shardID), shardID }), - ); - } - - // AFTER THIS QUEUE IS CREATED WE WAIT FOR ALL SHARDS TO LOAD BEFORE NEXT CLUSTER - // 5 SECONDS PER SHARD + EXTRA 10 TO BE SAFE - await sleep(config.shardsPerCluster * 5000 + 10000); - } - }); -} - -startup(); -setInterval(startup, 60000 * 5); diff --git a/tests/channels/category_children.ts b/tests/channels/category_children.ts index 3c012bec1..a649e066f 100644 --- a/tests/channels/category_children.ts +++ b/tests/channels/category_children.ts @@ -1,17 +1,17 @@ -import { defaultTestOptions, tempData } from "../ws/start_bot.ts"; -import { assertExists } from "../deps.ts"; import { cache } from "../../src/cache.ts"; import { categoryChildren, createChannel } from "../../src/helpers/mod.ts"; import { DiscordChannelTypes } from "../../src/types/channels/channel_types.ts"; -import { delayUntil } from "../util/delay_until.ts"; import { bigintToSnowflake } from "../../src/util/bigint.ts"; +import { assertExists } from "../deps.ts"; +import { delayUntil } from "../util/delay_until.ts"; +import { defaultTestOptions, tempData } from "../ws/start_bot.ts"; Deno.test({ name: "[channel] category channel ids", async fn() { const category = await createChannel(tempData.guildId, { name: "Discordeno-test", - type: DiscordChannelTypes.GUILD_CATEGORY, + type: DiscordChannelTypes.GuildCategory, }); // Assertions diff --git a/tests/channels/channel_overwrite_has_permission.ts b/tests/channels/channel_overwrite_has_permission.ts index 239f81886..ff84e4add 100644 --- a/tests/channels/channel_overwrite_has_permission.ts +++ b/tests/channels/channel_overwrite_has_permission.ts @@ -10,13 +10,12 @@ import { assertEquals, assertExists } from "../deps.ts"; import { delayUntil } from "../util/delay_until.ts"; import { defaultTestOptions, tempData } from "../ws/start_bot.ts"; -// TODO: whats save? -async function ifItFailsBlameWolf(options: CreateGuildChannel, _save = false) { +async function ifItFailsBlameWolf(options: CreateGuildChannel) { const channel = await createChannel(tempData.guildId, options); // Assertions assertExists(channel); - assertEquals(channel.type, options.type || DiscordChannelTypes.GUILD_TEXT); + assertEquals(channel.type, options.type || DiscordChannelTypes.GuildText); // Delay the execution by 5 seconds to allow CHANNEL_CREATE event to be processed await delayUntil(10000, () => cache.channels.has(channel.id)); @@ -54,13 +53,12 @@ Deno.test({ permissionOverwrites: [ { id: bigintToSnowflake(botId), - type: DiscordOverwriteTypes.MEMBER, + type: DiscordOverwriteTypes.Member, allow: ["VIEW_CHANNEL"], deny: [], }, ], }, - true, ); }, ...defaultTestOptions, diff --git a/tests/channels/clone_channel.ts b/tests/channels/clone_channel.ts index df772deb5..9838a7698 100644 --- a/tests/channels/clone_channel.ts +++ b/tests/channels/clone_channel.ts @@ -10,8 +10,7 @@ import { assertEquals, assertExists } from "../deps.ts"; import { delayUntil } from "../util/delay_until.ts"; import { defaultTestOptions, tempData } from "../ws/start_bot.ts"; -// TODO: whats save -async function ifItFailsBlameWolf(options: CreateGuildChannel, _save = false) { +async function ifItFailsBlameWolf(options: CreateGuildChannel) { const channel = await createChannel(tempData.guildId, options); const cloned = await cloneChannel(channel.id); @@ -51,7 +50,7 @@ async function ifItFailsBlameWolf(options: CreateGuildChannel, _save = false) { Deno.test({ name: "[channel] clone a new text channel", async fn() { - await ifItFailsBlameWolf({ name: "Discordeno-clone-test" }, false); + await ifItFailsBlameWolf({ name: "Discordeno-clone-test" }); }, ...defaultTestOptions, }); @@ -62,9 +61,8 @@ Deno.test({ await ifItFailsBlameWolf( { name: "Discordeno-clone-test", - type: DiscordChannelTypes.GUILD_CATEGORY, + type: DiscordChannelTypes.GuildCategory, }, - false, ); }, ...defaultTestOptions, @@ -76,9 +74,8 @@ Deno.test({ await ifItFailsBlameWolf( { name: "Discordeno-clone-test", - type: DiscordChannelTypes.GUILD_VOICE, + type: DiscordChannelTypes.GuildVoice, }, - false, ); }, ...defaultTestOptions, @@ -90,10 +87,9 @@ Deno.test({ await ifItFailsBlameWolf( { name: "discordeno-clone-test", - type: DiscordChannelTypes.GUILD_VOICE, + type: DiscordChannelTypes.GuildVoice, bitrate: 32000, }, - false, ); }, ...defaultTestOptions, @@ -105,10 +101,9 @@ Deno.test({ await ifItFailsBlameWolf( { name: "Discordeno-clone-test", - type: DiscordChannelTypes.GUILD_VOICE, + type: DiscordChannelTypes.GuildVoice, userLimit: 32, }, - false, ); }, ...defaultTestOptions, @@ -122,7 +117,6 @@ Deno.test({ name: "Discordeno-clone-test", rateLimitPerUser: 2423, }, - false, ); }, ...defaultTestOptions, @@ -133,7 +127,6 @@ Deno.test({ async fn() { await ifItFailsBlameWolf( { name: "Discordeno-clone-test", nsfw: true }, - false, ); }, ...defaultTestOptions, @@ -148,13 +141,12 @@ Deno.test({ permissionOverwrites: [ { id: bigintToSnowflake(botId), - type: DiscordOverwriteTypes.MEMBER, + type: DiscordOverwriteTypes.Member, allow: ["VIEW_CHANNEL"], deny: [], }, ], }, - false, ); }, ...defaultTestOptions, diff --git a/tests/channels/create_channel.ts b/tests/channels/create_channel.ts index b6148d75c..63b44ec7e 100644 --- a/tests/channels/create_channel.ts +++ b/tests/channels/create_channel.ts @@ -1,20 +1,20 @@ -import { defaultTestOptions, tempData } from "../ws/start_bot.ts"; -import { assertEquals, assertExists } from "../deps.ts"; -import { cache } from "../../src/cache.ts"; -import { DiscordChannelTypes } from "../../src/types/channels/channel_types.ts"; -import { CreateGuildChannel } from "../../src/types/guilds/create_guild_channel.ts"; -import { createChannel } from "../../src/helpers/channels/create_channel.ts"; -import { delayUntil } from "../util/delay_until.ts"; -import { DiscordOverwriteTypes } from "../../src/types/channels/overwrite_types.ts"; import { botId } from "../../src/bot.ts"; +import { cache } from "../../src/cache.ts"; +import { createChannel } from "../../src/helpers/channels/create_channel.ts"; +import { DiscordChannelTypes } from "../../src/types/channels/channel_types.ts"; +import { DiscordOverwriteTypes } from "../../src/types/channels/overwrite_types.ts"; +import { CreateGuildChannel } from "../../src/types/guilds/create_guild_channel.ts"; import { bigintToSnowflake } from "../../src/util/bigint.ts"; +import { assertEquals, assertExists } from "../deps.ts"; +import { delayUntil } from "../util/delay_until.ts"; +import { defaultTestOptions, tempData } from "../ws/start_bot.ts"; async function ifItFailsBlameWolf(options: CreateGuildChannel, save = false) { const channel = await createChannel(tempData.guildId, options); // Assertions assertExists(channel); - assertEquals(channel.type, options.type || DiscordChannelTypes.GUILD_TEXT); + assertEquals(channel.type, options.type || DiscordChannelTypes.GuildText); if (save) tempData.channelId = channel.id; @@ -61,7 +61,7 @@ Deno.test({ await ifItFailsBlameWolf( { name: "Discordeno-test", - type: DiscordChannelTypes.GUILD_CATEGORY, + type: DiscordChannelTypes.GuildCategory, }, true, ); @@ -91,7 +91,7 @@ Deno.test({ await ifItFailsBlameWolf( { name: "Discordeno-test", - type: DiscordChannelTypes.GUILD_VOICE, + type: DiscordChannelTypes.GuildVoice, }, true, ); @@ -105,7 +105,7 @@ Deno.test({ await ifItFailsBlameWolf( { name: "discordeno-test", - type: DiscordChannelTypes.GUILD_VOICE, + type: DiscordChannelTypes.GuildVoice, bitrate: 32000, }, true, @@ -120,7 +120,7 @@ Deno.test({ await ifItFailsBlameWolf( { name: "Discordeno-test", - type: DiscordChannelTypes.GUILD_VOICE, + type: DiscordChannelTypes.GuildVoice, userLimit: 32, }, true, @@ -160,7 +160,7 @@ Deno.test({ permissionOverwrites: [ { id: bigintToSnowflake(botId), - type: DiscordOverwriteTypes.MEMBER, + type: DiscordOverwriteTypes.Member, allow: ["VIEW_CHANNEL"], deny: [], }, diff --git a/tests/channels/delete_channel.ts b/tests/channels/delete_channel.ts index d2b46cb05..57cb9c986 100644 --- a/tests/channels/delete_channel.ts +++ b/tests/channels/delete_channel.ts @@ -1,8 +1,8 @@ import { cache } from "../../src/cache.ts"; import { createChannel } from "../../src/helpers/channels/create_channel.ts"; import { deleteChannel } from "../../src/helpers/channels/delete_channel.ts"; -import { defaultTestOptions, tempData } from "../ws/start_bot.ts"; import { delayUntil } from "../util/delay_until.ts"; +import { defaultTestOptions, tempData } from "../ws/start_bot.ts"; Deno.test({ name: "[channel] delete a channel without a reason.", @@ -21,7 +21,7 @@ Deno.test({ } // Delete the channel now without a reason - await deleteChannel(tempData.guildId, channel.id); + await deleteChannel(channel.id); // wait 5 seconds to give it time for CHANNEL_DELETE event await delayUntil(3000, () => !cache.channels.has(channel.id)); // Make sure it is gone from cache @@ -51,7 +51,7 @@ Deno.test({ } // Delete the channel now without a reason - await deleteChannel(tempData.guildId, channel.id, "with a reason"); + await deleteChannel(channel.id, "with a reason"); // wait 5 seconds to give it time for CHANNEL_DELETE event await delayUntil(10000, () => !cache.channels.has(channel.id)); // Make sure it is gone from cache diff --git a/tests/channels/delete_channel_overwrite.ts b/tests/channels/delete_channel_overwrite.ts index a17e2f099..d5337c631 100644 --- a/tests/channels/delete_channel_overwrite.ts +++ b/tests/channels/delete_channel_overwrite.ts @@ -15,7 +15,7 @@ async function ifItFailsBlameWolf(options: CreateGuildChannel, _save = false) { // Assertions assertExists(channel); - assertEquals(channel.type, options.type || DiscordChannelTypes.GUILD_TEXT); + assertEquals(channel.type, options.type || DiscordChannelTypes.GuildText); // Delay the execution by 5 seconds to allow CHANNEL_CREATE event to be processed await delayUntil(10000, () => cache.channels.has(channel.id)); @@ -56,7 +56,7 @@ Deno.test({ permissionOverwrites: [ { id: bigintToSnowflake(botId), - type: DiscordOverwriteTypes.MEMBER, + type: DiscordOverwriteTypes.Member, allow: ["VIEW_CHANNEL"], deny: [], }, diff --git a/tests/channels/edit_channel_overwrite.ts b/tests/channels/edit_channel_overwrite.ts index 64dbcb787..e74c244cd 100644 --- a/tests/channels/edit_channel_overwrite.ts +++ b/tests/channels/edit_channel_overwrite.ts @@ -11,13 +11,12 @@ import { assertEquals, assertExists } from "../deps.ts"; import { delayUntil } from "../util/delay_until.ts"; import { defaultTestOptions, tempData } from "../ws/start_bot.ts"; -// TODO: whats save -async function ifItFailsBlameWolf(options: CreateGuildChannel, _save = false) { +async function ifItFailsBlameWolf(options: CreateGuildChannel) { const channel = await createChannel(tempData.guildId, options); // Assertions assertExists(channel); - assertEquals(channel.type, options.type || DiscordChannelTypes.GUILD_TEXT); + assertEquals(channel.type, options.type || DiscordChannelTypes.GuildText); // Delay the execution by 5 seconds to allow CHANNEL_CREATE event to be processed await delayUntil(10000, () => cache.channels.has(channel.id)); @@ -36,7 +35,7 @@ async function ifItFailsBlameWolf(options: CreateGuildChannel, _save = false) { } await editChannelOverwrite(channel.guildId, channel.id, botId, { - type: DiscordOverwriteTypes.MEMBER, + type: DiscordOverwriteTypes.Member, allow: ["VIEW_CHANNEL", "ADD_REACTIONS"], deny: [], }); @@ -72,13 +71,12 @@ Deno.test({ permissionOverwrites: [ { id: bigintToSnowflake(botId), - type: DiscordOverwriteTypes.MEMBER, + type: DiscordOverwriteTypes.Member, allow: ["VIEW_CHANNEL"], deny: [], }, ], }, - true, ); }, ...defaultTestOptions, diff --git a/tests/channels/is_channel_synced.ts b/tests/channels/is_channel_synced.ts index 76c9c51dc..6a4d96db7 100644 --- a/tests/channels/is_channel_synced.ts +++ b/tests/channels/is_channel_synced.ts @@ -1,24 +1,24 @@ +import { botId } from "../../src/bot.ts"; import { cache } from "../../src/cache.ts"; import { createChannel } from "../../src/helpers/channels/create_channel.ts"; -import { defaultTestOptions, tempData } from "../ws/start_bot.ts"; -import { delayUntil } from "../util/delay_until.ts"; -import { assertEquals, assertExists } from "../deps.ts"; import { isChannelSynced } from "../../src/helpers/channels/is_channel_synced.ts"; import { DiscordChannelTypes } from "../../src/types/channels/channel_types.ts"; -import { botId } from "../../src/bot.ts"; import { DiscordOverwriteTypes } from "../../src/types/channels/overwrite_types.ts"; import { bigintToSnowflake } from "../../src/util/bigint.ts"; +import { assertEquals, assertExists } from "../deps.ts"; +import { delayUntil } from "../util/delay_until.ts"; +import { defaultTestOptions, tempData } from "../ws/start_bot.ts"; Deno.test({ name: "[channel] is channel synced.", async fn() { const category = await createChannel(tempData.guildId, { name: "synced-category", - type: DiscordChannelTypes.GUILD_CATEGORY, + type: DiscordChannelTypes.GuildCategory, permissionOverwrites: [ { id: bigintToSnowflake(botId), - type: DiscordOverwriteTypes.MEMBER, + type: DiscordOverwriteTypes.Member, allow: ["VIEW_CHANNEL"], deny: [], }, diff --git a/tests/deps.ts b/tests/deps.ts index 9e4747cff..8ecc89d22 100644 --- a/tests/deps.ts +++ b/tests/deps.ts @@ -2,4 +2,5 @@ export { assertArrayIncludes, assertEquals, assertExists, + assertThrows, } from "https://deno.land/std@0.90.0/testing/asserts.ts"; diff --git a/tests/util/utils.ts b/tests/util/utils.ts index c8a0fb686..233bf229e 100644 --- a/tests/util/utils.ts +++ b/tests/util/utils.ts @@ -1,8 +1,11 @@ +import { ApplicationCommandOption } from "../../src/types/interactions/commands/application_command_option.ts"; +import { DiscordApplicationCommandOptionTypes } from "../../src/types/interactions/commands/application_command_option_types.ts"; import { - camelKeysToSnakeCase, - snakeKeysToCamelCase, + camelize, + snakelize, + validateSlashCommands, } from "../../src/util/utils.ts"; -import { assertEquals } from "../deps.ts"; +import { assertEquals, assertThrows } from "../deps.ts"; const testSnakeObject = { // deno-lint-ignore camelcase @@ -58,9 +61,9 @@ const someElseOther = { Deno.test({ name: "[utils] convert snake case keys to camel case", fn() { - const result = snakeKeysToCamelCase(testSnakeObject); + const result = camelize(testSnakeObject); assertEquals(result, testCamelObject); - const resultTwo = snakeKeysToCamelCase(someOther); + const resultTwo = camelize(someOther); assertEquals(resultTwo, someOther); }, }); @@ -68,9 +71,58 @@ Deno.test({ Deno.test({ name: "[utils] convert camel case keys to snake case", fn() { - const result = camelKeysToSnakeCase(testCamelObject); + const result = snakelize(testCamelObject); assertEquals(result, testSnakeObject); - const resultTwo = camelKeysToSnakeCase(someElseOther); + const resultTwo = snakelize(someElseOther); assertEquals(resultTwo, someElseOther); }, }); + +Deno.test({ + name: "[utils] validateSlashCommands(): validates name", + fn() { + assertThrows(() => + validateSlashCommands([{ + // The maximum length of the name of an application command is 32. + name: "a".repeat(33), + }]) + ); + + validateSlashCommands([{ + name: "workingname", + }]); + }, +}); + +Deno.test({ + name: "[utils] validateSlashCommands(): validates description", + fn() { + assertThrows(() => + // The maximum length of the description of an application command is 100. + validateSlashCommands([{ description: "a".repeat(101) }]) + ); + + validateSlashCommands([{ + description: "valid description (should not throw)", + }]); + }, +}); + +Deno.test({ + name: "[utils] validateSlashCommands(): validates number of options", + fn() { + const option = { + name: "option1", + description: "The description of the application command's option.", + type: DiscordApplicationCommandOptionTypes.String, + }; + // The maximum number of options an application command can "accomodate" is 25. + const options: ApplicationCommandOption[] = Array(26).fill(option); + + assertThrows(() => validateSlashCommands([{ options }])); + + validateSlashCommands([{ + options: [option], + }]); + }, +}); diff --git a/tests/ws/start_bot.ts b/tests/ws/start_bot.ts index a68b2d0fc..266da17e9 100644 --- a/tests/ws/start_bot.ts +++ b/tests/ws/start_bot.ts @@ -36,11 +36,10 @@ Deno.test({ await startBot({ token, intents: [ - "GUILD_MESSAGES", - "GUILDS", - "GUILD_EMOJIS", - "GUILD_MESSAGE_REACTIONS", - "GUILD_EMOJIS", + "GuildMessages", + "Guilds", + "GuildEmojis", + "GuildMessageReactions", ], });