From f1f4322673e2618d7acf1a0aae42465d68d24dba Mon Sep 17 00:00:00 2001 From: Jonathan Ho Date: Sat, 18 Mar 2023 18:45:22 -0700 Subject: [PATCH 1/6] ci(site): add trigger on more file (#2837) --- .github/workflows/site.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/site.yml b/.github/workflows/site.yml index fe915515d..80d3c1001 100644 --- a/.github/workflows/site.yml +++ b/.github/workflows/site.yml @@ -10,11 +10,19 @@ on: paths: - "website/**" - ".github/workflows/site.yml" + - "jsdoc2md.json" + - "typedoc.json" + - "package.json" + - "packages/**" pull_request: branches: ["main"] paths: - "website/**" - ".github/workflows/site.yml" + - "jsdoc2md.json" + - "typedoc.json" + - "package.json" + - "packages/**" # Allows you to run this workflow manually from the Actions tab workflow_dispatch: From 922b31b308ced7fc709e097db1796229e8be04a5 Mon Sep 17 00:00:00 2001 From: Skillz4Killz <23035000+Skillz4Killz@users.noreply.github.com> Date: Thu, 23 Mar 2023 04:42:19 +0000 Subject: [PATCH 2/6] fix: exit on rest e2e and more tests --- packages/rest/package.json | 2 +- packages/rest/tests/e2e/message.spec.ts | 24 ++++++++++++++- packages/rest/tests/e2e/misc.spec.ts | 39 +++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 2 deletions(-) create mode 100644 packages/rest/tests/e2e/misc.spec.ts diff --git a/packages/rest/package.json b/packages/rest/package.json index 5db02088f..6103d4861 100644 --- a/packages/rest/package.json +++ b/packages/rest/package.json @@ -18,7 +18,7 @@ "test:unit-coverage": "c8 mocha --no-warnings 'tests/unit/**/*.spec.ts'", "test:unit": "c8 --r lcov mocha --no-warnings 'tests/unit/**/*.spec.ts' && node ../../scripts/coveragePathFixing.js rest", "test:deno-unit": "swc tests --delete-dir-on-start --out-dir denoTestsDist && node ../../scripts/fixDenoTestExtension.js && deno test -A --import-map ../../denoImportMap.json denoTestsDist/unit", - "test:e2e": "c8 --r lcov mocha --no-warnings --jobs 1 --t 30000 'tests/e2e/**/*.spec.ts' && node ../../scripts/coveragePathFixing.js rest", + "test:e2e": "c8 --r lcov mocha --exit --no-warnings --jobs 1 --t 30000 'tests/e2e/**/*.spec.ts' && node ../../scripts/coveragePathFixing.js rest", "test:unit:watch": "mocha --no-warnings --watch --parallel 'tests/unit/**/*.spec.ts'", "test:type": "tsc --noEmit", "test:test-type": "tsc --project tsconfig.test.json" diff --git a/packages/rest/tests/e2e/message.spec.ts b/packages/rest/tests/e2e/message.spec.ts index 047dc94a3..68b42604d 100644 --- a/packages/rest/tests/e2e/message.spec.ts +++ b/packages/rest/tests/e2e/message.spec.ts @@ -1,4 +1,4 @@ -import { urlToBase64, processReactionString } from '@discordeno/utils' +import { processReactionString, urlToBase64 } from '@discordeno/utils' import { expect } from 'chai' import { describe, it } from 'mocha' import { e2ecache, rest } from './utils.js' @@ -128,6 +128,28 @@ describe('Manage reactions', async () => { }) }) +describe("Manage pins", () => { +it('Pin, get, and unpin messages', async () => { + const channel = await rest.createChannel(e2ecache.guild.id, { name: 'pinning' }) + const message = await rest.sendMessage(channel.id, { content: 'pin me' }) + const message2 = await rest.sendMessage(channel.id, { content: 'pin me 2' }) + + await rest.pinMessage(channel.id, message.id) + await rest.pinMessage(channel.id, message2.id, 'with a reason') + + const pins = await rest.getPinnedMessages(channel.id) + expect(pins.length).to.equal(2) + expect(pins.some(p => p.id === message.id)).to.equal(true) + + await rest.unpinMessage(channel.id, message.id) + await rest.unpinMessage(channel.id, message2.id, 'with a reason') + + const unpinned = await rest.getPinnedMessages(channel.id) + expect(unpinned.length).to.equal(0) +}) +}) + + describe('Rate limit manager testing', () => { it('Send 10 messages to 1 channel', async () => { const channel = await rest.createChannel(e2ecache.guild.id, { name: 'rate-limit-1' }) diff --git a/packages/rest/tests/e2e/misc.spec.ts b/packages/rest/tests/e2e/misc.spec.ts new file mode 100644 index 000000000..378659961 --- /dev/null +++ b/packages/rest/tests/e2e/misc.spec.ts @@ -0,0 +1,39 @@ +import { expect } from 'chai' +import { describe } from 'mocha' +import { e2ecache, rest } from './utils.js' + +describe('Typings', () => { + it('Trigger Typing Indication', async () => { + const channel = await rest.createChannel(e2ecache.guild.id, { name: 'typing' }) + await rest.triggerTypingIndicator(channel.id) + }) +}) + +describe('Commands', () => { + it('Upsert global commands', async () => { + await rest.upsertGlobalApplicationCommands([ + { + name: 'ping', + description: 'Ping the bot', + }, + ]) + + const cmds = await rest.getGlobalApplicationCommands() + const created = cmds.find((cmd) => cmd.name === 'ping' && cmd.description === 'Ping the bot') + expect(!!created?.id).to.be.true + + const made = await rest.getGlobalApplicationCommand(created!.id) + expect(created?.name).to.be.equal(made.name) + expect(created?.description).to.be.equal(made.description) + + const edited = await rest.editGlobalApplicationCommand(created!.id, { name: 'pong', description: 'edited description' }) + expect(edited.name).to.be.equal('pong') + expect(edited.name).to.not.be.equal(made.name) + expect(edited.description).to.be.equal('edited description') + expect(edited.description).to.not.be.equal(made.description) + + await rest.deleteGlobalApplicationCommand(created!.id) + + expect(rest.getGlobalApplicationCommand(created!.id)).to.throw + }) +}) From 206bae473b970ffbe50ed3429489501518f87d2f Mon Sep 17 00:00:00 2001 From: Awesome Stickz Date: Sat, 25 Mar 2023 21:05:05 +0530 Subject: [PATCH 3/6] feat: added handlers and transformers to bot package (#2843) --- packages/bot/src/bot.ts | 223 +++++++------- packages/bot/src/constants.ts | 4 + packages/bot/src/handler.ts | 75 +++++ .../src/handlers/channels/CHANNEL_CREATE.ts | 10 + .../src/handlers/channels/CHANNEL_DELETE.ts | 14 + .../handlers/channels/CHANNEL_PINS_UPDATE.ts | 12 + .../src/handlers/channels/CHANNEL_UPDATE.ts | 9 + .../channels/STAGE_INSTANCE_CREATE.ts | 13 + .../channels/STAGE_INSTANCE_DELETE.ts | 13 + .../channels/STAGE_INSTANCE_UPDATE.ts | 13 + .../src/handlers/channels/THREAD_CREATE.ts | 8 + .../src/handlers/channels/THREAD_DELETE.ts | 8 + .../src/handlers/channels/THREAD_LIST_SYNC.ts | 19 ++ .../channels/THREAD_MEMBERS_UPDATE.ts | 13 + .../handlers/channels/THREAD_MEMBER_UPDATE.ts | 13 + .../src/handlers/channels/THREAD_UPDATE.ts | 8 + packages/bot/src/handlers/channels/mod.ts | 12 + .../handlers/emojis/GUILD_EMOJIS_UPDATE.ts | 12 + packages/bot/src/handlers/emojis/mod.ts | 1 + .../guilds/GUILD_AUDIT_LOG_ENTRY_CREATE.ts | 8 + .../bot/src/handlers/guilds/GUILD_BAN_ADD.ts | 7 + .../src/handlers/guilds/GUILD_BAN_REMOVE.ts | 8 + .../bot/src/handlers/guilds/GUILD_CREATE.ts | 8 + .../bot/src/handlers/guilds/GUILD_DELETE.ts | 7 + .../guilds/GUILD_INTEGRATIONS_UPDATE.ts | 10 + .../bot/src/handlers/guilds/GUILD_UPDATE.ts | 9 + .../AUTO_MODERATION_ACTION_EXECUTION.ts | 8 + .../automod/AUTO_MODERATION_RULE_CREATE.ts | 8 + .../automod/AUTO_MODERATION_RULE_DELETE.ts | 8 + .../automod/AUTO_MODERATION_RULE_UPDATE.ts | 8 + .../bot/src/handlers/guilds/automod/mod.ts | 0 packages/bot/src/handlers/guilds/mod.ts | 9 + .../GUILD_SCHEDULED_EVENT_CREATE.ts | 7 + .../GUILD_SCHEDULED_EVENT_DELETE.ts | 7 + .../GUILD_SCHEDULED_EVENT_UPDATE.ts | 7 + .../GUILD_SCHEDULED_EVENT_USER_ADD.ts | 12 + .../GUILD_SCHEDULED_EVENT_USER_REMOVE.ts | 12 + .../handlers/guilds/scheduledEvents/mod.ts | 5 + .../integrations/INTEGRATION_CREATE.ts | 6 + .../integrations/INTEGRATION_DELETE.ts | 12 + .../integrations/INTEGRATION_UPDATE.ts | 6 + packages/bot/src/handlers/integrations/mod.ts | 3 + .../interactions/INTERACTION_CREATE.ts | 6 + packages/bot/src/handlers/interactions/mod.ts | 1 + .../bot/src/handlers/invites/INVITE_CREATE.ts | 6 + .../bot/src/handlers/invites/INVITE_DELETE.ts | 15 + packages/bot/src/handlers/invites/mod.ts | 2 + .../handlers/members/GUILD_MEMBERS_CHUNK.ts | 29 ++ .../src/handlers/members/GUILD_MEMBER_ADD.ts | 10 + .../handlers/members/GUILD_MEMBER_REMOVE.ts | 10 + .../handlers/members/GUILD_MEMBER_UPDATE.ts | 9 + packages/bot/src/handlers/members/mod.ts | 4 + .../src/handlers/messages/MESSAGE_CREATE.ts | 8 + .../src/handlers/messages/MESSAGE_DELETE.ts | 12 + .../handlers/messages/MESSAGE_DELETE_BULK.ts | 15 + .../handlers/messages/MESSAGE_REACTION_ADD.ts | 18 ++ .../messages/MESSAGE_REACTION_REMOVE.ts | 14 + .../messages/MESSAGE_REACTION_REMOVE_ALL.ts | 12 + .../messages/MESSAGE_REACTION_REMOVE_EMOJI.ts | 13 + .../src/handlers/messages/MESSAGE_UPDATE.ts | 9 + packages/bot/src/handlers/messages/mod.ts | 8 + .../bot/src/handlers/misc/PRESENCE_UPDATE.ts | 6 + packages/bot/src/handlers/misc/READY.ts | 22 ++ .../bot/src/handlers/misc/TYPING_START.ts | 17 ++ packages/bot/src/handlers/misc/USER_UPDATE.ts | 7 + packages/bot/src/handlers/misc/mod.ts | 4 + packages/bot/src/handlers/mod.ts | 12 + .../src/handlers/roles/GUILD_ROLE_CREATE.ts | 12 + .../src/handlers/roles/GUILD_ROLE_DELETE.ts | 10 + .../src/handlers/roles/GUILD_ROLE_UPDATE.ts | 13 + packages/bot/src/handlers/roles/mod.ts | 3 + .../src/handlers/voice/VOICE_SERVER_UPDATE.ts | 12 + .../src/handlers/voice/VOICE_STATE_UPDATE.ts | 11 + packages/bot/src/handlers/voice/mod.ts | 2 + .../src/handlers/webhooks/WEBHOOKS_UPDATE.ts | 10 + packages/bot/src/handlers/webhooks/mod.ts | 1 + packages/bot/src/index.ts | 3 + packages/bot/src/optionalize.ts | 79 +++++ packages/bot/src/transformer.ts | 221 ++++++++++++++ packages/bot/src/transformers/activity.ts | 41 +++ packages/bot/src/transformers/application.ts | 33 ++ .../src/transformers/applicationCommand.ts | 25 ++ .../transformers/applicationCommandOption.ts | 55 ++++ .../applicationCommandOptionChoice.ts | 15 + .../applicationCommandPermission.ts | 20 ++ packages/bot/src/transformers/attachment.ts | 22 ++ .../bot/src/transformers/auditLogEntry.ts | 133 ++++++++ .../transformers/automodActionExecution.ts | 29 ++ packages/bot/src/transformers/automodRule.ts | 38 +++ packages/bot/src/transformers/channel.ts | 64 ++++ packages/bot/src/transformers/component.ts | 87 ++++++ packages/bot/src/transformers/embed.ts | 59 ++++ packages/bot/src/transformers/emoji.ts | 18 ++ packages/bot/src/transformers/gatewayBot.ts | 19 ++ packages/bot/src/transformers/guild.ts | 104 +++++++ packages/bot/src/transformers/integration.ts | 40 +++ packages/bot/src/transformers/interaction.ts | 149 +++++++++ packages/bot/src/transformers/invite.ts | 39 +++ packages/bot/src/transformers/member.ts | 44 +++ packages/bot/src/transformers/message.ts | 99 ++++++ packages/bot/src/transformers/mod.ts | 36 +++ packages/bot/src/transformers/presence.ts | 31 ++ .../bot/src/transformers/reverse/activity.ts | 44 +++ .../transformers/reverse/allowedMentions.ts | 11 + .../src/transformers/reverse/application.ts | 26 ++ .../reverse/applicationCommand.ts | 20 ++ .../reverse/applicationCommandOption.ts | 25 ++ .../reverse/applicationCommandOptionChoice.ts | 14 + .../reverse/applicationCommandPermission.ts | 19 ++ .../src/transformers/reverse/attachment.ts | 18 ++ .../src/transformers/reverse/auditLogEntry.ts | 151 +++++++++ .../bot/src/transformers/reverse/component.ts | 42 +++ .../reverse/createApplicationCommand.ts | 32 ++ .../bot/src/transformers/reverse/embed.ts | 55 ++++ .../bot/src/transformers/reverse/emoji.ts | 16 + .../src/transformers/reverse/gatewayBot.ts | 15 + .../reverse/interactionResponse.ts | 26 ++ .../bot/src/transformers/reverse/member.ts | 37 +++ packages/bot/src/transformers/reverse/mod.ts | 16 + .../bot/src/transformers/reverse/presence.ts | 25 ++ packages/bot/src/transformers/reverse/team.ts | 21 ++ .../transformers/reverse/widgetSettings.ts | 10 + packages/bot/src/transformers/role.ts | 25 ++ .../bot/src/transformers/scheduledEvent.ts | 29 ++ .../bot/src/transformers/stageInstance.ts | 17 ++ packages/bot/src/transformers/sticker.ts | 38 +++ packages/bot/src/transformers/team.ts | 25 ++ packages/bot/src/transformers/template.ts | 23 ++ packages/bot/src/transformers/threadMember.ts | 26 ++ .../transformers/toggles/ToggleBitfield.ts | 49 +++ .../bot/src/transformers/toggles/emoji.ts | 68 +++++ .../bot/src/transformers/toggles/guild.ts | 287 ++++++++++++++++++ .../bot/src/transformers/toggles/index.ts | 7 + .../bot/src/transformers/toggles/member.ts | 60 ++++ packages/bot/src/transformers/toggles/role.ts | 68 +++++ packages/bot/src/transformers/toggles/user.ts | 68 +++++ .../bot/src/transformers/toggles/voice.ts | 92 ++++++ packages/bot/src/transformers/voiceRegion.ts | 19 ++ packages/bot/src/transformers/voiceState.ts | 21 ++ packages/bot/src/transformers/webhook.ts | 37 +++ .../bot/src/transformers/welcomeScreen.ts | 19 ++ packages/bot/src/transformers/widget.ts | 30 ++ .../bot/src/transformers/widgetSettings.ts | 14 + packages/bot/src/types.ts | 202 ++++++++++++ packages/bot/src/utils.ts | 9 + 145 files changed, 4241 insertions(+), 116 deletions(-) create mode 100644 packages/bot/src/constants.ts create mode 100644 packages/bot/src/handler.ts create mode 100644 packages/bot/src/handlers/channels/CHANNEL_CREATE.ts create mode 100644 packages/bot/src/handlers/channels/CHANNEL_DELETE.ts create mode 100644 packages/bot/src/handlers/channels/CHANNEL_PINS_UPDATE.ts create mode 100644 packages/bot/src/handlers/channels/CHANNEL_UPDATE.ts create mode 100644 packages/bot/src/handlers/channels/STAGE_INSTANCE_CREATE.ts create mode 100644 packages/bot/src/handlers/channels/STAGE_INSTANCE_DELETE.ts create mode 100644 packages/bot/src/handlers/channels/STAGE_INSTANCE_UPDATE.ts create mode 100644 packages/bot/src/handlers/channels/THREAD_CREATE.ts create mode 100644 packages/bot/src/handlers/channels/THREAD_DELETE.ts create mode 100644 packages/bot/src/handlers/channels/THREAD_LIST_SYNC.ts create mode 100644 packages/bot/src/handlers/channels/THREAD_MEMBERS_UPDATE.ts create mode 100644 packages/bot/src/handlers/channels/THREAD_MEMBER_UPDATE.ts create mode 100644 packages/bot/src/handlers/channels/THREAD_UPDATE.ts create mode 100644 packages/bot/src/handlers/channels/mod.ts create mode 100644 packages/bot/src/handlers/emojis/GUILD_EMOJIS_UPDATE.ts create mode 100644 packages/bot/src/handlers/emojis/mod.ts create mode 100644 packages/bot/src/handlers/guilds/GUILD_AUDIT_LOG_ENTRY_CREATE.ts create mode 100644 packages/bot/src/handlers/guilds/GUILD_BAN_ADD.ts create mode 100644 packages/bot/src/handlers/guilds/GUILD_BAN_REMOVE.ts create mode 100644 packages/bot/src/handlers/guilds/GUILD_CREATE.ts create mode 100644 packages/bot/src/handlers/guilds/GUILD_DELETE.ts create mode 100644 packages/bot/src/handlers/guilds/GUILD_INTEGRATIONS_UPDATE.ts create mode 100644 packages/bot/src/handlers/guilds/GUILD_UPDATE.ts create mode 100644 packages/bot/src/handlers/guilds/automod/AUTO_MODERATION_ACTION_EXECUTION.ts create mode 100644 packages/bot/src/handlers/guilds/automod/AUTO_MODERATION_RULE_CREATE.ts create mode 100644 packages/bot/src/handlers/guilds/automod/AUTO_MODERATION_RULE_DELETE.ts create mode 100644 packages/bot/src/handlers/guilds/automod/AUTO_MODERATION_RULE_UPDATE.ts create mode 100644 packages/bot/src/handlers/guilds/automod/mod.ts create mode 100644 packages/bot/src/handlers/guilds/mod.ts create mode 100644 packages/bot/src/handlers/guilds/scheduledEvents/GUILD_SCHEDULED_EVENT_CREATE.ts create mode 100644 packages/bot/src/handlers/guilds/scheduledEvents/GUILD_SCHEDULED_EVENT_DELETE.ts create mode 100644 packages/bot/src/handlers/guilds/scheduledEvents/GUILD_SCHEDULED_EVENT_UPDATE.ts create mode 100644 packages/bot/src/handlers/guilds/scheduledEvents/GUILD_SCHEDULED_EVENT_USER_ADD.ts create mode 100644 packages/bot/src/handlers/guilds/scheduledEvents/GUILD_SCHEDULED_EVENT_USER_REMOVE.ts create mode 100644 packages/bot/src/handlers/guilds/scheduledEvents/mod.ts create mode 100644 packages/bot/src/handlers/integrations/INTEGRATION_CREATE.ts create mode 100644 packages/bot/src/handlers/integrations/INTEGRATION_DELETE.ts create mode 100644 packages/bot/src/handlers/integrations/INTEGRATION_UPDATE.ts create mode 100644 packages/bot/src/handlers/integrations/mod.ts create mode 100644 packages/bot/src/handlers/interactions/INTERACTION_CREATE.ts create mode 100644 packages/bot/src/handlers/interactions/mod.ts create mode 100644 packages/bot/src/handlers/invites/INVITE_CREATE.ts create mode 100644 packages/bot/src/handlers/invites/INVITE_DELETE.ts create mode 100644 packages/bot/src/handlers/invites/mod.ts create mode 100644 packages/bot/src/handlers/members/GUILD_MEMBERS_CHUNK.ts create mode 100644 packages/bot/src/handlers/members/GUILD_MEMBER_ADD.ts create mode 100644 packages/bot/src/handlers/members/GUILD_MEMBER_REMOVE.ts create mode 100644 packages/bot/src/handlers/members/GUILD_MEMBER_UPDATE.ts create mode 100644 packages/bot/src/handlers/members/mod.ts create mode 100644 packages/bot/src/handlers/messages/MESSAGE_CREATE.ts create mode 100644 packages/bot/src/handlers/messages/MESSAGE_DELETE.ts create mode 100644 packages/bot/src/handlers/messages/MESSAGE_DELETE_BULK.ts create mode 100644 packages/bot/src/handlers/messages/MESSAGE_REACTION_ADD.ts create mode 100644 packages/bot/src/handlers/messages/MESSAGE_REACTION_REMOVE.ts create mode 100644 packages/bot/src/handlers/messages/MESSAGE_REACTION_REMOVE_ALL.ts create mode 100644 packages/bot/src/handlers/messages/MESSAGE_REACTION_REMOVE_EMOJI.ts create mode 100644 packages/bot/src/handlers/messages/MESSAGE_UPDATE.ts create mode 100644 packages/bot/src/handlers/messages/mod.ts create mode 100644 packages/bot/src/handlers/misc/PRESENCE_UPDATE.ts create mode 100644 packages/bot/src/handlers/misc/READY.ts create mode 100644 packages/bot/src/handlers/misc/TYPING_START.ts create mode 100644 packages/bot/src/handlers/misc/USER_UPDATE.ts create mode 100644 packages/bot/src/handlers/misc/mod.ts create mode 100644 packages/bot/src/handlers/mod.ts create mode 100644 packages/bot/src/handlers/roles/GUILD_ROLE_CREATE.ts create mode 100644 packages/bot/src/handlers/roles/GUILD_ROLE_DELETE.ts create mode 100644 packages/bot/src/handlers/roles/GUILD_ROLE_UPDATE.ts create mode 100644 packages/bot/src/handlers/roles/mod.ts create mode 100644 packages/bot/src/handlers/voice/VOICE_SERVER_UPDATE.ts create mode 100644 packages/bot/src/handlers/voice/VOICE_STATE_UPDATE.ts create mode 100644 packages/bot/src/handlers/voice/mod.ts create mode 100644 packages/bot/src/handlers/webhooks/WEBHOOKS_UPDATE.ts create mode 100644 packages/bot/src/handlers/webhooks/mod.ts create mode 100644 packages/bot/src/optionalize.ts create mode 100644 packages/bot/src/transformer.ts create mode 100644 packages/bot/src/transformers/activity.ts create mode 100644 packages/bot/src/transformers/application.ts create mode 100644 packages/bot/src/transformers/applicationCommand.ts create mode 100644 packages/bot/src/transformers/applicationCommandOption.ts create mode 100644 packages/bot/src/transformers/applicationCommandOptionChoice.ts create mode 100644 packages/bot/src/transformers/applicationCommandPermission.ts create mode 100644 packages/bot/src/transformers/attachment.ts create mode 100644 packages/bot/src/transformers/auditLogEntry.ts create mode 100644 packages/bot/src/transformers/automodActionExecution.ts create mode 100644 packages/bot/src/transformers/automodRule.ts create mode 100644 packages/bot/src/transformers/channel.ts create mode 100644 packages/bot/src/transformers/component.ts create mode 100644 packages/bot/src/transformers/embed.ts create mode 100644 packages/bot/src/transformers/emoji.ts create mode 100644 packages/bot/src/transformers/gatewayBot.ts create mode 100644 packages/bot/src/transformers/guild.ts create mode 100644 packages/bot/src/transformers/integration.ts create mode 100644 packages/bot/src/transformers/interaction.ts create mode 100644 packages/bot/src/transformers/invite.ts create mode 100644 packages/bot/src/transformers/member.ts create mode 100644 packages/bot/src/transformers/message.ts create mode 100644 packages/bot/src/transformers/mod.ts create mode 100644 packages/bot/src/transformers/presence.ts create mode 100644 packages/bot/src/transformers/reverse/activity.ts create mode 100644 packages/bot/src/transformers/reverse/allowedMentions.ts create mode 100644 packages/bot/src/transformers/reverse/application.ts create mode 100644 packages/bot/src/transformers/reverse/applicationCommand.ts create mode 100644 packages/bot/src/transformers/reverse/applicationCommandOption.ts create mode 100644 packages/bot/src/transformers/reverse/applicationCommandOptionChoice.ts create mode 100644 packages/bot/src/transformers/reverse/applicationCommandPermission.ts create mode 100644 packages/bot/src/transformers/reverse/attachment.ts create mode 100644 packages/bot/src/transformers/reverse/auditLogEntry.ts create mode 100644 packages/bot/src/transformers/reverse/component.ts create mode 100644 packages/bot/src/transformers/reverse/createApplicationCommand.ts create mode 100644 packages/bot/src/transformers/reverse/embed.ts create mode 100644 packages/bot/src/transformers/reverse/emoji.ts create mode 100644 packages/bot/src/transformers/reverse/gatewayBot.ts create mode 100644 packages/bot/src/transformers/reverse/interactionResponse.ts create mode 100644 packages/bot/src/transformers/reverse/member.ts create mode 100644 packages/bot/src/transformers/reverse/mod.ts create mode 100644 packages/bot/src/transformers/reverse/presence.ts create mode 100644 packages/bot/src/transformers/reverse/team.ts create mode 100644 packages/bot/src/transformers/reverse/widgetSettings.ts create mode 100644 packages/bot/src/transformers/role.ts create mode 100644 packages/bot/src/transformers/scheduledEvent.ts create mode 100644 packages/bot/src/transformers/stageInstance.ts create mode 100644 packages/bot/src/transformers/sticker.ts create mode 100644 packages/bot/src/transformers/team.ts create mode 100644 packages/bot/src/transformers/template.ts create mode 100644 packages/bot/src/transformers/threadMember.ts create mode 100644 packages/bot/src/transformers/toggles/ToggleBitfield.ts create mode 100644 packages/bot/src/transformers/toggles/emoji.ts create mode 100644 packages/bot/src/transformers/toggles/guild.ts create mode 100644 packages/bot/src/transformers/toggles/index.ts create mode 100644 packages/bot/src/transformers/toggles/member.ts create mode 100644 packages/bot/src/transformers/toggles/role.ts create mode 100644 packages/bot/src/transformers/toggles/user.ts create mode 100644 packages/bot/src/transformers/toggles/voice.ts create mode 100644 packages/bot/src/transformers/voiceRegion.ts create mode 100644 packages/bot/src/transformers/voiceState.ts create mode 100644 packages/bot/src/transformers/webhook.ts create mode 100644 packages/bot/src/transformers/welcomeScreen.ts create mode 100644 packages/bot/src/transformers/widget.ts create mode 100644 packages/bot/src/transformers/widgetSettings.ts create mode 100644 packages/bot/src/types.ts create mode 100644 packages/bot/src/utils.ts diff --git a/packages/bot/src/bot.ts b/packages/bot/src/bot.ts index bdb4e879c..f8610c345 100644 --- a/packages/bot/src/bot.ts +++ b/packages/bot/src/bot.ts @@ -1,57 +1,27 @@ import type { CreateGatewayManagerOptions, GatewayManager } from '@discordeno/gateway' -import { ShardSocketCloseCodes, createGatewayManager } from '@discordeno/gateway' +import { createGatewayManager, ShardSocketCloseCodes } from '@discordeno/gateway' import type { CreateRestManagerOptions, RestManager } from '@discordeno/rest' import { createRestManager } from '@discordeno/rest' -import type { - Camelize, - DiscordAuditLogEntry, - DiscordAutoModerationActionExecution, - DiscordAutoModerationRule, - DiscordChannel, - DiscordChannelPinsUpdate, - DiscordGatewayPayload, - DiscordGuild, - DiscordGuildApplicationCommandPermissions, - DiscordGuildBanAddRemove, - DiscordGuildEmojisUpdate, - DiscordGuildMemberAdd, - DiscordGuildMemberRemove, - DiscordGuildMemberUpdate, - DiscordGuildMembersChunk, - DiscordGuildRoleCreate, - DiscordGuildRoleDelete, - DiscordGuildRoleUpdate, - DiscordGuildStickersUpdate, - DiscordIntegrationCreateUpdate, - DiscordIntegrationDelete, - DiscordInteraction, - DiscordInviteCreate, - DiscordInviteDelete, - DiscordMessage, - DiscordMessageDelete, - DiscordMessageDeleteBulk, - DiscordMessageReactionAdd, - DiscordMessageReactionRemove, - DiscordMessageReactionRemoveAll, - DiscordMessageReactionRemoveEmoji, - DiscordPresenceUpdate, - DiscordReady, - DiscordScheduledEvent, - DiscordScheduledEventUserAdd, - DiscordScheduledEventUserRemove, - DiscordStageInstance, - DiscordThreadListSync, - DiscordThreadMemberUpdate, - DiscordThreadMembersUpdate, - DiscordTypingStart, - DiscordUnavailableGuild, - DiscordUser, - DiscordVoiceServerUpdate, - DiscordVoiceState, - DiscordWebhookUpdate, - GatewayIntents, -} from '@discordeno/types' -import { createLogger } from '@discordeno/utils' +import type { DiscordEmoji, DiscordGatewayPayload, DiscordReady, GatewayIntents } from '@discordeno/types' +import { Collection, createLogger } from '@discordeno/utils' +import type { Transformers } from './transformer' +import type { AuditLogEntry } from './transformers/auditLogEntry' +import type { AutoModerationActionExecution } from './transformers/automodActionExecution' +import type { AutoModerationRule } from './transformers/automodRule' +import type { Channel } from './transformers/channel' +import type { Emoji } from './transformers/emoji' +import type { Guild } from './transformers/guild' +import type { Integration } from './transformers/integration' +import type { Interaction } from './transformers/interaction' +import type { Invite } from './transformers/invite' +import type { Member, User } from './transformers/member' +import type { Message } from './transformers/message' +import type { PresenceUpdate } from './transformers/presence' +import type { Role } from './transformers/role' +import type { ScheduledEvent } from './transformers/scheduledEvent' +import type { ThreadMember } from './transformers/threadMember' +import type { VoiceState } from './transformers/voiceState' +import type { bigintToSnowflake, snowflakeToBigint } from './utils.js' /** * Create a bot object that will maintain the rest and gateway connection. @@ -118,6 +88,8 @@ export interface CreateBotOptions { } export interface Bot { + id: bigint + applicationId: bigint /** The rest manager. */ rest: RestManager /** The gateway manager. */ @@ -126,6 +98,11 @@ export interface Bot { events: Partial /** A logger utility to make it easy to log nice and useful things in the bot code. */ logger: ReturnType + transformers: Transformers + utils: { + snowflakeToBigint: typeof snowflakeToBigint + bigintToSnowflake: typeof bigintToSnowflake + } /** Start the bot connection to the gateway. */ start: () => Promise /** Shuts down all the bot connections to the gateway. */ @@ -133,69 +110,83 @@ export interface Bot { } export interface EventHandlers { - // Custom events here - dispatchRequirements: (payload: Camelize, shardId: number) => unknown - raw: (payload: Camelize, shardId: number) => unknown - - // Gateway events below this - applicationCommandPermissionsUpdate: (payload: Camelize, shardId: number) => unknown - auditLogEntryCreate: (payload: Camelize, shardId: number) => unknown - autoModerationRuleCreate: (payload: Camelize, shardId: number) => unknown - autoModerationRuleUpdate: (payload: Camelize, shardId: number) => unknown - autoModerationRuleDelete: (payload: Camelize, shardId: number) => unknown - autoModerationActionExecution: (payload: Camelize, shardId: number) => unknown - channelCreate: (payload: Camelize, shardId: number) => unknown - channelUpdate: (payload: Camelize, shardId: number) => unknown - channelDelete: (payload: Camelize, shardId: number) => unknown - channelPinsUpdate: (payload: Camelize, shardId: number) => unknown - threadCreate: (payload: Camelize, shardId: number) => unknown - threadUpdate: (payload: Camelize, shardId: number) => unknown - threadDelete: (payload: Camelize, shardId: number) => unknown - threadListSync: (payload: Camelize, shardId: number) => unknown - threadMemberUpdate: (payload: Camelize, shardId: number) => unknown - threadMembersUpdate: (payload: Camelize, shardId: number) => unknown - guildCreate: (payload: Camelize, shardId: number) => unknown - guildUpdate: (payload: Camelize, shardId: number) => unknown - guildDelete: (payload: Camelize, shardId: number) => unknown - guildBanAdd: (payload: Camelize, shardId: number) => unknown - guildBanRemove: (payload: Camelize, shardId: number) => unknown - guildEmojisUpdate: (payload: Camelize, shardId: number) => unknown - guildStickersUpdate: (payload: Camelize, shardId: number) => unknown - guildIntegrationsUpdate: (payload: Camelize, shardId: number) => unknown - guildMemberAdd: (payload: Camelize, shardId: number) => unknown - guildMemberRemove: (payload: Camelize, shardId: number) => unknown - guildMemberUpdate: (payload: Camelize, shardId: number) => unknown - guildMembersChunk: (payload: Camelize, shardId: number) => unknown - guildRoleCreate: (payload: Camelize, shardId: number) => unknown - guildRoleUpdate: (payload: Camelize, shardId: number) => unknown - guildRoleDelete: (payload: Camelize, shardId: number) => unknown - guildScheduledEventCreate: (payload: Camelize, shardId: number) => unknown - guildScheduledEventUpdate: (payload: Camelize, shardId: number) => unknown - guildScheduledEventDelete: (payload: Camelize, shardId: number) => unknown - guildScheduledEventUserAdd: (payload: Camelize, shardId: number) => unknown - guildScheduledEventUserRemove: (payload: Camelize, shardId: number) => unknown - integrationCreate: (payload: Camelize, shardId: number) => unknown - integrationUpdate: (payload: Camelize, shardId: number) => unknown - integrationDelete: (payload: Camelize, shardId: number) => unknown - interactionCreate: (payload: Camelize, shardId: number) => unknown - inviteCreate: (payload: Camelize, shardId: number) => unknown - inviteDelete: (payload: Camelize, shardId: number) => unknown - messageCreate: (payload: Camelize, shardId: number) => unknown - messageUpdate: (payload: Camelize, shardId: number) => unknown - messageDelete: (payload: Camelize, shardId: number) => unknown - messageDeleteBulk: (payload: Camelize, shardId: number) => unknown - messageReactionAdd: (payload: Camelize, shardId: number) => unknown - messageReactionRemove: (payload: Camelize, shardId: number) => unknown - messageReactionRemoveAll: (payload: Camelize, shardId: number) => unknown - messageReactionRemoveEmoji: (payload: Camelize, shardId: number) => unknown - presenceUpdate: (payload: Camelize, shardId: number) => unknown - ready: (payload: Camelize, shardId: number) => unknown - stageInstanceCreate: (payload: Camelize, shardId: number) => unknown - stageInstanceUpdate: (payload: Camelize, shardId: number) => unknown - stageInstanceDelete: (payload: Camelize, shardId: number) => unknown - typingStart: (payload: Camelize, shardId: number) => unknown - userUpdate: (payload: Camelize, shardId: number) => unknown - voiceStateUpdate: (payload: Camelize, shardId: number) => unknown - voiceServerUpdate: (payload: Camelize, shardId: number) => unknown - webhooksUpdate: (payload: Camelize, shardId: number) => unknown + debug: (text: string, ...args: any[]) => unknown + auditLogEntryCreate: (log: AuditLogEntry, guildId: bigint) => unknown + automodRuleCreate: (rule: AutoModerationRule) => unknown + automodRuleUpdate: (rule: AutoModerationRule) => unknown + automodRuleDelete: (rule: AutoModerationRule) => unknown + automodActionExecution: (payload: AutoModerationActionExecution) => unknown + threadCreate: (thread: Channel) => unknown + threadDelete: (thread: Channel) => unknown + threadMemberUpdate: (payload: { id: bigint; guildId: bigint; joinedAt: number; flags: number }) => unknown + threadMembersUpdate: (payload: { id: bigint; guildId: bigint; addedMembers?: ThreadMember[]; removedMemberIds?: bigint[] }) => unknown + threadUpdate: (thread: Channel) => unknown + scheduledEventCreate: (event: ScheduledEvent) => unknown + scheduledEventUpdate: (event: ScheduledEvent) => unknown + scheduledEventDelete: (event: ScheduledEvent) => unknown + /** Sent when a user has subscribed to a guild scheduled event. EXPERIMENTAL! */ + scheduledEventUserAdd: (payload: { guildScheduledEventId: bigint; guildId: bigint; userId: bigint }) => unknown + /** Sent when a user has unsubscribed to a guild scheduled event. EXPERIMENTAL! */ + scheduledEventUserRemove: (payload: { guildScheduledEventId: bigint; guildId: bigint; userId: bigint }) => unknown + ready: ( + payload: { + shardId: number + v: number + user: User + guilds: bigint[] + sessionId: string + shard?: number[] + applicationId: bigint + }, + rawPayload: DiscordReady, + ) => unknown + interactionCreate: (interaction: Interaction) => unknown + integrationCreate: (integration: Integration) => unknown + integrationDelete: (payload: { id: bigint; guildId: bigint; applicationId?: bigint }) => unknown + integrationUpdate: (payload: { guildId: bigint }) => unknown + inviteCreate: (invite: Invite) => unknown + inviteDelete: (payload: { channelId: bigint; guildId?: bigint; code: string }) => unknown + guildMemberAdd: (member: Member, user: User) => unknown + guildMemberRemove: (user: User, guildId: bigint) => unknown + guildMemberUpdate: (member: Member, user: User) => unknown + messageCreate: (message: Message) => unknown + messageDelete: (payload: { id: bigint; channelId: bigint; guildId?: bigint }, message?: Message) => unknown + messageDeleteBulk: (payload: { ids: bigint[]; channelId: bigint; guildId?: bigint }) => unknown + messageUpdate: (message: Message, oldMessage?: Message) => unknown + reactionAdd: (payload: { + userId: bigint + channelId: bigint + messageId: bigint + guildId?: bigint + member?: Member + user?: User + emoji: Emoji + }) => unknown + reactionRemove: (payload: { userId: bigint; channelId: bigint; messageId: bigint; guildId?: bigint; emoji: Emoji }) => unknown + reactionRemoveEmoji: (payload: { channelId: bigint; messageId: bigint; guildId?: bigint; emoji: Emoji }) => unknown + reactionRemoveAll: (payload: { channelId: bigint; messageId: bigint; guildId?: bigint }) => unknown + presenceUpdate: (presence: PresenceUpdate, oldPresence?: PresenceUpdate) => unknown + voiceServerUpdate: (payload: { token: string; endpoint?: string; guildId: bigint }) => unknown + voiceStateUpdate: (voiceState: VoiceState) => unknown + channelCreate: (channel: Channel) => unknown + dispatchRequirements: (data: DiscordGatewayPayload, shardId: number) => unknown + channelDelete: (channel: Channel) => unknown + channelPinsUpdate: (data: { guildId?: bigint; channelId: bigint; lastPinTimestamp?: number }) => unknown + channelUpdate: (channel: Channel) => unknown + stageInstanceCreate: (data: { id: bigint; guildId: bigint; channelId: bigint; topic: string }) => unknown + stageInstanceDelete: (data: { id: bigint; guildId: bigint; channelId: bigint; topic: string }) => unknown + stageInstanceUpdate: (data: { id: bigint; guildId: bigint; channelId: bigint; topic: string }) => unknown + guildEmojisUpdate: (payload: { guildId: bigint; emojis: Collection }) => unknown + guildBanAdd: (user: User, guildId: bigint) => unknown + guildBanRemove: (user: User, guildId: bigint) => unknown + guildCreate: (guild: Guild) => unknown + guildDelete: (id: bigint, shardId: number) => unknown + guildUpdate: (guild: Guild) => unknown + raw: (data: DiscordGatewayPayload, shardId: number) => unknown + roleCreate: (role: Role) => unknown + roleDelete: (payload: { guildId: bigint; roleId: bigint }) => unknown + roleUpdate: (role: Role) => unknown + webhooksUpdate: (payload: { channelId: bigint; guildId: bigint }) => unknown + botUpdate: (user: User) => unknown + typingStart: (payload: { guildId: bigint | undefined; channelId: bigint; userId: bigint; timestamp: number; member: Member | undefined }) => unknown } diff --git a/packages/bot/src/constants.ts b/packages/bot/src/constants.ts new file mode 100644 index 000000000..2e939842a --- /dev/null +++ b/packages/bot/src/constants.ts @@ -0,0 +1,4 @@ +export const SLASH_COMMANDS_NAME_REGEX = /^[-_\p{L}\p{N}\p{sc=Deva}\p{sc=Thai}]{1,32}$/u +export const CONTEXT_MENU_COMMANDS_NAME_REGEX = /^[\w-\s]{1,32}$/ +export const CHANNEL_MENTION_REGEX = /<#[0-9]+>/g +export const DISCORD_SNOWFLAKE_REGEX = /^(?\d{17,19})$/ diff --git a/packages/bot/src/handler.ts b/packages/bot/src/handler.ts new file mode 100644 index 000000000..b5d09486c --- /dev/null +++ b/packages/bot/src/handler.ts @@ -0,0 +1,75 @@ +import * as handlers from './handlers/mod.js' +import type { Bot, DiscordGatewayPayload, GatewayDispatchEventNames } from './index.js' +import type { BotGatewayHandlerOptions } from './types.js' + +export function createBotGatewayHandlers( + options: Partial, +): Record any> { + return { + // misc + READY: options.READY ?? handlers.handleReady, + // channels + CHANNEL_CREATE: options.CHANNEL_CREATE ?? handlers.handleChannelCreate, + CHANNEL_DELETE: options.CHANNEL_DELETE ?? handlers.handleChannelDelete, + CHANNEL_PINS_UPDATE: options.CHANNEL_PINS_UPDATE ?? handlers.handleChannelPinsUpdate, + CHANNEL_UPDATE: options.CHANNEL_UPDATE ?? handlers.handleChannelUpdate, + THREAD_CREATE: options.THREAD_CREATE ?? handlers.handleThreadCreate, + THREAD_UPDATE: options.THREAD_UPDATE ?? handlers.handleThreadUpdate, + THREAD_DELETE: options.THREAD_DELETE ?? handlers.handleThreadDelete, + THREAD_LIST_SYNC: options.THREAD_LIST_SYNC ?? handlers.handleThreadListSync, + THREAD_MEMBERS_UPDATE: options.THREAD_MEMBERS_UPDATE ?? handlers.handleThreadMembersUpdate, + STAGE_INSTANCE_CREATE: options.STAGE_INSTANCE_CREATE ?? handlers.handleStageInstanceCreate, + STAGE_INSTANCE_UPDATE: options.STAGE_INSTANCE_UPDATE ?? handlers.handleStageInstanceUpdate, + STAGE_INSTANCE_DELETE: options.STAGE_INSTANCE_DELETE ?? handlers.handleStageInstanceDelete, + + // guilds + GUILD_AUDIT_LOG_ENTRY_CREATE: options.GUILD_AUDIT_LOG_ENTRY_CREATE ?? handlers.handleGuildAuditLogEntryCreate, + GUILD_BAN_ADD: options.GUILD_BAN_ADD ?? handlers.handleGuildBanAdd, + GUILD_BAN_REMOVE: options.GUILD_BAN_REMOVE ?? handlers.handleGuildBanRemove, + GUILD_CREATE: options.GUILD_CREATE ?? handlers.handleGuildCreate, + GUILD_DELETE: options.GUILD_DELETE ?? handlers.handleGuildDelete, + GUILD_EMOJIS_UPDATE: options.GUILD_EMOJIS_UPDATE ?? handlers.handleGuildEmojisUpdate, + GUILD_INTEGRATIONS_UPDATE: options.GUILD_INTEGRATIONS_UPDATE ?? handlers.handleGuildIntegrationsUpdate, + GUILD_MEMBER_ADD: options.GUILD_MEMBER_ADD ?? handlers.handleGuildMemberAdd, + GUILD_MEMBER_REMOVE: options.GUILD_MEMBER_REMOVE ?? handlers.handleGuildMemberRemove, + GUILD_MEMBER_UPDATE: options.GUILD_MEMBER_UPDATE ?? handlers.handleGuildMemberUpdate, + GUILD_MEMBERS_CHUNK: options.GUILD_MEMBERS_CHUNK ?? handlers.handleGuildMembersChunk, + GUILD_ROLE_CREATE: options.GUILD_ROLE_CREATE ?? handlers.handleGuildRoleCreate, + GUILD_ROLE_DELETE: options.GUILD_ROLE_DELETE ?? handlers.handleGuildRoleDelete, + GUILD_ROLE_UPDATE: options.GUILD_ROLE_UPDATE ?? handlers.handleGuildRoleUpdate, + GUILD_UPDATE: options.GUILD_UPDATE ?? handlers.handleGuildUpdate, + // guild events + GUILD_SCHEDULED_EVENT_CREATE: options.GUILD_SCHEDULED_EVENT_CREATE ?? handlers.handleGuildScheduledEventCreate, + GUILD_SCHEDULED_EVENT_DELETE: options.GUILD_SCHEDULED_EVENT_DELETE ?? handlers.handleGuildScheduledEventDelete, + GUILD_SCHEDULED_EVENT_UPDATE: options.GUILD_SCHEDULED_EVENT_UPDATE ?? handlers.handleGuildScheduledEventUpdate, + GUILD_SCHEDULED_EVENT_USER_ADD: options.GUILD_SCHEDULED_EVENT_USER_ADD ?? handlers.handleGuildScheduledEventUserAdd, + GUILD_SCHEDULED_EVENT_USER_REMOVE: options.GUILD_SCHEDULED_EVENT_USER_REMOVE ?? handlers.handleGuildScheduledEventUserRemove, + // interactions + INTERACTION_CREATE: options.INTERACTION_CREATE ?? handlers.handleInteractionCreate, + // invites + INVITE_CREATE: options.INVITE_CREATE ?? handlers.handleInviteCreate, + INVITE_DELETE: options.INVITE_DELETE ?? handlers.handleInviteCreate, + // messages + MESSAGE_CREATE: options.MESSAGE_CREATE ?? handlers.handleMessageCreate, + MESSAGE_DELETE_BULK: options.MESSAGE_DELETE_BULK ?? handlers.handleMessageDeleteBulk, + MESSAGE_DELETE: options.MESSAGE_DELETE ?? handlers.handleMessageDelete, + MESSAGE_REACTION_ADD: options.MESSAGE_REACTION_ADD ?? handlers.handleMessageReactionAdd, + MESSAGE_REACTION_REMOVE_ALL: options.MESSAGE_REACTION_REMOVE_ALL ?? handlers.handleMessageReactionRemoveAll, + MESSAGE_REACTION_REMOVE_EMOJI: options.MESSAGE_REACTION_REMOVE_EMOJI ?? handlers.handleMessageReactionRemoveEmoji, + MESSAGE_REACTION_REMOVE: options.MESSAGE_REACTION_REMOVE ?? handlers.handleMessageReactionRemove, + MESSAGE_UPDATE: options.MESSAGE_UPDATE ?? handlers.handleMessageUpdate, + // presence + PRESENCE_UPDATE: options.PRESENCE_UPDATE ?? handlers.handlePresenceUpdate, + TYPING_START: options.TYPING_START ?? handlers.handleTypingStart, + USER_UPDATE: options.USER_UPDATE ?? handlers.handleUserUpdate, + // voice + VOICE_SERVER_UPDATE: options.VOICE_SERVER_UPDATE ?? handlers.handleVoiceServerUpdate, + VOICE_STATE_UPDATE: options.VOICE_STATE_UPDATE ?? handlers.handleVoiceStateUpdate, + // webhooks + WEBHOOKS_UPDATE: options.WEBHOOKS_UPDATE ?? handlers.handleWebhooksUpdate, + // integrations + INTEGRATION_CREATE: options.INTEGRATION_CREATE ?? handlers.handleIntegrationCreate, + INTEGRATION_UPDATE: options.INTEGRATION_UPDATE ?? handlers.handleIntegrationUpdate, + INTEGRATION_DELETE: options.INTEGRATION_DELETE ?? handlers.handleIntegrationDelete, + } +} diff --git a/packages/bot/src/handlers/channels/CHANNEL_CREATE.ts b/packages/bot/src/handlers/channels/CHANNEL_CREATE.ts new file mode 100644 index 000000000..98209eaf7 --- /dev/null +++ b/packages/bot/src/handlers/channels/CHANNEL_CREATE.ts @@ -0,0 +1,10 @@ +import type { DiscordChannel, DiscordenoShard, DiscordGatewayPayload } from '@discordeno/bot' +import type { Bot } from '../../index.js' + +export async function handleChannelCreate(bot: Bot, payload: DiscordGatewayPayload, shard: DiscordenoShard) { + const channel = bot.transformers.channel(bot, { + channel: payload.d as DiscordChannel, + }) + + bot.events.channelCreate?.(channel) +} diff --git a/packages/bot/src/handlers/channels/CHANNEL_DELETE.ts b/packages/bot/src/handlers/channels/CHANNEL_DELETE.ts new file mode 100644 index 000000000..4d0e1ccf5 --- /dev/null +++ b/packages/bot/src/handlers/channels/CHANNEL_DELETE.ts @@ -0,0 +1,14 @@ +import type { DiscordChannel, DiscordGatewayPayload } from '@discordeno/types' +import type { Bot } from '../../bot.js' + +export async function handleChannelDelete(bot: Bot, data: DiscordGatewayPayload) { + const payload = data.d as DiscordChannel + if (!payload.guild_id) return + + bot.events.channelDelete?.( + bot.transformers.channel(bot, { + channel: payload, + guildId: payload.guild_id ? bot.transformers.snowflake(payload.guild_id) : undefined, + }), + ) +} diff --git a/packages/bot/src/handlers/channels/CHANNEL_PINS_UPDATE.ts b/packages/bot/src/handlers/channels/CHANNEL_PINS_UPDATE.ts new file mode 100644 index 000000000..2e95f8524 --- /dev/null +++ b/packages/bot/src/handlers/channels/CHANNEL_PINS_UPDATE.ts @@ -0,0 +1,12 @@ +import type { DiscordChannelPinsUpdate, DiscordGatewayPayload } from '@discordeno/types' +import type { Bot } from '../../bot.js' + +export async function handleChannelPinsUpdate(bot: Bot, data: DiscordGatewayPayload) { + const payload = data.d as DiscordChannelPinsUpdate + + bot.events.channelPinsUpdate?.({ + guildId: payload.guild_id ? bot.transformers.snowflake(payload.guild_id) : undefined, + channelId: bot.transformers.snowflake(payload.channel_id), + lastPinTimestamp: payload.last_pin_timestamp ? Date.parse(payload.last_pin_timestamp) : undefined, + }) +} diff --git a/packages/bot/src/handlers/channels/CHANNEL_UPDATE.ts b/packages/bot/src/handlers/channels/CHANNEL_UPDATE.ts new file mode 100644 index 000000000..e95c0b16f --- /dev/null +++ b/packages/bot/src/handlers/channels/CHANNEL_UPDATE.ts @@ -0,0 +1,9 @@ +import type { DiscordChannel, DiscordGatewayPayload } from '@discordeno/types' +import type { Bot } from '../../bot.js' + +export async function handleChannelUpdate(bot: Bot, data: DiscordGatewayPayload) { + const payload = data.d as DiscordChannel + const channel = bot.transformers.channel(bot, { channel: payload }) + + bot.events.channelUpdate?.(channel) +} diff --git a/packages/bot/src/handlers/channels/STAGE_INSTANCE_CREATE.ts b/packages/bot/src/handlers/channels/STAGE_INSTANCE_CREATE.ts new file mode 100644 index 000000000..3f9504498 --- /dev/null +++ b/packages/bot/src/handlers/channels/STAGE_INSTANCE_CREATE.ts @@ -0,0 +1,13 @@ +import type { DiscordGatewayPayload, DiscordStageInstance } from '@discordeno/types' +import type { Bot } from '../../bot.js' + +export function handleStageInstanceCreate(bot: Bot, data: DiscordGatewayPayload) { + const payload = data.d as DiscordStageInstance + + bot.events.stageInstanceCreate?.({ + id: bot.transformers.snowflake(payload.id), + guildId: bot.transformers.snowflake(payload.guild_id), + channelId: bot.transformers.snowflake(payload.channel_id), + topic: payload.topic, + }) +} diff --git a/packages/bot/src/handlers/channels/STAGE_INSTANCE_DELETE.ts b/packages/bot/src/handlers/channels/STAGE_INSTANCE_DELETE.ts new file mode 100644 index 000000000..70081696e --- /dev/null +++ b/packages/bot/src/handlers/channels/STAGE_INSTANCE_DELETE.ts @@ -0,0 +1,13 @@ +import type { DiscordGatewayPayload, DiscordStageInstance } from '@discordeno/types' +import type { Bot } from '../../bot.js' + +export function handleStageInstanceDelete(bot: Bot, data: DiscordGatewayPayload) { + const payload = data.d as DiscordStageInstance + + bot.events.stageInstanceDelete?.({ + id: bot.transformers.snowflake(payload.id), + guildId: bot.transformers.snowflake(payload.guild_id), + channelId: bot.transformers.snowflake(payload.channel_id), + topic: payload.topic, + }) +} diff --git a/packages/bot/src/handlers/channels/STAGE_INSTANCE_UPDATE.ts b/packages/bot/src/handlers/channels/STAGE_INSTANCE_UPDATE.ts new file mode 100644 index 000000000..9dff85a98 --- /dev/null +++ b/packages/bot/src/handlers/channels/STAGE_INSTANCE_UPDATE.ts @@ -0,0 +1,13 @@ +import type { DiscordGatewayPayload, DiscordStageInstance } from '@discordeno/types' +import type { Bot } from '../../bot.js' + +export function handleStageInstanceUpdate(bot: Bot, data: DiscordGatewayPayload) { + const payload = data.d as DiscordStageInstance + + bot.events.stageInstanceUpdate?.({ + id: bot.transformers.snowflake(payload.id), + guildId: bot.transformers.snowflake(payload.guild_id), + channelId: bot.transformers.snowflake(payload.channel_id), + topic: payload.topic, + }) +} diff --git a/packages/bot/src/handlers/channels/THREAD_CREATE.ts b/packages/bot/src/handlers/channels/THREAD_CREATE.ts new file mode 100644 index 000000000..7833fe923 --- /dev/null +++ b/packages/bot/src/handlers/channels/THREAD_CREATE.ts @@ -0,0 +1,8 @@ +import type { DiscordChannel, DiscordGatewayPayload } from '@discordeno/types' +import type { Bot } from '../../index.js' + +export async function handleThreadCreate(bot: Bot, data: DiscordGatewayPayload) { + const payload = data.d as DiscordChannel + + bot.events.threadCreate?.(bot.transformers.channel(bot, { channel: payload })) +} diff --git a/packages/bot/src/handlers/channels/THREAD_DELETE.ts b/packages/bot/src/handlers/channels/THREAD_DELETE.ts new file mode 100644 index 000000000..3c74ee586 --- /dev/null +++ b/packages/bot/src/handlers/channels/THREAD_DELETE.ts @@ -0,0 +1,8 @@ +import type { DiscordChannel, DiscordGatewayPayload } from '@discordeno/types' +import type { Bot } from '../../index.js' + +export async function handleThreadDelete(bot: Bot, data: DiscordGatewayPayload) { + const payload = data.d as DiscordChannel + + bot.events.threadDelete?.(bot.transformers.channel(bot, { channel: payload })) +} diff --git a/packages/bot/src/handlers/channels/THREAD_LIST_SYNC.ts b/packages/bot/src/handlers/channels/THREAD_LIST_SYNC.ts new file mode 100644 index 000000000..7dafb77ee --- /dev/null +++ b/packages/bot/src/handlers/channels/THREAD_LIST_SYNC.ts @@ -0,0 +1,19 @@ +import type { DiscordGatewayPayload, DiscordThreadListSync } from '@discordeno/types' +import type { Bot } from '../../index.js' + +export async function handleThreadListSync(bot: Bot, data: DiscordGatewayPayload) { + const payload = data.d as DiscordThreadListSync + + const guildId = bot.transformers.snowflake(payload.guild_id) + + return { + guildId, + channelIds: payload.channel_ids?.map((id) => bot.transformers.snowflake(id)), + threads: payload.threads.map((thread) => bot.transformers.channel(bot, { channel: thread, guildId })), + members: payload.members.map((member) => ({ + id: member.id ? bot.transformers.snowflake(member.id) : undefined, + userId: member.user_id ? bot.transformers.snowflake(member.user_id) : undefined, + joinTimestamp: Date.parse(member.join_timestamp), + })), + } +} diff --git a/packages/bot/src/handlers/channels/THREAD_MEMBERS_UPDATE.ts b/packages/bot/src/handlers/channels/THREAD_MEMBERS_UPDATE.ts new file mode 100644 index 000000000..ab382c42f --- /dev/null +++ b/packages/bot/src/handlers/channels/THREAD_MEMBERS_UPDATE.ts @@ -0,0 +1,13 @@ +import type { DiscordGatewayPayload, DiscordThreadMembersUpdate } from '@discordeno/types' +import type { Bot } from '../../index.js' + +export async function handleThreadMembersUpdate(bot: Bot, data: DiscordGatewayPayload) { + const payload = data.d as DiscordThreadMembersUpdate + + bot.events.threadMembersUpdate?.({ + id: bot.transformers.snowflake(payload.id), + guildId: bot.transformers.snowflake(payload.guild_id), + addedMembers: payload.added_members?.map((member) => bot.transformers.threadMember?.(bot, member)), + removedMemberIds: payload.removed_member_ids?.map((id) => bot.transformers.snowflake(id)), + }) +} diff --git a/packages/bot/src/handlers/channels/THREAD_MEMBER_UPDATE.ts b/packages/bot/src/handlers/channels/THREAD_MEMBER_UPDATE.ts new file mode 100644 index 000000000..45ab4b9dd --- /dev/null +++ b/packages/bot/src/handlers/channels/THREAD_MEMBER_UPDATE.ts @@ -0,0 +1,13 @@ +import type { DiscordGatewayPayload, DiscordThreadMemberUpdate } from '@discordeno/types' +import type { Bot } from '../../index.js' + +export async function handleThreadMemberUpdate(bot: Bot, data: DiscordGatewayPayload) { + const payload = data.d as DiscordThreadMemberUpdate + + bot.events.threadMemberUpdate?.({ + id: bot.transformers.snowflake(payload.id), + guildId: bot.transformers.snowflake(payload.guild_id), + joinedAt: Date.parse(payload.joined_at), + flags: payload.flags, + }) +} diff --git a/packages/bot/src/handlers/channels/THREAD_UPDATE.ts b/packages/bot/src/handlers/channels/THREAD_UPDATE.ts new file mode 100644 index 000000000..0d73d8ae6 --- /dev/null +++ b/packages/bot/src/handlers/channels/THREAD_UPDATE.ts @@ -0,0 +1,8 @@ +import type { DiscordChannel, DiscordGatewayPayload } from '@discordeno/types' +import type { Bot } from '../../index.js' + +export async function handleThreadUpdate(bot: Bot, data: DiscordGatewayPayload) { + const payload = data.d as DiscordChannel + + bot.events.threadUpdate?.(bot.transformers.channel(bot, { channel: payload })) +} diff --git a/packages/bot/src/handlers/channels/mod.ts b/packages/bot/src/handlers/channels/mod.ts new file mode 100644 index 000000000..c55e6612d --- /dev/null +++ b/packages/bot/src/handlers/channels/mod.ts @@ -0,0 +1,12 @@ +export * from "./CHANNEL_CREATE.js"; +export * from "./CHANNEL_DELETE.js"; +export * from "./CHANNEL_PINS_UPDATE.js"; +export * from "./CHANNEL_UPDATE.js"; +export * from "./STAGE_INSTANCE_CREATE.js"; +export * from "./STAGE_INSTANCE_DELETE.js"; +export * from "./STAGE_INSTANCE_UPDATE.js"; +export * from "./THREAD_CREATE.js"; +export * from "./THREAD_DELETE.js"; +export * from "./THREAD_LIST_SYNC.js"; +export * from "./THREAD_MEMBERS_UPDATE.js"; +export * from "./THREAD_UPDATE.js"; diff --git a/packages/bot/src/handlers/emojis/GUILD_EMOJIS_UPDATE.ts b/packages/bot/src/handlers/emojis/GUILD_EMOJIS_UPDATE.ts new file mode 100644 index 000000000..30c233409 --- /dev/null +++ b/packages/bot/src/handlers/emojis/GUILD_EMOJIS_UPDATE.ts @@ -0,0 +1,12 @@ +import type { DiscordGatewayPayload, DiscordGuildEmojisUpdate } from '@discordeno/types' +import type { Bot } from '../../bot.js' +import type { Collection } from '../../util/collection.js' + +export async function handleGuildEmojisUpdate(bot: Bot, data: DiscordGatewayPayload) { + const payload = data.d as DiscordGuildEmojisUpdate + + bot.events.guildEmojisUpdate?.({ + guildId: bot.transformers.snowflake(payload.guild_id), + emojis: new Collection(payload.emojis.map((emoji) => [bot.transformers.snowflake(emoji.id!), emoji])), + }) +} diff --git a/packages/bot/src/handlers/emojis/mod.ts b/packages/bot/src/handlers/emojis/mod.ts new file mode 100644 index 000000000..5a442ee5d --- /dev/null +++ b/packages/bot/src/handlers/emojis/mod.ts @@ -0,0 +1 @@ +export * from "./GUILD_EMOJIS_UPDATE.js"; diff --git a/packages/bot/src/handlers/guilds/GUILD_AUDIT_LOG_ENTRY_CREATE.ts b/packages/bot/src/handlers/guilds/GUILD_AUDIT_LOG_ENTRY_CREATE.ts new file mode 100644 index 000000000..b4dc645eb --- /dev/null +++ b/packages/bot/src/handlers/guilds/GUILD_AUDIT_LOG_ENTRY_CREATE.ts @@ -0,0 +1,8 @@ +import type { DiscordAuditLogEntry, DiscordGatewayPayload } from '@discordeno/types' +import type { Bot } from '../../bot.js' + +export async function handleGuildAuditLogEntryCreate(bot: Bot, data: DiscordGatewayPayload) { + // TODO: better type here + const payload = data.d as DiscordAuditLogEntry & { guild_id: string } + bot.events.auditLogEntryCreate?.(bot.transformers.auditLogEntry(bot, payload), bot.transformers.snowflake(payload.guild_id)) +} diff --git a/packages/bot/src/handlers/guilds/GUILD_BAN_ADD.ts b/packages/bot/src/handlers/guilds/GUILD_BAN_ADD.ts new file mode 100644 index 000000000..95981e14a --- /dev/null +++ b/packages/bot/src/handlers/guilds/GUILD_BAN_ADD.ts @@ -0,0 +1,7 @@ +import type { DiscordGatewayPayload, DiscordGuildBanAddRemove } from '@discordeno/types' +import type { Bot } from '../../bot.js' + +export async function handleGuildBanAdd(bot: Bot, data: DiscordGatewayPayload) { + const payload = data.d as DiscordGuildBanAddRemove + bot.events.guildBanAdd?.(bot.transformers.user(bot, payload.user), bot.transformers.snowflake(payload.guild_id)) +} diff --git a/packages/bot/src/handlers/guilds/GUILD_BAN_REMOVE.ts b/packages/bot/src/handlers/guilds/GUILD_BAN_REMOVE.ts new file mode 100644 index 000000000..ab3539c75 --- /dev/null +++ b/packages/bot/src/handlers/guilds/GUILD_BAN_REMOVE.ts @@ -0,0 +1,8 @@ +import type { DiscordGatewayPayload, DiscordGuildBanAddRemove } from '@discordeno/types' +import type { Bot } from '../../bot.js' + +export async function handleGuildBanRemove(bot: Bot, data: DiscordGatewayPayload) { + const payload = data.d as DiscordGuildBanAddRemove + + await bot.events.guildBanRemove?.(bot.transformers.user(bot, payload.user), bot.transformers.snowflake(payload.guild_id)) +} diff --git a/packages/bot/src/handlers/guilds/GUILD_CREATE.ts b/packages/bot/src/handlers/guilds/GUILD_CREATE.ts new file mode 100644 index 000000000..64a5f2066 --- /dev/null +++ b/packages/bot/src/handlers/guilds/GUILD_CREATE.ts @@ -0,0 +1,8 @@ +import type { DiscordGatewayPayload, DiscordGuild } from '@discordeno/types' +import type { Bot } from '../../bot.js' +import type { Guild } from '../../transformers/guild.js' + +export function handleGuildCreate(bot: Bot, data: DiscordGatewayPayload, shardId: number) { + const payload = data.d as DiscordGuild + bot.events.guildCreate?.(bot.transformers.guild(bot, { guild: payload, shardId }) as Guild) +} diff --git a/packages/bot/src/handlers/guilds/GUILD_DELETE.ts b/packages/bot/src/handlers/guilds/GUILD_DELETE.ts new file mode 100644 index 000000000..e90bdc6b8 --- /dev/null +++ b/packages/bot/src/handlers/guilds/GUILD_DELETE.ts @@ -0,0 +1,7 @@ +import type { DiscordGatewayPayload, DiscordUnavailableGuild } from '@discordeno/types' +import type { Bot } from '../../bot.js' + +export async function handleGuildDelete(bot: Bot, data: DiscordGatewayPayload, shardId: number) { + const payload = data.d as DiscordUnavailableGuild + bot.events.guildDelete?.(bot.transformers.snowflake(payload.id), shardId) +} diff --git a/packages/bot/src/handlers/guilds/GUILD_INTEGRATIONS_UPDATE.ts b/packages/bot/src/handlers/guilds/GUILD_INTEGRATIONS_UPDATE.ts new file mode 100644 index 000000000..e18113b67 --- /dev/null +++ b/packages/bot/src/handlers/guilds/GUILD_INTEGRATIONS_UPDATE.ts @@ -0,0 +1,10 @@ +import type { DiscordGatewayPayload, DiscordGuildIntegrationsUpdate } from '@discordeno/types' +import type { Bot } from '../../bot.js' + +export async function handleGuildIntegrationsUpdate(bot: Bot, data: DiscordGatewayPayload) { + const payload = data.d as DiscordGuildIntegrationsUpdate + + bot.events.integrationUpdate?.({ + guildId: bot.transformers.snowflake(payload.guild_id), + }) +} diff --git a/packages/bot/src/handlers/guilds/GUILD_UPDATE.ts b/packages/bot/src/handlers/guilds/GUILD_UPDATE.ts new file mode 100644 index 000000000..a9ba8853b --- /dev/null +++ b/packages/bot/src/handlers/guilds/GUILD_UPDATE.ts @@ -0,0 +1,9 @@ +import type { DiscordGatewayPayload, DiscordGuild } from '@discordeno/types' +import type { Bot } from '../../bot.js' +import type { Guild } from '../../transformers/guild.js' + +export function handleGuildUpdate(bot: Bot, data: DiscordGatewayPayload, shardId: number) { + const payload = data.d as DiscordGuild + + bot.events.guildUpdate?.(bot.transformers.guild(bot, { guild: payload, shardId }) as Guild) +} diff --git a/packages/bot/src/handlers/guilds/automod/AUTO_MODERATION_ACTION_EXECUTION.ts b/packages/bot/src/handlers/guilds/automod/AUTO_MODERATION_ACTION_EXECUTION.ts new file mode 100644 index 000000000..dfdc8acd4 --- /dev/null +++ b/packages/bot/src/handlers/guilds/automod/AUTO_MODERATION_ACTION_EXECUTION.ts @@ -0,0 +1,8 @@ +import type { DiscordAutoModerationActionExecution, DiscordGatewayPayload } from '@discordeno/types' +import type { Bot } from '../../../bot.js' + +/** Requires the MANAGE_GUILD permission. */ +export function handleAutoModerationActionExecution(bot: Bot, data: DiscordGatewayPayload, shardId: number) { + const payload = data.d as DiscordAutoModerationActionExecution + bot.events.automodActionExecution?.(bot.events.automodActionExecution(payload)) +} diff --git a/packages/bot/src/handlers/guilds/automod/AUTO_MODERATION_RULE_CREATE.ts b/packages/bot/src/handlers/guilds/automod/AUTO_MODERATION_RULE_CREATE.ts new file mode 100644 index 000000000..cb94337d5 --- /dev/null +++ b/packages/bot/src/handlers/guilds/automod/AUTO_MODERATION_RULE_CREATE.ts @@ -0,0 +1,8 @@ +import type { DiscordAutoModerationRule, DiscordGatewayPayload } from '@discordeno/types' +import type { Bot } from '../../../bot.js' + +/** Requires the MANAGE_GUILD permission. */ +export function handleAutoModerationRuleCreate(bot: Bot, data: DiscordGatewayPayload, shardId: number) { + const payload = data.d as DiscordAutoModerationRule + bot.events.automodRuleCreate?.(bot.events.automodRule(payload)) +} diff --git a/packages/bot/src/handlers/guilds/automod/AUTO_MODERATION_RULE_DELETE.ts b/packages/bot/src/handlers/guilds/automod/AUTO_MODERATION_RULE_DELETE.ts new file mode 100644 index 000000000..cc9319550 --- /dev/null +++ b/packages/bot/src/handlers/guilds/automod/AUTO_MODERATION_RULE_DELETE.ts @@ -0,0 +1,8 @@ +import type { DiscordAutoModerationRule, DiscordGatewayPayload } from '@discordeno/types' +import type { Bot } from '../../../bot.js' + +/** Requires the MANAGE_GUILD permission. */ +export function handleAutoModerationRuleDelete(bot: Bot, data: DiscordGatewayPayload, shardId: number) { + const payload = data.d as DiscordAutoModerationRule + bot.events.automodRuleDelete?.(bot.events.automodRule(payload)) +} diff --git a/packages/bot/src/handlers/guilds/automod/AUTO_MODERATION_RULE_UPDATE.ts b/packages/bot/src/handlers/guilds/automod/AUTO_MODERATION_RULE_UPDATE.ts new file mode 100644 index 000000000..63f3f7e46 --- /dev/null +++ b/packages/bot/src/handlers/guilds/automod/AUTO_MODERATION_RULE_UPDATE.ts @@ -0,0 +1,8 @@ +import type { DiscordAutoModerationRule, DiscordGatewayPayload } from '@discordeno/types' +import type { Bot } from '../../../bot.js' + +/** Requires the MANAGE_GUILD permission. */ +export function handleAutoModerationRuleUpdate(bot: Bot, data: DiscordGatewayPayload, shardId: number) { + const payload = data.d as DiscordAutoModerationRule + bot.events.automodRuleUpdate?.(bot.transformers.automodRule(bot, payload)) +} diff --git a/packages/bot/src/handlers/guilds/automod/mod.ts b/packages/bot/src/handlers/guilds/automod/mod.ts new file mode 100644 index 000000000..e69de29bb diff --git a/packages/bot/src/handlers/guilds/mod.ts b/packages/bot/src/handlers/guilds/mod.ts new file mode 100644 index 000000000..29e68bfa6 --- /dev/null +++ b/packages/bot/src/handlers/guilds/mod.ts @@ -0,0 +1,9 @@ +export * from "./scheduledEvents/mod.js"; + +export * from "./GUILD_AUDIT_LOG_ENTRY_CREATE.js"; +export * from "./GUILD_BAN_ADD.js"; +export * from "./GUILD_BAN_REMOVE.js"; +export * from "./GUILD_CREATE.js"; +export * from "./GUILD_DELETE.js"; +export * from "./GUILD_INTEGRATIONS_UPDATE.js"; +export * from "./GUILD_UPDATE.js"; diff --git a/packages/bot/src/handlers/guilds/scheduledEvents/GUILD_SCHEDULED_EVENT_CREATE.ts b/packages/bot/src/handlers/guilds/scheduledEvents/GUILD_SCHEDULED_EVENT_CREATE.ts new file mode 100644 index 000000000..84812cb6d --- /dev/null +++ b/packages/bot/src/handlers/guilds/scheduledEvents/GUILD_SCHEDULED_EVENT_CREATE.ts @@ -0,0 +1,7 @@ +import type { DiscordGatewayPayload, DiscordScheduledEvent } from '@discordeno/types' +import type { Bot } from '../../../bot.js' + +export function handleGuildScheduledEventCreate(bot: Bot, data: DiscordGatewayPayload, shardId: number) { + const payload = data.d as DiscordScheduledEvent + bot.events.scheduledEventCreate?.(bot.transformers.scheduledEvent(bot, payload)) +} diff --git a/packages/bot/src/handlers/guilds/scheduledEvents/GUILD_SCHEDULED_EVENT_DELETE.ts b/packages/bot/src/handlers/guilds/scheduledEvents/GUILD_SCHEDULED_EVENT_DELETE.ts new file mode 100644 index 000000000..247e5063f --- /dev/null +++ b/packages/bot/src/handlers/guilds/scheduledEvents/GUILD_SCHEDULED_EVENT_DELETE.ts @@ -0,0 +1,7 @@ +import type { DiscordGatewayPayload, DiscordScheduledEvent } from '@discordeno/types' +import type { Bot } from '../../../bot.js' + +export function handleGuildScheduledEventDelete(bot: Bot, data: DiscordGatewayPayload) { + const payload = data.d as DiscordScheduledEvent + bot.events.scheduledEventDelete?.(bot.transformers.scheduledEvent(bot, payload)) +} diff --git a/packages/bot/src/handlers/guilds/scheduledEvents/GUILD_SCHEDULED_EVENT_UPDATE.ts b/packages/bot/src/handlers/guilds/scheduledEvents/GUILD_SCHEDULED_EVENT_UPDATE.ts new file mode 100644 index 000000000..2c87cc8e0 --- /dev/null +++ b/packages/bot/src/handlers/guilds/scheduledEvents/GUILD_SCHEDULED_EVENT_UPDATE.ts @@ -0,0 +1,7 @@ +import type { DiscordGatewayPayload, DiscordScheduledEvent } from '@discordeno/types' +import type { Bot } from '../../../bot.js' + +export function handleGuildScheduledEventUpdate(bot: Bot, data: DiscordGatewayPayload) { + const payload = data.d as DiscordScheduledEvent + bot.events.scheduledEventUpdate?.(bot.transformers.scheduledEvent(bot, payload)) +} diff --git a/packages/bot/src/handlers/guilds/scheduledEvents/GUILD_SCHEDULED_EVENT_USER_ADD.ts b/packages/bot/src/handlers/guilds/scheduledEvents/GUILD_SCHEDULED_EVENT_USER_ADD.ts new file mode 100644 index 000000000..d73cfb2e5 --- /dev/null +++ b/packages/bot/src/handlers/guilds/scheduledEvents/GUILD_SCHEDULED_EVENT_USER_ADD.ts @@ -0,0 +1,12 @@ +import type { DiscordGatewayPayload, DiscordScheduledEventUserAdd } from '@discordeno/types' +import type { Bot } from '../../../bot.js' + +export function handleGuildScheduledEventUserAdd(bot: Bot, data: DiscordGatewayPayload) { + const payload = data.d as DiscordScheduledEventUserAdd + + return bot.events.scheduledEventUserAdd?.({ + guildScheduledEventId: bot.transformers.snowflake(payload.guild_scheduled_event_id), + userId: bot.transformers.snowflake(payload.user_id), + guildId: bot.transformers.snowflake(payload.guild_id), + }) +} diff --git a/packages/bot/src/handlers/guilds/scheduledEvents/GUILD_SCHEDULED_EVENT_USER_REMOVE.ts b/packages/bot/src/handlers/guilds/scheduledEvents/GUILD_SCHEDULED_EVENT_USER_REMOVE.ts new file mode 100644 index 000000000..fe11c0662 --- /dev/null +++ b/packages/bot/src/handlers/guilds/scheduledEvents/GUILD_SCHEDULED_EVENT_USER_REMOVE.ts @@ -0,0 +1,12 @@ +import type { DiscordGatewayPayload, DiscordScheduledEventUserRemove } from '@discordeno/types' +import type { Bot } from '../../../bot.js' + +export function handleGuildScheduledEventUserRemove(bot: Bot, data: DiscordGatewayPayload) { + const payload = data.d as DiscordScheduledEventUserRemove + + return bot.events.scheduledEventUserRemove?.({ + guildScheduledEventId: bot.transformers.snowflake(payload.guild_scheduled_event_id), + userId: bot.transformers.snowflake(payload.user_id), + guildId: bot.transformers.snowflake(payload.guild_id), + }) +} diff --git a/packages/bot/src/handlers/guilds/scheduledEvents/mod.ts b/packages/bot/src/handlers/guilds/scheduledEvents/mod.ts new file mode 100644 index 000000000..ce7cf1545 --- /dev/null +++ b/packages/bot/src/handlers/guilds/scheduledEvents/mod.ts @@ -0,0 +1,5 @@ +export * from "./GUILD_SCHEDULED_EVENT_CREATE.js"; +export * from "./GUILD_SCHEDULED_EVENT_DELETE.js"; +export * from "./GUILD_SCHEDULED_EVENT_UPDATE.js"; +export * from "./GUILD_SCHEDULED_EVENT_USER_ADD.js"; +export * from "./GUILD_SCHEDULED_EVENT_USER_REMOVE.js"; diff --git a/packages/bot/src/handlers/integrations/INTEGRATION_CREATE.ts b/packages/bot/src/handlers/integrations/INTEGRATION_CREATE.ts new file mode 100644 index 000000000..afe6f51bf --- /dev/null +++ b/packages/bot/src/handlers/integrations/INTEGRATION_CREATE.ts @@ -0,0 +1,6 @@ +import type { DiscordGatewayPayload, DiscordIntegrationCreateUpdate } from '@discordeno/types' +import type { Bot } from '../../index.js' + +export function handleIntegrationCreate(bot: Bot, data: DiscordGatewayPayload) { + bot.events.integrationCreate?.(bot.transformers.integration(bot, data.d as DiscordIntegrationCreateUpdate)) +} diff --git a/packages/bot/src/handlers/integrations/INTEGRATION_DELETE.ts b/packages/bot/src/handlers/integrations/INTEGRATION_DELETE.ts new file mode 100644 index 000000000..e43bd1534 --- /dev/null +++ b/packages/bot/src/handlers/integrations/INTEGRATION_DELETE.ts @@ -0,0 +1,12 @@ +import type { DiscordGatewayPayload, DiscordIntegrationDelete } from '@discordeno/types' +import type { Bot } from '../../index.js' + +export function handleIntegrationDelete(bot: Bot, data: DiscordGatewayPayload) { + const payload = data.d as DiscordIntegrationDelete + + bot.events.integrationDelete?.({ + id: bot.transformers.snowflake(payload.id), + guildId: bot.transformers.snowflake(payload.guild_id), + applicationId: payload.application_id ? bot.transformers.snowflake(payload.application_id) : undefined, + }) +} diff --git a/packages/bot/src/handlers/integrations/INTEGRATION_UPDATE.ts b/packages/bot/src/handlers/integrations/INTEGRATION_UPDATE.ts new file mode 100644 index 000000000..4a339b90c --- /dev/null +++ b/packages/bot/src/handlers/integrations/INTEGRATION_UPDATE.ts @@ -0,0 +1,6 @@ +import type { DiscordGatewayPayload, DiscordIntegrationCreateUpdate } from '@discordeno/types' +import type { Bot } from '../../index.js' + +export function handleIntegrationUpdate(bot: Bot, data: DiscordGatewayPayload) { + bot.events.integrationUpdate?.(bot.transformers.integration(bot, data.d as DiscordIntegrationCreateUpdate)) +} diff --git a/packages/bot/src/handlers/integrations/mod.ts b/packages/bot/src/handlers/integrations/mod.ts new file mode 100644 index 000000000..afff9f98e --- /dev/null +++ b/packages/bot/src/handlers/integrations/mod.ts @@ -0,0 +1,3 @@ +export * from "./INTEGRATION_CREATE.js"; +export * from "./INTEGRATION_DELETE.js"; +export * from "./INTEGRATION_UPDATE.js"; diff --git a/packages/bot/src/handlers/interactions/INTERACTION_CREATE.ts b/packages/bot/src/handlers/interactions/INTERACTION_CREATE.ts new file mode 100644 index 000000000..aea7d719d --- /dev/null +++ b/packages/bot/src/handlers/interactions/INTERACTION_CREATE.ts @@ -0,0 +1,6 @@ +import type { DiscordGatewayPayload, DiscordInteraction } from '@discordeno/types' +import type { Bot } from '../../index.js' + +export async function handleInteractionCreate(bot: Bot, data: DiscordGatewayPayload) { + bot.events.interactionCreate?.(bot.transformers.interaction(bot, data.d as DiscordInteraction)) +} diff --git a/packages/bot/src/handlers/interactions/mod.ts b/packages/bot/src/handlers/interactions/mod.ts new file mode 100644 index 000000000..b4de5f934 --- /dev/null +++ b/packages/bot/src/handlers/interactions/mod.ts @@ -0,0 +1 @@ +export * from "./INTERACTION_CREATE.js"; diff --git a/packages/bot/src/handlers/invites/INVITE_CREATE.ts b/packages/bot/src/handlers/invites/INVITE_CREATE.ts new file mode 100644 index 000000000..89473a63d --- /dev/null +++ b/packages/bot/src/handlers/invites/INVITE_CREATE.ts @@ -0,0 +1,6 @@ +import type { DiscordGatewayPayload, DiscordInviteCreate } from '@discordeno/types' +import type { Bot } from '../../index.js' + +export function handleInviteCreate(bot: Bot, data: DiscordGatewayPayload) { + bot.events.inviteCreate?.(bot.transformers.invite(bot, data.d as DiscordInviteCreate)) +} diff --git a/packages/bot/src/handlers/invites/INVITE_DELETE.ts b/packages/bot/src/handlers/invites/INVITE_DELETE.ts new file mode 100644 index 000000000..e77f064bc --- /dev/null +++ b/packages/bot/src/handlers/invites/INVITE_DELETE.ts @@ -0,0 +1,15 @@ +import type { DiscordGatewayPayload, DiscordInviteDelete } from '@discordeno/types' +import type { Bot } from '../../index.js' + +export function handleInviteDelete(bot: Bot, data: DiscordGatewayPayload) { + const payload = data.d as DiscordInviteDelete + + bot.events.inviteDelete?.({ + /** The channel of the invite */ + channelId: bot.transformers.snowflake(payload.channel_id), + /** The guild of the invite */ + guildId: payload.guild_id ? bot.transformers.snowflake(payload.guild_id) : undefined, + /** The unique invite code */ + code: payload.code, + }) +} diff --git a/packages/bot/src/handlers/invites/mod.ts b/packages/bot/src/handlers/invites/mod.ts new file mode 100644 index 000000000..118a3b364 --- /dev/null +++ b/packages/bot/src/handlers/invites/mod.ts @@ -0,0 +1,2 @@ +export * from "./INVITE_CREATE.js"; +export * from "./INVITE_DELETE.js"; diff --git a/packages/bot/src/handlers/members/GUILD_MEMBERS_CHUNK.ts b/packages/bot/src/handlers/members/GUILD_MEMBERS_CHUNK.ts new file mode 100644 index 000000000..ef28ebe57 --- /dev/null +++ b/packages/bot/src/handlers/members/GUILD_MEMBERS_CHUNK.ts @@ -0,0 +1,29 @@ +import type { DiscordGatewayPayload, DiscordGuildMembersChunk } from '@discordeno/types' +import { PresenceStatus } from '@discordeno/types' +import type { Bot } from '../../index.js' + +export async function handleGuildMembersChunk(bot: Bot, data: DiscordGatewayPayload) { + const payload = data.d as DiscordGuildMembersChunk + + const guildId = bot.transformers.snowflake(payload.guild_id) + + return { + guildId, + members: payload.members.map((m) => bot.transformers.member(bot, m, guildId, bot.transformers.snowflake(m.user.id))), + chunkIndex: payload.chunk_index, + chunkCount: payload.chunk_count, + notFound: payload.not_found?.map((id) => bot.transformers.snowflake(id)), + presences: payload.presences?.map((presence) => ({ + user: bot.transformers.user(bot, presence.user), + guildId, + status: PresenceStatus[presence.status], + activities: presence.activities.map((activity) => bot.transformers.activity(bot, activity)), + clientStatus: { + desktop: presence.client_status.desktop, + mobile: presence.client_status.mobile, + web: presence.client_status.web, + }, + })), + nonce: payload.nonce, + } +} diff --git a/packages/bot/src/handlers/members/GUILD_MEMBER_ADD.ts b/packages/bot/src/handlers/members/GUILD_MEMBER_ADD.ts new file mode 100644 index 000000000..2e592fc6b --- /dev/null +++ b/packages/bot/src/handlers/members/GUILD_MEMBER_ADD.ts @@ -0,0 +1,10 @@ +import type { DiscordGatewayPayload, DiscordGuildMemberAdd } from '@discordeno/types' +import type { Bot } from '../../index.js' + +export async function handleGuildMemberAdd(bot: Bot, data: DiscordGatewayPayload) { + const payload = data.d as DiscordGuildMemberAdd + const guildId = bot.transformers.snowflake(payload.guild_id) + const user = bot.transformers.user(bot, payload.user) + const member = bot.transformers.member(bot, payload, guildId, user.id) + bot.events.guildMemberAdd?.(member, user) +} diff --git a/packages/bot/src/handlers/members/GUILD_MEMBER_REMOVE.ts b/packages/bot/src/handlers/members/GUILD_MEMBER_REMOVE.ts new file mode 100644 index 000000000..38d2e07da --- /dev/null +++ b/packages/bot/src/handlers/members/GUILD_MEMBER_REMOVE.ts @@ -0,0 +1,10 @@ +import type { DiscordGatewayPayload, DiscordGuildMemberRemove } from '@discordeno/types' +import type { Bot } from '../../index.js' + +export async function handleGuildMemberRemove(bot: Bot, data: DiscordGatewayPayload) { + const payload = data.d as DiscordGuildMemberRemove + const guildId = bot.transformers.snowflake(payload.guild_id) + const user = bot.transformers.user(bot, payload.user) + + bot.events.guildMemberRemove?.(user, guildId) +} diff --git a/packages/bot/src/handlers/members/GUILD_MEMBER_UPDATE.ts b/packages/bot/src/handlers/members/GUILD_MEMBER_UPDATE.ts new file mode 100644 index 000000000..77251f50a --- /dev/null +++ b/packages/bot/src/handlers/members/GUILD_MEMBER_UPDATE.ts @@ -0,0 +1,9 @@ +import type { DiscordGatewayPayload, DiscordGuildMemberUpdate } from '@discordeno/types' +import type { Bot } from '../../index.js' + +export async function handleGuildMemberUpdate(bot: Bot, data: DiscordGatewayPayload) { + const payload = data.d as DiscordGuildMemberUpdate + + const user = bot.transformers.user(bot, payload.user) + bot.events.guildMemberUpdate?.(bot.transformers.member(bot, payload, bot.transformers.snowflake(payload.guild_id), user.id), user) +} diff --git a/packages/bot/src/handlers/members/mod.ts b/packages/bot/src/handlers/members/mod.ts new file mode 100644 index 000000000..0348756a5 --- /dev/null +++ b/packages/bot/src/handlers/members/mod.ts @@ -0,0 +1,4 @@ +export * from "./GUILD_MEMBER_ADD.js"; +export * from "./GUILD_MEMBER_REMOVE.js"; +export * from "./GUILD_MEMBER_UPDATE.js"; +export * from "./GUILD_MEMBERS_CHUNK.js"; diff --git a/packages/bot/src/handlers/messages/MESSAGE_CREATE.ts b/packages/bot/src/handlers/messages/MESSAGE_CREATE.ts new file mode 100644 index 000000000..ded09d135 --- /dev/null +++ b/packages/bot/src/handlers/messages/MESSAGE_CREATE.ts @@ -0,0 +1,8 @@ +import type { DiscordGatewayPayload, DiscordMessage } from '@discordeno/types' +import type { Bot } from '../../index.js' + +export async function handleMessageCreate(bot: Bot, data: DiscordGatewayPayload) { + const payload = data.d as DiscordMessage + + bot.events.messageCreate?.(bot.events.message(payload)) +} diff --git a/packages/bot/src/handlers/messages/MESSAGE_DELETE.ts b/packages/bot/src/handlers/messages/MESSAGE_DELETE.ts new file mode 100644 index 000000000..1b3eb3b4c --- /dev/null +++ b/packages/bot/src/handlers/messages/MESSAGE_DELETE.ts @@ -0,0 +1,12 @@ +import type { DiscordGatewayPayload, DiscordMessageDelete } from '@discordeno/types' +import type { Bot } from '../../index.js' + +export async function handleMessageDelete(bot: Bot, data: DiscordGatewayPayload) { + const payload = data.d as DiscordMessageDelete + + bot.events.messageDelete?.({ + id: bot.transformers.snowflake(payload.id), + channelId: bot.transformers.snowflake(payload.channel_id), + guildId: payload.guild_id ? bot.transformers.snowflake(payload.guild_id) : undefined, + }) +} diff --git a/packages/bot/src/handlers/messages/MESSAGE_DELETE_BULK.ts b/packages/bot/src/handlers/messages/MESSAGE_DELETE_BULK.ts new file mode 100644 index 000000000..1d75d239d --- /dev/null +++ b/packages/bot/src/handlers/messages/MESSAGE_DELETE_BULK.ts @@ -0,0 +1,15 @@ +import type { DiscordGatewayPayload, DiscordMessageDeleteBulk } from '@discordeno/types' +import type { Bot } from '../../index.js' + +export async function handleMessageDeleteBulk(bot: Bot, data: DiscordGatewayPayload) { + const payload = data.d as DiscordMessageDeleteBulk + + const channelId = bot.transformers.snowflake(payload.channel_id) + const guildId = payload.guild_id ? bot.transformers.snowflake(payload.guild_id) : undefined + + bot.events.messageDeleteBulk?.({ + ids: payload.ids.map((id) => bot.transformers.snowflake(id)), + channelId: bot.transformers.snowflake(payload.channel_id), + guildId: payload.guild_id ? bot.transformers.snowflake(payload.guild_id) : undefined, + }) +} diff --git a/packages/bot/src/handlers/messages/MESSAGE_REACTION_ADD.ts b/packages/bot/src/handlers/messages/MESSAGE_REACTION_ADD.ts new file mode 100644 index 000000000..930d91097 --- /dev/null +++ b/packages/bot/src/handlers/messages/MESSAGE_REACTION_ADD.ts @@ -0,0 +1,18 @@ +import type { DiscordGatewayPayload, DiscordMessageReactionAdd } from '@discordeno/types' +import type { Bot } from '../../index.js' + +export async function handleMessageReactionAdd(bot: Bot, data: DiscordGatewayPayload) { + const payload = data.d as DiscordMessageReactionAdd + + const guildId = payload.guild_id ? bot.transformers.snowflake(payload.guild_id) : undefined + const userId = bot.transformers.snowflake(payload.user_id) + bot.events.reactionAdd?.({ + userId, + channelId: bot.transformers.snowflake(payload.channel_id), + messageId: bot.transformers.snowflake(payload.message_id), + guildId, + member: payload.member && guildId ? bot.transformers.member(bot, payload.member, guildId, userId) : undefined, + user: payload.member ? bot.transformers.user(bot, payload.member.user) : undefined, + emoji: bot.events.emoji(payload.emoji), + }) +} diff --git a/packages/bot/src/handlers/messages/MESSAGE_REACTION_REMOVE.ts b/packages/bot/src/handlers/messages/MESSAGE_REACTION_REMOVE.ts new file mode 100644 index 000000000..81645bf7c --- /dev/null +++ b/packages/bot/src/handlers/messages/MESSAGE_REACTION_REMOVE.ts @@ -0,0 +1,14 @@ +import type { DiscordGatewayPayload, DiscordMessageReactionRemove } from '@discordeno/types' +import type { Bot } from '../../index.js' + +export async function handleMessageReactionRemove(bot: Bot, data: DiscordGatewayPayload) { + const payload = data.d as DiscordMessageReactionRemove + + bot.events.reactionRemove?.({ + userId: bot.transformers.snowflake(payload.user_id), + channelId: bot.transformers.snowflake(payload.channel_id), + messageId: bot.transformers.snowflake(payload.message_id), + guildId: payload.guild_id ? bot.transformers.snowflake(payload.guild_id) : undefined, + emoji: bot.transformers.emoji(bot, payload.emoji), + }) +} diff --git a/packages/bot/src/handlers/messages/MESSAGE_REACTION_REMOVE_ALL.ts b/packages/bot/src/handlers/messages/MESSAGE_REACTION_REMOVE_ALL.ts new file mode 100644 index 000000000..24e57cc95 --- /dev/null +++ b/packages/bot/src/handlers/messages/MESSAGE_REACTION_REMOVE_ALL.ts @@ -0,0 +1,12 @@ +import type { DiscordGatewayPayload, DiscordMessageReactionRemoveAll } from '@discordeno/types' +import type { Bot } from '../../index.js' + +export async function handleMessageReactionRemoveAll(bot: Bot, data: DiscordGatewayPayload) { + const payload = data.d as DiscordMessageReactionRemoveAll + + bot.events.reactionRemoveAll?.({ + channelId: bot.transformers.snowflake(payload.channel_id), + messageId: bot.transformers.snowflake(payload.message_id), + guildId: payload.guild_id ? bot.transformers.snowflake(payload.guild_id) : undefined, + }) +} diff --git a/packages/bot/src/handlers/messages/MESSAGE_REACTION_REMOVE_EMOJI.ts b/packages/bot/src/handlers/messages/MESSAGE_REACTION_REMOVE_EMOJI.ts new file mode 100644 index 000000000..8c8dacdca --- /dev/null +++ b/packages/bot/src/handlers/messages/MESSAGE_REACTION_REMOVE_EMOJI.ts @@ -0,0 +1,13 @@ +import type { DiscordGatewayPayload, DiscordMessageReactionRemoveEmoji } from '@discordeno/types' +import type { Bot } from '../../index.js' + +export async function handleMessageReactionRemoveEmoji(bot: Bot, data: DiscordGatewayPayload) { + const payload = data.d as DiscordMessageReactionRemoveEmoji + + bot.events.reactionRemoveEmoji?.({ + channelId: bot.transformers.snowflake(payload.channel_id), + messageId: bot.transformers.snowflake(payload.message_id), + guildId: payload.guild_id ? bot.transformers.snowflake(payload.guild_id) : undefined, + emoji: bot.transformers.emoji(bot, payload.emoji), + }) +} diff --git a/packages/bot/src/handlers/messages/MESSAGE_UPDATE.ts b/packages/bot/src/handlers/messages/MESSAGE_UPDATE.ts new file mode 100644 index 000000000..8076aa2be --- /dev/null +++ b/packages/bot/src/handlers/messages/MESSAGE_UPDATE.ts @@ -0,0 +1,9 @@ +import type { DiscordGatewayPayload, DiscordMessage } from '@discordeno/types' +import type { Bot } from '../../index.js' + +export async function handleMessageUpdate(bot: Bot, data: DiscordGatewayPayload) { + const payload = data.d as DiscordMessage + if (!payload.edited_timestamp) return + + bot.events.messageUpdate?.(bot.transformers.message(bot, payload)) +} diff --git a/packages/bot/src/handlers/messages/mod.ts b/packages/bot/src/handlers/messages/mod.ts new file mode 100644 index 000000000..ad6fef398 --- /dev/null +++ b/packages/bot/src/handlers/messages/mod.ts @@ -0,0 +1,8 @@ +export * from "./MESSAGE_CREATE.js"; +export * from "./MESSAGE_DELETE_BULK.js"; +export * from "./MESSAGE_DELETE.js"; +export * from "./MESSAGE_REACTION_ADD.js"; +export * from "./MESSAGE_REACTION_REMOVE_ALL.js"; +export * from "./MESSAGE_REACTION_REMOVE_EMOJI.js"; +export * from "./MESSAGE_REACTION_REMOVE.js"; +export * from "./MESSAGE_UPDATE.js"; diff --git a/packages/bot/src/handlers/misc/PRESENCE_UPDATE.ts b/packages/bot/src/handlers/misc/PRESENCE_UPDATE.ts new file mode 100644 index 000000000..695ac9aa3 --- /dev/null +++ b/packages/bot/src/handlers/misc/PRESENCE_UPDATE.ts @@ -0,0 +1,6 @@ +import type { DiscordGatewayPayload, DiscordPresenceUpdate } from '@discordeno/types' +import type { Bot } from '../../index.js' + +export async function handlePresenceUpdate(bot: Bot, data: DiscordGatewayPayload) { + bot.events.presenceUpdate?.(bot.transformers.presence(bot, data.d as DiscordPresenceUpdate)) +} diff --git a/packages/bot/src/handlers/misc/READY.ts b/packages/bot/src/handlers/misc/READY.ts new file mode 100644 index 000000000..7615f89e4 --- /dev/null +++ b/packages/bot/src/handlers/misc/READY.ts @@ -0,0 +1,22 @@ +import type { DiscordGatewayPayload, DiscordReady } from '@discordeno/types' +import type { Bot } from '../../index.js' + +export function handleReady(bot: Bot, data: DiscordGatewayPayload, shardId: number) { + const payload = data.d as DiscordReady + // Triggered on each shard + bot.events.ready?.( + { + shardId, + v: payload.v, + user: bot.transformers.user(bot, payload.user), + guilds: payload.guilds.map((p) => bot.transformers.snowflake(p.id)), + sessionId: payload.session_id, + shard: payload.shard, + applicationId: bot.transformers.snowflake(payload.application.id), + }, + payload, + ) + + bot.id = bot.transformers.snowflake(payload.user.id) + bot.applicationId = bot.transformers.snowflake(payload.application.id) +} diff --git a/packages/bot/src/handlers/misc/TYPING_START.ts b/packages/bot/src/handlers/misc/TYPING_START.ts new file mode 100644 index 000000000..c8799d107 --- /dev/null +++ b/packages/bot/src/handlers/misc/TYPING_START.ts @@ -0,0 +1,17 @@ +import type { DiscordGatewayPayload, DiscordTypingStart } from '@discordeno/types' +import type { Bot } from '../../index.js' + +export function handleTypingStart(bot: Bot, data: DiscordGatewayPayload) { + const payload = data.d as DiscordTypingStart + + const guildId = payload.guild_id ? bot.transformers.snowflake(payload.guild_id) : undefined + const userId = bot.transformers.snowflake(payload.user_id) + + bot.events.typingStart?.({ + guildId, + channelId: bot.transformers.snowflake(payload.channel_id), + userId, + timestamp: payload.timestamp, + member: payload.member && guildId ? bot.transformers.member(bot, payload.member, guildId, userId) : undefined, + }) +} diff --git a/packages/bot/src/handlers/misc/USER_UPDATE.ts b/packages/bot/src/handlers/misc/USER_UPDATE.ts new file mode 100644 index 000000000..742395451 --- /dev/null +++ b/packages/bot/src/handlers/misc/USER_UPDATE.ts @@ -0,0 +1,7 @@ +import type { DiscordGatewayPayload, DiscordUser } from '@discordeno/types' +import type { Bot } from '../../index.js' + +export async function handleUserUpdate(bot: Bot, data: DiscordGatewayPayload) { + const payload = data.d as DiscordUser + bot.events.botUpdate?.(bot.transformers.user(bot, payload)) +} diff --git a/packages/bot/src/handlers/misc/mod.ts b/packages/bot/src/handlers/misc/mod.ts new file mode 100644 index 000000000..0b8c5a74c --- /dev/null +++ b/packages/bot/src/handlers/misc/mod.ts @@ -0,0 +1,4 @@ +export * from "./PRESENCE_UPDATE.js"; +export * from "./READY.js"; +export * from "./TYPING_START.js"; +export * from "./USER_UPDATE.js"; diff --git a/packages/bot/src/handlers/mod.ts b/packages/bot/src/handlers/mod.ts new file mode 100644 index 000000000..505b37914 --- /dev/null +++ b/packages/bot/src/handlers/mod.ts @@ -0,0 +1,12 @@ +export * from "./channels/mod.js"; +export * from "./emojis/mod.js"; +export * from "./guilds/mod.js"; +export * from "./integrations/mod.js"; +export * from "./interactions/mod.js"; +export * from "./invites/mod.js"; +export * from "./members/mod.js"; +export * from "./messages/mod.js"; +export * from "./misc/mod.js"; +export * from "./roles/mod.js"; +export * from "./voice/mod.js"; +export * from "./webhooks/mod.js"; diff --git a/packages/bot/src/handlers/roles/GUILD_ROLE_CREATE.ts b/packages/bot/src/handlers/roles/GUILD_ROLE_CREATE.ts new file mode 100644 index 000000000..ee9acb9bf --- /dev/null +++ b/packages/bot/src/handlers/roles/GUILD_ROLE_CREATE.ts @@ -0,0 +1,12 @@ +import type { DiscordGatewayPayload, DiscordGuildRoleCreate } from '@discordeno/types' +import type { Bot } from '../../index.js' + +export async function handleGuildRoleCreate(bot: Bot, data: DiscordGatewayPayload) { + const payload = data.d as DiscordGuildRoleCreate + bot.events.roleCreate?.( + bot.transformers.role(bot, { + role: payload.role, + guildId: bot.transformers.snowflake(payload.guild_id), + }), + ) +} diff --git a/packages/bot/src/handlers/roles/GUILD_ROLE_DELETE.ts b/packages/bot/src/handlers/roles/GUILD_ROLE_DELETE.ts new file mode 100644 index 000000000..9a4b24fc4 --- /dev/null +++ b/packages/bot/src/handlers/roles/GUILD_ROLE_DELETE.ts @@ -0,0 +1,10 @@ +import type { DiscordGatewayPayload, DiscordGuildRoleDelete } from '@discordeno/types' +import type { Bot } from '../../index.js' + +export async function handleGuildRoleDelete(bot: Bot, data: DiscordGatewayPayload) { + const payload = data.d as DiscordGuildRoleDelete + bot.events.roleDelete?.({ + roleId: bot.transformers.snowflake(payload.role_id), + guildId: bot.transformers.snowflake(payload.guild_id), + }) +} diff --git a/packages/bot/src/handlers/roles/GUILD_ROLE_UPDATE.ts b/packages/bot/src/handlers/roles/GUILD_ROLE_UPDATE.ts new file mode 100644 index 000000000..d6b253289 --- /dev/null +++ b/packages/bot/src/handlers/roles/GUILD_ROLE_UPDATE.ts @@ -0,0 +1,13 @@ +import type { DiscordGatewayPayload, DiscordGuildRoleUpdate } from '@discordeno/types' +import type { Bot } from '../../index.js' + +export async function handleGuildRoleUpdate(bot: Bot, data: DiscordGatewayPayload) { + const payload = data.d as DiscordGuildRoleUpdate + + bot.events.roleUpdate?.( + bot.transformers.role(bot, { + role: payload.role, + guildId: bot.transformers.snowflake(payload.guild_id), + }), + ) +} diff --git a/packages/bot/src/handlers/roles/mod.ts b/packages/bot/src/handlers/roles/mod.ts new file mode 100644 index 000000000..6ba9e7a0b --- /dev/null +++ b/packages/bot/src/handlers/roles/mod.ts @@ -0,0 +1,3 @@ +export * from "./GUILD_ROLE_CREATE.js"; +export * from "./GUILD_ROLE_DELETE.js"; +export * from "./GUILD_ROLE_UPDATE.js"; diff --git a/packages/bot/src/handlers/voice/VOICE_SERVER_UPDATE.ts b/packages/bot/src/handlers/voice/VOICE_SERVER_UPDATE.ts new file mode 100644 index 000000000..11461f593 --- /dev/null +++ b/packages/bot/src/handlers/voice/VOICE_SERVER_UPDATE.ts @@ -0,0 +1,12 @@ +import type { DiscordGatewayPayload, DiscordVoiceServerUpdate } from '@discordeno/types' +import type { Bot } from '../../index.js' + +export async function handleVoiceServerUpdate(bot: Bot, data: DiscordGatewayPayload) { + const payload = data.d as DiscordVoiceServerUpdate + + bot.events.voiceServerUpdate?.({ + token: payload.token, + guildId: bot.transformers.snowflake(payload.guild_id), + endpoint: payload.endpoint ?? undefined, + }) +} diff --git a/packages/bot/src/handlers/voice/VOICE_STATE_UPDATE.ts b/packages/bot/src/handlers/voice/VOICE_STATE_UPDATE.ts new file mode 100644 index 000000000..4006c67e5 --- /dev/null +++ b/packages/bot/src/handlers/voice/VOICE_STATE_UPDATE.ts @@ -0,0 +1,11 @@ +import type { DiscordGatewayPayload, DiscordVoiceState } from '@discordeno/types' +import type { Bot } from '../../index.js' + +export async function handleVoiceStateUpdate(bot: Bot, data: DiscordGatewayPayload) { + const payload = data.d as DiscordVoiceState + if (!payload.guild_id) return + + const guildId = bot.transformers.snowflake(payload.guild_id) + + bot.events.voiceStateUpdate?.(bot.transformers.voiceState(bot, { voiceState: payload, guildId })) +} diff --git a/packages/bot/src/handlers/voice/mod.ts b/packages/bot/src/handlers/voice/mod.ts new file mode 100644 index 000000000..6df599417 --- /dev/null +++ b/packages/bot/src/handlers/voice/mod.ts @@ -0,0 +1,2 @@ +export * from "./VOICE_SERVER_UPDATE.js"; +export * from "./VOICE_STATE_UPDATE.js"; diff --git a/packages/bot/src/handlers/webhooks/WEBHOOKS_UPDATE.ts b/packages/bot/src/handlers/webhooks/WEBHOOKS_UPDATE.ts new file mode 100644 index 000000000..5937fe0f4 --- /dev/null +++ b/packages/bot/src/handlers/webhooks/WEBHOOKS_UPDATE.ts @@ -0,0 +1,10 @@ +import type { DiscordGatewayPayload, DiscordWebhookUpdate } from '@discordeno/types' +import type { Bot } from '../../index.js' + +export function handleWebhooksUpdate(bot: Bot, data: DiscordGatewayPayload) { + const payload = data.d as DiscordWebhookUpdate + bot.events.webhooksUpdate?.({ + channelId: bot.transformers.snowflake(payload.channel_id), + guildId: bot.transformers.snowflake(payload.guild_id), + }) +} diff --git a/packages/bot/src/handlers/webhooks/mod.ts b/packages/bot/src/handlers/webhooks/mod.ts new file mode 100644 index 000000000..4967148bb --- /dev/null +++ b/packages/bot/src/handlers/webhooks/mod.ts @@ -0,0 +1 @@ +export * from "./WEBHOOKS_UPDATE.js"; diff --git a/packages/bot/src/index.ts b/packages/bot/src/index.ts index 3aecb00d7..432d86276 100644 --- a/packages/bot/src/index.ts +++ b/packages/bot/src/index.ts @@ -3,3 +3,6 @@ export * from '@discordeno/rest' export * from '@discordeno/types' export * from '@discordeno/utils' export * from './bot.js' +export * from './handler.js' +export * from './transformer.js' +export * from './utils.js' diff --git a/packages/bot/src/optionalize.ts b/packages/bot/src/optionalize.ts new file mode 100644 index 000000000..99503aafd --- /dev/null +++ b/packages/bot/src/optionalize.ts @@ -0,0 +1,79 @@ +type OptionalizeAux = Id< + & { + [K in KeysWithUndefined]?: Optionalize; + } + & { + [K in Exclude>]: T[K] extends ObjectLiteral ? Optionalize : T[K]; + } +>; + +/** + * Makes all of properties in T optional when they're null | undefined + * it is recursive + */ +export type Optionalize = T extends object + ? T extends Array ? number extends T["length"] ? T[number] extends object ? Array> + : T + : Partial + : OptionalizeAux + : T; + +export type KeysWithUndefined = { + [K in keyof T]-?: undefined extends T[K] ? K + : null extends T[K] ? K + : never; +}[keyof T]; + +/** + * alternative to 'object' or '{}' + * @example: + * export const o: ObjectLiteral = [] as object; // error + * export const o: object = []; // no error + */ +export type ObjectLiteral = { + [K in PropertyKey]: T; +}; + +/** + * object identity type + */ +export type Id = T extends infer U ? { + [K in keyof U]: U[K]; +} +: never; + +/** Array with no utilty methods, aka Object.create(null) */ +export type ArrayWithNoPrototype = { + [index: number]: T | ArrayWithNoPrototype; +}; + +/** + * Allows any type but T + * it is recursive + * @example + * export type RequestData = Record>; + */ +export type AnythingBut = Exclude< + | Primitive + | { + [K in PropertyKey]: AnythingBut; + } + | ArrayWithNoPrototype< + | Primitive + | { + [K in PropertyKey]: AnythingBut; + } + >, + T +>; + +/** Non object primitives */ +export type Primitive = + | string + | number + | symbol + | bigint + | boolean + | undefined + | null; +// | object <- don't make object a primitive \ No newline at end of file diff --git a/packages/bot/src/transformer.ts b/packages/bot/src/transformer.ts new file mode 100644 index 000000000..759e1627a --- /dev/null +++ b/packages/bot/src/transformer.ts @@ -0,0 +1,221 @@ +import type { + AllowedMentions, + ApplicationCommandOption, + ApplicationCommandOptionChoice, + BigString, + CreateApplicationCommand, + DiscordActivity, + DiscordAllowedMentions, + DiscordApplication, + DiscordApplicationCommand, + DiscordApplicationCommandOption, + DiscordApplicationCommandOptionChoice, + DiscordAttachment, + DiscordAuditLogEntry, + DiscordAutoModerationActionExecution, + DiscordAutoModerationRule, + DiscordChannel, + DiscordCreateApplicationCommand, + DiscordEmbed, + DiscordEmoji, + DiscordGetGatewayBot, + DiscordGuild, + DiscordGuildApplicationCommandPermissions, + DiscordGuildWidget, + DiscordGuildWidgetSettings, + DiscordIntegrationCreateUpdate, + DiscordInteraction, + DiscordInteractionDataOption, + DiscordInviteCreate, + DiscordMember, + DiscordMessage, + DiscordPresenceUpdate, + DiscordRole, + DiscordScheduledEvent, + DiscordStageInstance, + DiscordSticker, + DiscordStickerPack, + DiscordTeam, + DiscordTemplate, + DiscordThreadMember, + DiscordUser, + DiscordVoiceRegion, + DiscordVoiceState, + DiscordWebhook, + DiscordWelcomeScreen, + InteractionResponse, +} from '@discordeno/types' +import { bigintToSnowflake, Bot, snowflakeToBigint } from './index.js' +import { Activity, transformActivity } from './transformers/activity' +import { Application, transformApplication } from './transformers/application' +import { ApplicationCommand, transformApplicationCommand } from './transformers/applicationCommand' +import { transformApplicationCommandOption } from './transformers/applicationCommandOption' +import { transformApplicationCommandOptionChoice } from './transformers/applicationCommandOptionChoice' +import { ApplicationCommandPermission, transformApplicationCommandPermission } from './transformers/applicationCommandPermission' +import { Attachment, transformAttachment } from './transformers/attachment' +import { AuditLogEntry, transformAuditLogEntry } from './transformers/auditLogEntry' +import { transformAutoModerationActionExecution, type AutoModerationActionExecution } from './transformers/automodActionExecution.js' +import { AutoModerationRule, transformAutoModerationRule } from './transformers/automodRule' +import { Channel, transformChannel } from './transformers/channel' +import { Component, transformComponent } from './transformers/component' +import { Embed, transformEmbed } from './transformers/embed' +import { Emoji, transformEmoji } from './transformers/emoji' +import { GetGatewayBot, transformGatewayBot } from './transformers/gatewayBot' +import { Guild, transformGuild } from './transformers/guild' +import { Integration, transformIntegration } from './transformers/integration' +import { Interaction, InteractionDataOption, transformInteraction, transformInteractionDataOption } from './transformers/interaction' +import { Invite, transformInvite } from './transformers/invite' +import { Member, transformMember, transformUser, User } from './transformers/member' +import { Message, transformMessage } from './transformers/message' +import { + transformActivityToDiscordActivity, + transformApplicationCommandOptionChoiceToDiscordApplicationCommandOptionChoice, + transformApplicationCommandOptionToDiscordApplicationCommandOption, + transformApplicationCommandToDiscordApplicationCommand, + transformApplicationToDiscordApplication, + transformAttachmentToDiscordAttachment, + transformComponentToDiscordComponent, + transformEmbedToDiscordEmbed, + transformMemberToDiscordMember, + transformTeamToDiscordTeam, + transformUserToDiscordUser, +} from './transformers/mod' +import { PresenceUpdate, transformPresence } from './transformers/presence' +import { transformAllowedMentionsToDiscordAllowedMentions } from './transformers/reverse/allowedMentions' +import { transformCreateApplicationCommandToDiscordCreateApplicationCommand } from './transformers/reverse/createApplicationCommand.js' +import { transformInteractionResponseToDiscordInteractionResponse } from './transformers/reverse/interactionResponse.js' +import { Role, transformRole } from './transformers/role' +import { ScheduledEvent, transformScheduledEvent } from './transformers/scheduledEvent' +import { StageInstance, transformStageInstance } from './transformers/stageInstance' +import { Sticker, StickerPack, transformSticker, transformStickerPack } from './transformers/sticker' +import { Team, transformTeam } from './transformers/team' +import { Template, transformTemplate } from './transformers/template' +import { ThreadMember, transformThreadMember } from './transformers/threadMember' +import { transformVoiceRegion, VoiceRegions } from './transformers/voiceRegion' +import { transformVoiceState, VoiceState } from './transformers/voiceState' +import { transformWebhook, Webhook } from './transformers/webhook' +import { transformWelcomeScreen, WelcomeScreen } from './transformers/welcomeScreen' +import { GuildWidget, transformWidget } from './transformers/widget' +import { GuildWidgetSettings, transformWidgetSettings } from './transformers/widgetSettings' +import type { DiscordComponent, DiscordInteractionResponse } from './types.js' + +export interface Transformers { + reverse: { + allowedMentions: (bot: Bot, payload: AllowedMentions) => DiscordAllowedMentions + embed: (bot: Bot, payload: Embed) => DiscordEmbed + component: (bot: Bot, payload: Component) => DiscordComponent + activity: (bot: Bot, payload: Activity) => DiscordActivity + member: (bot: Bot, payload: Member) => DiscordMember + user: (bot: Bot, payload: User) => DiscordUser + team: (bot: Bot, payload: Team) => DiscordTeam + application: (bot: Bot, payload: Application) => DiscordApplication + snowflake: (snowflake: BigString) => string + createApplicationCommand: (bot: Bot, payload: CreateApplicationCommand) => DiscordCreateApplicationCommand + applicationCommand: (bot: Bot, payload: ApplicationCommand) => DiscordApplicationCommand + applicationCommandOption: (bot: Bot, payload: ApplicationCommandOption) => DiscordApplicationCommandOption + applicationCommandOptionChoice: (bot: Bot, payload: ApplicationCommandOptionChoice) => DiscordApplicationCommandOptionChoice + interactionResponse: (bot: Bot, payload: InteractionResponse) => DiscordInteractionResponse + attachment: (bot: Bot, payload: Attachment) => DiscordAttachment + } + snowflake: (snowflake: BigString) => bigint + gatewayBot: (payload: DiscordGetGatewayBot) => GetGatewayBot + automodRule: (bot: Bot, payload: DiscordAutoModerationRule) => AutoModerationRule + automodActionExecution: (bot: Bot, payload: DiscordAutoModerationActionExecution) => AutoModerationActionExecution + channel: (bot: Bot, payload: { channel: DiscordChannel } & { guildId?: bigint }) => Channel + guild: (bot: Bot, payload: { guild: DiscordGuild } & { shardId: number }) => Guild + user: (bot: Bot, payload: DiscordUser) => User + member: (bot: Bot, payload: DiscordMember, guildId: bigint, userId: bigint) => Member + message: (bot: Bot, payload: DiscordMessage) => Message + role: (bot: Bot, payload: { role: DiscordRole } & { guildId: bigint }) => Role + voiceState: (bot: Bot, payload: { voiceState: DiscordVoiceState } & { guildId: bigint }) => VoiceState + interaction: (bot: Bot, payload: DiscordInteraction) => Interaction + interactionDataOptions: (bot: Bot, payload: DiscordInteractionDataOption) => InteractionDataOption + integration: (bot: Bot, payload: DiscordIntegrationCreateUpdate) => Integration + invite: (bot: Bot, invite: DiscordInviteCreate) => Invite + application: (bot: Bot, payload: DiscordApplication) => Application + team: (bot: Bot, payload: DiscordTeam) => Team + emoji: (bot: Bot, payload: DiscordEmoji) => Emoji + activity: (bot: Bot, payload: DiscordActivity) => Activity + presence: (bot: Bot, payload: DiscordPresenceUpdate) => PresenceUpdate + attachment: (bot: Bot, payload: DiscordAttachment) => Attachment + embed: (bot: Bot, payload: DiscordEmbed) => Embed + component: (bot: Bot, payload: DiscordComponent) => Component + webhook: (bot: Bot, payload: DiscordWebhook) => Webhook + auditLogEntry: (bot: Bot, payload: DiscordAuditLogEntry) => AuditLogEntry + applicationCommand: (bot: Bot, payload: DiscordApplicationCommand) => ApplicationCommand + applicationCommandOption: (bot: Bot, payload: DiscordApplicationCommandOption) => ApplicationCommandOption + applicationCommandPermission: (bot: Bot, payload: DiscordGuildApplicationCommandPermissions) => ApplicationCommandPermission + scheduledEvent: (bot: Bot, payload: DiscordScheduledEvent) => ScheduledEvent + threadMember: (bot: Bot, payload: DiscordThreadMember) => ThreadMember + welcomeScreen: (bot: Bot, payload: DiscordWelcomeScreen) => WelcomeScreen + voiceRegion: (bot: Bot, payload: DiscordVoiceRegion) => VoiceRegions + widget: (bot: Bot, payload: DiscordGuildWidget) => GuildWidget + widgetSettings: (bot: Bot, payload: DiscordGuildWidgetSettings) => GuildWidgetSettings + stageInstance: (bot: Bot, payload: DiscordStageInstance) => StageInstance + sticker: (bot: Bot, payload: DiscordSticker) => Sticker + stickerPack: (bot: Bot, payload: DiscordStickerPack) => StickerPack + applicationCommandOptionChoice: (bot: Bot, payload: DiscordApplicationCommandOptionChoice) => ApplicationCommandOptionChoice + template: (bot: Bot, payload: DiscordTemplate) => Template +} + +export function createTransformers(options: Partial) { + return { + reverse: { + allowedMentions: options.reverse?.allowedMentions || transformAllowedMentionsToDiscordAllowedMentions, + embed: options.reverse?.embed || transformEmbedToDiscordEmbed, + component: options.reverse?.component || transformComponentToDiscordComponent, + activity: options.reverse?.activity || transformActivityToDiscordActivity, + member: options.reverse?.member || transformMemberToDiscordMember, + user: options.reverse?.user || transformUserToDiscordUser, + team: options.reverse?.team || transformTeamToDiscordTeam, + application: options.reverse?.application || transformApplicationToDiscordApplication, + snowflake: options.reverse?.snowflake || bigintToSnowflake, + createApplicationCommand: options.reverse?.createApplicationCommand || transformCreateApplicationCommandToDiscordCreateApplicationCommand, + applicationCommand: options.reverse?.applicationCommand || transformApplicationCommandToDiscordApplicationCommand, + applicationCommandOption: options.reverse?.applicationCommandOption || transformApplicationCommandOptionToDiscordApplicationCommandOption, + applicationCommandOptionChoice: + options.reverse?.applicationCommandOptionChoice || transformApplicationCommandOptionChoiceToDiscordApplicationCommandOptionChoice, + interactionResponse: options.reverse?.interactionResponse || transformInteractionResponseToDiscordInteractionResponse, + attachment: options.reverse?.attachment || transformAttachmentToDiscordAttachment, + }, + automodRule: options.automodRule || transformAutoModerationRule, + automodActionExecution: options.automodActionExecution || transformAutoModerationActionExecution, + activity: options.activity || transformActivity, + application: options.application || transformApplication, + attachment: options.attachment || transformAttachment, + channel: options.channel || transformChannel, + component: options.component || transformComponent, + embed: options.embed || transformEmbed, + emoji: options.emoji || transformEmoji, + guild: options.guild || transformGuild, + integration: options.integration || transformIntegration, + interaction: options.interaction || transformInteraction, + interactionDataOptions: options.interactionDataOptions || transformInteractionDataOption, + invite: options.invite || transformInvite, + member: options.member || transformMember, + message: options.message || transformMessage, + presence: options.presence || transformPresence, + role: options.role || transformRole, + user: options.user || transformUser, + team: options.team || transformTeam, + voiceState: options.voiceState || transformVoiceState, + snowflake: options.snowflake || snowflakeToBigint, + webhook: options.webhook || transformWebhook, + auditLogEntry: options.auditLogEntry || transformAuditLogEntry, + applicationCommand: options.applicationCommand || transformApplicationCommand, + applicationCommandOption: options.applicationCommandOption || transformApplicationCommandOption, + applicationCommandPermission: options.applicationCommandPermission || transformApplicationCommandPermission, + scheduledEvent: options.scheduledEvent || transformScheduledEvent, + threadMember: options.threadMember || transformThreadMember, + welcomeScreen: options.welcomeScreen || transformWelcomeScreen, + voiceRegion: options.voiceRegion || transformVoiceRegion, + widget: options.widget || transformWidget, + widgetSettings: options.widgetSettings || transformWidgetSettings, + stageInstance: options.stageInstance || transformStageInstance, + sticker: options.sticker || transformSticker, + stickerPack: options.stickerPack || transformStickerPack, + gatewayBot: options.gatewayBot || transformGatewayBot, + applicationCommandOptionChoice: options.applicationCommandOptionChoice || transformApplicationCommandOptionChoice, + template: options.template || transformTemplate, + } +} diff --git a/packages/bot/src/transformers/activity.ts b/packages/bot/src/transformers/activity.ts new file mode 100644 index 000000000..cb142e6ca --- /dev/null +++ b/packages/bot/src/transformers/activity.ts @@ -0,0 +1,41 @@ +import type { DiscordActivity } from '@discordeno/bot' +import type { Bot } from '../index.js' +import type { Optionalize } from '../optionalize.js' + +export function transformActivity(bot: Bot, payload: DiscordActivity) { + const activity = { + name: payload.name, + type: payload.type, + url: payload.url ?? undefined, + createdAt: payload.created_at, + startedAt: payload.timestamps?.start, + endedAt: payload.timestamps?.end, + applicationId: payload.application_id ? bot.transformers.snowflake(payload.application_id) : undefined, + details: payload.details ?? undefined, + state: payload.state ?? undefined, + emoji: payload.emoji + ? { + name: payload.emoji.name, + animated: payload.emoji.animated, + id: payload.emoji.id ? bot.transformers.snowflake(payload.emoji.id) : undefined, + } + : undefined, + partyId: payload.party?.id, + partyCurrentSize: payload.party?.size?.[0], + partyMaxSize: payload.party?.size?.[1], + largeImage: payload.assets?.large_image, + largeText: payload.assets?.large_text, + smallImage: payload.assets?.small_image, + smallText: payload.assets?.small_text, + join: payload.secrets?.join, + spectate: payload.secrets?.spectate, + match: payload.secrets?.match, + instance: payload.instance, + flags: payload.flags, + buttons: payload.buttons, + } + + return activity as Optionalize +} + +export interface Activity extends ReturnType {} diff --git a/packages/bot/src/transformers/application.ts b/packages/bot/src/transformers/application.ts new file mode 100644 index 000000000..7cb85ce4e --- /dev/null +++ b/packages/bot/src/transformers/application.ts @@ -0,0 +1,33 @@ +import { DiscordApplication, iconHashToBigInt } from '@discordeno/bot' +import type { Bot } from '../index.js' +import type { Optionalize } from '../optionalize.js' + +export function transformApplication(bot: Bot, payload: DiscordApplication) { + const application = { + name: payload.name, + description: payload.description, + rpcOrigins: payload.rpc_origins, + botPublic: payload.bot_public, + botRequireCodeGrant: payload.bot_require_code_grant, + termsOfServiceUrl: payload.terms_of_service_url, + privacyPolicyUrl: payload.privacy_policy_url, + verifyKey: payload.verify_key, + primarySkuId: payload.primary_sku_id, + slug: payload.slug, + coverImage: payload.cover_image ? iconHashToBigInt(payload.cover_image) : undefined, + flags: payload.flags, + + id: bot.transformers.snowflake(payload.id), + icon: payload.icon ? iconHashToBigInt(payload.icon) : undefined, + owner: payload.owner + ? // @ts-ignore the partial here wont break anything + bot.transformers.user(bot, payload.owner) + : undefined, + team: payload.team ? bot.transformers.team(bot, payload.team) : undefined, + guildId: payload.guild_id ? bot.transformers.snowflake(payload.guild_id) : undefined, + } + + return application as Optionalize +} + +export interface Application extends ReturnType {} diff --git a/packages/bot/src/transformers/applicationCommand.ts b/packages/bot/src/transformers/applicationCommand.ts new file mode 100644 index 000000000..7cae93949 --- /dev/null +++ b/packages/bot/src/transformers/applicationCommand.ts @@ -0,0 +1,25 @@ +import type { DiscordApplicationCommand } from '@discordeno/types' +import type { Bot } from '../index.js' +import type { Optionalize } from '../optionalize.js' + +export function transformApplicationCommand(bot: Bot, payload: DiscordApplicationCommand) { + const applicationCommand = { + id: bot.transformers.snowflake(payload.id), + applicationId: bot.transformers.snowflake(payload.application_id), + guildId: payload.guild_id ? bot.transformers.snowflake(payload.guild_id) : undefined, + name: payload.name, + nameLocalizations: payload.name_localizations ?? undefined, + description: payload.description, + descriptionLocalizations: payload.description_localizations ?? undefined, + defaultMemberPermissions: payload.default_member_permissions ? bot.transformers.snowflake(payload.default_member_permissions) : undefined, + dmPermission: payload.dm_permission ?? false, + type: payload.type, + version: payload.version, + + options: payload.options?.map((option) => bot.transformers.applicationCommandOption(bot, option)), + } + + return applicationCommand as Optionalize +} + +export interface ApplicationCommand extends ReturnType {} diff --git a/packages/bot/src/transformers/applicationCommandOption.ts b/packages/bot/src/transformers/applicationCommandOption.ts new file mode 100644 index 000000000..78c77eb40 --- /dev/null +++ b/packages/bot/src/transformers/applicationCommandOption.ts @@ -0,0 +1,55 @@ +import type { ApplicationCommandOptionTypes, ChannelTypes, DiscordApplicationCommandOption, Localization } from '@discordeno/types' +import type { Bot } from '../index.js' +import type { ApplicationCommandOptionChoice } from './applicationCommandOptionChoice.js' + +export function transformApplicationCommandOption(bot: Bot, payload: DiscordApplicationCommandOption): ApplicationCommandOption { + return { + type: payload.type, + name: payload.name, + nameLocalizations: payload.name_localizations ?? undefined, + description: payload.description, + descriptionLocalizations: payload.description_localizations ?? undefined, + required: payload.required ?? false, + choices: payload.choices?.map((choice) => bot.transformers.applicationCommandOptionChoice(bot, choice)), + autocomplete: payload.autocomplete, + channelTypes: payload.channel_types, + minValue: payload.min_value, + maxValue: payload.max_value, + minLength: payload.min_length, + maxLength: payload.max_length, + options: payload.options?.map((option) => bot.transformers.applicationCommandOption(bot, option)), + } +} + +// THIS TRANSFORMER HAS A CIRCULAR REFERENCE TO CALL ITSELF FOR OPTIONS SO AN AUTOMATED TYPE CAN NOT BE CREATED! + +export interface ApplicationCommandOption { + /** Value of Application Command Option Type */ + type: ApplicationCommandOptionTypes + /** 1-32 character name matching lowercase `^[\w-]{1,32}$` */ + name: string + /** Localization object for the `name` field. Values follow the same restrictions as `name` */ + nameLocalizations?: Localization + /** 1-100 character description */ + description: string + /** Localization object for the `description` field. Values follow the same restrictions as `description` */ + descriptionLocalizations?: Localization + /** If the parameter is required or optional--default `false` */ + required?: boolean + /** Choices for `string` and `int` types for the user to pick from */ + choices?: ApplicationCommandOptionChoice[] + /** If the option is a subcommand or subcommand group type, this nested options will be the parameters */ + options?: ApplicationCommandOption[] + /** If the option is a channel type, the channels shown will be restricted to these types */ + channelTypes?: ChannelTypes[] + /** Minimum number desired. */ + minValue?: number + /** Maximum number desired. */ + maxValue?: number + /** Minimum length desired. */ + minLength?: number + /** Maximum length desired. */ + maxLength?: number + /** if autocomplete interactions are enabled for this `String`, `Integer`, or `Number` type option */ + autocomplete?: boolean +} diff --git a/packages/bot/src/transformers/applicationCommandOptionChoice.ts b/packages/bot/src/transformers/applicationCommandOptionChoice.ts new file mode 100644 index 000000000..b343e06da --- /dev/null +++ b/packages/bot/src/transformers/applicationCommandOptionChoice.ts @@ -0,0 +1,15 @@ +import type { DiscordApplicationCommandOptionChoice } from '@discordeno/types' +import type { Bot } from '../index.js' +import type { Optionalize } from '../optionalize.js' + +export function transformApplicationCommandOptionChoice(bot: Bot, payload: DiscordApplicationCommandOptionChoice) { + const applicationCommandChoice = { + name: payload.name, + nameLocalizations: payload.name_localizations ?? undefined, + value: payload.value, + } + + return applicationCommandChoice as Optionalize +} + +export interface ApplicationCommandOptionChoice extends ReturnType {} diff --git a/packages/bot/src/transformers/applicationCommandPermission.ts b/packages/bot/src/transformers/applicationCommandPermission.ts new file mode 100644 index 000000000..cf1cff30b --- /dev/null +++ b/packages/bot/src/transformers/applicationCommandPermission.ts @@ -0,0 +1,20 @@ +import type { DiscordGuildApplicationCommandPermissions } from '@discordeno/types' +import type { Bot } from '../index.js' +import type { Optionalize } from '../optionalize.js' + +export function transformApplicationCommandPermission(bot: Bot, payload: DiscordGuildApplicationCommandPermissions) { + const applicationCommandPermission = { + id: bot.transformers.snowflake(payload.id), + applicationId: bot.transformers.snowflake(payload.application_id), + guildId: bot.transformers.snowflake(payload.guild_id), + permissions: payload.permissions.map((perm) => ({ + id: bot.transformers.snowflake(perm.id), + type: perm.type, + permission: perm.permission, + })), + } + + return applicationCommandPermission as Optionalize +} + +export interface ApplicationCommandPermission extends ReturnType {} diff --git a/packages/bot/src/transformers/attachment.ts b/packages/bot/src/transformers/attachment.ts new file mode 100644 index 000000000..7fe1bcde7 --- /dev/null +++ b/packages/bot/src/transformers/attachment.ts @@ -0,0 +1,22 @@ +import type { DiscordAttachment } from '@discordeno/types' +import type { Bot } from '../index.js' +import type { Optionalize } from '../optionalize.js' + +export function transformAttachment(bot: Bot, payload: DiscordAttachment) { + const attachment = { + id: bot.transformers.snowflake(payload.id), + filename: payload.filename, + contentType: payload.content_type, + size: payload.size, + url: payload.url, + proxyUrl: payload.proxy_url, + height: payload.height ?? undefined, + width: payload.width ?? undefined, + ephemeral: payload.ephemeral, + description: payload.description, + } + + return attachment as Optionalize +} + +export interface Attachment extends ReturnType {} diff --git a/packages/bot/src/transformers/auditLogEntry.ts b/packages/bot/src/transformers/auditLogEntry.ts new file mode 100644 index 000000000..b92b735f9 --- /dev/null +++ b/packages/bot/src/transformers/auditLogEntry.ts @@ -0,0 +1,133 @@ +import type { DiscordAuditLogEntry } from '@discordeno/types' +import type { Bot } from '../index.js' +import type { Optionalize } from '../optionalize.js' + +export function transformAuditLogEntry(bot: Bot, payload: DiscordAuditLogEntry) { + const auditLogEntry = { + id: bot.transformers.snowflake(payload.id), + changes: payload.changes?.map((change) => { + switch (change.key) { + case '$add': + case '$remove': + return { + key: change.key, + new: change.new_value?.map((val) => ({ + id: val.id ? bot.transformers.snowflake(val.id) : undefined, + name: val.name, + })), + old: change.old_value?.map((val) => ({ + id: val?.id ? bot.transformers.snowflake(val.id) : undefined, + name: val?.name, + })), + } + case 'discovery_splash_hash': + case 'banner_hash': + case 'rules_channel_id': + case 'public_updates_channel_id': + case 'icon_hash': + case 'image_hash': + case 'splash_hash': + case 'owner_id': + case 'widget_channel_id': + case 'system_channel_id': + case 'application_id': + case 'permissions': + case 'allow': + case 'deny': + case 'channel_id': + case 'inviter_id': + case 'avatar_hash': + case 'id': + return { + key: change.key, + old: change.old_value ? bot.transformers.snowflake(change.old_value) : undefined, + new: change.new_value ? bot.transformers.snowflake(change.new_value) : undefined, + } + case 'name': + case 'description': + case 'preferred_locale': + case 'region': + case 'afk_channel_id': + case 'vanity_url_code': + case 'topic': + case 'code': + case 'nick': + case 'location': + return { + key: change.key, + old: change.old_value, + new: change.new_value, + } + case 'afk_timeout': + case 'mfa_level': + case 'verification_level': + case 'explicit_content_filter': + case 'default_message_notifications': + case 'prune_delete_days': + case 'position': + case 'bitrate': + case 'rate_limit_per_user': + case 'color': + case 'max_uses': + case 'uses': + case 'max_age': + case 'expire_behavior': + case 'expire_grace_period': + case 'user_limit': + case 'privacy_level': + case 'entity_type': + case 'status': + return { + key: change.key, + old: change.old_value ? Number(change.old_value) : undefined, + new: change.new_value ? Number(change.new_value) : undefined, + } + case 'widget_enabled': + case 'nsfw': + case 'hoist': + case 'mentionable': + case 'temporary': + case 'deaf': + case 'mute': + case 'enable_emoticons': + return { + key: change.key, + old: change.old_value ?? false, + new: change.new_value ?? false, + } + case 'permission_overwrites': + return { + key: change.key, + old: change.old_value, + new: change.new_value, + } + default: + return { + key: change.key, + old: change.old_value, + new: change.new_value, + } + } + }), + userId: payload.user_id ? bot.transformers.snowflake(payload.user_id) : undefined, + targetId: payload.target_id ? bot.transformers.snowflake(payload.target_id) : undefined, + actionType: payload.action_type, + options: payload.options + ? { + deleteMemberDays: payload.options.delete_member_days ? Number(payload.options.delete_member_days) : 0, + membersRemoved: payload.options.members_removed ? Number(payload.options.members_removed) : 0, + channelId: payload.options.channel_id ? bot.transformers.snowflake(payload.options.channel_id) : undefined, + messageId: payload.options.message_id ? bot.transformers.snowflake(payload.options.message_id) : undefined, + count: payload.options.count ? Number(payload.options.count) : 0, + id: payload.options.id ? bot.transformers.snowflake(payload.options.id) : undefined, + type: Number(payload.options.type), + roleName: payload.options.role_name, + } + : undefined, + reason: payload.reason, + } + + return auditLogEntry as Optionalize +} + +export interface AuditLogEntry extends ReturnType {} diff --git a/packages/bot/src/transformers/automodActionExecution.ts b/packages/bot/src/transformers/automodActionExecution.ts new file mode 100644 index 000000000..cf9a62c08 --- /dev/null +++ b/packages/bot/src/transformers/automodActionExecution.ts @@ -0,0 +1,29 @@ +import type { DiscordAutoModerationActionExecution } from '@discordeno/types' +import type { Bot } from '../index.js' +import type { Optionalize } from '../optionalize.js' + +export function transformAutoModerationActionExecution(bot: Bot, payload: DiscordAutoModerationActionExecution) { + const rule = { + content: payload.content, + ruleTriggerType: payload.rule_trigger_type, + guildId: bot.transformers.snowflake(payload.guild_id), + ruleId: bot.transformers.snowflake(payload.rule_id), + userId: bot.transformers.snowflake(payload.user_id), + channelId: payload.channel_id ? bot.transformers.snowflake(payload.channel_id) : undefined, + messageId: payload.message_id ? bot.transformers.snowflake(payload.message_id) : undefined, + alertSystemMessageId: payload.alert_system_message_id ? bot.transformers.snowflake(payload.alert_system_message_id) : undefined, + matchedKeyword: payload.matched_keyword ?? '', + matchedContent: payload.matched_content ?? '', + action: { + type: payload.action.type, + metadata: { + durationSeconds: payload.action.metadata.duration_seconds, + channelId: payload.action.metadata.channel_id ? bot.transformers.snowflake(payload.action.metadata.channel_id) : undefined, + }, + }, + } + + return rule as Optionalize +} + +export interface AutoModerationActionExecution extends ReturnType {} diff --git a/packages/bot/src/transformers/automodRule.ts b/packages/bot/src/transformers/automodRule.ts new file mode 100644 index 000000000..7432e8eb1 --- /dev/null +++ b/packages/bot/src/transformers/automodRule.ts @@ -0,0 +1,38 @@ +import type { DiscordAutoModerationRule } from '@discordeno/types' +import type { Bot } from '../index.js' +import type { Optionalize } from '../optionalize.js' + +export function transformAutoModerationRule(bot: Bot, payload: DiscordAutoModerationRule) { + const rule = { + name: payload.name, + eventType: payload.event_type, + triggerType: payload.trigger_type, + enabled: payload.enabled, + id: bot.transformers.snowflake(payload.id), + guildId: bot.transformers.snowflake(payload.guild_id), + creatorId: bot.transformers.snowflake(payload.creator_id), + exemptRoles: payload.exempt_roles.map((id) => bot.transformers.snowflake(id)), + exemptChannels: payload.exempt_channels.map((id) => bot.transformers.snowflake(id)), + triggerMetadata: payload.trigger_metadata + ? { + keywordFilter: payload.trigger_metadata.keyword_filter, + presets: payload.trigger_metadata.presets, + allowList: payload.trigger_metadata.allow_list, + mentionTotalLimit: payload.trigger_metadata.mention_total_limit, + } + : undefined, + actions: payload.actions.map((action) => ({ + type: action.type, + metadata: action.metadata + ? { + channelId: action.metadata.channel_id ? bot.transformers.snowflake(action.metadata.channel_id) : undefined, + durationSeconds: action.metadata.duration_seconds, + } + : undefined, + })), + } + + return rule as Optionalize +} + +export interface AutoModerationRule extends ReturnType {} diff --git a/packages/bot/src/transformers/channel.ts b/packages/bot/src/transformers/channel.ts new file mode 100644 index 000000000..aaba4896c --- /dev/null +++ b/packages/bot/src/transformers/channel.ts @@ -0,0 +1,64 @@ +import type { DiscordChannel } from '@discordeno/types' +import type { Bot } from '../index.js' +import type { Optionalize } from '../optionalize.js' + +const Mask = (1n << 64n) - 1n + +export function packOverwrites(allow: string, deny: string, id: string, type: number) { + return pack64(allow, 0) | pack64(deny, 1) | pack64(id, 2) | pack64(type, 3) +} +function unpack64(v: bigint, shift: number) { + return (v >> BigInt(shift * 64)) & Mask +} +function pack64(v: string | number, shift: number) { + const b = BigInt(v) + if (b < 0 || b > Mask) throw new Error('should have been a 64 bit unsigned integer: ' + v) + return b << BigInt(shift * 64) +} +export function separateOverwrites(v: bigint) { + return [Number(unpack64(v, 3)), unpack64(v, 2), unpack64(v, 0), unpack64(v, 1)] as [number, bigint, bigint, bigint] +} + +export function transformChannel(bot: Bot, payload: { channel: DiscordChannel } & { guildId?: bigint }) { + const channel = { + // UNTRANSFORMED STUFF HERE + type: payload.channel.type, + position: payload.channel.position, + name: payload.channel.name, + topic: payload.channel.topic ?? undefined, + nsfw: payload.channel.nsfw, + bitrate: payload.channel.bitrate, + userLimit: payload.channel.user_limit, + rateLimitPerUser: payload.channel.rate_limit_per_user, + // recipients: payload.channel.recipients?.map((r) => bot.transformers.user(bot, r)), + rtcRegion: payload.channel.rtc_region ?? undefined, + videoQualityMode: payload.channel.video_quality_mode, + guildId: payload.guildId || (payload.channel.guild_id ? bot.transformers.snowflake(payload.channel.guild_id) : 0n), + lastPinTimestamp: payload.channel.last_pin_timestamp ? Date.parse(payload.channel.last_pin_timestamp) : undefined, + permissionOverwrites: payload.channel.permission_overwrites + ? payload.channel.permission_overwrites.map((o) => packOverwrites(o.allow || '0', o.deny || '0', o.id, o.type)) + : [], + + id: bot.transformers.snowflake(payload.channel.id), + permissions: payload.channel.permissions ? bot.transformers.snowflake(payload.channel.permissions) : undefined, + lastMessageId: payload.channel.last_message_id ? bot.transformers.snowflake(payload.channel.last_message_id) : undefined, + ownerId: payload.channel.owner_id ? bot.transformers.snowflake(payload.channel.owner_id) : undefined, + applicationId: payload.channel.application_id ? bot.transformers.snowflake(payload.channel.application_id) : undefined, + parentId: payload.channel.parent_id ? bot.transformers.snowflake(payload.channel.parent_id) : undefined, + memberCount: payload.channel.member_count, + messageCount: payload.channel.message_count, + archiveTimestamp: payload.channel.thread_metadata?.archive_timestamp ? Date.parse(payload.channel.thread_metadata.archive_timestamp) : undefined, + autoArchiveDuration: payload.channel.thread_metadata?.auto_archive_duration, + botIsMember: Boolean(payload.channel.member), + archived: payload.channel.thread_metadata?.archived, + locked: payload.channel.thread_metadata?.locked, + invitable: payload.channel.thread_metadata?.invitable, + createTimestamp: payload.channel.thread_metadata?.create_timestamp ? Date.parse(payload.channel.thread_metadata.create_timestamp) : undefined, + newlyCreated: payload.channel.newly_created, + flags: payload.channel.flags, + } + + return channel as Optionalize +} + +export interface Channel extends ReturnType {} diff --git a/packages/bot/src/transformers/component.ts b/packages/bot/src/transformers/component.ts new file mode 100644 index 000000000..064ebbafc --- /dev/null +++ b/packages/bot/src/transformers/component.ts @@ -0,0 +1,87 @@ +// import type { DiscordComponent } from '@discordeno/types' +import type { ButtonStyles, MessageComponentTypes, SelectOption, TextStyles } from '@discordeno/types' +import type { Bot } from '../index.js' + +export function transformComponent(bot: Bot, payload: any /* TODO: Fix, needs DiscordComponent type */): Component { + return { + type: payload.type, + customId: payload.custom_id, + disabled: payload.disabled, + style: payload.style, + label: payload.label, + emoji: payload.emoji + ? { + id: payload.emoji.id ? bot.transformers.snowflake(payload.emoji.id) : undefined, + name: payload.emoji.name, + animated: payload.emoji.animated, + } + : undefined, + url: payload.url, + // @ts-expect-error TODO: Fix + options: payload.options?.map((option) => ({ + label: option.label, + value: option.value, + description: option.description, + emoji: option.emoji + ? { + id: option.emoji.id ? bot.transformers.snowflake(option.emoji.id) : undefined, + name: option.emoji.name, + animated: option.emoji.animated, + } + : undefined, + default: option.default, + })), + placeholder: payload.placeholder, + minValues: payload.min_values, + maxValues: payload.max_values, + minLength: payload.min_length, + maxLength: payload.max_length, + value: payload.value, + // @ts-expect-error TODO: Fix + components: payload.components?.map((component) => bot.transformers.component(bot, component)), + } +} + +// THIS TRANSFORMER HAS A CIRCULAR REFERENCE TO CALL ITSELF FOR COMPONENTS SO AN AUTOMATED TYPE CAN NOT BE CREATED! + +export interface Component { + /** component type */ + type: MessageComponentTypes + /** a developer-defined identifier for the component, max 100 characters */ + customId?: string + /** whether this component is required to be filled, default true */ + required?: boolean + /** whether the component is disabled, default false */ + disabled?: boolean + /** For different styles/colors of the buttons */ + style?: ButtonStyles | TextStyles + /** text that appears on the button (max 80 characters) */ + label?: string + /** the dev-define value of the option, max 100 characters for select or 4000 for input. */ + value?: string + /** Emoji object that includes fields of name, id, and animated supporting unicode and custom emojis. */ + emoji?: { + /** Emoji id */ + id?: bigint + /** Emoji name */ + name?: string + /** Whether this emoji is animated */ + animated?: boolean + } + /** optional url for link-style buttons that can navigate a user to the web. Only type 5 Link buttons can have a url */ + url?: string + /** The choices! Maximum of 25 items. */ + options?: SelectOption[] + /** A custom placeholder text if nothing is selected. Maximum 150 characters. */ + placeholder?: string + /** The minimum number of items that must be selected. Default 1. Between 1-25. */ + minValues?: number + /** The maximum number of items that can be selected. Default 1. Between 1-25. */ + maxValues?: number + /** The minimum input length for a text input. Between 0-4000. */ + minLength?: number + /**The maximum input length for a text input. Between 1-4000. */ + maxLength?: number + /** a list of child components */ + components?: Component[] +} diff --git a/packages/bot/src/transformers/embed.ts b/packages/bot/src/transformers/embed.ts new file mode 100644 index 000000000..c48728883 --- /dev/null +++ b/packages/bot/src/transformers/embed.ts @@ -0,0 +1,59 @@ +import type { DiscordEmbed } from '@discordeno/types' +import type { Bot } from '../index.js' +import type { Optionalize } from '../optionalize.js' + +export function transformEmbed(bot: Bot, payload: DiscordEmbed) { + const embed = { + title: payload.title, + type: payload.type, + description: payload.description, + url: payload.url, + timestamp: payload.timestamp ? Date.parse(payload.timestamp) : undefined, + color: payload.color, + footer: payload.footer + ? { + text: payload.footer.text, + iconUrl: payload.footer.icon_url, + proxyIconUrl: payload.footer.proxy_icon_url, + } + : undefined, + image: payload.image + ? { + url: payload.image.url, + proxyUrl: payload.image.proxy_url, + height: payload.image.height, + width: payload.image.width, + } + : undefined, + thumbnail: payload.thumbnail + ? { + url: payload.thumbnail.url, + proxyUrl: payload.thumbnail.proxy_url, + height: payload.thumbnail.height, + width: payload.thumbnail.width, + } + : undefined, + video: payload.video + ? { + url: payload.video.url, + proxyUrl: payload.video.proxy_url, + height: payload.video.height, + width: payload.video.width, + } + : undefined, + provider: payload.provider, + author: payload.author + ? { + name: payload.author.name, + url: payload.author.url, + iconUrl: payload.author.icon_url, + proxyIconUrl: payload.author.proxy_icon_url, + } + : undefined, + fields: payload.fields, + } + + return embed as Optionalize +} + +export interface Embed extends ReturnType {} diff --git a/packages/bot/src/transformers/emoji.ts b/packages/bot/src/transformers/emoji.ts new file mode 100644 index 000000000..4afbe4895 --- /dev/null +++ b/packages/bot/src/transformers/emoji.ts @@ -0,0 +1,18 @@ +import type { DiscordEmoji } from '@discordeno/types' +import type { Bot } from '../index.js' +import type { Optionalize } from '../optionalize.js' +import { EmojiToggles } from './toggles/emoji.js' + +export function transformEmoji(bot: Bot, payload: DiscordEmoji) { + const emoji = { + id: payload.id ? bot.transformers.snowflake(payload.id) : undefined, + name: payload.name || undefined, + roles: payload.roles?.map((id) => bot.transformers.snowflake(id)), + user: payload.user ? bot.transformers.user(bot, payload.user) : undefined, + toggles: new EmojiToggles(payload), + } + + return emoji as Optionalize +} + +export interface Emoji extends ReturnType {} diff --git a/packages/bot/src/transformers/gatewayBot.ts b/packages/bot/src/transformers/gatewayBot.ts new file mode 100644 index 000000000..7c85eace2 --- /dev/null +++ b/packages/bot/src/transformers/gatewayBot.ts @@ -0,0 +1,19 @@ +import type { DiscordGetGatewayBot } from '@discordeno/types' +import type { Optionalize } from '../optionalize.js' + +export function transformGatewayBot(payload: DiscordGetGatewayBot) { + const gatewayBot = { + url: payload.url, + shards: payload.shards, + sessionStartLimit: { + total: payload.session_start_limit.total, + remaining: payload.session_start_limit.remaining, + resetAfter: payload.session_start_limit.reset_after, + maxConcurrency: payload.session_start_limit.max_concurrency, + }, + } + + return gatewayBot as Optionalize +} + +export interface GetGatewayBot extends ReturnType {} diff --git a/packages/bot/src/transformers/guild.ts b/packages/bot/src/transformers/guild.ts new file mode 100644 index 000000000..555e47335 --- /dev/null +++ b/packages/bot/src/transformers/guild.ts @@ -0,0 +1,104 @@ +import type { DiscordGuild } from '@discordeno/types' +import { Collection, iconHashToBigInt } from '@discordeno/utils' +import type { Bot } from '../index.js' +import type { Optionalize } from '../optionalize.js' +import type { Emoji } from '../transformers/emoji.js' +import { GuildToggles } from './toggles/guild.js' + +export function transformGuild(bot: Bot, payload: { guild: DiscordGuild } & { shardId: number }) { + const guildId = bot.transformers.snowflake(payload.guild.id) + + const guild = { + afkTimeout: payload.guild.afk_timeout, + approximateMemberCount: payload.guild.approximate_member_count, + approximatePresenceCount: payload.guild.approximate_presence_count, + defaultMessageNotifications: payload.guild.default_message_notifications, + description: payload.guild.description, + explicitContentFilter: payload.guild.explicit_content_filter, + toggles: new GuildToggles(payload.guild), + maxMembers: payload.guild.max_members, + maxPresences: payload.guild.max_presences ?? undefined, + maxVideoChannelUsers: payload.guild.max_video_channel_users, + mfaLevel: payload.guild.mfa_level, + name: payload.guild.name, + nsfwLevel: payload.guild.nsfw_level, + preferredLocale: payload.guild.preferred_locale, + premiumSubscriptionCount: payload.guild.premium_subscription_count, + premiumTier: payload.guild.premium_tier, + stageInstances: payload.guild.stage_instances?.map((si) => ({ + /** The id of this Stage instance */ + id: bot.transformers.snowflake(si.id), + /** The guild id of the associated Stage channel */ + guildId, + /** The id of the associated Stage channel */ + channelId: bot.transformers.snowflake(si.channel_id), + /** The topic of the Stage instance (1-120 characters) */ + topic: si.topic, + })), + systemChannelFlags: payload.guild.system_channel_flags, + vanityUrlCode: payload.guild.vanity_url_code, + verificationLevel: payload.guild.verification_level, + welcomeScreen: payload.guild.welcome_screen + ? { + description: payload.guild.welcome_screen.description ?? undefined, + welcomeChannels: payload.guild.welcome_screen.welcome_channels.map((wc) => ({ + channelId: bot.transformers.snowflake(wc.channel_id), + description: wc.description, + emojiId: wc.emoji_id ? bot.transformers.snowflake(wc.emoji_id) : undefined, + emojiName: wc.emoji_name ?? undefined, + })), + } + : undefined, + discoverySplash: payload.guild.discovery_splash ? iconHashToBigInt(payload.guild.discovery_splash) : undefined, + + joinedAt: payload.guild.joined_at ? Date.parse(payload.guild.joined_at) : undefined, + memberCount: payload.guild.member_count ?? 0, + shardId: payload.shardId, + icon: payload.guild.icon ? iconHashToBigInt(payload.guild.icon) : undefined, + banner: payload.guild.banner ? iconHashToBigInt(payload.guild.banner) : undefined, + splash: payload.guild.splash ? iconHashToBigInt(payload.guild.splash) : undefined, + channels: new Collection( + payload.guild.channels?.map((channel) => { + const result = bot.transformers.channel(bot, { channel, guildId }) + return [result.id, result] + }), + ), + members: new Collection( + payload.guild.members?.map((member) => { + const result = bot.transformers.member(bot, member, guildId, bot.transformers.snowflake(member.user!.id)) + return [result.id, result] + }), + ), + roles: new Collection( + payload.guild.roles?.map((role) => { + const result = bot.transformers.role(bot, { role, guildId }) + return [result.id, result] + }), + ), + emojis: new Collection( + (payload.guild.emojis || []).map((emoji) => { + const em: Emoji = bot.transformers.emoji(bot, emoji) + return [em.id!, em] + }), + ), + voiceStates: new Collection( + (payload.guild.voice_states || []).map((vs) => bot.transformers.voiceState(bot, { voiceState: vs, guildId })).map((vs) => [vs.userId, vs]), + ), + + id: guildId, + // WEIRD EDGE CASE WITH BOT CREATED SERVERS + ownerId: payload.guild.owner_id ? bot.transformers.snowflake(payload.guild.owner_id) : 0n, + permissions: payload.guild.permissions ? bot.transformers.snowflake(payload.guild.permissions) : 0n, + afkChannelId: payload.guild.afk_channel_id ? bot.transformers.snowflake(payload.guild.afk_channel_id) : undefined, + widgetChannelId: payload.guild.widget_channel_id ? bot.transformers.snowflake(payload.guild.widget_channel_id) : undefined, + applicationId: payload.guild.application_id ? bot.transformers.snowflake(payload.guild.application_id) : undefined, + systemChannelId: payload.guild.system_channel_id ? bot.transformers.snowflake(payload.guild.system_channel_id) : undefined, + rulesChannelId: payload.guild.rules_channel_id ? bot.transformers.snowflake(payload.guild.rules_channel_id) : undefined, + publicUpdatesChannelId: payload.guild.public_updates_channel_id ? bot.transformers.snowflake(payload.guild.public_updates_channel_id) : undefined, + premiumProgressBarEnabled: payload.guild.premium_progress_bar_enabled, + } + + return guild as Optionalize +} + +export interface Guild extends ReturnType {} diff --git a/packages/bot/src/transformers/integration.ts b/packages/bot/src/transformers/integration.ts new file mode 100644 index 000000000..64e06ba69 --- /dev/null +++ b/packages/bot/src/transformers/integration.ts @@ -0,0 +1,40 @@ +import type { DiscordIntegrationCreateUpdate } from '@discordeno/types' +import { Bot, iconHashToBigInt } from '../index.js' +import type { Optionalize } from '../optionalize.js' + +export function transformIntegration(bot: Bot, payload: DiscordIntegrationCreateUpdate) { + const integration = { + guildId: bot.transformers.snowflake(payload.guild_id), + id: bot.transformers.snowflake(payload.id), + name: payload.name, + type: payload.type, + enabled: payload.enabled, + syncing: payload.syncing, + roleId: payload.role_id ? bot.transformers.snowflake(payload.role_id) : undefined, + enableEmoticons: payload.enable_emoticons, + expireBehavior: payload.expire_behavior, + expireGracePeriod: payload.expire_grace_period, + user: payload.user ? bot.transformers.user(bot, payload.user) : undefined, + account: { + id: bot.transformers.snowflake(payload.account.id), + name: payload.account.name, + }, + syncedAt: payload.synced_at ? Date.parse(payload.synced_at) : undefined, + subscriberCount: payload.subscriber_count, + revoked: payload.revoked, + application: payload.application + ? { + id: bot.transformers.snowflake(payload.application.id), + name: payload.application.name, + icon: payload.application.icon ? iconHashToBigInt(payload.application.icon) : undefined, + description: payload.application.description, + bot: payload.application.bot ? bot.transformers.user(bot, payload.application.bot) : undefined, + } + : undefined, + scopes: payload.scopes, + } + + return integration as Optionalize +} + +export interface Integration extends ReturnType {} diff --git a/packages/bot/src/transformers/interaction.ts b/packages/bot/src/transformers/interaction.ts new file mode 100644 index 000000000..35f7159a0 --- /dev/null +++ b/packages/bot/src/transformers/interaction.ts @@ -0,0 +1,149 @@ +import type { ChannelTypes, DiscordAttachment, DiscordInteraction, DiscordInteractionDataOption } from '@discordeno/types' +import { Collection } from '@discordeno/utils' +import type { Bot } from '../index.js' +import type { Optionalize } from '../optionalize.js' +import type { DiscordInteractionDataResolved } from '../types.js' +import type { Attachment } from './attachment.js' +import type { Member, User } from './member.js' +import type { Message } from './message.js' +import type { Role } from './role.js' + +export function transformInteraction(bot: Bot, payload: DiscordInteraction) { + const guildId = payload.guild_id ? bot.transformers.snowflake(payload.guild_id) : undefined + const user = bot.transformers.user(bot, payload.member?.user || payload.user!) + + const interaction = { + // UNTRANSFORMED STUFF HERE + type: payload.type, + token: payload.token, + version: payload.version, + locale: payload.locale, + guildLocale: payload.guild_locale, + + // TRANSFORMED STUFF BELOW + guildId, + user, + id: bot.transformers.snowflake(payload.id), + applicationId: bot.transformers.snowflake(payload.application_id), + appPermissions: payload.app_permissions ? bot.transformers.snowflake(payload.app_permissions) : undefined, + message: payload.message ? bot.transformers.message(bot, payload.message) : undefined, + channelId: payload.channel_id ? bot.transformers.snowflake(payload.channel_id) : undefined, + member: payload.member && guildId ? bot.transformers.member(bot, payload.member, guildId, user.id) : undefined, + + data: payload.data + ? { + componentType: payload.data.component_type, + customId: payload.data.custom_id, + components: payload.data.components?.map((component) => bot.transformers.component(bot, component)), + values: payload.data.values, + id: payload.data.id ? bot.transformers.snowflake(payload.data.id) : undefined, + name: payload.data.name, + resolved: payload.data.resolved ? transformInteractionDataResolved(bot, payload.data.resolved, guildId) : undefined, + options: payload.data.options?.map((opt) => bot.transformers.interactionDataOptions(bot, opt)), + targetId: payload.data.target_id ? bot.transformers.snowflake(payload.data.target_id) : undefined, + guildId: payload.data.guild_id ? bot.transformers.snowflake(payload.data.guild_id) : undefined, + } + : undefined, + } + + return interaction as Optionalize +} + +export function transformInteractionDataOption(bot: Bot, option: DiscordInteractionDataOption) { + const opt = { + name: option.name, + type: option.type, + value: option.value, + options: option.options, + focused: option.focused, + } + + return opt as Optionalize +} + +export function transformInteractionDataResolved(bot: Bot, resolved: DiscordInteractionDataResolved, guildId?: bigint) { + const transformed: { + messages?: Collection + users?: Collection + members?: Collection + roles?: Collection + channels?: Collection + attachments?: Collection + } = {} + + if (resolved.messages) { + transformed.messages = new Collection( + Object.entries(resolved.messages).map(([id, value]) => { + const message: Message = bot.transformers.message(bot, value) + return [message.id, message] + }), + ) + } + + if (resolved.users) { + transformed.users = new Collection( + Object.entries(resolved.users).map(([id, value]) => { + const user = bot.transformers.user(bot, value) + return [user.id, user] + }), + ) + } + + if (guildId && resolved.members) { + transformed.members = new Collection( + Object.entries(resolved.members).map(([id, value]) => { + const member: Member = bot.transformers.member(bot, value, guildId, bot.transformers.snowflake(id)) + return [member.id, member] + }), + ) + } + + if (guildId && resolved.roles) { + transformed.roles = new Collection( + Object.entries(resolved.roles).map(([id, value]) => { + const role = bot.transformers.role(bot, { role: value, guildId }) + return [role.id, role] + }), + ) + } + + if (resolved.channels) { + transformed.channels = new Collection( + Object.entries(resolved.channels).map(([key, value]) => { + const id = bot.transformers.snowflake(key) + const channel = value as { + id: string + name: string + type: ChannelTypes + permissions: string + } + return [ + id, + { + id, + name: channel.name, + type: channel.type, + permissions: bot.transformers.snowflake(channel.permissions), + }, + ] + }), + ) + } + + if (resolved.attachments) { + transformed.attachments = new Collection( + Object.entries(resolved.attachments).map(([key, value]) => { + const id = bot.transformers.snowflake(key) + return [id, bot.transformers.attachment(bot, value as DiscordAttachment)] + }), + ) + } + + // TODO: fix + // return transformed as Optionalize + return transformed as any +} + +export interface Interaction extends ReturnType {} +export interface InteractionDataResolved extends ReturnType {} +export interface InteractionDataOption extends ReturnType {} diff --git a/packages/bot/src/transformers/invite.ts b/packages/bot/src/transformers/invite.ts new file mode 100644 index 000000000..bfc5af6d6 --- /dev/null +++ b/packages/bot/src/transformers/invite.ts @@ -0,0 +1,39 @@ +import type { DiscordInviteCreate } from '@discordeno/types' +import type { Bot } from '../index.js' +import type { Optionalize } from '../optionalize.js' + +export function transformInvite(bot: Bot, invite: DiscordInviteCreate) { + const transformedInvite = { + /** The channel the invite is for */ + channelId: bot.transformers.snowflake(invite.channel_id), + /** The unique invite code */ + code: invite.code, + /** The time at which the invite was created */ + createdAt: Date.parse(invite.created_at), + /** The guild of the invite */ + guildId: invite.guild_id ? bot.transformers.snowflake(invite.guild_id) : undefined, + /** The user that created the invite */ + inviter: invite.inviter ? bot.transformers.user(bot, invite.inviter) : undefined, + /** How long the invite is valid for (in seconds) */ + maxAge: invite.max_age, + /** The maximum number of times the invite can be used */ + maxUses: invite.max_uses, + /** The type of target for this voice channel invite */ + targetType: invite.target_type, + /** The target user for this invite */ + targetUser: invite.target_user ? bot.transformers.user(bot, invite.target_user) : undefined, + /** The embedded application to open for this voice channel embedded application invite */ + targetApplication: invite.target_application + ? // @ts-ignore should not break anything even though its partial. if it does blame wolf :) + bot.transformers.application(bot, invite.target_application) + : undefined, + /** Whether or not the invite is temporary (invited users will be kicked on disconnect unless they're assigned a role) */ + temporary: invite.temporary, + /** How many times the invite has been used (always will be 0) */ + uses: invite.uses, + } + + return transformedInvite as Optionalize +} + +export interface Invite extends ReturnType {} diff --git a/packages/bot/src/transformers/member.ts b/packages/bot/src/transformers/member.ts new file mode 100644 index 000000000..507e1effc --- /dev/null +++ b/packages/bot/src/transformers/member.ts @@ -0,0 +1,44 @@ +import type { DiscordMember, DiscordUser } from '@discordeno/types' +import { iconHashToBigInt } from '@discordeno/utils' +import type { Bot } from '../bot.js' +import type { Optionalize } from '../optionalize.js' +import { MemberToggles } from './toggles/member.js' +import { UserToggles } from './toggles/user.js' + +export function transformUser(bot: Bot, payload: DiscordUser) { + const user = { + id: bot.transformers.snowflake(payload.id || ''), + username: payload.username, + discriminator: payload.discriminator, + avatar: payload.avatar ? iconHashToBigInt(payload.avatar) : undefined, + locale: payload.locale, + email: payload.email ?? undefined, + flags: payload.flags, + premiumType: payload.premium_type, + publicFlags: payload.public_flags, + toggles: new UserToggles(payload), + } + + return user as Optionalize +} + +export function transformMember(bot: Bot, payload: DiscordMember, guildId: bigint, userId: bigint) { + const member = { + id: userId, + guildId, + user: payload.user ? bot.transformers.user(bot, payload.user) : undefined, + nick: payload.nick ?? undefined, + roles: payload.roles.map((id) => bot.transformers.snowflake(id)), + joinedAt: Date.parse(payload.joined_at), + premiumSince: payload.premium_since ? Date.parse(payload.premium_since) : undefined, + avatar: payload.avatar ? iconHashToBigInt(payload.avatar) : undefined, + permissions: payload.permissions ? bot.transformers.snowflake(payload.permissions) : undefined, + communicationDisabledUntil: payload.communication_disabled_until ? Date.parse(payload.communication_disabled_until) : undefined, + toggles: new MemberToggles(payload), + } + + return member as Optionalize +} + +export interface Member extends ReturnType {} +export interface User extends ReturnType {} diff --git a/packages/bot/src/transformers/message.ts b/packages/bot/src/transformers/message.ts new file mode 100644 index 000000000..37af070df --- /dev/null +++ b/packages/bot/src/transformers/message.ts @@ -0,0 +1,99 @@ +import type { DiscordMessage } from '@discordeno/types' +import { CHANNEL_MENTION_REGEX } from '../constants.js' +import { Bot, iconHashToBigInt } from '../index.js' +import type { Optionalize } from '../optionalize.js' +import { MemberToggles } from './toggles/member.js' + +export function transformMessage(bot: Bot, payload: DiscordMessage) { + const guildId = payload.guild_id ? bot.transformers.snowflake(payload.guild_id) : undefined + const userId = bot.transformers.snowflake(payload.author.id) + + const message = { + // UNTRANSFORMED STUFF HERE + content: payload.content || '', + isFromBot: payload.author.bot || false, + tag: `${payload.author.username}#${payload.author.discriminator}`, + timestamp: Date.parse(payload.timestamp), + editedTimestamp: payload.edited_timestamp ? Date.parse(payload.edited_timestamp) : undefined, + bitfield: (payload.tts ? 1n : 0n) | (payload.mention_everyone ? 2n : 0n) | (payload.pinned ? 4n : 0n), + attachments: payload.attachments?.map((attachment) => bot.transformers.attachment(bot, attachment)), + embeds: payload.embeds?.map((embed) => bot.transformers.embed(bot, embed)), + reactions: payload.reactions?.map((reaction) => ({ + me: reaction.me, + count: reaction.count, + emoji: bot.transformers.emoji(bot, reaction.emoji), + })), + type: payload.type, + activity: payload.activity + ? { + type: payload.activity.type, + partyId: payload.activity.party_id, + } + : undefined, + application: payload.application, + flags: payload.flags, + interaction: payload.interaction + ? { + id: bot.transformers.snowflake(payload.interaction.id), + type: payload.interaction.type, + name: payload.interaction.name, + user: bot.transformers.user(bot, payload.interaction.user), + member: payload.interaction.member + ? { + id: userId, + guildId, + nick: payload.interaction.member.nick ?? undefined, + roles: payload.interaction.member.roles?.map((id) => bot.transformers.snowflake(id)), + joinedAt: payload.interaction.member.joined_at ? Date.parse(payload.interaction.member.joined_at) : undefined, + premiumSince: payload.interaction.member.premium_since ? Date.parse(payload.interaction.member.premium_since) : undefined, + toggles: new MemberToggles(payload.interaction.member), + avatar: payload.interaction.member.avatar ? iconHashToBigInt(payload.interaction.member.avatar) : undefined, + permissions: payload.interaction.member.permissions ? bot.transformers.snowflake(payload.interaction.member.permissions) : undefined, + communicationDisabledUntil: payload.interaction.member.communication_disabled_until + ? Date.parse(payload.interaction.member.communication_disabled_until) + : undefined, + } + : undefined, + } + : undefined, + thread: payload.thread ? bot.transformers.channel(bot, { channel: payload.thread, guildId }) : undefined, + components: payload.components?.map((component) => bot.transformers.component(bot, component)), + stickerItems: payload.sticker_items?.map((sticker) => ({ + id: bot.transformers.snowflake(sticker.id), + name: sticker.name, + formatType: sticker.format_type, + })), + + // TRANSFORMED STUFF BELOW + id: bot.transformers.snowflake(payload.id), + guildId, + channelId: bot.transformers.snowflake(payload.channel_id), + webhookId: payload.webhook_id ? bot.transformers.snowflake(payload.webhook_id) : undefined, + authorId: userId, + applicationId: payload.application_id ? bot.transformers.snowflake(payload.application_id) : undefined, + messageReference: payload.message_reference + ? { + messageId: payload.message_reference.message_id ? bot.transformers.snowflake(payload.message_reference.message_id) : undefined, + channelId: payload.message_reference.channel_id ? bot.transformers.snowflake(payload.message_reference.channel_id) : undefined, + guildId: payload.message_reference.guild_id ? bot.transformers.snowflake(payload.message_reference.guild_id) : undefined, + } + : undefined, + mentionedUserIds: payload.mentions ? payload.mentions.map((m) => bot.transformers.snowflake(m.id)) : [], + mentionedRoleIds: payload.mention_roles ? payload.mention_roles.map((id) => bot.transformers.snowflake(id)) : [], + mentionedChannelIds: [ + // Keep any ids tht discord sends + ...(payload.mention_channels ?? []).map((m) => bot.transformers.snowflake(m.id)), + // Add any other ids that can be validated in a channel mention format + ...(payload.content?.match(CHANNEL_MENTION_REGEX) || []).map((text) => + // converts the <#123> into 123 + bot.transformers.snowflake(text.substring(2, text.length - 1)), + ), + ], + member: payload.member && guildId ? bot.transformers.member(bot, payload.member, guildId, userId) : undefined, + nonce: payload.nonce, + } + + return message as Optionalize +} + +export interface Message extends ReturnType {} diff --git a/packages/bot/src/transformers/mod.ts b/packages/bot/src/transformers/mod.ts new file mode 100644 index 000000000..0931cc1d9 --- /dev/null +++ b/packages/bot/src/transformers/mod.ts @@ -0,0 +1,36 @@ +export * from './activity.js' +export * from './application.js' +export * from './applicationCommand.js' +export * from './applicationCommandOption.js' +export * from './applicationCommandOptionChoice.js' +export * from './applicationCommandPermission.js' +export * from './attachment.js' +export * from './auditLogEntry.js' +export * from './automodRule.js' +export * from './channel.js' +export * from './component.js' +export * from './embed.js' +export * from './emoji.js' +export * from './gatewayBot.js' +export * from './guild.js' +export * from './integration.js' +export * from './interaction.js' +export * from './invite.js' +export * from './member.js' +export * from './message.js' +export * from './presence.js' +export * from './reverse/mod.js' +export * from './role.js' +export * from './scheduledEvent.js' +export * from './stageInstance.js' +export * from './sticker.js' +export * from './team.js' +export * from './template.js' +export * from './threadMember.js' +export * from './toggles/index.js' +export * from './voiceRegion.js' +export * from './voiceState.js' +export * from './webhook.js' +export * from './welcomeScreen.js' +export * from './widget.js' +export * from './widgetSettings.js' diff --git a/packages/bot/src/transformers/presence.ts b/packages/bot/src/transformers/presence.ts new file mode 100644 index 000000000..8a25d8dbb --- /dev/null +++ b/packages/bot/src/transformers/presence.ts @@ -0,0 +1,31 @@ +import { DiscordPresenceUpdate, PresenceStatus } from '@discordeno/types' +import { Bot, iconHashToBigInt } from '../index.js' +import type { Optionalize } from '../optionalize.js' +import { UserToggles } from './toggles/user.js' + +export function transformPresence(bot: Bot, payload: DiscordPresenceUpdate) { + const presence = { + user: { + id: bot.transformers.snowflake(payload.user.id || ''), + username: payload.user.username ?? undefined, + discriminator: payload.user.discriminator ?? undefined, + avatar: payload.user.avatar ? iconHashToBigInt(payload.user.avatar) : undefined, + locale: payload.user.locale ?? undefined, + email: payload.user.email ?? undefined, + flags: payload.user.flags ?? undefined, + premiumType: payload.user.premium_type ?? undefined, + publicFlags: payload.user.public_flags ?? undefined, + toggles: new UserToggles(payload.user), + }, + guildId: bot.transformers.snowflake(payload.guild_id), + status: PresenceStatus[payload.status], + activities: payload.activities.map((activity) => bot.transformers.activity(bot, activity)), + desktop: payload.client_status.desktop, + mobile: payload.client_status.mobile, + web: payload.client_status.web, + } + + return presence as Optionalize +} + +export interface PresenceUpdate extends ReturnType {} diff --git a/packages/bot/src/transformers/reverse/activity.ts b/packages/bot/src/transformers/reverse/activity.ts new file mode 100644 index 000000000..0c5184bed --- /dev/null +++ b/packages/bot/src/transformers/reverse/activity.ts @@ -0,0 +1,44 @@ +import type { DiscordActivity } from '@discordeno/bot' +import type { Bot } from '../../index.js' +import type { Activity } from '../activity.js' + +export function transformActivityToDiscordActivity(bot: Bot, payload: Activity): DiscordActivity { + return { + name: payload.name, + type: payload.type, + url: payload.url ?? undefined, + created_at: payload.createdAt, + timestamps: { + start: payload.startedAt, + end: payload.endedAt, + }, + application_id: payload.applicationId?.toString(), + details: payload.details ?? undefined, + state: payload.state ?? undefined, + emoji: payload.emoji + ? { + name: payload.emoji.name, + animated: payload.emoji.animated, + id: payload.emoji.id?.toString(), + } + : undefined, + party: { + id: payload.partyId, + size: payload.partyCurrentSize && payload.partyMaxSize ? [payload.partyCurrentSize, payload.partyMaxSize] : undefined, + }, + assets: { + large_image: payload.largeImage, + large_text: payload.largeText, + small_image: payload.largeImage, + small_text: payload.largeText, + }, + secrets: { + join: payload.join, + spectate: payload.spectate, + match: payload.match, + }, + instance: payload.instance, + flags: payload.flags, + buttons: payload.buttons, + } +} diff --git a/packages/bot/src/transformers/reverse/allowedMentions.ts b/packages/bot/src/transformers/reverse/allowedMentions.ts new file mode 100644 index 000000000..3a26109f9 --- /dev/null +++ b/packages/bot/src/transformers/reverse/allowedMentions.ts @@ -0,0 +1,11 @@ +import type { AllowedMentions, DiscordAllowedMentions } from '@discordeno/bot' +import type { Bot } from '../../index.js' + +export function transformAllowedMentionsToDiscordAllowedMentions(bot: Bot, mentions: AllowedMentions): DiscordAllowedMentions { + return { + parse: mentions.parse, + replied_user: mentions.repliedUser, + users: mentions.users?.map((id) => id.toString()), + roles: mentions.roles?.map((id) => id.toString()), + } +} diff --git a/packages/bot/src/transformers/reverse/application.ts b/packages/bot/src/transformers/reverse/application.ts new file mode 100644 index 000000000..4ea6b65d8 --- /dev/null +++ b/packages/bot/src/transformers/reverse/application.ts @@ -0,0 +1,26 @@ +import { DiscordApplication, iconBigintToHash } from '@discordeno/bot' +import type { Bot } from '../../index.js' +import type { Application } from '../application.js' + +export function transformApplicationToDiscordApplication(bot: Bot, payload: Application): DiscordApplication { + return { + name: payload.name, + description: payload.description, + rpc_origins: payload.rpcOrigins, + bot_public: payload.botPublic, + bot_require_code_grant: payload.botRequireCodeGrant, + terms_of_service_url: payload.termsOfServiceUrl, + privacy_policy_url: payload.privacyPolicyUrl, + verify_key: payload.verifyKey, + primary_sku_id: payload.primarySkuId, + slug: payload.slug, + cover_image: payload.coverImage ? iconBigintToHash(payload.coverImage) : undefined, + flags: payload.flags, + + id: payload.id.toString(), + icon: payload.icon ? iconBigintToHash(payload.icon) : null, + owner: payload.owner ? bot.transformers.reverse.user(bot, payload.owner) : undefined, + team: payload.team ? bot.transformers.reverse.team(bot, payload.team) : null, + guild_id: payload.guildId?.toString(), + } +} diff --git a/packages/bot/src/transformers/reverse/applicationCommand.ts b/packages/bot/src/transformers/reverse/applicationCommand.ts new file mode 100644 index 000000000..a63c01c59 --- /dev/null +++ b/packages/bot/src/transformers/reverse/applicationCommand.ts @@ -0,0 +1,20 @@ +import type { DiscordApplicationCommand } from '@discordeno/bot' +import type { Bot } from '../../index.js' +import type { ApplicationCommand } from '../applicationCommand.js' + +export function transformApplicationCommandToDiscordApplicationCommand(bot: Bot, payload: ApplicationCommand): DiscordApplicationCommand { + return { + id: bot.transformers.reverse.snowflake(payload.id), + type: payload.type, + application_id: bot.transformers.reverse.snowflake(payload.applicationId), + guild_id: payload.guildId ? bot.transformers.reverse.snowflake(payload.guildId) : undefined, + name: payload.name, + name_localizations: payload.nameLocalizations, + description: payload.description, + description_localizations: payload.descriptionLocalizations, + options: payload.options?.map((option) => bot.transformers.applicationCommandOption(bot, option)), + default_member_permissions: payload.defaultMemberPermissions ? bot.transformers.reverse.snowflake(payload.defaultMemberPermissions) : null, + dm_permission: payload.dmPermission, + version: payload.version, + } +} diff --git a/packages/bot/src/transformers/reverse/applicationCommandOption.ts b/packages/bot/src/transformers/reverse/applicationCommandOption.ts new file mode 100644 index 000000000..6c5820896 --- /dev/null +++ b/packages/bot/src/transformers/reverse/applicationCommandOption.ts @@ -0,0 +1,25 @@ +import type { DiscordApplicationCommandOption } from '@discordeno/bot' +import type { Bot } from '../../index.js' +import type { ApplicationCommandOption } from '../applicationCommandOption.js' + +export function transformApplicationCommandOptionToDiscordApplicationCommandOption( + bot: Bot, + payload: ApplicationCommandOption, +): DiscordApplicationCommandOption { + return { + type: payload.type, + name: payload.name, + name_localizations: payload.nameLocalizations, + description: payload.description, + description_localizations: payload.descriptionLocalizations, + required: payload.required, + choices: payload.choices?.map((choice) => bot.transformers.reverse.applicationCommandOptionChoice(bot, choice)), + options: payload.options?.map((option) => bot.transformers.reverse.applicationCommandOption(bot, option)), + channel_types: payload.channelTypes, + min_value: payload.minValue, + max_value: payload.maxValue, + min_length: payload.minLength, + max_length: payload.maxLength, + autocomplete: payload.autocomplete, + } +} diff --git a/packages/bot/src/transformers/reverse/applicationCommandOptionChoice.ts b/packages/bot/src/transformers/reverse/applicationCommandOptionChoice.ts new file mode 100644 index 000000000..c380669b7 --- /dev/null +++ b/packages/bot/src/transformers/reverse/applicationCommandOptionChoice.ts @@ -0,0 +1,14 @@ +import type { DiscordApplicationCommandOptionChoice } from '@discordeno/bot' +import type { Bot } from '../../index.js' +import type { ApplicationCommandOptionChoice } from '../applicationCommandOptionChoice.js' + +export function transformApplicationCommandOptionChoiceToDiscordApplicationCommandOptionChoice( + bot: Bot, + payload: ApplicationCommandOptionChoice, +): DiscordApplicationCommandOptionChoice { + return { + name: payload.name, + name_localizations: payload.nameLocalizations, + value: payload.value, + } +} diff --git a/packages/bot/src/transformers/reverse/applicationCommandPermission.ts b/packages/bot/src/transformers/reverse/applicationCommandPermission.ts new file mode 100644 index 000000000..3ce0721b5 --- /dev/null +++ b/packages/bot/src/transformers/reverse/applicationCommandPermission.ts @@ -0,0 +1,19 @@ +import type { DiscordGuildApplicationCommandPermissions } from '@discordeno/bot' +import type { Bot } from '../../index.js' +import type { ApplicationCommandPermission } from '../applicationCommandPermission.js' + +export function transformApplicationCommandPermissionToDiscordApplicationCommandPermission( + bot: Bot, + payload: ApplicationCommandPermission, +): DiscordGuildApplicationCommandPermissions { + return { + id: bot.transformers.reverse.snowflake(payload.id), + application_id: bot.transformers.reverse.snowflake(payload.applicationId), + guild_id: bot.transformers.reverse.snowflake(payload.guildId), + permissions: payload.permissions.map((perm) => ({ + id: bot.transformers.reverse.snowflake(perm.id), + type: perm.type, + permission: perm.permission, + })), + } +} diff --git a/packages/bot/src/transformers/reverse/attachment.ts b/packages/bot/src/transformers/reverse/attachment.ts new file mode 100644 index 000000000..8bb5374d3 --- /dev/null +++ b/packages/bot/src/transformers/reverse/attachment.ts @@ -0,0 +1,18 @@ +import type { DiscordAttachment } from '@discordeno/bot' +import type { Bot } from '../../index.js' +import type { Attachment } from '../attachment.js' + +export function transformAttachmentToDiscordAttachment(bot: Bot, payload: Attachment): DiscordAttachment { + return { + id: bot.transformers.reverse.snowflake(payload.id), + filename: payload.filename, + content_type: payload.contentType, + size: payload.size, + url: payload.url, + proxy_url: payload.proxyUrl, + height: payload.height, + width: payload.width, + ephemeral: payload.ephemeral, + description: payload.description, + } +} diff --git a/packages/bot/src/transformers/reverse/auditLogEntry.ts b/packages/bot/src/transformers/reverse/auditLogEntry.ts new file mode 100644 index 000000000..36f08fc1c --- /dev/null +++ b/packages/bot/src/transformers/reverse/auditLogEntry.ts @@ -0,0 +1,151 @@ +import type { DiscordAuditLogEntry } from '@discordeno/types' +import type { Bot } from '../../index.js' +import type { AuditLogEntry } from '../auditLogEntry.js' + +export function transformAuditLogEntryToDiscordAuditLogEntry(bot: Bot, payload: AuditLogEntry): DiscordAuditLogEntry { + return { + id: bot.transformers.reverse.snowflake(payload.id), + // @ts-expect-error: ts can't identify return type of switch case + changes: payload.changes?.map((change) => { + switch (change.key) { + case '$add': + case '$remove': + return { + key: change.key, + new_value: ( + change.new as { + id: bigint | undefined + name: string | undefined + }[] + )?.map((val) => ({ + id: val.id ? bot.transformers.reverse.snowflake(val.id) : undefined, + name: val.name, + })), + old_value: ( + change.old as + | { + id: bigint | undefined + name: string | undefined + }[] + | undefined + )?.map((val) => ({ + id: val?.id ? bot.transformers.reverse.snowflake(val.id) : undefined, + name: val?.name, + })), + } + case 'discovery_splash_hash': + case 'banner_hash': + case 'rules_channel_id': + case 'public_updates_channel_id': + case 'icon_hash': + case 'image_hash': + case 'splash_hash': + case 'owner_id': + case 'widget_channel_id': + case 'system_channel_id': + case 'application_id': + case 'permissions': + case 'allow': + case 'deny': + case 'channel_id': + case 'inviter_id': + case 'avatar_hash': + case 'id': + return { + key: change.key, + old_value: change.old ? bot.transformers.reverse.snowflake(change.old as bigint) : '', + new_value: change.new ? bot.transformers.reverse.snowflake(change.new as bigint) : '', + } + case 'name': + case 'description': + case 'preferred_locale': + case 'region': + case 'afk_channel_id': + case 'vanity_url_code': + case 'topic': + case 'code': + case 'nick': + case 'location': + return { + key: change.key, + old_value: change.old, + new_value: change.new, + } + case 'afk_timeout': + case 'mfa_level': + case 'verification_level': + case 'explicit_content_filter': + case 'default_message_notifications': + case 'prune_delete_days': + case 'position': + case 'bitrate': + case 'rate_limit_per_user': + case 'color': + case 'max_uses': + case 'uses': + case 'max_age': + case 'expire_behavior': + case 'expire_grace_period': + case 'user_limit': + case 'privacy_level': + case 'entity_type': + case 'status': + return { + key: change.key, + old_value: change.old ? Number(change.old) : '', + new_value: change.new ? Number(change.new) : '', + } + case 'widget_enabled': + case 'nsfw': + case 'hoist': + case 'mentionable': + case 'temporary': + case 'deaf': + case 'mute': + case 'enable_emoticons': + return { + key: change.key, + old_value: change.old, + new_value: change.new, + } + case 'permission_overwrites': + return { + key: change.key, + old_value: change.old, + new_value: change.new, + } + default: + return { + key: change.key, + old_value: change.old, + new_value: change.new, + } + } + }), + user_id: payload.userId ? bot.transformers.reverse.snowflake(payload.userId) : null, + target_id: payload.targetId ? bot.transformers.reverse.snowflake(payload.targetId) : null, + action_type: payload.actionType, + + options: payload.options + ? { + // respect transformer as reference than type + delete_member_days: payload.options.deleteMemberDays === 0 ? payload.options.deleteMemberDays.toString() : '', + members_removed: payload.options.membersRemoved === 0 ? payload.options.membersRemoved.toString() : '', + channel_id: payload.options.channelId ? bot.transformers.reverse.snowflake(payload.options.channelId) : '', + message_id: payload.options.messageId ? bot.transformers.reverse.snowflake(payload.options.messageId) : '', + count: payload.options.count === 0 ? payload.options.count.toString() : '', + id: payload.options.id ? bot.transformers.reverse.snowflake(payload.options.id) : '', + type: payload.options.type.toString(), + role_name: payload.options.roleName, + // make up value to make ts shut up, the orginal value do not persevere in transformer + application_id: '', + // TODO: Fix + // @ts-expect-error + auto_moderation_rule_name: payload.options.autoModerationRuleName, + // @ts-expect-error + auto_moderation_rule_trigger_type: payload.options.autoModerationRuleTriggerType, + } + : undefined, + reason: payload.reason, + } +} diff --git a/packages/bot/src/transformers/reverse/component.ts b/packages/bot/src/transformers/reverse/component.ts new file mode 100644 index 000000000..9ac0d522b --- /dev/null +++ b/packages/bot/src/transformers/reverse/component.ts @@ -0,0 +1,42 @@ +import type { Bot } from '../../index.js' +import type { DiscordComponent } from '../../types.js' +import type { Component } from '../component.js' + +export function transformComponentToDiscordComponent(bot: Bot, payload: Component): DiscordComponent { + return { + type: payload.type, + custom_id: payload.customId, + disabled: payload.disabled, + required: payload.required, + style: payload.style, + label: payload.label, + emoji: payload.emoji + ? { + id: payload.emoji.id?.toString(), + name: payload.emoji.name, + animated: payload.emoji.animated, + } + : undefined, + url: payload.url, + options: payload.options?.map((option) => ({ + label: option.label, + value: option.value, + description: option.description, + emoji: option.emoji + ? { + id: option.emoji.id?.toString(), + name: option.emoji.name, + animated: option.emoji.animated, + } + : undefined, + default: option.default, + })), + placeholder: payload.placeholder, + min_values: payload.minValues, + max_values: payload.maxValues, + min_length: payload.minLength, + max_length: payload.maxLength, + value: payload.value, + components: payload.components?.map((component) => bot.transformers.reverse.component(bot, component)), + } +} diff --git a/packages/bot/src/transformers/reverse/createApplicationCommand.ts b/packages/bot/src/transformers/reverse/createApplicationCommand.ts new file mode 100644 index 000000000..73a98e6ca --- /dev/null +++ b/packages/bot/src/transformers/reverse/createApplicationCommand.ts @@ -0,0 +1,32 @@ +import type { CreateApplicationCommand, DiscordCreateApplicationCommand } from '@discordeno/bot' +import { calculateBits } from '@discordeno/utils' +import type { Bot } from '../../index.js' +import { isContextApplicationCommand } from '../../types.js' + +export function transformCreateApplicationCommandToDiscordCreateApplicationCommand( + bot: Bot, + payload: CreateApplicationCommand, +): DiscordCreateApplicationCommand { + if (isContextApplicationCommand(payload)) { + return { + name: payload.name, + name_localizations: payload.nameLocalizations, + description: '', + description_localizations: {}, + type: payload.type, + default_member_permissions: payload.defaultMemberPermissions ? calculateBits(payload.defaultMemberPermissions) : null, + dm_permission: payload.dmPermission, + } + } + + return { + name: payload.name, + name_localizations: payload.nameLocalizations, + description: payload.description, + description_localizations: payload.descriptionLocalizations, + type: payload.type, + options: payload.options?.map((option) => bot.transformers.reverse.applicationCommandOption(bot, option)), + default_member_permissions: payload.defaultMemberPermissions ? calculateBits(payload.defaultMemberPermissions) : null, + dm_permission: payload.dmPermission, + } +} diff --git a/packages/bot/src/transformers/reverse/embed.ts b/packages/bot/src/transformers/reverse/embed.ts new file mode 100644 index 000000000..af4ad028d --- /dev/null +++ b/packages/bot/src/transformers/reverse/embed.ts @@ -0,0 +1,55 @@ +import type { DiscordEmbed } from '@discordeno/types' +import type { Bot } from '../../index.js' +import type { Embed } from '../embed.js' + +export function transformEmbedToDiscordEmbed(bot: Bot, payload: Embed): DiscordEmbed { + return { + title: payload.title, + type: payload.type, + description: payload.description, + url: payload.url, + timestamp: payload.timestamp ? new Date(payload.timestamp).toISOString() : undefined, + color: payload.color, + footer: payload.footer + ? { + text: payload.footer.text, + icon_url: payload.footer.iconUrl, + proxy_icon_url: payload.footer.proxyIconUrl, + } + : undefined, + image: payload.image + ? { + url: payload.image.url, + proxy_url: payload.image.proxyUrl, + height: payload.image.height, + width: payload.image.width, + } + : undefined, + thumbnail: payload.thumbnail + ? { + url: payload.thumbnail.url, + proxy_url: payload.thumbnail.proxyUrl, + height: payload.thumbnail.height, + width: payload.thumbnail.width, + } + : undefined, + video: payload.video + ? { + url: payload.video.url, + proxy_url: payload.video.proxyUrl, + height: payload.video.height, + width: payload.video.width, + } + : undefined, + provider: payload.provider, + author: payload.author + ? { + name: payload.author.name, + url: payload.author.url, + icon_url: payload.author.iconUrl, + proxy_icon_url: payload.author.proxyIconUrl, + } + : undefined, + fields: payload.fields, + } +} diff --git a/packages/bot/src/transformers/reverse/emoji.ts b/packages/bot/src/transformers/reverse/emoji.ts new file mode 100644 index 000000000..5621d10bb --- /dev/null +++ b/packages/bot/src/transformers/reverse/emoji.ts @@ -0,0 +1,16 @@ +import type { DiscordEmoji } from '@discordeno/types' +import type { Bot } from '../../index.js' +import type { Emoji } from '../emoji.js' + +export function transformEmojiToDiscordEmoji(bot: Bot, payload: Emoji): DiscordEmoji { + return { + id: payload.id ? bot.transformers.reverse.snowflake(payload.id) : undefined, + name: payload.name || undefined, + roles: payload.roles?.map((id) => bot.transformers.reverse.snowflake(id)), + user: payload.user ? bot.transformers.reverse.user(bot, payload.user) : undefined, + require_colons: payload.toggles.requireColons, + managed: payload.toggles.managed, + animated: payload.toggles.animated, + available: payload.toggles.available, + } +} diff --git a/packages/bot/src/transformers/reverse/gatewayBot.ts b/packages/bot/src/transformers/reverse/gatewayBot.ts new file mode 100644 index 000000000..58352eb59 --- /dev/null +++ b/packages/bot/src/transformers/reverse/gatewayBot.ts @@ -0,0 +1,15 @@ +import type { DiscordGetGatewayBot } from '@discordeno/types' +import type { GetGatewayBot } from '../gatewayBot.js' + +export function transformGatewayBotToDiscordGatewayBot(payload: GetGatewayBot): DiscordGetGatewayBot { + return { + url: payload.url, + shards: payload.shards, + session_start_limit: { + total: payload.sessionStartLimit.total, + remaining: payload.sessionStartLimit.remaining, + reset_after: payload.sessionStartLimit.resetAfter, + max_concurrency: payload.sessionStartLimit.maxConcurrency, + }, + } +} diff --git a/packages/bot/src/transformers/reverse/interactionResponse.ts b/packages/bot/src/transformers/reverse/interactionResponse.ts new file mode 100644 index 000000000..f1a4c586a --- /dev/null +++ b/packages/bot/src/transformers/reverse/interactionResponse.ts @@ -0,0 +1,26 @@ +import type { Bot } from '../../index.js' +import type { BotInteractionResponse, DiscordInteractionResponse } from '../../types.js' + +export function transformInteractionResponseToDiscordInteractionResponse(bot: Bot, payload: BotInteractionResponse): DiscordInteractionResponse { + // If no mentions are provided, force disable mentions + if (payload.data && !payload.data?.allowedMentions) { + payload.data.allowedMentions = { parse: [] } + } + + return { + type: payload.type, + data: payload.data + ? { + tts: payload.data.tts, + title: payload.data.title, + flags: payload.data.flags, + content: payload.data.content, + choices: payload.data.choices?.map((choice) => bot.transformers.reverse.applicationCommandOptionChoice(bot, choice)), + custom_id: payload.data.customId, + embeds: payload.data.embeds?.map((embed) => bot.transformers.reverse.embed(bot, embed)), + allowed_mentions: bot.transformers.reverse.allowedMentions(bot, payload.data.allowedMentions!), + components: payload.data.components?.map((component) => bot.transformers.reverse.component(bot, component)), + } + : undefined, + } +} diff --git a/packages/bot/src/transformers/reverse/member.ts b/packages/bot/src/transformers/reverse/member.ts new file mode 100644 index 000000000..f76dda277 --- /dev/null +++ b/packages/bot/src/transformers/reverse/member.ts @@ -0,0 +1,37 @@ +import type { DiscordMember, DiscordUser } from '@discordeno/types' +import { iconBigintToHash } from '@discordeno/utils' +import type { Bot } from '../../bot.js' +import type { Member, User } from '../member.js' + +export function transformUserToDiscordUser(bot: Bot, payload: User): DiscordUser { + return { + id: bot.utils.bigintToSnowflake(payload.id), + username: payload.username, + discriminator: payload.discriminator, + avatar: payload.avatar ? iconBigintToHash(payload.avatar) : null, + locale: payload.locale, + email: payload.email ?? undefined, + flags: payload.flags, + premium_type: payload.premiumType, + public_flags: payload.publicFlags, + bot: payload.toggles.bot, + system: payload.toggles.system, + mfa_enabled: payload.toggles.mfaEnabled, + verified: payload.toggles.verified, + } +} + +export function transformMemberToDiscordMember(bot: Bot, payload: Member): DiscordMember { + return { + nick: payload.nick ?? undefined, + roles: payload.roles.map((id) => bot.utils.bigintToSnowflake(id)), + joined_at: new Date(payload.joinedAt).toISOString(), + premium_since: payload.premiumSince ? new Date(payload.premiumSince).toISOString() : undefined, + avatar: payload.avatar ? iconBigintToHash(payload.avatar) : undefined, + permissions: payload.permissions ? bot.utils.bigintToSnowflake(payload.permissions) : undefined, + communication_disabled_until: payload.communicationDisabledUntil ? new Date(payload.communicationDisabledUntil).toISOString() : undefined, + deaf: payload.toggles.deaf, + mute: payload.toggles.mute, + pending: payload.toggles.pending, + } +} diff --git a/packages/bot/src/transformers/reverse/mod.ts b/packages/bot/src/transformers/reverse/mod.ts new file mode 100644 index 000000000..733f18215 --- /dev/null +++ b/packages/bot/src/transformers/reverse/mod.ts @@ -0,0 +1,16 @@ +export * from "./activity.js"; +export * from "./application.js"; +export * from "./applicationCommand.js"; +export * from "./applicationCommandOption.js"; +export * from "./applicationCommandOptionChoice.js"; +export * from "./applicationCommandPermission.js"; +export * from "./attachment.js"; +export * from "./auditLogEntry.js"; +export * from "./component.js"; +export * from "./embed.js"; +export * from "./emoji.js"; +export * from "./gatewayBot.js"; +export * from "./member.js"; +export * from "./presence.js"; +export * from "./team.js"; +export * from "./widgetSettings.js"; diff --git a/packages/bot/src/transformers/reverse/presence.ts b/packages/bot/src/transformers/reverse/presence.ts new file mode 100644 index 000000000..568e13796 --- /dev/null +++ b/packages/bot/src/transformers/reverse/presence.ts @@ -0,0 +1,25 @@ +import { DiscordPresenceUpdate, PresenceStatus } from '@discordeno/types' +import type { Bot } from '../../index.js' +import type { PresenceUpdate } from '../presence.js' + +export const reverseStatusTypes = Object.freeze({ + 0: 'online', + 1: 'dnd', + 2: 'idle', + 4: 'offline', +} as const) + +export function transformPresenceToDiscordPresence(bot: Bot, payload: PresenceUpdate): DiscordPresenceUpdate { + return { + user: bot.transformers.reverse.user(bot, payload.user), + guild_id: bot.transformers.reverse.snowflake(payload.guildId), + // TODO: find better way + status: (PresenceStatus[payload.status] ?? 'offline') as 'offline', + activities: payload.activities.map((activity) => bot.transformers.reverse.activity(bot, activity)), + client_status: { + desktop: payload.desktop, + mobile: payload.mobile, + web: payload.web, + }, + } +} diff --git a/packages/bot/src/transformers/reverse/team.ts b/packages/bot/src/transformers/reverse/team.ts new file mode 100644 index 000000000..e9df4d565 --- /dev/null +++ b/packages/bot/src/transformers/reverse/team.ts @@ -0,0 +1,21 @@ +import type { DiscordTeam } from '@discordeno/types' +import { Bot, iconBigintToHash } from '../../index.js' +import type { Team } from '../team.js' + +export function transformTeamToDiscordTeam(bot: Bot, payload: Team): DiscordTeam { + const id = bot.utils.bigintToSnowflake(payload.id) + + return { + name: payload.name, + + id, + icon: payload.icon ? iconBigintToHash(payload.icon) : null, + owner_user_id: bot.utils.bigintToSnowflake(payload.ownerUserId), + members: payload.members.map((member) => ({ + membership_state: member.membershipState, + permissions: member.permissions, + team_id: id, + user: bot.transformers.reverse.user(bot, member.user), + })), + } +} diff --git a/packages/bot/src/transformers/reverse/widgetSettings.ts b/packages/bot/src/transformers/reverse/widgetSettings.ts new file mode 100644 index 000000000..b403dd8ae --- /dev/null +++ b/packages/bot/src/transformers/reverse/widgetSettings.ts @@ -0,0 +1,10 @@ +import type { DiscordGuildWidgetSettings } from '@discordeno/types' +import type { Bot } from '../../index.js' +import type { GuildWidgetSettings } from '../widgetSettings.js' + +export function transformWidgetSettingsToDiscordWidgetSettings(bot: Bot, payload: GuildWidgetSettings): DiscordGuildWidgetSettings { + return { + enabled: payload.enabled, + channel_id: payload.channelId ?? null, + } +} diff --git a/packages/bot/src/transformers/role.ts b/packages/bot/src/transformers/role.ts new file mode 100644 index 000000000..6d9136c33 --- /dev/null +++ b/packages/bot/src/transformers/role.ts @@ -0,0 +1,25 @@ +import type { DiscordRole } from '@discordeno/types' +import { Bot, iconHashToBigInt } from '../index.js' +import type { Optionalize } from '../optionalize.js' +import { RoleToggles } from './toggles/role.js' + +export function transformRole(bot: Bot, payload: { role: DiscordRole } & { guildId: bigint }) { + const role = { + name: payload.role.name, + guildId: payload.guildId, + position: payload.role.position, + color: payload.role.color, + toggles: new RoleToggles(payload.role), + + id: bot.transformers.snowflake(payload.role.id), + botId: payload.role.tags?.bot_id ? bot.transformers.snowflake(payload.role.tags.bot_id) : undefined, + integrationId: payload.role.tags?.integration_id ? bot.transformers.snowflake(payload.role.tags.integration_id) : undefined, + permissions: bot.transformers.snowflake(payload.role.permissions), + icon: payload.role.icon ? iconHashToBigInt(payload.role.icon) : undefined, + unicodeEmoji: payload.role.unicode_emoji, + } + + return role as Optionalize +} + +export interface Role extends ReturnType {} diff --git a/packages/bot/src/transformers/scheduledEvent.ts b/packages/bot/src/transformers/scheduledEvent.ts new file mode 100644 index 000000000..cdeeeee26 --- /dev/null +++ b/packages/bot/src/transformers/scheduledEvent.ts @@ -0,0 +1,29 @@ +import type { DiscordScheduledEvent } from '@discordeno/types' +import { Bot, iconHashToBigInt } from '../index.js' +import type { Optionalize } from '../optionalize.js' + +export function transformScheduledEvent(bot: Bot, payload: DiscordScheduledEvent) { + const scheduledEvent = { + id: bot.transformers.snowflake(payload.id), + guildId: bot.transformers.snowflake(payload.guild_id), + channelId: payload.channel_id ? bot.transformers.snowflake(payload.channel_id) : undefined, + creatorId: payload.creator_id ? bot.transformers.snowflake(payload.creator_id) : 0n, + scheduledStartTime: Date.parse(payload.scheduled_start_time), + scheduledEndTime: payload.scheduled_end_time ? Date.parse(payload.scheduled_end_time) : undefined, + entityId: payload.entity_id ? bot.transformers.snowflake(payload.entity_id) : undefined, + creator: payload.creator ? bot.transformers.user(bot, payload.creator) : undefined, + + name: payload.name, + description: payload.description, + privacyLevel: payload.privacy_level, + status: payload.status, + entityType: payload.entity_type, + userCount: payload.user_count || 0, + location: payload.entity_metadata?.location, + image: payload.image ? iconHashToBigInt(payload.image) : undefined, + } + + return scheduledEvent as Optionalize +} + +export interface ScheduledEvent extends ReturnType {} diff --git a/packages/bot/src/transformers/stageInstance.ts b/packages/bot/src/transformers/stageInstance.ts new file mode 100644 index 000000000..3ef9c4036 --- /dev/null +++ b/packages/bot/src/transformers/stageInstance.ts @@ -0,0 +1,17 @@ +import type { DiscordStageInstance } from '@discordeno/types' +import type { Bot } from '../index.js' +import type { Optionalize } from '../optionalize.js' + +export function transformStageInstance(bot: Bot, payload: DiscordStageInstance) { + const stageInstance = { + id: bot.transformers.snowflake(payload.id), + guildId: bot.transformers.snowflake(payload.guild_id), + channelId: bot.transformers.snowflake(payload.channel_id), + topic: payload.topic, + guildScheduledEventId: payload.guild_scheduled_event_id ? bot.transformers.snowflake(payload.guild_scheduled_event_id) : undefined, + } + + return stageInstance as Optionalize +} + +export interface StageInstance extends ReturnType {} diff --git a/packages/bot/src/transformers/sticker.ts b/packages/bot/src/transformers/sticker.ts new file mode 100644 index 000000000..0c2f144b3 --- /dev/null +++ b/packages/bot/src/transformers/sticker.ts @@ -0,0 +1,38 @@ +import type { DiscordSticker, DiscordStickerPack } from '@discordeno/types' +import type { Bot } from '../index.js' +import type { Optionalize } from '../optionalize.js' + +export function transformSticker(bot: Bot, payload: DiscordSticker) { + const sticker = { + id: bot.utils.snowflakeToBigint(payload.id), + packId: payload.pack_id ? bot.utils.snowflakeToBigint(payload.pack_id) : undefined, + name: payload.name, + description: payload.description, + tags: payload.tags, + type: payload.type, + formatType: payload.format_type, + available: payload.available, + guildId: payload.guild_id ? bot.utils.snowflakeToBigint(payload.guild_id) : undefined, + user: payload.user ? bot.transformers.user(bot, payload.user) : undefined, + sortValue: payload.sort_value, + } + + return sticker as Optionalize +} + +export function transformStickerPack(bot: Bot, payload: DiscordStickerPack) { + const pack = { + id: bot.transformers.snowflake(payload.id), + stickers: payload.stickers.map((sticker) => bot.transformers.sticker(bot, sticker)), + name: payload.name, + skuId: bot.transformers.snowflake(payload.sku_id), + coverStickerId: payload.cover_sticker_id ? bot.transformers.snowflake(payload.cover_sticker_id) : undefined, + description: payload.description, + bannerAssetId: payload.banner_asset_id ? bot.transformers.snowflake(payload.banner_asset_id) : undefined, + } + + return pack as Optionalize +} + +export interface Sticker extends ReturnType {} +export interface StickerPack extends ReturnType {} diff --git a/packages/bot/src/transformers/team.ts b/packages/bot/src/transformers/team.ts new file mode 100644 index 000000000..cc6d85f2a --- /dev/null +++ b/packages/bot/src/transformers/team.ts @@ -0,0 +1,25 @@ +import type { DiscordTeam } from '@discordeno/types' +import { Bot, iconHashToBigInt } from '../index.js' +import type { Optionalize } from '../optionalize.js' + +export function transformTeam(bot: Bot, payload: DiscordTeam) { + const id = bot.transformers.snowflake(payload.id) + + const team = { + name: payload.name, + + id, + icon: payload.icon ? iconHashToBigInt(payload.icon) : undefined, + ownerUserId: bot.transformers.snowflake(payload.owner_user_id), + members: payload.members.map((member) => ({ + membershipState: member.membership_state, + permissions: member.permissions, + teamId: id, + user: bot.transformers.user(bot, member.user), + })), + } + + return team as Optionalize +} + +export interface Team extends ReturnType {} diff --git a/packages/bot/src/transformers/template.ts b/packages/bot/src/transformers/template.ts new file mode 100644 index 000000000..3ed9883dc --- /dev/null +++ b/packages/bot/src/transformers/template.ts @@ -0,0 +1,23 @@ +import type { DiscordTemplate } from '@discordeno/types' +import type { Bot } from '../index.js' +import type { Optionalize } from '../optionalize.js' + +export function transformTemplate(bot: Bot, payload: DiscordTemplate) { + const template = { + code: payload.code, + name: payload.name, + description: payload.description, + usageCount: payload.usage_count, + creatorId: bot.transformers.snowflake(payload.creator_id), + creator: bot.transformers.user(bot, payload.creator), + createdAt: Date.parse(payload.created_at), + updatedAt: Date.parse(payload.updated_at), + sourceGuildId: bot.transformers.snowflake(payload.source_guild_id), + serializedSourceGuild: payload.serialized_source_guild, + isDirty: payload.is_dirty ?? undefined, + } + + return template as Optionalize +} + +export interface Template extends ReturnType {} diff --git a/packages/bot/src/transformers/threadMember.ts b/packages/bot/src/transformers/threadMember.ts new file mode 100644 index 000000000..b444c41f1 --- /dev/null +++ b/packages/bot/src/transformers/threadMember.ts @@ -0,0 +1,26 @@ +import type { DiscordThreadMember } from '@discordeno/types' +import type { Bot } from '../index.js' +import type { Optionalize } from '../optionalize.js' +import type { DiscordThreadMemberGuildCreate } from '../types.js' + +export function transformThreadMember(bot: Bot, payload: DiscordThreadMember) { + const threadMember = { + id: payload.id ? bot.transformers.snowflake(payload.id) : undefined, + userId: payload.user_id ? bot.transformers.snowflake(payload.user_id) : undefined, + joinTimestamp: Date.parse(payload.join_timestamp), + flags: payload.flags, + } + + return threadMember as Optionalize +} + +export function transformThreadMemberGuildCreate(bot: Bot, payload: DiscordThreadMemberGuildCreate) { + const threadMember = { + joinTimestamp: Date.parse(payload.join_timestamp), + } + + return threadMember as Optionalize +} + +export interface ThreadMember extends ReturnType {} +export interface ThreadMemberGuildCreate extends ReturnType {} diff --git a/packages/bot/src/transformers/toggles/ToggleBitfield.ts b/packages/bot/src/transformers/toggles/ToggleBitfield.ts new file mode 100644 index 000000000..8715c161b --- /dev/null +++ b/packages/bot/src/transformers/toggles/ToggleBitfield.ts @@ -0,0 +1,49 @@ +export class ToggleBitfield { + bitfield = 0; + + constructor(bitfield?: number) { + if (bitfield) this.bitfield = bitfield; + } + + /** Tests whether or not this bitfield has the permission requested. */ + contains(bits: number) { + return Boolean(this.bitfield & bits); + } + + /** Adds some bits to the bitfield. */ + add(bits: number) { + this.bitfield |= bits; + return this; + } + + /** Removes some bits from the bitfield. */ + remove(bits: number) { + this.bitfield &= ~bits; + return this; + } +} + +export class ToggleBitfieldBigint { + bitfield = 0n; + + constructor(bitfield?: bigint) { + if (bitfield) this.bitfield = bitfield; + } + + /** Tests whether or not this bitfield has the permission requested. */ + contains(bits: bigint) { + return Boolean(this.bitfield & bits); + } + + /** Adds some bits to the bitfield. */ + add(bits: bigint) { + this.bitfield |= bits; + return this; + } + + /** Removes some bits from the bitfield. */ + remove(bits: bigint) { + this.bitfield &= ~bits; + return this; + } +} diff --git a/packages/bot/src/transformers/toggles/emoji.ts b/packages/bot/src/transformers/toggles/emoji.ts new file mode 100644 index 000000000..d83171a09 --- /dev/null +++ b/packages/bot/src/transformers/toggles/emoji.ts @@ -0,0 +1,68 @@ +import type { DiscordEmoji } from '@discordeno/bot' +import { ToggleBitfield } from './ToggleBitfield.js' + +export const EmojiToggle = { + /** Whether this emoji must be wrapped in colons */ + requireColons: 1 << 0, + /** Whether this emoji is managed */ + managed: 1 << 1, + /** Whether this emoji is animated */ + animated: 1 << 2, + /** Whether this emoji can be used, may be false due to loss of Server Boosts */ + available: 1 << 3, +} + +export class EmojiToggles extends ToggleBitfield { + constructor(roleOrTogglesInt: DiscordEmoji | number) { + super() + + if (typeof roleOrTogglesInt === 'number') this.bitfield = roleOrTogglesInt + else { + const role = roleOrTogglesInt + + if (role.require_colons) this.add(EmojiToggle.requireColons) + if (role.managed) this.add(EmojiToggle.managed) + if (role.animated) this.add(EmojiToggle.animated) + if (role.available) this.add(EmojiToggle.available) + } + } + + /** Whether this emoji must be wrapped in colons */ + get requireColons() { + return this.has('requireColons') + } + + /** Whether this emoji is managed */ + get managed() { + return this.has('managed') + } + + /** Whether this emoji is animated */ + get animated() { + return this.has('animated') + } + + /** Whether this emoji can be used, may be false due to loss of Server Boosts */ + get available() { + return this.has('available') + } + + /** Checks whether or not the permissions exist in this */ + has(permissions: EmojiToggleKeys | EmojiToggleKeys[]) { + if (!Array.isArray(permissions)) return super.contains(EmojiToggle[permissions]) + + return super.contains(permissions.reduce((a, b) => (a |= EmojiToggle[b]), 0)) + } + + /** Lists all the toggles for the role and whether or not each is true or false. */ + list() { + const json: Record = {} + for (const [key, value] of Object.entries(EmojiToggle)) { + json[key] = super.contains(value) + } + + return json as Record + } +} + +export type EmojiToggleKeys = keyof typeof EmojiToggle diff --git a/packages/bot/src/transformers/toggles/guild.ts b/packages/bot/src/transformers/toggles/guild.ts new file mode 100644 index 000000000..d1e80098f --- /dev/null +++ b/packages/bot/src/transformers/toggles/guild.ts @@ -0,0 +1,287 @@ +import { DiscordGuild, GuildFeatures } from '@discordeno/bot' +import { ToggleBitfieldBigint } from './ToggleBitfield.js' + +const featureNames = [ + 'inviteSplash', + 'vipRegions', + 'vanityUrl', + 'verified', + 'partnered', + 'community', + 'developerSupportServer', + 'news', + 'discoverable', + 'featurable', + 'animatedIcon', + 'banner', + 'welcomeScreenEnabled', + 'memberVerificationGateEnabled', + 'previewEnabled', + 'ticketedEventsEnabled', + 'monetizationEnabled', + 'moreStickers', + 'privateThreads', + 'roleIcons', + 'autoModeration', + 'invitesDisabled', + 'animatedBanner', +] + +export const GuildToggle = { + /** Whether the bot is the owner of the guild */ + owner: 1n << 0n, + /** Whether the server widget is enabled */ + widgetEnabled: 1n << 1n, + /** Whether this is considered a large guild */ + large: 1n << 2n, + /** Whether this guild is unavailable due to an outage */ + unavailable: 1n << 3n, + /** Whether the guild has the boost progress bar enabled */ + premiumProgressBarEnabled: 1n << 4n, + + // GUILD FEATURES ARE BELOW THIS + + /** Whether the guild has access to set an invite splash background */ + inviteSplash: 1n << 5n, + /** Whether the guild has access to set 384 kbps bitrate in voice (previously VIP voice servers) */ + vipRegions: 1n << 6n, + /** Whether the guild has access to set a vanity URL */ + vanityUrl: 1n << 7n, + /** Whether the guild is verified */ + verified: 1n << 8n, + /** Whether the guild is partnered */ + partnered: 1n << 9n, + /** Whether the guild can enable welcome screen, Membership Screening, stage channels and discovery, and receives community updates */ + community: 1n << 10n, + /** Whether the guild has access to set an animated guild banner image */ + animatedBanner: 1n << 11n, + /** Whether the guild has access to create news channels */ + news: 1n << 12n, + /** Whether the guild is able to be discovered in the directory */ + discoverable: 1n << 13n, + /** Whether the guild is able to be featured in the directory */ + featurable: 1n << 15n, + /** Whether the guild has access to set an animated guild icon */ + animatedIcon: 1n << 16n, + /** Whether the guild has access to set a guild banner image */ + banner: 1n << 17n, + /** Whether the guild has enabled the welcome screen */ + welcomeScreenEnabled: 1n << 18n, + /** Whether the guild has enabled [Membership Screening](https://discord.com/developers/docs/resources/guild#membership-screening-object) */ + memberVerificationGateEnabled: 1n << 19n, + /** Whether the guild can be previewed before joining via Membership Screening or the directory */ + previewEnabled: 1n << 20n, + /** Whether the guild has enabled ticketed events */ + ticketedEventsEnabled: 1n << 21n, + /** Whether the guild has enabled monetization */ + monetizationEnabled: 1n << 22n, + /** Whether the guild has increased custom sticker slots */ + moreStickers: 1n << 23n, + /** Whether the guild has access to create private threads */ + privateThreads: 1n << 26n, + /** Whether the guild is able to set role icons */ + roleIcons: 1n << 27n, + /** Whether the guild has set up auto moderation rules */ + autoModeration: 1n << 28n, + /** Whether the guild has paused invites, preventing new users from joining */ + invitesDisabled: 1n << 29n, + /** Whether the guild has been set as a support server on the App Directory */ + developerSupportServer: 1n << 30n, +} + +export class GuildToggles extends ToggleBitfieldBigint { + constructor(guildOrTogglesBigint: DiscordGuild | bigint) { + super() + + if (typeof guildOrTogglesBigint == 'bigint') this.bitfield = guildOrTogglesBigint + else { + const guild = guildOrTogglesBigint + // Cause discord be smart like that + if (!guild.features) guild.features = [] + + if (guild.owner) this.add(GuildToggle.owner) + if (guild.widget_enabled) this.add(GuildToggle.widgetEnabled) + if (guild.large) this.add(GuildToggle.large) + if (guild.unavailable) this.add(GuildToggle.unavailable) + if (guild.premium_progress_bar_enabled) this.add(GuildToggle.premiumProgressBarEnabled) + + if (guild.features.includes(GuildFeatures.InviteSplash)) this.add(GuildToggle.inviteSplash) + if (guild.features.includes(GuildFeatures.VipRegions)) this.add(GuildToggle.vipRegions) + if (guild.features.includes(GuildFeatures.VanityUrl)) this.add(GuildToggle.vanityUrl) + if (guild.features.includes(GuildFeatures.Verified)) this.add(GuildToggle.verified) + if (guild.features.includes(GuildFeatures.Partnered)) this.add(GuildToggle.partnered) + if (guild.features.includes(GuildFeatures.Community)) this.add(GuildToggle.community) + if (guild.features.includes(GuildFeatures.DeveloperSupportServer)) this.add(GuildToggle.developerSupportServer) + if (guild.features.includes(GuildFeatures.AnimatedBanner)) this.add(GuildToggle.animatedBanner) + if (guild.features.includes(GuildFeatures.News)) this.add(GuildToggle.news) + if (guild.features.includes(GuildFeatures.Discoverable)) this.add(GuildToggle.discoverable) + if (guild.features.includes(GuildFeatures.Featurable)) this.add(GuildToggle.featurable) + if (guild.features.includes(GuildFeatures.AnimatedIcon)) this.add(GuildToggle.animatedIcon) + if (guild.features.includes(GuildFeatures.Banner)) this.add(GuildToggle.banner) + if (guild.features.includes(GuildFeatures.WelcomeScreenEnabled)) this.add(GuildToggle.welcomeScreenEnabled) + if (guild.features.includes(GuildFeatures.MemberVerificationGateEnabled)) { + this.add(GuildToggle.memberVerificationGateEnabled) + } + if (guild.features.includes(GuildFeatures.PreviewEnabled)) this.add(GuildToggle.previewEnabled) + if (guild.features.includes(GuildFeatures.TicketedEventsEnabled)) this.add(GuildToggle.ticketedEventsEnabled) + if (guild.features.includes(GuildFeatures.MonetizationEnabled)) this.add(GuildToggle.monetizationEnabled) + if (guild.features.includes(GuildFeatures.MoreStickers)) this.add(GuildToggle.moreStickers) + if (guild.features.includes(GuildFeatures.PrivateThreads)) this.add(GuildToggle.privateThreads) + if (guild.features.includes(GuildFeatures.RoleIcons)) this.add(GuildToggle.roleIcons) + if (guild.features.includes(GuildFeatures.AutoModeration)) this.add(GuildToggle.autoModeration) + if (guild.features.includes(GuildFeatures.InvitesDisabled)) this.add(GuildToggle.invitesDisabled) + } + } + + get features() { + const features: GuildToggleKeys[] = [] + for (const key of Object.keys(GuildToggle)) { + if (!featureNames.includes(key)) continue + if (!super.contains(GuildToggle[key as GuildToggleKeys])) continue + + features.push(key as GuildToggleKeys) + } + + return features + } + + /** Whether the bot is the owner of the guild */ + get owner() { + return this.has('owner') + } + + /** Whether the server widget is enabled */ + get widgetEnabled() { + return this.has('widgetEnabled') + } + + /** Whether this is considered a large guild */ + get large() { + return this.has('large') + } + + /** Whether this guild is unavailable due to an outage */ + get unavailable() { + return this.has('unavailable') + } + + /** Whether the guild has the boost progress bar enabled */ + get premiumProgressBarEnabled() { + return this.has('premiumProgressBarEnabled') + } + + /** Whether the guild has access to set an invite splash background */ + get inviteSplash() { + return this.has('inviteSplash') + } + /** Whether the guild has access to set 384 kbps bitrate in voice (previously VIP voice servers) */ + get vipRegions() { + return this.has('vipRegions') + } + /** Whether the guild has access to set a vanity URL */ + get vanityUrl() { + return this.has('vanityUrl') + } + /** Whether the guild is verified */ + get verified() { + return this.has('verified') + } + /** Whether the guild is partnered */ + get partnered() { + return this.has('partnered') + } + /** Whether the guild can enable welcome screen, Membership Screening, stage channels and discovery, and receives community updates */ + get community() { + return this.has('community') + } + /** Whether the Guild has been set as a support server on the App Directory */ + get developerSupportServer() { + return this.has('developerSupportServer') + } + /** Whether the guild has access to set an animated guild banner image */ + get animatedBanner() { + return this.has('animatedBanner') + } + /** Whether the guild has access to create news channels */ + get news() { + return this.has('news') + } + /** Whether the guild is able to be discovered in the directory */ + get discoverable() { + return this.has('discoverable') + } + /** Whether the guild is able to be featured in the directory */ + get featurable() { + return this.has('featurable') + } + /** Whether the guild has access to set an animated guild icon */ + get animatedIcon() { + return this.has('animatedIcon') + } + /** Whether the guild has access to set a guild banner image */ + get banner() { + return this.has('banner') + } + /** Whether the guild has enabled the welcome screen */ + get welcomeScreenEnabled() { + return this.has('welcomeScreenEnabled') + } + /** Whether the guild has enabled [Membership Screening](https://discord.com/developers/docs/resources/guild#membership-screening-object) */ + get memberVerificationGateEnabled() { + return this.has('memberVerificationGateEnabled') + } + /** Whether the guild can be previewed before joining via Membership Screening or the directory */ + get previewEnabled() { + return this.has('previewEnabled') + } + /** Whether the guild has enabled ticketed events */ + get ticketedEventsEnabled() { + return this.has('ticketedEventsEnabled') + } + /** Whether the guild has enabled monetization */ + get monetizationEnabled() { + return this.has('monetizationEnabled') + } + /** Whether the guild has increased custom sticker slots */ + get moreStickers() { + return this.has('moreStickers') + } + + /** Whether the guild has access to create private threads */ + get privateThreads() { + return this.has('privateThreads') + } + /** Whether the guild is able to set role icons */ + get roleIcons() { + return this.has('roleIcons') + } + + /** Whether the guild has set up auto moderation rules */ + get autoModeration() { + return this.has('autoModeration') + } + + /** Whether the guild has paused invites, preventing new users from joining */ + get invitesDisabled() { + return this.has('invitesDisabled') + } + + /** Checks whether or not the permissions exist in this */ + has(permissions: GuildToggleKeys | GuildToggleKeys[]) { + if (!Array.isArray(permissions)) return super.contains(GuildToggle[permissions]) + + return super.contains(permissions.reduce((a, b) => (a |= GuildToggle[b]), 0n)) + } + + /** Lists all the toggles for the role and whether or not each is true or false. */ + list() { + const json: Record = {} + for (const [key, value] of Object.entries(GuildToggle)) { + json[key] = super.contains(value) + } + + return json as Record + } +} + +export type GuildToggleKeys = keyof typeof GuildToggle diff --git a/packages/bot/src/transformers/toggles/index.ts b/packages/bot/src/transformers/toggles/index.ts new file mode 100644 index 000000000..48c016dab --- /dev/null +++ b/packages/bot/src/transformers/toggles/index.ts @@ -0,0 +1,7 @@ +export * from "./emoji.js"; +export * from "./guild.js"; +export * from "./member.js"; +export * from "./role.js"; +export * from "./ToggleBitfield.js"; +export * from "./user.js"; +export * from "./voice.js"; diff --git a/packages/bot/src/transformers/toggles/member.ts b/packages/bot/src/transformers/toggles/member.ts new file mode 100644 index 000000000..5137e1401 --- /dev/null +++ b/packages/bot/src/transformers/toggles/member.ts @@ -0,0 +1,60 @@ +import type { DiscordMember } from '@discordeno/bot' +import { ToggleBitfield } from './ToggleBitfield.js' + +export const MemberToggle = { + /** Whether the user is deafened in voice channels */ + deaf: 1 << 0, + /** Whether the user is muted in voice channels */ + mute: 1 << 1, + /** Whether the user has not yet passed the guild's Membership Screening requirements */ + pending: 1 << 2, +} + +export class MemberToggles extends ToggleBitfield { + constructor(memberOrTogglesInt: Partial | number) { + super() + + if (typeof memberOrTogglesInt === 'number') this.bitfield = memberOrTogglesInt + else { + const member = memberOrTogglesInt + + if (member.deaf) this.add(MemberToggle.deaf) + if (member.mute) this.add(MemberToggle.mute) + if (member.pending) this.add(MemberToggle.pending) + } + } + + /** Whether the user belongs to an OAuth2 application */ + get deaf() { + return this.has('deaf') + } + + /** Whether the user is muted in voice channels */ + get mute() { + return this.has('mute') + } + + /** Whether the user has not yet passed the guild's Membership Screening requirements */ + get pending() { + return this.has('pending') + } + + /** Checks whether or not the permissions exist in this */ + has(permissions: MemberToggleKeys | MemberToggleKeys[]) { + if (!Array.isArray(permissions)) return super.contains(MemberToggle[permissions]) + + return super.contains(permissions.reduce((a, b) => (a |= MemberToggle[b]), 0)) + } + + /** Lists all the toggles for the role and whether or not each is true or false. */ + list() { + const json: Record = {} + for (const [key, value] of Object.entries(MemberToggle)) { + json[key] = super.contains(value) + } + + return json as Record + } +} + +export type MemberToggleKeys = keyof typeof MemberToggle diff --git a/packages/bot/src/transformers/toggles/role.ts b/packages/bot/src/transformers/toggles/role.ts new file mode 100644 index 000000000..d68083521 --- /dev/null +++ b/packages/bot/src/transformers/toggles/role.ts @@ -0,0 +1,68 @@ +import type { DiscordRole } from '@discordeno/bot' +import { ToggleBitfield } from './ToggleBitfield.js' + +export const RoleToggle = { + /** If this role is showed separately in the user listing */ + hoist: 1 << 0, + /** Whether this role is managed by an integration */ + managed: 1 << 1, + /** Whether this role is mentionable */ + mentionable: 1 << 2, + /** Whether this is the guilds premium subscriber role */ + premiumSubscriber: 1 << 3, +} + +export class RoleToggles extends ToggleBitfield { + constructor(roleOrTogglesInt: DiscordRole | number) { + super() + + if (typeof roleOrTogglesInt === 'number') this.bitfield = roleOrTogglesInt + else { + const role = roleOrTogglesInt + + if (role.hoist) this.add(RoleToggle.hoist) + if (role.managed) this.add(RoleToggle.managed) + if (role.mentionable) this.add(RoleToggle.mentionable) + if (role.tags?.premium_subscriber === null) this.add(RoleToggle.premiumSubscriber) + } + } + + /** If this role is showed separately in the user listing */ + get hoist() { + return this.has('hoist') + } + + /** Whether this role is managed by an integration */ + get managed() { + return this.has('managed') + } + + /** Whether this role is mentionable */ + get mentionable() { + return this.has('mentionable') + } + + /** Whether this is the guilds premium subscriber role */ + get premiumSubscriber() { + return this.has('premiumSubscriber') + } + + /** Checks whether or not the permissions exist in this */ + has(permissions: RoleToggleKeys | RoleToggleKeys[]) { + if (!Array.isArray(permissions)) return super.contains(RoleToggle[permissions]) + + return super.contains(permissions.reduce((a, b) => (a |= RoleToggle[b]), 0)) + } + + /** Lists all the toggles for the role and whether or not each is true or false. */ + list() { + const json: Record = {} + for (const [key, value] of Object.entries(RoleToggle)) { + json[key] = super.contains(value) + } + + return json as Record + } +} + +export type RoleToggleKeys = keyof typeof RoleToggle diff --git a/packages/bot/src/transformers/toggles/user.ts b/packages/bot/src/transformers/toggles/user.ts new file mode 100644 index 000000000..ebe5df6c2 --- /dev/null +++ b/packages/bot/src/transformers/toggles/user.ts @@ -0,0 +1,68 @@ +import type { DiscordUser } from '@discordeno/bot' +import { ToggleBitfield } from './ToggleBitfield.js' + +export const UserToggle = { + /** Whether the user belongs to an OAuth2 application */ + bot: 1 << 0, + /** Whether the user is an Official Discord System user (part of the urgent message system) */ + system: 1 << 1, + /** Whether the user has two factor enabled on their account */ + mfaEnabled: 1 << 2, + /** Whether the email on this account has been verified */ + verified: 1 << 3, +} + +export class UserToggles extends ToggleBitfield { + constructor(userOrTogglesInt: DiscordUser | number) { + super() + + if (typeof userOrTogglesInt === 'number') this.bitfield = userOrTogglesInt + else { + const user = userOrTogglesInt + + if (user.bot) this.add(UserToggle.bot) + if (user.system) this.add(UserToggle.system) + if (user.mfa_enabled) this.add(UserToggle.mfaEnabled) + if (user.verified) this.add(UserToggle.verified) + } + } + + /** Whether the user belongs to an OAuth2 application */ + get bot() { + return this.has('bot') + } + + /** Whether the user is an Official Discord System user (part of the urgent message system) */ + get system() { + return this.has('system') + } + + /** Whether the user has two factor enabled on their account */ + get mfaEnabled() { + return this.has('mfaEnabled') + } + + /** Whether the email on this account has been verified */ + get verified() { + return this.has('verified') + } + + /** Checks whether or not the permissions exist in this */ + has(permissions: UserToggleKeys | UserToggleKeys[]) { + if (!Array.isArray(permissions)) return super.contains(UserToggle[permissions]) + + return super.contains(permissions.reduce((a, b) => (a |= UserToggle[b]), 0)) + } + + /** Lists all the toggles for the role and whether or not each is true or false. */ + list() { + const json: Record = {} + for (const [key, value] of Object.entries(UserToggle)) { + json[key] = super.contains(value) + } + + return json as Record + } +} + +export type UserToggleKeys = keyof typeof UserToggle diff --git a/packages/bot/src/transformers/toggles/voice.ts b/packages/bot/src/transformers/toggles/voice.ts new file mode 100644 index 000000000..c34223bcb --- /dev/null +++ b/packages/bot/src/transformers/toggles/voice.ts @@ -0,0 +1,92 @@ +import type { DiscordVoiceState } from '@discordeno/bot' +import { ToggleBitfield } from './ToggleBitfield.js' + +export const VoiceStateToggle = { + /** Whether this user is deafened by the server */ + deaf: 1 << 0, + /** Whether this user is muted by the server */ + mute: 1 << 1, + /** Whether this user is locally deafened */ + selfDeaf: 1 << 2, + /** Whether this user is locally muted */ + selfMute: 1 << 3, + /** Whether this user is streaming using "Go Live" */ + selfStream: 1 << 4, + /** Whether this user's camera is enabled */ + selfVideo: 1 << 5, + /** Whether this user is muted by the current user */ + suppress: 1 << 6, +} + +export class VoiceStateToggles extends ToggleBitfield { + constructor(voiceOrTogglesInt: DiscordVoiceState | number) { + super() + + if (typeof voiceOrTogglesInt === 'number') this.bitfield = voiceOrTogglesInt + else { + const voice = voiceOrTogglesInt + + if (voice.deaf) this.add(VoiceStateToggle.deaf) + if (voice.mute) this.add(VoiceStateToggle.mute) + if (voice.self_deaf) this.add(VoiceStateToggle.selfDeaf) + if (voice.self_mute) this.add(VoiceStateToggle.selfMute) + if (voice.self_stream) this.add(VoiceStateToggle.selfStream) + if (voice.self_video) this.add(VoiceStateToggle.selfVideo) + if (voice.suppress) this.add(VoiceStateToggle.suppress) + } + } + + /** Whether this user is deafened by the server */ + get deaf() { + return this.has('deaf') + } + + /** Whether this user is muted by the server */ + get mute() { + return this.has('mute') + } + + /** Whether this user is locally deafened */ + get selfDeaf() { + return this.has('selfDeaf') + } + + /** Whether this user is locally muted */ + get selfMute() { + return this.has('selfMute') + } + + /** Whether this user is streaming using "Go Live" */ + get selfStream() { + return this.has('selfStream') + } + + /** Whether this user's camera is enabled */ + get selfVideo() { + return this.has('selfVideo') + } + + /** Whether this user is muted by the current user */ + get suppress() { + return this.has('suppress') + } + + /** Checks whether or not the permissions exist in this */ + has(permissions: VoiceStateToggleKeys | VoiceStateToggleKeys[]) { + if (!Array.isArray(permissions)) return super.contains(VoiceStateToggle[permissions]) + + return super.contains(permissions.reduce((a, b) => (a |= VoiceStateToggle[b]), 0)) + } + + /** Lists all the toggles for the role and whether or not each is true or false. */ + list() { + const json: Record = {} + for (const [key, value] of Object.entries(VoiceStateToggle)) { + json[key] = super.contains(value) + } + + return json as Record + } +} + +export type VoiceStateToggleKeys = keyof typeof VoiceStateToggle diff --git a/packages/bot/src/transformers/voiceRegion.ts b/packages/bot/src/transformers/voiceRegion.ts new file mode 100644 index 000000000..461ff7954 --- /dev/null +++ b/packages/bot/src/transformers/voiceRegion.ts @@ -0,0 +1,19 @@ +import type { DiscordVoiceRegion } from '@discordeno/types' +import type { Bot } from '../index.js' +import type { Optionalize } from '../optionalize.js' + +// TODO: Rename `VoiceRegions` to `VoiceRegion`. + +export function transformVoiceRegion(bot: Bot, payload: DiscordVoiceRegion) { + const voiceRegion = { + id: payload.id, + name: payload.name, + optimal: payload.optimal, + deprecated: payload.deprecated, + custom: payload.custom, + } + + return voiceRegion as Optionalize +} + +export interface VoiceRegions extends ReturnType {} diff --git a/packages/bot/src/transformers/voiceState.ts b/packages/bot/src/transformers/voiceState.ts new file mode 100644 index 000000000..0b9bc42d7 --- /dev/null +++ b/packages/bot/src/transformers/voiceState.ts @@ -0,0 +1,21 @@ +import type { DiscordVoiceState } from '@discordeno/types' +import type { Bot } from '../index.js' +import type { Optionalize } from '../optionalize.js' +import { VoiceStateToggles } from './toggles/voice.js' + +export function transformVoiceState(bot: Bot, payload: { voiceState: DiscordVoiceState } & { guildId: bigint }) { + const voiceState = { + toggles: new VoiceStateToggles(payload.voiceState), + + requestToSpeakTimestamp: payload.voiceState.request_to_speak_timestamp ? Date.parse(payload.voiceState.request_to_speak_timestamp) : undefined, + sessionId: payload.voiceState.session_id, + + channelId: payload.voiceState.channel_id ? bot.transformers.snowflake(payload.voiceState.channel_id) : undefined, + guildId: payload.guildId || (payload.voiceState.guild_id ? bot.transformers.snowflake(payload.voiceState.guild_id) : 0n), + userId: payload.voiceState.user_id ? bot.transformers.snowflake(payload.voiceState.user_id) : 0n, + } + + return voiceState as Optionalize +} + +export interface VoiceState extends ReturnType {} diff --git a/packages/bot/src/transformers/webhook.ts b/packages/bot/src/transformers/webhook.ts new file mode 100644 index 000000000..45a5cb297 --- /dev/null +++ b/packages/bot/src/transformers/webhook.ts @@ -0,0 +1,37 @@ +import type { DiscordWebhook } from '@discordeno/types' +import { Bot, iconHashToBigInt } from '../index.js' +import type { Optionalize } from '../optionalize.js' + +export function transformWebhook(bot: Bot, payload: DiscordWebhook) { + const webhook = { + id: bot.transformers.snowflake(payload.id), + type: payload.type, + guildId: payload.guild_id ? bot.transformers.snowflake(payload.guild_id) : undefined, + channelId: payload.channel_id ? bot.transformers.snowflake(payload.channel_id) : undefined, + user: payload.user ? bot.transformers.user(bot, payload.user) : undefined, + name: payload.name || '', + avatar: payload.avatar ? iconHashToBigInt(payload.avatar) : undefined, + token: payload.token, + applicationId: payload.application_id ? bot.transformers.snowflake(payload.application_id) : undefined, + sourceGuild: payload.source_guild + ? { + id: bot.transformers.snowflake(payload.source_guild.id!), + name: payload.source_guild.name!, + icon: payload.source_guild.icon ? iconHashToBigInt(payload.source_guild.icon) : undefined, + } + : undefined, + /** The channel that this webhook is following (returned for Channel Follower Webhooks) */ + sourceChannel: payload.source_channel + ? { + id: bot.transformers.snowflake(payload.source_channel.id!), + name: payload.source_channel.name || '', + } + : undefined, + /** The url used for executing the webhook (returned by the webhooks OAuth2 flow) */ + url: payload.url, + } + + return webhook as Optionalize +} + +export interface Webhook extends ReturnType {} diff --git a/packages/bot/src/transformers/welcomeScreen.ts b/packages/bot/src/transformers/welcomeScreen.ts new file mode 100644 index 000000000..2852be551 --- /dev/null +++ b/packages/bot/src/transformers/welcomeScreen.ts @@ -0,0 +1,19 @@ +import type { DiscordWelcomeScreen } from '@discordeno/types' +import type { Bot } from '../index.js' +import type { Optionalize } from '../optionalize.js' + +export function transformWelcomeScreen(bot: Bot, payload: DiscordWelcomeScreen) { + const welcomeScreen = { + description: payload.description ?? undefined, + welcomeChannels: payload.welcome_channels.map((channel) => ({ + channelId: bot.transformers.snowflake(channel.channel_id), + description: channel.description, + emojiId: channel.emoji_id ? bot.transformers.snowflake(channel.emoji_id) : undefined, + emojiName: channel.emoji_name ?? undefined, + })), + } + + return welcomeScreen as Optionalize +} + +export interface WelcomeScreen extends ReturnType {} diff --git a/packages/bot/src/transformers/widget.ts b/packages/bot/src/transformers/widget.ts new file mode 100644 index 000000000..c54a30599 --- /dev/null +++ b/packages/bot/src/transformers/widget.ts @@ -0,0 +1,30 @@ +import { iconHashToBigInt } from '@discordeno/bot' +import type { DiscordGuildWidget } from '@discordeno/types' +import type { Bot } from '../index.js' +import type { Optionalize } from '../optionalize.js' + +export function transformWidget(bot: Bot, payload: DiscordGuildWidget) { + const widget = { + id: bot.transformers.snowflake(payload.id), + name: payload.name, + instant_invite: payload.instant_invite, + channels: payload.channels.map((channel) => ({ + id: bot.transformers.snowflake(channel.id), + name: channel.name, + position: channel.position, + })), + members: payload.members.map((member) => ({ + id: bot.transformers.snowflake(member.id), + username: member.username, + discriminator: member.discriminator, + avatar: member.avatar ? iconHashToBigInt(member.avatar) : undefined, + status: member.status, + avatarUrl: member.avatar_url, + })), + presenceCount: payload.presence_count, + } + + return widget as Optionalize +} + +export interface GuildWidget extends ReturnType {} diff --git a/packages/bot/src/transformers/widgetSettings.ts b/packages/bot/src/transformers/widgetSettings.ts new file mode 100644 index 000000000..28568be6a --- /dev/null +++ b/packages/bot/src/transformers/widgetSettings.ts @@ -0,0 +1,14 @@ +import type { DiscordGuildWidgetSettings } from '@discordeno/types' +import type { Bot } from '../index.js' +import type { Optionalize } from '../optionalize.js' + +export function transformWidgetSettings(bot: Bot, payload: DiscordGuildWidgetSettings) { + const widget = { + enabled: payload.enabled, + channelId: payload.channel_id ?? undefined, + } + + return widget as Optionalize +} + +export interface GuildWidgetSettings extends ReturnType {} diff --git a/packages/bot/src/types.ts b/packages/bot/src/types.ts new file mode 100644 index 000000000..0e784d462 --- /dev/null +++ b/packages/bot/src/types.ts @@ -0,0 +1,202 @@ +import { + AllowedMentions, + ApplicationCommandOptionChoice, + ApplicationCommandTypes, + ButtonStyles, + CreateApplicationCommand, + CreateContextApplicationCommand, + DiscordAllowedMentions, + DiscordApplicationCommandOptionChoice, + DiscordAttachment, + DiscordChannel, + DiscordEmbed, + DiscordInteractionMember, + DiscordMessage, + DiscordRole, + DiscordSelectOption, + DiscordUser, + FileContent, + InteractionResponseTypes, + MessageComponents, + MessageComponentTypes, + TextStyles, +} from '@discordeno/types' +import type * as handlers from './handlers/mod.js' +import type { Embed } from './transformers/embed' + +export function isContextApplicationCommand(command: CreateApplicationCommand): command is CreateContextApplicationCommand { + return command.type === ApplicationCommandTypes.Message || command.type === ApplicationCommandTypes.User +} + +export interface DiscordInteractionResponse { + type: InteractionResponseTypes + data?: DiscordInteractionCallbackData +} + +export interface DiscordInteractionCallbackData { + tts?: boolean + title?: string + flags?: number + content?: string + choices?: DiscordApplicationCommandOptionChoice[] + custom_id?: string + embeds?: DiscordEmbed[] + allowed_mentions?: DiscordAllowedMentions + components?: DiscordComponent[] +} + +export interface DiscordComponent { + /** component type */ + type: MessageComponentTypes + /** a developer-defined identifier for the component, max 100 characters */ + custom_id?: string + /** whether the component is disabled, default false */ + disabled?: boolean + /** For different styles/colors of the buttons */ + style?: ButtonStyles | TextStyles + /** text that appears on the button (max 80 characters) */ + label?: string + /** the dev-define value of the option, max 100 characters for select or 4000 for input. */ + value?: string + /** Emoji object that includes fields of name, id, and animated supporting unicode and custom emojis. */ + emoji?: { + /** Emoji id */ + id?: string + /** Emoji name */ + name?: string + /** Whether this emoji is animated */ + animated?: boolean + } + /** optional url for link-style buttons that can navigate a user to the web. Only type 5 Link buttons can have a url */ + url?: string + /** The choices! Maximum of 25 items. */ + options?: DiscordSelectOption[] + /** A custom placeholder text if nothing is selected. Maximum 150 characters. */ + placeholder?: string + /** The minimum number of items that must be selected. Default 1. Between 1-25. */ + min_values?: number + /** The maximum number of items that can be selected. Default 1. Between 1-25. */ + max_values?: number + /** The minimum input length for a text input. Between 0-4000. */ + min_length?: number + /**The maximum input length for a text input. Between 1-4000. */ + max_length?: number + /** a list of child components */ + components?: DiscordComponent[] + /** whether this component is required to be filled, default true */ + required?: boolean +} + +/** https://discord.com/developers/docs/interactions/slash-commands#interaction-response */ +export interface BotInteractionResponse { + /** The type of response */ + type: InteractionResponseTypes + /** An optional response message */ + data?: BotInteractionCallbackData +} + +export interface BotInteractionCallbackData { + /** The message contents (up to 2000 characters) */ + content?: string + /** True if this is a TTS message */ + tts?: boolean + /** Embedded `rich` content (up to 6000 characters) */ + embeds?: Array + /** Allowed mentions for the message */ + allowedMentions?: AllowedMentions + /** The contents of the file being sent */ + file?: FileContent | FileContent[] + /** The customId you want to use for this modal response. */ + customId?: string + /** The title you want to use for this modal response. */ + title?: string + /** The components you would like to have sent in this message */ + components?: MessageComponents + /** Message flags combined as a bit field (only SUPPRESS_EMBEDS and EPHEMERAL can be set) */ + flags?: number + /** Autocomplete choices (max of 25 choices) */ + choices?: ApplicationCommandOptionChoice[] +} + +export interface DiscordInteractionResponse { + type: InteractionResponseTypes + data?: DiscordInteractionCallbackData +} + +export interface DiscordInteractionDataResolved { + /** The Ids and Message objects */ + messages?: Record + /** The Ids and User objects */ + users?: Record + /** The Ids and partial Member objects */ + members?: Record> + /** The Ids and Role objects */ + roles?: Record + /** The Ids and partial Channel objects */ + channels?: Record> + /** The Ids and attachments objects */ + attachments?: Record +} + +export interface DiscordThreadMemberGuildCreate { + /** Any user-thread settings, currently only used for notifications */ + flags: number + /** The time the current user last joined the thread */ + join_timestamp: string +} + +export interface BotGatewayHandlerOptions { + READY: typeof handlers.handleReady + CHANNEL_CREATE: typeof handlers.handleChannelCreate + CHANNEL_DELETE: typeof handlers.handleChannelDelete + CHANNEL_PINS_UPDATE: typeof handlers.handleChannelPinsUpdate + CHANNEL_UPDATE: typeof handlers.handleChannelUpdate + THREAD_CREATE: typeof handlers.handleThreadCreate + THREAD_UPDATE: typeof handlers.handleThreadUpdate + THREAD_DELETE: typeof handlers.handleThreadDelete + THREAD_LIST_SYNC: typeof handlers.handleThreadListSync + THREAD_MEMBERS_UPDATE: typeof handlers.handleThreadMembersUpdate + STAGE_INSTANCE_CREATE: typeof handlers.handleStageInstanceCreate + STAGE_INSTANCE_UPDATE: typeof handlers.handleStageInstanceUpdate + STAGE_INSTANCE_DELETE: typeof handlers.handleStageInstanceDelete + GUILD_AUDIT_LOG_ENTRY_CREATE: typeof handlers.handleGuildAuditLogEntryCreate + GUILD_BAN_ADD: typeof handlers.handleGuildBanAdd + GUILD_BAN_REMOVE: typeof handlers.handleGuildBanRemove + GUILD_CREATE: typeof handlers.handleGuildCreate + GUILD_DELETE: typeof handlers.handleGuildDelete + GUILD_EMOJIS_UPDATE: typeof handlers.handleGuildEmojisUpdate + GUILD_INTEGRATIONS_UPDATE: typeof handlers.handleGuildIntegrationsUpdate + GUILD_MEMBER_ADD: typeof handlers.handleGuildMemberAdd + GUILD_MEMBER_REMOVE: typeof handlers.handleGuildMemberRemove + GUILD_MEMBER_UPDATE: typeof handlers.handleGuildMemberUpdate + GUILD_MEMBERS_CHUNK: typeof handlers.handleGuildMembersChunk + GUILD_ROLE_CREATE: typeof handlers.handleGuildRoleCreate + GUILD_ROLE_DELETE: typeof handlers.handleGuildRoleDelete + GUILD_ROLE_UPDATE: typeof handlers.handleGuildRoleUpdate + GUILD_SCHEDULED_EVENT_CREATE: typeof handlers.handleGuildScheduledEventCreate + GUILD_SCHEDULED_EVENT_DELETE: typeof handlers.handleGuildScheduledEventDelete + GUILD_SCHEDULED_EVENT_UPDATE: typeof handlers.handleGuildScheduledEventUpdate + GUILD_SCHEDULED_EVENT_USER_ADD: typeof handlers.handleGuildScheduledEventUserAdd + GUILD_SCHEDULED_EVENT_USER_REMOVE: typeof handlers.handleGuildScheduledEventUserRemove + GUILD_UPDATE: typeof handlers.handleGuildUpdate + INTERACTION_CREATE: typeof handlers.handleInteractionCreate + INVITE_CREATE: typeof handlers.handleInviteCreate + INVITE_DELETE: typeof handlers.handleInviteCreate + MESSAGE_CREATE: typeof handlers.handleMessageCreate + MESSAGE_DELETE_BULK: typeof handlers.handleMessageDeleteBulk + MESSAGE_DELETE: typeof handlers.handleMessageDelete + MESSAGE_REACTION_ADD: typeof handlers.handleMessageReactionAdd + MESSAGE_REACTION_REMOVE_ALL: typeof handlers.handleMessageReactionRemoveAll + MESSAGE_REACTION_REMOVE_EMOJI: typeof handlers.handleMessageReactionRemoveEmoji + MESSAGE_REACTION_REMOVE: typeof handlers.handleMessageReactionRemove + MESSAGE_UPDATE: typeof handlers.handleMessageUpdate + PRESENCE_UPDATE: typeof handlers.handlePresenceUpdate + TYPING_START: typeof handlers.handleTypingStart + USER_UPDATE: typeof handlers.handleUserUpdate + VOICE_SERVER_UPDATE: typeof handlers.handleVoiceServerUpdate + VOICE_STATE_UPDATE: typeof handlers.handleVoiceStateUpdate + WEBHOOKS_UPDATE: typeof handlers.handleWebhooksUpdate + INTEGRATION_CREATE: typeof handlers.handleIntegrationCreate + INTEGRATION_UPDATE: typeof handlers.handleIntegrationUpdate + INTEGRATION_DELETE: typeof handlers.handleIntegrationDelete +} diff --git a/packages/bot/src/utils.ts b/packages/bot/src/utils.ts new file mode 100644 index 000000000..f199e16c5 --- /dev/null +++ b/packages/bot/src/utils.ts @@ -0,0 +1,9 @@ +import type { BigString } from '@discordeno/types' + +export function snowflakeToBigint(snowflake: BigString) { + return BigInt(snowflake) | 0n +} + +export function bigintToSnowflake(snowflake: BigString) { + return snowflake === 0n ? '' : snowflake.toString() +} From a6c3ffe0ee5da59724676539305f8981f8eca215 Mon Sep 17 00:00:00 2001 From: Jonathan Ho Date: Sat, 25 Mar 2023 08:35:47 -0700 Subject: [PATCH 4/6] test(bot): fix test type (#2839) --- packages/bot/tests/e2e/resetguilds.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/bot/tests/e2e/resetguilds.spec.ts b/packages/bot/tests/e2e/resetguilds.spec.ts index 84e47c955..3b9c11ad5 100644 --- a/packages/bot/tests/e2e/resetguilds.spec.ts +++ b/packages/bot/tests/e2e/resetguilds.spec.ts @@ -17,12 +17,12 @@ describe('[Bot] Delete any guild owned guilds', () => { events: { message: async (shard, data) => { // TRIGGER RAW EVENT - bot.events.raw?.(data, shard) + bot.events.raw?.(data, shard.id) if (!data.t) return // RUN DISPATCH CHECK - await bot.events.dispatchRequirements?.(data, shard) + await bot.events.dispatchRequirements?.(data, shard.id) bot.events[ data.t.toLowerCase().replace(/_([a-z])/g, function (g) { return g[1].toUpperCase() From fe81c94fc0a8ee1713fbb51c8f76af427c0bedbb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 25 Mar 2023 10:36:13 -0500 Subject: [PATCH 5/6] chore(deps): bump http-cache-semantics from 4.1.0 to 4.1.1 (#2838) Bumps [http-cache-semantics](https://github.com/kornelski/http-cache-semantics) from 4.1.0 to 4.1.1. - [Release notes](https://github.com/kornelski/http-cache-semantics/releases) - [Commits](https://github.com/kornelski/http-cache-semantics/compare/v4.1.0...v4.1.1) --- updated-dependencies: - dependency-name: http-cache-semantics dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/yarn.lock b/yarn.lock index a43b3b5fb..775fbf9bd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2710,20 +2710,13 @@ __metadata: languageName: node linkType: hard -"http-cache-semantics@npm:^4.0.0": +"http-cache-semantics@npm:^4.0.0, http-cache-semantics@npm:^4.1.0": version: 4.1.1 resolution: "http-cache-semantics@npm:4.1.1" checksum: 83ac0bc60b17a3a36f9953e7be55e5c8f41acc61b22583060e8dedc9dd5e3607c823a88d0926f9150e571f90946835c7fe150732801010845c72cd8bbff1a236 languageName: node linkType: hard -"http-cache-semantics@npm:^4.1.0": - version: 4.1.0 - resolution: "http-cache-semantics@npm:4.1.0" - checksum: 974de94a81c5474be07f269f9fd8383e92ebb5a448208223bfb39e172a9dbc26feff250192ecc23b9593b3f92098e010406b0f24bd4d588d631f80214648ed42 - languageName: node - linkType: hard - "http-proxy-agent@npm:^5.0.0": version: 5.0.0 resolution: "http-proxy-agent@npm:5.0.0" From 39bac9fe0ec377cc3a9b85f5075f9b562b301f5f Mon Sep 17 00:00:00 2001 From: Skillz4Killz <23035000+Skillz4Killz@users.noreply.github.com> Date: Sun, 26 Mar 2023 12:34:41 +0000 Subject: [PATCH 6/6] fix: ts errors --- packages/bot/src/bot.ts | 57 +++--- packages/bot/src/{handler.ts => handlers.ts} | 51 +++-- .../src/handlers/channels/CHANNEL_CREATE.ts | 4 +- .../src/handlers/channels/CHANNEL_DELETE.ts | 2 +- .../handlers/channels/CHANNEL_PINS_UPDATE.ts | 2 +- .../src/handlers/channels/CHANNEL_UPDATE.ts | 2 +- .../channels/STAGE_INSTANCE_CREATE.ts | 2 +- .../channels/STAGE_INSTANCE_DELETE.ts | 2 +- .../channels/STAGE_INSTANCE_UPDATE.ts | 2 +- .../src/handlers/channels/THREAD_CREATE.ts | 2 +- .../src/handlers/channels/THREAD_DELETE.ts | 2 +- .../src/handlers/channels/THREAD_LIST_SYNC.ts | 2 +- .../channels/THREAD_MEMBERS_UPDATE.ts | 2 +- .../handlers/channels/THREAD_MEMBER_UPDATE.ts | 2 +- .../src/handlers/channels/THREAD_UPDATE.ts | 2 +- .../handlers/channels/{mod.ts => index.ts} | 0 .../handlers/emojis/GUILD_EMOJIS_UPDATE.ts | 4 +- .../src/handlers/emojis/{mod.ts => index.ts} | 0 .../guilds/GUILD_AUDIT_LOG_ENTRY_CREATE.ts | 2 +- .../bot/src/handlers/guilds/GUILD_BAN_ADD.ts | 2 +- .../src/handlers/guilds/GUILD_BAN_REMOVE.ts | 2 +- .../bot/src/handlers/guilds/GUILD_CREATE.ts | 5 +- .../bot/src/handlers/guilds/GUILD_DELETE.ts | 2 +- .../guilds/GUILD_INTEGRATIONS_UPDATE.ts | 2 +- .../handlers/guilds/GUILD_STICKERS_UPDATE.ts | 12 ++ .../bot/src/handlers/guilds/GUILD_UPDATE.ts | 5 +- .../AUTO_MODERATION_ACTION_EXECUTION.ts | 4 +- .../automod/AUTO_MODERATION_RULE_CREATE.ts | 4 +- .../automod/AUTO_MODERATION_RULE_DELETE.ts | 4 +- .../automod/AUTO_MODERATION_RULE_UPDATE.ts | 2 +- .../bot/src/handlers/guilds/automod/index.ts | 4 + .../bot/src/handlers/guilds/automod/mod.ts | 0 .../src/handlers/guilds/{mod.ts => index.ts} | 4 +- .../GUILD_SCHEDULED_EVENT_CREATE.ts | 2 +- .../GUILD_SCHEDULED_EVENT_DELETE.ts | 2 +- .../GUILD_SCHEDULED_EVENT_UPDATE.ts | 2 +- .../GUILD_SCHEDULED_EVENT_USER_ADD.ts | 4 +- .../GUILD_SCHEDULED_EVENT_USER_REMOVE.ts | 4 +- .../scheduledEvents/{mod.ts => index.ts} | 0 packages/bot/src/handlers/index.ts | 12 ++ .../integrations/INTEGRATION_CREATE.ts | 2 +- .../integrations/INTEGRATION_DELETE.ts | 2 +- .../integrations/INTEGRATION_UPDATE.ts | 2 +- .../integrations/{mod.ts => index.ts} | 0 .../APPLICATION_COMMAND_PERMISSIONS_UPDATE.ts | 6 + .../interactions/INTERACTION_CREATE.ts | 2 +- .../bot/src/handlers/interactions/index.ts | 2 + packages/bot/src/handlers/interactions/mod.ts | 1 - .../bot/src/handlers/invites/INVITE_CREATE.ts | 2 +- .../bot/src/handlers/invites/INVITE_DELETE.ts | 2 +- .../src/handlers/invites/{mod.ts => index.ts} | 0 .../handlers/members/GUILD_MEMBERS_CHUNK.ts | 2 +- .../src/handlers/members/GUILD_MEMBER_ADD.ts | 2 +- .../handlers/members/GUILD_MEMBER_REMOVE.ts | 2 +- .../handlers/members/GUILD_MEMBER_UPDATE.ts | 2 +- .../src/handlers/members/{mod.ts => index.ts} | 0 .../src/handlers/messages/MESSAGE_CREATE.ts | 4 +- .../src/handlers/messages/MESSAGE_DELETE.ts | 2 +- .../handlers/messages/MESSAGE_DELETE_BULK.ts | 6 +- .../handlers/messages/MESSAGE_REACTION_ADD.ts | 4 +- .../messages/MESSAGE_REACTION_REMOVE.ts | 2 +- .../messages/MESSAGE_REACTION_REMOVE_ALL.ts | 2 +- .../messages/MESSAGE_REACTION_REMOVE_EMOJI.ts | 2 +- .../src/handlers/messages/MESSAGE_UPDATE.ts | 2 +- .../handlers/messages/{mod.ts => index.ts} | 0 .../bot/src/handlers/misc/PRESENCE_UPDATE.ts | 2 +- packages/bot/src/handlers/misc/READY.ts | 2 +- .../bot/src/handlers/misc/TYPING_START.ts | 2 +- packages/bot/src/handlers/misc/USER_UPDATE.ts | 2 +- .../src/handlers/misc/{mod.ts => index.ts} | 0 packages/bot/src/handlers/mod.ts | 12 -- .../src/handlers/roles/GUILD_ROLE_CREATE.ts | 2 +- .../src/handlers/roles/GUILD_ROLE_DELETE.ts | 2 +- .../src/handlers/roles/GUILD_ROLE_UPDATE.ts | 2 +- .../src/handlers/roles/{mod.ts => index.ts} | 0 .../src/handlers/voice/VOICE_SERVER_UPDATE.ts | 2 +- .../src/handlers/voice/VOICE_STATE_UPDATE.ts | 2 +- .../src/handlers/voice/{mod.ts => index.ts} | 0 .../src/handlers/webhooks/WEBHOOKS_UPDATE.ts | 2 +- .../handlers/webhooks/{mod.ts => index.ts} | 0 packages/bot/src/index.ts | 4 +- .../src/{transformer.ts => transformers.ts} | 189 +++++++++--------- packages/bot/src/transformers/activity.ts | 1 + packages/bot/src/transformers/application.ts | 5 +- .../src/transformers/applicationCommand.ts | 1 + .../applicationCommandOptionChoice.ts | 1 + .../applicationCommandPermission.ts | 1 + packages/bot/src/transformers/attachment.ts | 1 + .../bot/src/transformers/auditLogEntry.ts | 3 + .../transformers/automodActionExecution.ts | 1 + packages/bot/src/transformers/automodRule.ts | 1 + packages/bot/src/transformers/channel.ts | 15 +- packages/bot/src/transformers/component.ts | 8 +- packages/bot/src/transformers/embed.ts | 1 + packages/bot/src/transformers/emoji.ts | 3 +- packages/bot/src/transformers/gatewayBot.ts | 1 + packages/bot/src/transformers/guild.ts | 3 +- .../bot/src/transformers/{mod.ts => index.ts} | 2 +- packages/bot/src/transformers/integration.ts | 3 +- packages/bot/src/transformers/interaction.ts | 11 +- packages/bot/src/transformers/invite.ts | 3 +- packages/bot/src/transformers/member.ts | 2 + packages/bot/src/transformers/message.ts | 9 +- packages/bot/src/transformers/presence.ts | 5 +- .../src/transformers/reverse/application.ts | 2 +- .../src/transformers/reverse/auditLogEntry.ts | 11 +- .../bot/src/transformers/reverse/component.ts | 2 +- .../reverse/createApplicationCommand.ts | 2 +- .../bot/src/transformers/reverse/emoji.ts | 2 +- .../transformers/reverse/{mod.ts => index.ts} | 0 .../reverse/interactionResponse.ts | 2 +- .../bot/src/transformers/reverse/member.ts | 6 +- .../bot/src/transformers/reverse/presence.ts | 2 +- packages/bot/src/transformers/reverse/team.ts | 6 +- packages/bot/src/transformers/role.ts | 3 +- .../bot/src/transformers/scheduledEvent.ts | 5 +- .../bot/src/transformers/stageInstance.ts | 1 + packages/bot/src/transformers/sticker.ts | 8 +- packages/bot/src/transformers/team.ts | 3 +- packages/bot/src/transformers/template.ts | 1 + packages/bot/src/transformers/threadMember.ts | 4 +- .../transformers/toggles/ToggleBitfield.ts | 12 +- .../bot/src/transformers/toggles/emoji.ts | 12 +- .../bot/src/transformers/toggles/guild.ts | 85 +++++--- .../bot/src/transformers/toggles/member.ts | 10 +- packages/bot/src/transformers/toggles/role.ts | 12 +- packages/bot/src/transformers/toggles/user.ts | 12 +- .../bot/src/transformers/toggles/voice.ts | 18 +- packages/bot/src/transformers/voiceRegion.ts | 1 + packages/bot/src/transformers/voiceState.ts | 1 + packages/bot/src/transformers/webhook.ts | 7 +- .../bot/src/transformers/welcomeScreen.ts | 1 + packages/bot/src/transformers/widget.ts | 1 + .../bot/src/transformers/widgetSettings.ts | 1 + packages/bot/src/{types.ts => typings.ts} | 60 +++--- packages/rest/tests/e2e/guild.spec.ts | 11 + packages/rest/tests/e2e/message.spec.ts | 31 ++- packages/types/src/shared.ts | 1 + packages/utils/package.json | 2 +- packages/utils/src/bucket.ts | 25 ++- packages/utils/tests/bucket.spec.ts | 21 ++ 141 files changed, 546 insertions(+), 417 deletions(-) rename packages/bot/src/{handler.ts => handlers.ts} (83%) rename packages/bot/src/handlers/channels/{mod.ts => index.ts} (100%) rename packages/bot/src/handlers/emojis/{mod.ts => index.ts} (100%) create mode 100644 packages/bot/src/handlers/guilds/GUILD_STICKERS_UPDATE.ts create mode 100644 packages/bot/src/handlers/guilds/automod/index.ts delete mode 100644 packages/bot/src/handlers/guilds/automod/mod.ts rename packages/bot/src/handlers/guilds/{mod.ts => index.ts} (69%) rename packages/bot/src/handlers/guilds/scheduledEvents/{mod.ts => index.ts} (100%) create mode 100644 packages/bot/src/handlers/index.ts rename packages/bot/src/handlers/integrations/{mod.ts => index.ts} (100%) create mode 100644 packages/bot/src/handlers/interactions/APPLICATION_COMMAND_PERMISSIONS_UPDATE.ts create mode 100644 packages/bot/src/handlers/interactions/index.ts delete mode 100644 packages/bot/src/handlers/interactions/mod.ts rename packages/bot/src/handlers/invites/{mod.ts => index.ts} (100%) rename packages/bot/src/handlers/members/{mod.ts => index.ts} (100%) rename packages/bot/src/handlers/messages/{mod.ts => index.ts} (100%) rename packages/bot/src/handlers/misc/{mod.ts => index.ts} (100%) delete mode 100644 packages/bot/src/handlers/mod.ts rename packages/bot/src/handlers/roles/{mod.ts => index.ts} (100%) rename packages/bot/src/handlers/voice/{mod.ts => index.ts} (100%) rename packages/bot/src/handlers/webhooks/{mod.ts => index.ts} (100%) rename packages/bot/src/{transformer.ts => transformers.ts} (52%) rename packages/bot/src/transformers/{mod.ts => index.ts} (97%) rename packages/bot/src/transformers/reverse/{mod.ts => index.ts} (100%) rename packages/bot/src/{types.ts => typings.ts} (86%) diff --git a/packages/bot/src/bot.ts b/packages/bot/src/bot.ts index f8610c345..afe558285 100644 --- a/packages/bot/src/bot.ts +++ b/packages/bot/src/bot.ts @@ -3,25 +3,27 @@ import { createGatewayManager, ShardSocketCloseCodes } from '@discordeno/gateway import type { CreateRestManagerOptions, RestManager } from '@discordeno/rest' import { createRestManager } from '@discordeno/rest' import type { DiscordEmoji, DiscordGatewayPayload, DiscordReady, GatewayIntents } from '@discordeno/types' -import { Collection, createLogger } from '@discordeno/utils' -import type { Transformers } from './transformer' -import type { AuditLogEntry } from './transformers/auditLogEntry' -import type { AutoModerationActionExecution } from './transformers/automodActionExecution' -import type { AutoModerationRule } from './transformers/automodRule' -import type { Channel } from './transformers/channel' -import type { Emoji } from './transformers/emoji' -import type { Guild } from './transformers/guild' -import type { Integration } from './transformers/integration' -import type { Interaction } from './transformers/interaction' -import type { Invite } from './transformers/invite' -import type { Member, User } from './transformers/member' -import type { Message } from './transformers/message' -import type { PresenceUpdate } from './transformers/presence' -import type { Role } from './transformers/role' -import type { ScheduledEvent } from './transformers/scheduledEvent' -import type { ThreadMember } from './transformers/threadMember' -import type { VoiceState } from './transformers/voiceState' -import type { bigintToSnowflake, snowflakeToBigint } from './utils.js' +import { createLogger, getBotIdFromToken, type Collection } from '@discordeno/utils' +import { createBotGatewayHandlers } from './handlers.js' +import { createTransformers, type Transformers } from './transformers.js' +import type { ApplicationCommandPermission } from './transformers/applicationCommandPermission.js' +import type { AuditLogEntry } from './transformers/auditLogEntry.js' +import type { AutoModerationActionExecution } from './transformers/automodActionExecution.js' +import type { AutoModerationRule } from './transformers/automodRule.js' +import type { Channel } from './transformers/channel.js' +import type { Emoji } from './transformers/emoji.js' +import type { Guild } from './transformers/guild.js' +import type { Integration } from './transformers/integration.js' +import type { Interaction } from './transformers/interaction.js' +import type { Invite } from './transformers/invite.js' +import type { Member, User } from './transformers/member.js' +import type { Message } from './transformers/message.js' +import type { PresenceUpdate } from './transformers/presence.js' +import type { Role } from './transformers/role.js' +import type { ScheduledEvent } from './transformers/scheduledEvent.js' +import type { Sticker } from './transformers/sticker.js' +import type { ThreadMember } from './transformers/threadMember.js' +import type { VoiceState } from './transformers/voiceState.js' /** * Create a bot object that will maintain the rest and gateway connection. @@ -53,7 +55,13 @@ export function createBot(options: CreateBotOptions): Bot { options.rest.token = options.token options.gateway.intents = options.intents + const id = getBotIdFromToken(options.token) + const bot: Bot = { + id, + applicationId: id, + transformers: createTransformers({}), + handlers: createBotGatewayHandlers({}), rest: createRestManager(options.rest), gateway: createGatewayManager(options.gateway), events: options.events ?? {}, @@ -88,7 +96,9 @@ export interface CreateBotOptions { } export interface Bot { + /** The id of the bot. */ id: bigint + /** The application id of the bot. This is usually the same as id but in the case of old bots can be different. */ applicationId: bigint /** The rest manager. */ rest: RestManager @@ -98,11 +108,10 @@ export interface Bot { events: Partial /** A logger utility to make it easy to log nice and useful things in the bot code. */ logger: ReturnType + /** The functions that should transform discord objects to discordeno shaped objects. */ transformers: Transformers - utils: { - snowflakeToBigint: typeof snowflakeToBigint - bigintToSnowflake: typeof bigintToSnowflake - } + /** The handler functions that should handle incoming discord payloads from gateway and call an event. */ + handlers: ReturnType /** Start the bot connection to the gateway. */ start: () => Promise /** Shuts down all the bot connections to the gateway. */ @@ -111,6 +120,7 @@ export interface Bot { export interface EventHandlers { debug: (text: string, ...args: any[]) => unknown + applicationCommandPermissionsUpdate: (command: ApplicationCommandPermission) => unknown auditLogEntryCreate: (log: AuditLogEntry, guildId: bigint) => unknown automodRuleCreate: (rule: AutoModerationRule) => unknown automodRuleUpdate: (rule: AutoModerationRule) => unknown @@ -149,6 +159,7 @@ export interface EventHandlers { guildMemberAdd: (member: Member, user: User) => unknown guildMemberRemove: (user: User, guildId: bigint) => unknown guildMemberUpdate: (member: Member, user: User) => unknown + guildStickersUpdate: (stickers: Sticker[]) => unknown messageCreate: (message: Message) => unknown messageDelete: (payload: { id: bigint; channelId: bigint; guildId?: bigint }, message?: Message) => unknown messageDeleteBulk: (payload: { ids: bigint[]; channelId: bigint; guildId?: bigint }) => unknown diff --git a/packages/bot/src/handler.ts b/packages/bot/src/handlers.ts similarity index 83% rename from packages/bot/src/handler.ts rename to packages/bot/src/handlers.ts index b5d09486c..e560250f2 100644 --- a/packages/bot/src/handler.ts +++ b/packages/bot/src/handlers.ts @@ -1,28 +1,20 @@ -import * as handlers from './handlers/mod.js' +import * as handlers from './handlers/index.js' import type { Bot, DiscordGatewayPayload, GatewayDispatchEventNames } from './index.js' -import type { BotGatewayHandlerOptions } from './types.js' +import type { BotGatewayHandlerOptions } from './typings.js' export function createBotGatewayHandlers( options: Partial, ): Record any> { return { - // misc - READY: options.READY ?? handlers.handleReady, - // channels + APPLICATION_COMMAND_PERMISSIONS_UPDATE: options.APPLICATION_COMMAND_PERMISSIONS_UPDATE ?? handlers.handleApplicationCommandPermissionsUpdate, + AUTO_MODERATION_ACTION_EXECUTION: options.AUTO_MODERATION_ACTION_EXECUTION ?? handlers.handleAutoModerationActionExecution, + AUTO_MODERATION_RULE_CREATE: options.AUTO_MODERATION_RULE_CREATE ?? handlers.handleAutoModerationRuleCreate, + AUTO_MODERATION_RULE_DELETE: options.AUTO_MODERATION_RULE_DELETE ?? handlers.handleAutoModerationRuleDelete, + AUTO_MODERATION_RULE_UPDATE: options.AUTO_MODERATION_RULE_UPDATE ?? handlers.handleAutoModerationRuleUpdate, CHANNEL_CREATE: options.CHANNEL_CREATE ?? handlers.handleChannelCreate, CHANNEL_DELETE: options.CHANNEL_DELETE ?? handlers.handleChannelDelete, CHANNEL_PINS_UPDATE: options.CHANNEL_PINS_UPDATE ?? handlers.handleChannelPinsUpdate, CHANNEL_UPDATE: options.CHANNEL_UPDATE ?? handlers.handleChannelUpdate, - THREAD_CREATE: options.THREAD_CREATE ?? handlers.handleThreadCreate, - THREAD_UPDATE: options.THREAD_UPDATE ?? handlers.handleThreadUpdate, - THREAD_DELETE: options.THREAD_DELETE ?? handlers.handleThreadDelete, - THREAD_LIST_SYNC: options.THREAD_LIST_SYNC ?? handlers.handleThreadListSync, - THREAD_MEMBERS_UPDATE: options.THREAD_MEMBERS_UPDATE ?? handlers.handleThreadMembersUpdate, - STAGE_INSTANCE_CREATE: options.STAGE_INSTANCE_CREATE ?? handlers.handleStageInstanceCreate, - STAGE_INSTANCE_UPDATE: options.STAGE_INSTANCE_UPDATE ?? handlers.handleStageInstanceUpdate, - STAGE_INSTANCE_DELETE: options.STAGE_INSTANCE_DELETE ?? handlers.handleStageInstanceDelete, - - // guilds GUILD_AUDIT_LOG_ENTRY_CREATE: options.GUILD_AUDIT_LOG_ENTRY_CREATE ?? handlers.handleGuildAuditLogEntryCreate, GUILD_BAN_ADD: options.GUILD_BAN_ADD ?? handlers.handleGuildBanAdd, GUILD_BAN_REMOVE: options.GUILD_BAN_REMOVE ?? handlers.handleGuildBanRemove, @@ -37,19 +29,19 @@ export function createBotGatewayHandlers( GUILD_ROLE_CREATE: options.GUILD_ROLE_CREATE ?? handlers.handleGuildRoleCreate, GUILD_ROLE_DELETE: options.GUILD_ROLE_DELETE ?? handlers.handleGuildRoleDelete, GUILD_ROLE_UPDATE: options.GUILD_ROLE_UPDATE ?? handlers.handleGuildRoleUpdate, - GUILD_UPDATE: options.GUILD_UPDATE ?? handlers.handleGuildUpdate, - // guild events GUILD_SCHEDULED_EVENT_CREATE: options.GUILD_SCHEDULED_EVENT_CREATE ?? handlers.handleGuildScheduledEventCreate, GUILD_SCHEDULED_EVENT_DELETE: options.GUILD_SCHEDULED_EVENT_DELETE ?? handlers.handleGuildScheduledEventDelete, GUILD_SCHEDULED_EVENT_UPDATE: options.GUILD_SCHEDULED_EVENT_UPDATE ?? handlers.handleGuildScheduledEventUpdate, GUILD_SCHEDULED_EVENT_USER_ADD: options.GUILD_SCHEDULED_EVENT_USER_ADD ?? handlers.handleGuildScheduledEventUserAdd, GUILD_SCHEDULED_EVENT_USER_REMOVE: options.GUILD_SCHEDULED_EVENT_USER_REMOVE ?? handlers.handleGuildScheduledEventUserRemove, - // interactions + GUILD_STICKERS_UPDATE: options.GUILD_STICKERS_UPDATE ?? handlers.handleGuildStickersUpdate, + GUILD_UPDATE: options.GUILD_UPDATE ?? handlers.handleGuildUpdate, INTERACTION_CREATE: options.INTERACTION_CREATE ?? handlers.handleInteractionCreate, - // invites + INTEGRATION_CREATE: options.INTEGRATION_CREATE ?? handlers.handleIntegrationCreate, + INTEGRATION_UPDATE: options.INTEGRATION_UPDATE ?? handlers.handleIntegrationUpdate, + INTEGRATION_DELETE: options.INTEGRATION_DELETE ?? handlers.handleIntegrationDelete, INVITE_CREATE: options.INVITE_CREATE ?? handlers.handleInviteCreate, INVITE_DELETE: options.INVITE_DELETE ?? handlers.handleInviteCreate, - // messages MESSAGE_CREATE: options.MESSAGE_CREATE ?? handlers.handleMessageCreate, MESSAGE_DELETE_BULK: options.MESSAGE_DELETE_BULK ?? handlers.handleMessageDeleteBulk, MESSAGE_DELETE: options.MESSAGE_DELETE ?? handlers.handleMessageDelete, @@ -58,18 +50,23 @@ export function createBotGatewayHandlers( MESSAGE_REACTION_REMOVE_EMOJI: options.MESSAGE_REACTION_REMOVE_EMOJI ?? handlers.handleMessageReactionRemoveEmoji, MESSAGE_REACTION_REMOVE: options.MESSAGE_REACTION_REMOVE ?? handlers.handleMessageReactionRemove, MESSAGE_UPDATE: options.MESSAGE_UPDATE ?? handlers.handleMessageUpdate, - // presence PRESENCE_UPDATE: options.PRESENCE_UPDATE ?? handlers.handlePresenceUpdate, + READY: options.READY ?? handlers.handleReady, + STAGE_INSTANCE_CREATE: options.STAGE_INSTANCE_CREATE ?? handlers.handleStageInstanceCreate, + STAGE_INSTANCE_DELETE: options.STAGE_INSTANCE_DELETE ?? handlers.handleStageInstanceDelete, + STAGE_INSTANCE_UPDATE: options.STAGE_INSTANCE_UPDATE ?? handlers.handleStageInstanceUpdate, + THREAD_CREATE: options.THREAD_CREATE ?? handlers.handleThreadCreate, + THREAD_DELETE: options.THREAD_DELETE ?? handlers.handleThreadDelete, + THREAD_UPDATE: options.THREAD_UPDATE ?? handlers.handleThreadUpdate, + THREAD_LIST_SYNC: options.THREAD_LIST_SYNC ?? handlers.handleThreadListSync, + THREAD_MEMBER_UPDATE: options.THREAD_MEMBERS_UPDATE ?? handlers.handleThreadMembersUpdate, + THREAD_MEMBERS_UPDATE: options.THREAD_MEMBERS_UPDATE ?? handlers.handleThreadMembersUpdate, TYPING_START: options.TYPING_START ?? handlers.handleTypingStart, USER_UPDATE: options.USER_UPDATE ?? handlers.handleUserUpdate, - // voice VOICE_SERVER_UPDATE: options.VOICE_SERVER_UPDATE ?? handlers.handleVoiceServerUpdate, VOICE_STATE_UPDATE: options.VOICE_STATE_UPDATE ?? handlers.handleVoiceStateUpdate, - // webhooks WEBHOOKS_UPDATE: options.WEBHOOKS_UPDATE ?? handlers.handleWebhooksUpdate, - // integrations - INTEGRATION_CREATE: options.INTEGRATION_CREATE ?? handlers.handleIntegrationCreate, - INTEGRATION_UPDATE: options.INTEGRATION_UPDATE ?? handlers.handleIntegrationUpdate, - INTEGRATION_DELETE: options.INTEGRATION_DELETE ?? handlers.handleIntegrationDelete, } } + +export interface GatewayHandlers extends ReturnType {} diff --git a/packages/bot/src/handlers/channels/CHANNEL_CREATE.ts b/packages/bot/src/handlers/channels/CHANNEL_CREATE.ts index 98209eaf7..f5f1dae00 100644 --- a/packages/bot/src/handlers/channels/CHANNEL_CREATE.ts +++ b/packages/bot/src/handlers/channels/CHANNEL_CREATE.ts @@ -1,7 +1,7 @@ -import type { DiscordChannel, DiscordenoShard, DiscordGatewayPayload } from '@discordeno/bot' +import type { DiscordChannel, DiscordGatewayPayload } from '@discordeno/bot' import type { Bot } from '../../index.js' -export async function handleChannelCreate(bot: Bot, payload: DiscordGatewayPayload, shard: DiscordenoShard) { +export async function handleChannelCreate(bot: Bot, payload: DiscordGatewayPayload, shardId: number): Promise { const channel = bot.transformers.channel(bot, { channel: payload.d as DiscordChannel, }) diff --git a/packages/bot/src/handlers/channels/CHANNEL_DELETE.ts b/packages/bot/src/handlers/channels/CHANNEL_DELETE.ts index 4d0e1ccf5..44c8480b5 100644 --- a/packages/bot/src/handlers/channels/CHANNEL_DELETE.ts +++ b/packages/bot/src/handlers/channels/CHANNEL_DELETE.ts @@ -1,7 +1,7 @@ import type { DiscordChannel, DiscordGatewayPayload } from '@discordeno/types' import type { Bot } from '../../bot.js' -export async function handleChannelDelete(bot: Bot, data: DiscordGatewayPayload) { +export async function handleChannelDelete(bot: Bot, data: DiscordGatewayPayload): Promise { const payload = data.d as DiscordChannel if (!payload.guild_id) return diff --git a/packages/bot/src/handlers/channels/CHANNEL_PINS_UPDATE.ts b/packages/bot/src/handlers/channels/CHANNEL_PINS_UPDATE.ts index 2e95f8524..ff58a1624 100644 --- a/packages/bot/src/handlers/channels/CHANNEL_PINS_UPDATE.ts +++ b/packages/bot/src/handlers/channels/CHANNEL_PINS_UPDATE.ts @@ -1,7 +1,7 @@ import type { DiscordChannelPinsUpdate, DiscordGatewayPayload } from '@discordeno/types' import type { Bot } from '../../bot.js' -export async function handleChannelPinsUpdate(bot: Bot, data: DiscordGatewayPayload) { +export async function handleChannelPinsUpdate(bot: Bot, data: DiscordGatewayPayload): Promise { const payload = data.d as DiscordChannelPinsUpdate bot.events.channelPinsUpdate?.({ diff --git a/packages/bot/src/handlers/channels/CHANNEL_UPDATE.ts b/packages/bot/src/handlers/channels/CHANNEL_UPDATE.ts index e95c0b16f..45ef20a43 100644 --- a/packages/bot/src/handlers/channels/CHANNEL_UPDATE.ts +++ b/packages/bot/src/handlers/channels/CHANNEL_UPDATE.ts @@ -1,7 +1,7 @@ import type { DiscordChannel, DiscordGatewayPayload } from '@discordeno/types' import type { Bot } from '../../bot.js' -export async function handleChannelUpdate(bot: Bot, data: DiscordGatewayPayload) { +export async function handleChannelUpdate(bot: Bot, data: DiscordGatewayPayload): Promise { const payload = data.d as DiscordChannel const channel = bot.transformers.channel(bot, { channel: payload }) diff --git a/packages/bot/src/handlers/channels/STAGE_INSTANCE_CREATE.ts b/packages/bot/src/handlers/channels/STAGE_INSTANCE_CREATE.ts index 3f9504498..3f211abb0 100644 --- a/packages/bot/src/handlers/channels/STAGE_INSTANCE_CREATE.ts +++ b/packages/bot/src/handlers/channels/STAGE_INSTANCE_CREATE.ts @@ -1,7 +1,7 @@ import type { DiscordGatewayPayload, DiscordStageInstance } from '@discordeno/types' import type { Bot } from '../../bot.js' -export function handleStageInstanceCreate(bot: Bot, data: DiscordGatewayPayload) { +export async function handleStageInstanceCreate(bot: Bot, data: DiscordGatewayPayload): Promise { const payload = data.d as DiscordStageInstance bot.events.stageInstanceCreate?.({ diff --git a/packages/bot/src/handlers/channels/STAGE_INSTANCE_DELETE.ts b/packages/bot/src/handlers/channels/STAGE_INSTANCE_DELETE.ts index 70081696e..4be5f6633 100644 --- a/packages/bot/src/handlers/channels/STAGE_INSTANCE_DELETE.ts +++ b/packages/bot/src/handlers/channels/STAGE_INSTANCE_DELETE.ts @@ -1,7 +1,7 @@ import type { DiscordGatewayPayload, DiscordStageInstance } from '@discordeno/types' import type { Bot } from '../../bot.js' -export function handleStageInstanceDelete(bot: Bot, data: DiscordGatewayPayload) { +export async function handleStageInstanceDelete(bot: Bot, data: DiscordGatewayPayload): Promise { const payload = data.d as DiscordStageInstance bot.events.stageInstanceDelete?.({ diff --git a/packages/bot/src/handlers/channels/STAGE_INSTANCE_UPDATE.ts b/packages/bot/src/handlers/channels/STAGE_INSTANCE_UPDATE.ts index 9dff85a98..145be387c 100644 --- a/packages/bot/src/handlers/channels/STAGE_INSTANCE_UPDATE.ts +++ b/packages/bot/src/handlers/channels/STAGE_INSTANCE_UPDATE.ts @@ -1,7 +1,7 @@ import type { DiscordGatewayPayload, DiscordStageInstance } from '@discordeno/types' import type { Bot } from '../../bot.js' -export function handleStageInstanceUpdate(bot: Bot, data: DiscordGatewayPayload) { +export async function handleStageInstanceUpdate(bot: Bot, data: DiscordGatewayPayload): Promise { const payload = data.d as DiscordStageInstance bot.events.stageInstanceUpdate?.({ diff --git a/packages/bot/src/handlers/channels/THREAD_CREATE.ts b/packages/bot/src/handlers/channels/THREAD_CREATE.ts index 7833fe923..fe6a94d2b 100644 --- a/packages/bot/src/handlers/channels/THREAD_CREATE.ts +++ b/packages/bot/src/handlers/channels/THREAD_CREATE.ts @@ -1,7 +1,7 @@ import type { DiscordChannel, DiscordGatewayPayload } from '@discordeno/types' import type { Bot } from '../../index.js' -export async function handleThreadCreate(bot: Bot, data: DiscordGatewayPayload) { +export async function handleThreadCreate(bot: Bot, data: DiscordGatewayPayload): Promise { const payload = data.d as DiscordChannel bot.events.threadCreate?.(bot.transformers.channel(bot, { channel: payload })) diff --git a/packages/bot/src/handlers/channels/THREAD_DELETE.ts b/packages/bot/src/handlers/channels/THREAD_DELETE.ts index 3c74ee586..d8fcfb58a 100644 --- a/packages/bot/src/handlers/channels/THREAD_DELETE.ts +++ b/packages/bot/src/handlers/channels/THREAD_DELETE.ts @@ -1,7 +1,7 @@ import type { DiscordChannel, DiscordGatewayPayload } from '@discordeno/types' import type { Bot } from '../../index.js' -export async function handleThreadDelete(bot: Bot, data: DiscordGatewayPayload) { +export async function handleThreadDelete(bot: Bot, data: DiscordGatewayPayload): Promise { const payload = data.d as DiscordChannel bot.events.threadDelete?.(bot.transformers.channel(bot, { channel: payload })) diff --git a/packages/bot/src/handlers/channels/THREAD_LIST_SYNC.ts b/packages/bot/src/handlers/channels/THREAD_LIST_SYNC.ts index 7dafb77ee..fb5845cdd 100644 --- a/packages/bot/src/handlers/channels/THREAD_LIST_SYNC.ts +++ b/packages/bot/src/handlers/channels/THREAD_LIST_SYNC.ts @@ -1,7 +1,7 @@ import type { DiscordGatewayPayload, DiscordThreadListSync } from '@discordeno/types' import type { Bot } from '../../index.js' -export async function handleThreadListSync(bot: Bot, data: DiscordGatewayPayload) { +export async function handleThreadListSync(bot: Bot, data: DiscordGatewayPayload): Promise { const payload = data.d as DiscordThreadListSync const guildId = bot.transformers.snowflake(payload.guild_id) diff --git a/packages/bot/src/handlers/channels/THREAD_MEMBERS_UPDATE.ts b/packages/bot/src/handlers/channels/THREAD_MEMBERS_UPDATE.ts index ab382c42f..d767ac0b0 100644 --- a/packages/bot/src/handlers/channels/THREAD_MEMBERS_UPDATE.ts +++ b/packages/bot/src/handlers/channels/THREAD_MEMBERS_UPDATE.ts @@ -1,7 +1,7 @@ import type { DiscordGatewayPayload, DiscordThreadMembersUpdate } from '@discordeno/types' import type { Bot } from '../../index.js' -export async function handleThreadMembersUpdate(bot: Bot, data: DiscordGatewayPayload) { +export async function handleThreadMembersUpdate(bot: Bot, data: DiscordGatewayPayload, shardId: number): Promise { const payload = data.d as DiscordThreadMembersUpdate bot.events.threadMembersUpdate?.({ diff --git a/packages/bot/src/handlers/channels/THREAD_MEMBER_UPDATE.ts b/packages/bot/src/handlers/channels/THREAD_MEMBER_UPDATE.ts index 45ab4b9dd..867dfebbe 100644 --- a/packages/bot/src/handlers/channels/THREAD_MEMBER_UPDATE.ts +++ b/packages/bot/src/handlers/channels/THREAD_MEMBER_UPDATE.ts @@ -1,7 +1,7 @@ import type { DiscordGatewayPayload, DiscordThreadMemberUpdate } from '@discordeno/types' import type { Bot } from '../../index.js' -export async function handleThreadMemberUpdate(bot: Bot, data: DiscordGatewayPayload) { +export async function handleThreadMemberUpdate(bot: Bot, data: DiscordGatewayPayload, shardId: number): Promise { const payload = data.d as DiscordThreadMemberUpdate bot.events.threadMemberUpdate?.({ diff --git a/packages/bot/src/handlers/channels/THREAD_UPDATE.ts b/packages/bot/src/handlers/channels/THREAD_UPDATE.ts index 0d73d8ae6..1825d09df 100644 --- a/packages/bot/src/handlers/channels/THREAD_UPDATE.ts +++ b/packages/bot/src/handlers/channels/THREAD_UPDATE.ts @@ -1,7 +1,7 @@ import type { DiscordChannel, DiscordGatewayPayload } from '@discordeno/types' import type { Bot } from '../../index.js' -export async function handleThreadUpdate(bot: Bot, data: DiscordGatewayPayload) { +export async function handleThreadUpdate(bot: Bot, data: DiscordGatewayPayload): Promise { const payload = data.d as DiscordChannel bot.events.threadUpdate?.(bot.transformers.channel(bot, { channel: payload })) diff --git a/packages/bot/src/handlers/channels/mod.ts b/packages/bot/src/handlers/channels/index.ts similarity index 100% rename from packages/bot/src/handlers/channels/mod.ts rename to packages/bot/src/handlers/channels/index.ts diff --git a/packages/bot/src/handlers/emojis/GUILD_EMOJIS_UPDATE.ts b/packages/bot/src/handlers/emojis/GUILD_EMOJIS_UPDATE.ts index 30c233409..3f83dc8eb 100644 --- a/packages/bot/src/handlers/emojis/GUILD_EMOJIS_UPDATE.ts +++ b/packages/bot/src/handlers/emojis/GUILD_EMOJIS_UPDATE.ts @@ -1,8 +1,8 @@ import type { DiscordGatewayPayload, DiscordGuildEmojisUpdate } from '@discordeno/types' +import { Collection } from '@discordeno/utils' import type { Bot } from '../../bot.js' -import type { Collection } from '../../util/collection.js' -export async function handleGuildEmojisUpdate(bot: Bot, data: DiscordGatewayPayload) { +export async function handleGuildEmojisUpdate(bot: Bot, data: DiscordGatewayPayload): Promise { const payload = data.d as DiscordGuildEmojisUpdate bot.events.guildEmojisUpdate?.({ diff --git a/packages/bot/src/handlers/emojis/mod.ts b/packages/bot/src/handlers/emojis/index.ts similarity index 100% rename from packages/bot/src/handlers/emojis/mod.ts rename to packages/bot/src/handlers/emojis/index.ts diff --git a/packages/bot/src/handlers/guilds/GUILD_AUDIT_LOG_ENTRY_CREATE.ts b/packages/bot/src/handlers/guilds/GUILD_AUDIT_LOG_ENTRY_CREATE.ts index b4dc645eb..7e39e3420 100644 --- a/packages/bot/src/handlers/guilds/GUILD_AUDIT_LOG_ENTRY_CREATE.ts +++ b/packages/bot/src/handlers/guilds/GUILD_AUDIT_LOG_ENTRY_CREATE.ts @@ -1,7 +1,7 @@ import type { DiscordAuditLogEntry, DiscordGatewayPayload } from '@discordeno/types' import type { Bot } from '../../bot.js' -export async function handleGuildAuditLogEntryCreate(bot: Bot, data: DiscordGatewayPayload) { +export async function handleGuildAuditLogEntryCreate(bot: Bot, data: DiscordGatewayPayload): Promise { // TODO: better type here const payload = data.d as DiscordAuditLogEntry & { guild_id: string } bot.events.auditLogEntryCreate?.(bot.transformers.auditLogEntry(bot, payload), bot.transformers.snowflake(payload.guild_id)) diff --git a/packages/bot/src/handlers/guilds/GUILD_BAN_ADD.ts b/packages/bot/src/handlers/guilds/GUILD_BAN_ADD.ts index 95981e14a..ab4f34f3a 100644 --- a/packages/bot/src/handlers/guilds/GUILD_BAN_ADD.ts +++ b/packages/bot/src/handlers/guilds/GUILD_BAN_ADD.ts @@ -1,7 +1,7 @@ import type { DiscordGatewayPayload, DiscordGuildBanAddRemove } from '@discordeno/types' import type { Bot } from '../../bot.js' -export async function handleGuildBanAdd(bot: Bot, data: DiscordGatewayPayload) { +export async function handleGuildBanAdd(bot: Bot, data: DiscordGatewayPayload): Promise { const payload = data.d as DiscordGuildBanAddRemove bot.events.guildBanAdd?.(bot.transformers.user(bot, payload.user), bot.transformers.snowflake(payload.guild_id)) } diff --git a/packages/bot/src/handlers/guilds/GUILD_BAN_REMOVE.ts b/packages/bot/src/handlers/guilds/GUILD_BAN_REMOVE.ts index ab3539c75..44be39509 100644 --- a/packages/bot/src/handlers/guilds/GUILD_BAN_REMOVE.ts +++ b/packages/bot/src/handlers/guilds/GUILD_BAN_REMOVE.ts @@ -1,7 +1,7 @@ import type { DiscordGatewayPayload, DiscordGuildBanAddRemove } from '@discordeno/types' import type { Bot } from '../../bot.js' -export async function handleGuildBanRemove(bot: Bot, data: DiscordGatewayPayload) { +export async function handleGuildBanRemove(bot: Bot, data: DiscordGatewayPayload): Promise { const payload = data.d as DiscordGuildBanAddRemove await bot.events.guildBanRemove?.(bot.transformers.user(bot, payload.user), bot.transformers.snowflake(payload.guild_id)) diff --git a/packages/bot/src/handlers/guilds/GUILD_CREATE.ts b/packages/bot/src/handlers/guilds/GUILD_CREATE.ts index 64a5f2066..dd53bc2ff 100644 --- a/packages/bot/src/handlers/guilds/GUILD_CREATE.ts +++ b/packages/bot/src/handlers/guilds/GUILD_CREATE.ts @@ -1,8 +1,7 @@ import type { DiscordGatewayPayload, DiscordGuild } from '@discordeno/types' import type { Bot } from '../../bot.js' -import type { Guild } from '../../transformers/guild.js' -export function handleGuildCreate(bot: Bot, data: DiscordGatewayPayload, shardId: number) { +export async function handleGuildCreate(bot: Bot, data: DiscordGatewayPayload, shardId: number): Promise { const payload = data.d as DiscordGuild - bot.events.guildCreate?.(bot.transformers.guild(bot, { guild: payload, shardId }) as Guild) + bot.events.guildCreate?.(bot.transformers.guild(bot, { guild: payload, shardId })) } diff --git a/packages/bot/src/handlers/guilds/GUILD_DELETE.ts b/packages/bot/src/handlers/guilds/GUILD_DELETE.ts index e90bdc6b8..3db895c0a 100644 --- a/packages/bot/src/handlers/guilds/GUILD_DELETE.ts +++ b/packages/bot/src/handlers/guilds/GUILD_DELETE.ts @@ -1,7 +1,7 @@ import type { DiscordGatewayPayload, DiscordUnavailableGuild } from '@discordeno/types' import type { Bot } from '../../bot.js' -export async function handleGuildDelete(bot: Bot, data: DiscordGatewayPayload, shardId: number) { +export async function handleGuildDelete(bot: Bot, data: DiscordGatewayPayload, shardId: number): Promise { const payload = data.d as DiscordUnavailableGuild bot.events.guildDelete?.(bot.transformers.snowflake(payload.id), shardId) } diff --git a/packages/bot/src/handlers/guilds/GUILD_INTEGRATIONS_UPDATE.ts b/packages/bot/src/handlers/guilds/GUILD_INTEGRATIONS_UPDATE.ts index e18113b67..9832a747e 100644 --- a/packages/bot/src/handlers/guilds/GUILD_INTEGRATIONS_UPDATE.ts +++ b/packages/bot/src/handlers/guilds/GUILD_INTEGRATIONS_UPDATE.ts @@ -1,7 +1,7 @@ import type { DiscordGatewayPayload, DiscordGuildIntegrationsUpdate } from '@discordeno/types' import type { Bot } from '../../bot.js' -export async function handleGuildIntegrationsUpdate(bot: Bot, data: DiscordGatewayPayload) { +export async function handleGuildIntegrationsUpdate(bot: Bot, data: DiscordGatewayPayload): Promise { const payload = data.d as DiscordGuildIntegrationsUpdate bot.events.integrationUpdate?.({ diff --git a/packages/bot/src/handlers/guilds/GUILD_STICKERS_UPDATE.ts b/packages/bot/src/handlers/guilds/GUILD_STICKERS_UPDATE.ts new file mode 100644 index 000000000..6cbd16b3c --- /dev/null +++ b/packages/bot/src/handlers/guilds/GUILD_STICKERS_UPDATE.ts @@ -0,0 +1,12 @@ +import type { Bot, DiscordGatewayPayload, DiscordGuildStickersUpdate } from '../..' + +export async function handleGuildStickersUpdate(bot: Bot, data: DiscordGatewayPayload, shardId: number): Promise { + const payload = data.d as DiscordGuildStickersUpdate + + bot.events.guildStickersUpdate?.( + payload.stickers.map((sticker) => { + sticker.guild_id = payload.guild_id + return bot.transformers.sticker(bot, sticker) + }) + ) +} diff --git a/packages/bot/src/handlers/guilds/GUILD_UPDATE.ts b/packages/bot/src/handlers/guilds/GUILD_UPDATE.ts index a9ba8853b..ecfab428c 100644 --- a/packages/bot/src/handlers/guilds/GUILD_UPDATE.ts +++ b/packages/bot/src/handlers/guilds/GUILD_UPDATE.ts @@ -1,9 +1,8 @@ import type { DiscordGatewayPayload, DiscordGuild } from '@discordeno/types' import type { Bot } from '../../bot.js' -import type { Guild } from '../../transformers/guild.js' -export function handleGuildUpdate(bot: Bot, data: DiscordGatewayPayload, shardId: number) { +export async function handleGuildUpdate(bot: Bot, data: DiscordGatewayPayload, shardId: number): Promise { const payload = data.d as DiscordGuild - bot.events.guildUpdate?.(bot.transformers.guild(bot, { guild: payload, shardId }) as Guild) + bot.events.guildUpdate?.(bot.transformers.guild(bot, { guild: payload, shardId })) } diff --git a/packages/bot/src/handlers/guilds/automod/AUTO_MODERATION_ACTION_EXECUTION.ts b/packages/bot/src/handlers/guilds/automod/AUTO_MODERATION_ACTION_EXECUTION.ts index dfdc8acd4..75b30d952 100644 --- a/packages/bot/src/handlers/guilds/automod/AUTO_MODERATION_ACTION_EXECUTION.ts +++ b/packages/bot/src/handlers/guilds/automod/AUTO_MODERATION_ACTION_EXECUTION.ts @@ -2,7 +2,7 @@ import type { DiscordAutoModerationActionExecution, DiscordGatewayPayload } from import type { Bot } from '../../../bot.js' /** Requires the MANAGE_GUILD permission. */ -export function handleAutoModerationActionExecution(bot: Bot, data: DiscordGatewayPayload, shardId: number) { +export async function handleAutoModerationActionExecution(bot: Bot, data: DiscordGatewayPayload, shardId: number): Promise { const payload = data.d as DiscordAutoModerationActionExecution - bot.events.automodActionExecution?.(bot.events.automodActionExecution(payload)) + bot.events.automodActionExecution?.(bot.transformers.automodActionExecution(bot, payload)) } diff --git a/packages/bot/src/handlers/guilds/automod/AUTO_MODERATION_RULE_CREATE.ts b/packages/bot/src/handlers/guilds/automod/AUTO_MODERATION_RULE_CREATE.ts index cb94337d5..7685b4986 100644 --- a/packages/bot/src/handlers/guilds/automod/AUTO_MODERATION_RULE_CREATE.ts +++ b/packages/bot/src/handlers/guilds/automod/AUTO_MODERATION_RULE_CREATE.ts @@ -2,7 +2,7 @@ import type { DiscordAutoModerationRule, DiscordGatewayPayload } from '@discorde import type { Bot } from '../../../bot.js' /** Requires the MANAGE_GUILD permission. */ -export function handleAutoModerationRuleCreate(bot: Bot, data: DiscordGatewayPayload, shardId: number) { +export async function handleAutoModerationRuleCreate(bot: Bot, data: DiscordGatewayPayload, shardId: number): Promise { const payload = data.d as DiscordAutoModerationRule - bot.events.automodRuleCreate?.(bot.events.automodRule(payload)) + bot.events.automodRuleCreate?.(bot.transformers.automodRule(bot, payload)) } diff --git a/packages/bot/src/handlers/guilds/automod/AUTO_MODERATION_RULE_DELETE.ts b/packages/bot/src/handlers/guilds/automod/AUTO_MODERATION_RULE_DELETE.ts index cc9319550..2980b11b6 100644 --- a/packages/bot/src/handlers/guilds/automod/AUTO_MODERATION_RULE_DELETE.ts +++ b/packages/bot/src/handlers/guilds/automod/AUTO_MODERATION_RULE_DELETE.ts @@ -2,7 +2,7 @@ import type { DiscordAutoModerationRule, DiscordGatewayPayload } from '@discorde import type { Bot } from '../../../bot.js' /** Requires the MANAGE_GUILD permission. */ -export function handleAutoModerationRuleDelete(bot: Bot, data: DiscordGatewayPayload, shardId: number) { +export async function handleAutoModerationRuleDelete(bot: Bot, data: DiscordGatewayPayload, shardId: number): Promise { const payload = data.d as DiscordAutoModerationRule - bot.events.automodRuleDelete?.(bot.events.automodRule(payload)) + bot.events.automodRuleDelete?.(bot.transformers.automodRule(bot, payload)) } diff --git a/packages/bot/src/handlers/guilds/automod/AUTO_MODERATION_RULE_UPDATE.ts b/packages/bot/src/handlers/guilds/automod/AUTO_MODERATION_RULE_UPDATE.ts index 63f3f7e46..be7793ac6 100644 --- a/packages/bot/src/handlers/guilds/automod/AUTO_MODERATION_RULE_UPDATE.ts +++ b/packages/bot/src/handlers/guilds/automod/AUTO_MODERATION_RULE_UPDATE.ts @@ -2,7 +2,7 @@ import type { DiscordAutoModerationRule, DiscordGatewayPayload } from '@discorde import type { Bot } from '../../../bot.js' /** Requires the MANAGE_GUILD permission. */ -export function handleAutoModerationRuleUpdate(bot: Bot, data: DiscordGatewayPayload, shardId: number) { +export async function handleAutoModerationRuleUpdate(bot: Bot, data: DiscordGatewayPayload, shardId: number): Promise { const payload = data.d as DiscordAutoModerationRule bot.events.automodRuleUpdate?.(bot.transformers.automodRule(bot, payload)) } diff --git a/packages/bot/src/handlers/guilds/automod/index.ts b/packages/bot/src/handlers/guilds/automod/index.ts new file mode 100644 index 000000000..c47db435f --- /dev/null +++ b/packages/bot/src/handlers/guilds/automod/index.ts @@ -0,0 +1,4 @@ +export * from './AUTO_MODERATION_ACTION_EXECUTION.js' +export * from './AUTO_MODERATION_RULE_CREATE.js' +export * from './AUTO_MODERATION_RULE_DELETE.js' +export * from './AUTO_MODERATION_RULE_UPDATE.js' diff --git a/packages/bot/src/handlers/guilds/automod/mod.ts b/packages/bot/src/handlers/guilds/automod/mod.ts deleted file mode 100644 index e69de29bb..000000000 diff --git a/packages/bot/src/handlers/guilds/mod.ts b/packages/bot/src/handlers/guilds/index.ts similarity index 69% rename from packages/bot/src/handlers/guilds/mod.ts rename to packages/bot/src/handlers/guilds/index.ts index 29e68bfa6..ad793cefd 100644 --- a/packages/bot/src/handlers/guilds/mod.ts +++ b/packages/bot/src/handlers/guilds/index.ts @@ -1,4 +1,5 @@ -export * from "./scheduledEvents/mod.js"; +export * from "./automod/index.js"; +export * from "./scheduledEvents/index.js"; export * from "./GUILD_AUDIT_LOG_ENTRY_CREATE.js"; export * from "./GUILD_BAN_ADD.js"; @@ -6,4 +7,5 @@ export * from "./GUILD_BAN_REMOVE.js"; export * from "./GUILD_CREATE.js"; export * from "./GUILD_DELETE.js"; export * from "./GUILD_INTEGRATIONS_UPDATE.js"; +export * from "./GUILD_STICKERS_UPDATE.js"; export * from "./GUILD_UPDATE.js"; diff --git a/packages/bot/src/handlers/guilds/scheduledEvents/GUILD_SCHEDULED_EVENT_CREATE.ts b/packages/bot/src/handlers/guilds/scheduledEvents/GUILD_SCHEDULED_EVENT_CREATE.ts index 84812cb6d..b071779f3 100644 --- a/packages/bot/src/handlers/guilds/scheduledEvents/GUILD_SCHEDULED_EVENT_CREATE.ts +++ b/packages/bot/src/handlers/guilds/scheduledEvents/GUILD_SCHEDULED_EVENT_CREATE.ts @@ -1,7 +1,7 @@ import type { DiscordGatewayPayload, DiscordScheduledEvent } from '@discordeno/types' import type { Bot } from '../../../bot.js' -export function handleGuildScheduledEventCreate(bot: Bot, data: DiscordGatewayPayload, shardId: number) { +export async function handleGuildScheduledEventCreate(bot: Bot, data: DiscordGatewayPayload, shardId: number): Promise { const payload = data.d as DiscordScheduledEvent bot.events.scheduledEventCreate?.(bot.transformers.scheduledEvent(bot, payload)) } diff --git a/packages/bot/src/handlers/guilds/scheduledEvents/GUILD_SCHEDULED_EVENT_DELETE.ts b/packages/bot/src/handlers/guilds/scheduledEvents/GUILD_SCHEDULED_EVENT_DELETE.ts index 247e5063f..b056808cd 100644 --- a/packages/bot/src/handlers/guilds/scheduledEvents/GUILD_SCHEDULED_EVENT_DELETE.ts +++ b/packages/bot/src/handlers/guilds/scheduledEvents/GUILD_SCHEDULED_EVENT_DELETE.ts @@ -1,7 +1,7 @@ import type { DiscordGatewayPayload, DiscordScheduledEvent } from '@discordeno/types' import type { Bot } from '../../../bot.js' -export function handleGuildScheduledEventDelete(bot: Bot, data: DiscordGatewayPayload) { +export async function handleGuildScheduledEventDelete(bot: Bot, data: DiscordGatewayPayload): Promise { const payload = data.d as DiscordScheduledEvent bot.events.scheduledEventDelete?.(bot.transformers.scheduledEvent(bot, payload)) } diff --git a/packages/bot/src/handlers/guilds/scheduledEvents/GUILD_SCHEDULED_EVENT_UPDATE.ts b/packages/bot/src/handlers/guilds/scheduledEvents/GUILD_SCHEDULED_EVENT_UPDATE.ts index 2c87cc8e0..e60e2137d 100644 --- a/packages/bot/src/handlers/guilds/scheduledEvents/GUILD_SCHEDULED_EVENT_UPDATE.ts +++ b/packages/bot/src/handlers/guilds/scheduledEvents/GUILD_SCHEDULED_EVENT_UPDATE.ts @@ -1,7 +1,7 @@ import type { DiscordGatewayPayload, DiscordScheduledEvent } from '@discordeno/types' import type { Bot } from '../../../bot.js' -export function handleGuildScheduledEventUpdate(bot: Bot, data: DiscordGatewayPayload) { +export async function handleGuildScheduledEventUpdate(bot: Bot, data: DiscordGatewayPayload): Promise { const payload = data.d as DiscordScheduledEvent bot.events.scheduledEventUpdate?.(bot.transformers.scheduledEvent(bot, payload)) } diff --git a/packages/bot/src/handlers/guilds/scheduledEvents/GUILD_SCHEDULED_EVENT_USER_ADD.ts b/packages/bot/src/handlers/guilds/scheduledEvents/GUILD_SCHEDULED_EVENT_USER_ADD.ts index d73cfb2e5..6e2a9839c 100644 --- a/packages/bot/src/handlers/guilds/scheduledEvents/GUILD_SCHEDULED_EVENT_USER_ADD.ts +++ b/packages/bot/src/handlers/guilds/scheduledEvents/GUILD_SCHEDULED_EVENT_USER_ADD.ts @@ -1,10 +1,10 @@ import type { DiscordGatewayPayload, DiscordScheduledEventUserAdd } from '@discordeno/types' import type { Bot } from '../../../bot.js' -export function handleGuildScheduledEventUserAdd(bot: Bot, data: DiscordGatewayPayload) { +export async function handleGuildScheduledEventUserAdd(bot: Bot, data: DiscordGatewayPayload): Promise { const payload = data.d as DiscordScheduledEventUserAdd - return bot.events.scheduledEventUserAdd?.({ + bot.events.scheduledEventUserAdd?.({ guildScheduledEventId: bot.transformers.snowflake(payload.guild_scheduled_event_id), userId: bot.transformers.snowflake(payload.user_id), guildId: bot.transformers.snowflake(payload.guild_id), diff --git a/packages/bot/src/handlers/guilds/scheduledEvents/GUILD_SCHEDULED_EVENT_USER_REMOVE.ts b/packages/bot/src/handlers/guilds/scheduledEvents/GUILD_SCHEDULED_EVENT_USER_REMOVE.ts index fe11c0662..b4643c410 100644 --- a/packages/bot/src/handlers/guilds/scheduledEvents/GUILD_SCHEDULED_EVENT_USER_REMOVE.ts +++ b/packages/bot/src/handlers/guilds/scheduledEvents/GUILD_SCHEDULED_EVENT_USER_REMOVE.ts @@ -1,10 +1,10 @@ import type { DiscordGatewayPayload, DiscordScheduledEventUserRemove } from '@discordeno/types' import type { Bot } from '../../../bot.js' -export function handleGuildScheduledEventUserRemove(bot: Bot, data: DiscordGatewayPayload) { +export async function handleGuildScheduledEventUserRemove(bot: Bot, data: DiscordGatewayPayload): Promise { const payload = data.d as DiscordScheduledEventUserRemove - return bot.events.scheduledEventUserRemove?.({ + bot.events.scheduledEventUserRemove?.({ guildScheduledEventId: bot.transformers.snowflake(payload.guild_scheduled_event_id), userId: bot.transformers.snowflake(payload.user_id), guildId: bot.transformers.snowflake(payload.guild_id), diff --git a/packages/bot/src/handlers/guilds/scheduledEvents/mod.ts b/packages/bot/src/handlers/guilds/scheduledEvents/index.ts similarity index 100% rename from packages/bot/src/handlers/guilds/scheduledEvents/mod.ts rename to packages/bot/src/handlers/guilds/scheduledEvents/index.ts diff --git a/packages/bot/src/handlers/index.ts b/packages/bot/src/handlers/index.ts new file mode 100644 index 000000000..243289d18 --- /dev/null +++ b/packages/bot/src/handlers/index.ts @@ -0,0 +1,12 @@ +export * from './channels/index.js' +export * from './emojis/index.js' +export * from './guilds/index.js' +export * from './integrations/index.js' +export * from './interactions/index.js' +export * from './invites/index.js' +export * from './members/index.js' +export * from './messages/index.js' +export * from './misc/index.js' +export * from './roles/index.js' +export * from './voice/index.js' +export * from './webhooks/index.js' diff --git a/packages/bot/src/handlers/integrations/INTEGRATION_CREATE.ts b/packages/bot/src/handlers/integrations/INTEGRATION_CREATE.ts index afe6f51bf..0bf883a9a 100644 --- a/packages/bot/src/handlers/integrations/INTEGRATION_CREATE.ts +++ b/packages/bot/src/handlers/integrations/INTEGRATION_CREATE.ts @@ -1,6 +1,6 @@ import type { DiscordGatewayPayload, DiscordIntegrationCreateUpdate } from '@discordeno/types' import type { Bot } from '../../index.js' -export function handleIntegrationCreate(bot: Bot, data: DiscordGatewayPayload) { +export async function handleIntegrationCreate(bot: Bot, data: DiscordGatewayPayload): Promise { bot.events.integrationCreate?.(bot.transformers.integration(bot, data.d as DiscordIntegrationCreateUpdate)) } diff --git a/packages/bot/src/handlers/integrations/INTEGRATION_DELETE.ts b/packages/bot/src/handlers/integrations/INTEGRATION_DELETE.ts index e43bd1534..e7ae3f909 100644 --- a/packages/bot/src/handlers/integrations/INTEGRATION_DELETE.ts +++ b/packages/bot/src/handlers/integrations/INTEGRATION_DELETE.ts @@ -1,7 +1,7 @@ import type { DiscordGatewayPayload, DiscordIntegrationDelete } from '@discordeno/types' import type { Bot } from '../../index.js' -export function handleIntegrationDelete(bot: Bot, data: DiscordGatewayPayload) { +export async function handleIntegrationDelete(bot: Bot, data: DiscordGatewayPayload): Promise { const payload = data.d as DiscordIntegrationDelete bot.events.integrationDelete?.({ diff --git a/packages/bot/src/handlers/integrations/INTEGRATION_UPDATE.ts b/packages/bot/src/handlers/integrations/INTEGRATION_UPDATE.ts index 4a339b90c..7c07dfb77 100644 --- a/packages/bot/src/handlers/integrations/INTEGRATION_UPDATE.ts +++ b/packages/bot/src/handlers/integrations/INTEGRATION_UPDATE.ts @@ -1,6 +1,6 @@ import type { DiscordGatewayPayload, DiscordIntegrationCreateUpdate } from '@discordeno/types' import type { Bot } from '../../index.js' -export function handleIntegrationUpdate(bot: Bot, data: DiscordGatewayPayload) { +export async function handleIntegrationUpdate(bot: Bot, data: DiscordGatewayPayload): Promise { bot.events.integrationUpdate?.(bot.transformers.integration(bot, data.d as DiscordIntegrationCreateUpdate)) } diff --git a/packages/bot/src/handlers/integrations/mod.ts b/packages/bot/src/handlers/integrations/index.ts similarity index 100% rename from packages/bot/src/handlers/integrations/mod.ts rename to packages/bot/src/handlers/integrations/index.ts diff --git a/packages/bot/src/handlers/interactions/APPLICATION_COMMAND_PERMISSIONS_UPDATE.ts b/packages/bot/src/handlers/interactions/APPLICATION_COMMAND_PERMISSIONS_UPDATE.ts new file mode 100644 index 000000000..31bb21f60 --- /dev/null +++ b/packages/bot/src/handlers/interactions/APPLICATION_COMMAND_PERMISSIONS_UPDATE.ts @@ -0,0 +1,6 @@ +import type { Bot, DiscordGatewayPayload, DiscordGuildApplicationCommandPermissions } from "../.."; + +export async function handleApplicationCommandPermissionsUpdate(bot: Bot, data: DiscordGatewayPayload, shardId: number): Promise { + const payload = data.d as DiscordGuildApplicationCommandPermissions + bot.events.applicationCommandPermissionsUpdate?.(bot.transformers.applicationCommandPermission(bot, payload)) +} \ No newline at end of file diff --git a/packages/bot/src/handlers/interactions/INTERACTION_CREATE.ts b/packages/bot/src/handlers/interactions/INTERACTION_CREATE.ts index aea7d719d..aa62d785d 100644 --- a/packages/bot/src/handlers/interactions/INTERACTION_CREATE.ts +++ b/packages/bot/src/handlers/interactions/INTERACTION_CREATE.ts @@ -1,6 +1,6 @@ import type { DiscordGatewayPayload, DiscordInteraction } from '@discordeno/types' import type { Bot } from '../../index.js' -export async function handleInteractionCreate(bot: Bot, data: DiscordGatewayPayload) { +export async function handleInteractionCreate(bot: Bot, data: DiscordGatewayPayload): Promise { bot.events.interactionCreate?.(bot.transformers.interaction(bot, data.d as DiscordInteraction)) } diff --git a/packages/bot/src/handlers/interactions/index.ts b/packages/bot/src/handlers/interactions/index.ts new file mode 100644 index 000000000..224d68b0e --- /dev/null +++ b/packages/bot/src/handlers/interactions/index.ts @@ -0,0 +1,2 @@ +export * from './APPLICATION_COMMAND_PERMISSIONS_UPDATE.js' +export * from './INTERACTION_CREATE.js' diff --git a/packages/bot/src/handlers/interactions/mod.ts b/packages/bot/src/handlers/interactions/mod.ts deleted file mode 100644 index b4de5f934..000000000 --- a/packages/bot/src/handlers/interactions/mod.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./INTERACTION_CREATE.js"; diff --git a/packages/bot/src/handlers/invites/INVITE_CREATE.ts b/packages/bot/src/handlers/invites/INVITE_CREATE.ts index 89473a63d..aa9077e88 100644 --- a/packages/bot/src/handlers/invites/INVITE_CREATE.ts +++ b/packages/bot/src/handlers/invites/INVITE_CREATE.ts @@ -1,6 +1,6 @@ import type { DiscordGatewayPayload, DiscordInviteCreate } from '@discordeno/types' import type { Bot } from '../../index.js' -export function handleInviteCreate(bot: Bot, data: DiscordGatewayPayload) { +export async function handleInviteCreate(bot: Bot, data: DiscordGatewayPayload): Promise { bot.events.inviteCreate?.(bot.transformers.invite(bot, data.d as DiscordInviteCreate)) } diff --git a/packages/bot/src/handlers/invites/INVITE_DELETE.ts b/packages/bot/src/handlers/invites/INVITE_DELETE.ts index e77f064bc..6fdc70945 100644 --- a/packages/bot/src/handlers/invites/INVITE_DELETE.ts +++ b/packages/bot/src/handlers/invites/INVITE_DELETE.ts @@ -1,7 +1,7 @@ import type { DiscordGatewayPayload, DiscordInviteDelete } from '@discordeno/types' import type { Bot } from '../../index.js' -export function handleInviteDelete(bot: Bot, data: DiscordGatewayPayload) { +export async function handleInviteDelete(bot: Bot, data: DiscordGatewayPayload): Promise { const payload = data.d as DiscordInviteDelete bot.events.inviteDelete?.({ diff --git a/packages/bot/src/handlers/invites/mod.ts b/packages/bot/src/handlers/invites/index.ts similarity index 100% rename from packages/bot/src/handlers/invites/mod.ts rename to packages/bot/src/handlers/invites/index.ts diff --git a/packages/bot/src/handlers/members/GUILD_MEMBERS_CHUNK.ts b/packages/bot/src/handlers/members/GUILD_MEMBERS_CHUNK.ts index ef28ebe57..11ad62143 100644 --- a/packages/bot/src/handlers/members/GUILD_MEMBERS_CHUNK.ts +++ b/packages/bot/src/handlers/members/GUILD_MEMBERS_CHUNK.ts @@ -2,7 +2,7 @@ import type { DiscordGatewayPayload, DiscordGuildMembersChunk } from '@discorden import { PresenceStatus } from '@discordeno/types' import type { Bot } from '../../index.js' -export async function handleGuildMembersChunk(bot: Bot, data: DiscordGatewayPayload) { +export async function handleGuildMembersChunk(bot: Bot, data: DiscordGatewayPayload): Promise { const payload = data.d as DiscordGuildMembersChunk const guildId = bot.transformers.snowflake(payload.guild_id) diff --git a/packages/bot/src/handlers/members/GUILD_MEMBER_ADD.ts b/packages/bot/src/handlers/members/GUILD_MEMBER_ADD.ts index 2e592fc6b..dfe8bd898 100644 --- a/packages/bot/src/handlers/members/GUILD_MEMBER_ADD.ts +++ b/packages/bot/src/handlers/members/GUILD_MEMBER_ADD.ts @@ -1,7 +1,7 @@ import type { DiscordGatewayPayload, DiscordGuildMemberAdd } from '@discordeno/types' import type { Bot } from '../../index.js' -export async function handleGuildMemberAdd(bot: Bot, data: DiscordGatewayPayload) { +export async function handleGuildMemberAdd(bot: Bot, data: DiscordGatewayPayload): Promise { const payload = data.d as DiscordGuildMemberAdd const guildId = bot.transformers.snowflake(payload.guild_id) const user = bot.transformers.user(bot, payload.user) diff --git a/packages/bot/src/handlers/members/GUILD_MEMBER_REMOVE.ts b/packages/bot/src/handlers/members/GUILD_MEMBER_REMOVE.ts index 38d2e07da..6bcd65049 100644 --- a/packages/bot/src/handlers/members/GUILD_MEMBER_REMOVE.ts +++ b/packages/bot/src/handlers/members/GUILD_MEMBER_REMOVE.ts @@ -1,7 +1,7 @@ import type { DiscordGatewayPayload, DiscordGuildMemberRemove } from '@discordeno/types' import type { Bot } from '../../index.js' -export async function handleGuildMemberRemove(bot: Bot, data: DiscordGatewayPayload) { +export async function handleGuildMemberRemove(bot: Bot, data: DiscordGatewayPayload): Promise { const payload = data.d as DiscordGuildMemberRemove const guildId = bot.transformers.snowflake(payload.guild_id) const user = bot.transformers.user(bot, payload.user) diff --git a/packages/bot/src/handlers/members/GUILD_MEMBER_UPDATE.ts b/packages/bot/src/handlers/members/GUILD_MEMBER_UPDATE.ts index 77251f50a..33dc5e540 100644 --- a/packages/bot/src/handlers/members/GUILD_MEMBER_UPDATE.ts +++ b/packages/bot/src/handlers/members/GUILD_MEMBER_UPDATE.ts @@ -1,7 +1,7 @@ import type { DiscordGatewayPayload, DiscordGuildMemberUpdate } from '@discordeno/types' import type { Bot } from '../../index.js' -export async function handleGuildMemberUpdate(bot: Bot, data: DiscordGatewayPayload) { +export async function handleGuildMemberUpdate(bot: Bot, data: DiscordGatewayPayload): Promise { const payload = data.d as DiscordGuildMemberUpdate const user = bot.transformers.user(bot, payload.user) diff --git a/packages/bot/src/handlers/members/mod.ts b/packages/bot/src/handlers/members/index.ts similarity index 100% rename from packages/bot/src/handlers/members/mod.ts rename to packages/bot/src/handlers/members/index.ts diff --git a/packages/bot/src/handlers/messages/MESSAGE_CREATE.ts b/packages/bot/src/handlers/messages/MESSAGE_CREATE.ts index ded09d135..c0d6cca82 100644 --- a/packages/bot/src/handlers/messages/MESSAGE_CREATE.ts +++ b/packages/bot/src/handlers/messages/MESSAGE_CREATE.ts @@ -1,8 +1,8 @@ import type { DiscordGatewayPayload, DiscordMessage } from '@discordeno/types' import type { Bot } from '../../index.js' -export async function handleMessageCreate(bot: Bot, data: DiscordGatewayPayload) { +export async function handleMessageCreate(bot: Bot, data: DiscordGatewayPayload): Promise { const payload = data.d as DiscordMessage - bot.events.messageCreate?.(bot.events.message(payload)) + bot.events.messageCreate?.(bot.transformers.message(bot, payload)) } diff --git a/packages/bot/src/handlers/messages/MESSAGE_DELETE.ts b/packages/bot/src/handlers/messages/MESSAGE_DELETE.ts index 1b3eb3b4c..ca37a91f7 100644 --- a/packages/bot/src/handlers/messages/MESSAGE_DELETE.ts +++ b/packages/bot/src/handlers/messages/MESSAGE_DELETE.ts @@ -1,7 +1,7 @@ import type { DiscordGatewayPayload, DiscordMessageDelete } from '@discordeno/types' import type { Bot } from '../../index.js' -export async function handleMessageDelete(bot: Bot, data: DiscordGatewayPayload) { +export async function handleMessageDelete(bot: Bot, data: DiscordGatewayPayload): Promise { const payload = data.d as DiscordMessageDelete bot.events.messageDelete?.({ diff --git a/packages/bot/src/handlers/messages/MESSAGE_DELETE_BULK.ts b/packages/bot/src/handlers/messages/MESSAGE_DELETE_BULK.ts index 1d75d239d..9f1e2e2d1 100644 --- a/packages/bot/src/handlers/messages/MESSAGE_DELETE_BULK.ts +++ b/packages/bot/src/handlers/messages/MESSAGE_DELETE_BULK.ts @@ -1,7 +1,7 @@ import type { DiscordGatewayPayload, DiscordMessageDeleteBulk } from '@discordeno/types' import type { Bot } from '../../index.js' -export async function handleMessageDeleteBulk(bot: Bot, data: DiscordGatewayPayload) { +export async function handleMessageDeleteBulk(bot: Bot, data: DiscordGatewayPayload): Promise { const payload = data.d as DiscordMessageDeleteBulk const channelId = bot.transformers.snowflake(payload.channel_id) @@ -9,7 +9,7 @@ export async function handleMessageDeleteBulk(bot: Bot, data: DiscordGatewayPayl bot.events.messageDeleteBulk?.({ ids: payload.ids.map((id) => bot.transformers.snowflake(id)), - channelId: bot.transformers.snowflake(payload.channel_id), - guildId: payload.guild_id ? bot.transformers.snowflake(payload.guild_id) : undefined, + channelId, + guildId, }) } diff --git a/packages/bot/src/handlers/messages/MESSAGE_REACTION_ADD.ts b/packages/bot/src/handlers/messages/MESSAGE_REACTION_ADD.ts index 930d91097..871cad09f 100644 --- a/packages/bot/src/handlers/messages/MESSAGE_REACTION_ADD.ts +++ b/packages/bot/src/handlers/messages/MESSAGE_REACTION_ADD.ts @@ -1,7 +1,7 @@ import type { DiscordGatewayPayload, DiscordMessageReactionAdd } from '@discordeno/types' import type { Bot } from '../../index.js' -export async function handleMessageReactionAdd(bot: Bot, data: DiscordGatewayPayload) { +export async function handleMessageReactionAdd(bot: Bot, data: DiscordGatewayPayload): Promise { const payload = data.d as DiscordMessageReactionAdd const guildId = payload.guild_id ? bot.transformers.snowflake(payload.guild_id) : undefined @@ -13,6 +13,6 @@ export async function handleMessageReactionAdd(bot: Bot, data: DiscordGatewayPay guildId, member: payload.member && guildId ? bot.transformers.member(bot, payload.member, guildId, userId) : undefined, user: payload.member ? bot.transformers.user(bot, payload.member.user) : undefined, - emoji: bot.events.emoji(payload.emoji), + emoji: bot.transformers.emoji(bot, payload.emoji), }) } diff --git a/packages/bot/src/handlers/messages/MESSAGE_REACTION_REMOVE.ts b/packages/bot/src/handlers/messages/MESSAGE_REACTION_REMOVE.ts index 81645bf7c..a4264269c 100644 --- a/packages/bot/src/handlers/messages/MESSAGE_REACTION_REMOVE.ts +++ b/packages/bot/src/handlers/messages/MESSAGE_REACTION_REMOVE.ts @@ -1,7 +1,7 @@ import type { DiscordGatewayPayload, DiscordMessageReactionRemove } from '@discordeno/types' import type { Bot } from '../../index.js' -export async function handleMessageReactionRemove(bot: Bot, data: DiscordGatewayPayload) { +export async function handleMessageReactionRemove(bot: Bot, data: DiscordGatewayPayload): Promise { const payload = data.d as DiscordMessageReactionRemove bot.events.reactionRemove?.({ diff --git a/packages/bot/src/handlers/messages/MESSAGE_REACTION_REMOVE_ALL.ts b/packages/bot/src/handlers/messages/MESSAGE_REACTION_REMOVE_ALL.ts index 24e57cc95..f57a41d81 100644 --- a/packages/bot/src/handlers/messages/MESSAGE_REACTION_REMOVE_ALL.ts +++ b/packages/bot/src/handlers/messages/MESSAGE_REACTION_REMOVE_ALL.ts @@ -1,7 +1,7 @@ import type { DiscordGatewayPayload, DiscordMessageReactionRemoveAll } from '@discordeno/types' import type { Bot } from '../../index.js' -export async function handleMessageReactionRemoveAll(bot: Bot, data: DiscordGatewayPayload) { +export async function handleMessageReactionRemoveAll(bot: Bot, data: DiscordGatewayPayload): Promise { const payload = data.d as DiscordMessageReactionRemoveAll bot.events.reactionRemoveAll?.({ diff --git a/packages/bot/src/handlers/messages/MESSAGE_REACTION_REMOVE_EMOJI.ts b/packages/bot/src/handlers/messages/MESSAGE_REACTION_REMOVE_EMOJI.ts index 8c8dacdca..a10502cf3 100644 --- a/packages/bot/src/handlers/messages/MESSAGE_REACTION_REMOVE_EMOJI.ts +++ b/packages/bot/src/handlers/messages/MESSAGE_REACTION_REMOVE_EMOJI.ts @@ -1,7 +1,7 @@ import type { DiscordGatewayPayload, DiscordMessageReactionRemoveEmoji } from '@discordeno/types' import type { Bot } from '../../index.js' -export async function handleMessageReactionRemoveEmoji(bot: Bot, data: DiscordGatewayPayload) { +export async function handleMessageReactionRemoveEmoji(bot: Bot, data: DiscordGatewayPayload): Promise { const payload = data.d as DiscordMessageReactionRemoveEmoji bot.events.reactionRemoveEmoji?.({ diff --git a/packages/bot/src/handlers/messages/MESSAGE_UPDATE.ts b/packages/bot/src/handlers/messages/MESSAGE_UPDATE.ts index 8076aa2be..2af0246bc 100644 --- a/packages/bot/src/handlers/messages/MESSAGE_UPDATE.ts +++ b/packages/bot/src/handlers/messages/MESSAGE_UPDATE.ts @@ -1,7 +1,7 @@ import type { DiscordGatewayPayload, DiscordMessage } from '@discordeno/types' import type { Bot } from '../../index.js' -export async function handleMessageUpdate(bot: Bot, data: DiscordGatewayPayload) { +export async function handleMessageUpdate(bot: Bot, data: DiscordGatewayPayload): Promise { const payload = data.d as DiscordMessage if (!payload.edited_timestamp) return diff --git a/packages/bot/src/handlers/messages/mod.ts b/packages/bot/src/handlers/messages/index.ts similarity index 100% rename from packages/bot/src/handlers/messages/mod.ts rename to packages/bot/src/handlers/messages/index.ts diff --git a/packages/bot/src/handlers/misc/PRESENCE_UPDATE.ts b/packages/bot/src/handlers/misc/PRESENCE_UPDATE.ts index 695ac9aa3..794f332bd 100644 --- a/packages/bot/src/handlers/misc/PRESENCE_UPDATE.ts +++ b/packages/bot/src/handlers/misc/PRESENCE_UPDATE.ts @@ -1,6 +1,6 @@ import type { DiscordGatewayPayload, DiscordPresenceUpdate } from '@discordeno/types' import type { Bot } from '../../index.js' -export async function handlePresenceUpdate(bot: Bot, data: DiscordGatewayPayload) { +export async function handlePresenceUpdate(bot: Bot, data: DiscordGatewayPayload): Promise { bot.events.presenceUpdate?.(bot.transformers.presence(bot, data.d as DiscordPresenceUpdate)) } diff --git a/packages/bot/src/handlers/misc/READY.ts b/packages/bot/src/handlers/misc/READY.ts index 7615f89e4..709b9a858 100644 --- a/packages/bot/src/handlers/misc/READY.ts +++ b/packages/bot/src/handlers/misc/READY.ts @@ -1,7 +1,7 @@ import type { DiscordGatewayPayload, DiscordReady } from '@discordeno/types' import type { Bot } from '../../index.js' -export function handleReady(bot: Bot, data: DiscordGatewayPayload, shardId: number) { +export async function handleReady(bot: Bot, data: DiscordGatewayPayload, shardId: number): Promise { const payload = data.d as DiscordReady // Triggered on each shard bot.events.ready?.( diff --git a/packages/bot/src/handlers/misc/TYPING_START.ts b/packages/bot/src/handlers/misc/TYPING_START.ts index c8799d107..01cef0eba 100644 --- a/packages/bot/src/handlers/misc/TYPING_START.ts +++ b/packages/bot/src/handlers/misc/TYPING_START.ts @@ -1,7 +1,7 @@ import type { DiscordGatewayPayload, DiscordTypingStart } from '@discordeno/types' import type { Bot } from '../../index.js' -export function handleTypingStart(bot: Bot, data: DiscordGatewayPayload) { +export async function handleTypingStart(bot: Bot, data: DiscordGatewayPayload): Promise { const payload = data.d as DiscordTypingStart const guildId = payload.guild_id ? bot.transformers.snowflake(payload.guild_id) : undefined diff --git a/packages/bot/src/handlers/misc/USER_UPDATE.ts b/packages/bot/src/handlers/misc/USER_UPDATE.ts index 742395451..d790efffe 100644 --- a/packages/bot/src/handlers/misc/USER_UPDATE.ts +++ b/packages/bot/src/handlers/misc/USER_UPDATE.ts @@ -1,7 +1,7 @@ import type { DiscordGatewayPayload, DiscordUser } from '@discordeno/types' import type { Bot } from '../../index.js' -export async function handleUserUpdate(bot: Bot, data: DiscordGatewayPayload) { +export async function handleUserUpdate(bot: Bot, data: DiscordGatewayPayload): Promise { const payload = data.d as DiscordUser bot.events.botUpdate?.(bot.transformers.user(bot, payload)) } diff --git a/packages/bot/src/handlers/misc/mod.ts b/packages/bot/src/handlers/misc/index.ts similarity index 100% rename from packages/bot/src/handlers/misc/mod.ts rename to packages/bot/src/handlers/misc/index.ts diff --git a/packages/bot/src/handlers/mod.ts b/packages/bot/src/handlers/mod.ts deleted file mode 100644 index 505b37914..000000000 --- a/packages/bot/src/handlers/mod.ts +++ /dev/null @@ -1,12 +0,0 @@ -export * from "./channels/mod.js"; -export * from "./emojis/mod.js"; -export * from "./guilds/mod.js"; -export * from "./integrations/mod.js"; -export * from "./interactions/mod.js"; -export * from "./invites/mod.js"; -export * from "./members/mod.js"; -export * from "./messages/mod.js"; -export * from "./misc/mod.js"; -export * from "./roles/mod.js"; -export * from "./voice/mod.js"; -export * from "./webhooks/mod.js"; diff --git a/packages/bot/src/handlers/roles/GUILD_ROLE_CREATE.ts b/packages/bot/src/handlers/roles/GUILD_ROLE_CREATE.ts index ee9acb9bf..5e5138c8f 100644 --- a/packages/bot/src/handlers/roles/GUILD_ROLE_CREATE.ts +++ b/packages/bot/src/handlers/roles/GUILD_ROLE_CREATE.ts @@ -1,7 +1,7 @@ import type { DiscordGatewayPayload, DiscordGuildRoleCreate } from '@discordeno/types' import type { Bot } from '../../index.js' -export async function handleGuildRoleCreate(bot: Bot, data: DiscordGatewayPayload) { +export async function handleGuildRoleCreate(bot: Bot, data: DiscordGatewayPayload): Promise { const payload = data.d as DiscordGuildRoleCreate bot.events.roleCreate?.( bot.transformers.role(bot, { diff --git a/packages/bot/src/handlers/roles/GUILD_ROLE_DELETE.ts b/packages/bot/src/handlers/roles/GUILD_ROLE_DELETE.ts index 9a4b24fc4..0440cd755 100644 --- a/packages/bot/src/handlers/roles/GUILD_ROLE_DELETE.ts +++ b/packages/bot/src/handlers/roles/GUILD_ROLE_DELETE.ts @@ -1,7 +1,7 @@ import type { DiscordGatewayPayload, DiscordGuildRoleDelete } from '@discordeno/types' import type { Bot } from '../../index.js' -export async function handleGuildRoleDelete(bot: Bot, data: DiscordGatewayPayload) { +export async function handleGuildRoleDelete(bot: Bot, data: DiscordGatewayPayload): Promise { const payload = data.d as DiscordGuildRoleDelete bot.events.roleDelete?.({ roleId: bot.transformers.snowflake(payload.role_id), diff --git a/packages/bot/src/handlers/roles/GUILD_ROLE_UPDATE.ts b/packages/bot/src/handlers/roles/GUILD_ROLE_UPDATE.ts index d6b253289..63f641242 100644 --- a/packages/bot/src/handlers/roles/GUILD_ROLE_UPDATE.ts +++ b/packages/bot/src/handlers/roles/GUILD_ROLE_UPDATE.ts @@ -1,7 +1,7 @@ import type { DiscordGatewayPayload, DiscordGuildRoleUpdate } from '@discordeno/types' import type { Bot } from '../../index.js' -export async function handleGuildRoleUpdate(bot: Bot, data: DiscordGatewayPayload) { +export async function handleGuildRoleUpdate(bot: Bot, data: DiscordGatewayPayload): Promise { const payload = data.d as DiscordGuildRoleUpdate bot.events.roleUpdate?.( diff --git a/packages/bot/src/handlers/roles/mod.ts b/packages/bot/src/handlers/roles/index.ts similarity index 100% rename from packages/bot/src/handlers/roles/mod.ts rename to packages/bot/src/handlers/roles/index.ts diff --git a/packages/bot/src/handlers/voice/VOICE_SERVER_UPDATE.ts b/packages/bot/src/handlers/voice/VOICE_SERVER_UPDATE.ts index 11461f593..c3962dc8e 100644 --- a/packages/bot/src/handlers/voice/VOICE_SERVER_UPDATE.ts +++ b/packages/bot/src/handlers/voice/VOICE_SERVER_UPDATE.ts @@ -1,7 +1,7 @@ import type { DiscordGatewayPayload, DiscordVoiceServerUpdate } from '@discordeno/types' import type { Bot } from '../../index.js' -export async function handleVoiceServerUpdate(bot: Bot, data: DiscordGatewayPayload) { +export async function handleVoiceServerUpdate(bot: Bot, data: DiscordGatewayPayload): Promise { const payload = data.d as DiscordVoiceServerUpdate bot.events.voiceServerUpdate?.({ diff --git a/packages/bot/src/handlers/voice/VOICE_STATE_UPDATE.ts b/packages/bot/src/handlers/voice/VOICE_STATE_UPDATE.ts index 4006c67e5..025622bb1 100644 --- a/packages/bot/src/handlers/voice/VOICE_STATE_UPDATE.ts +++ b/packages/bot/src/handlers/voice/VOICE_STATE_UPDATE.ts @@ -1,7 +1,7 @@ import type { DiscordGatewayPayload, DiscordVoiceState } from '@discordeno/types' import type { Bot } from '../../index.js' -export async function handleVoiceStateUpdate(bot: Bot, data: DiscordGatewayPayload) { +export async function handleVoiceStateUpdate(bot: Bot, data: DiscordGatewayPayload): Promise { const payload = data.d as DiscordVoiceState if (!payload.guild_id) return diff --git a/packages/bot/src/handlers/voice/mod.ts b/packages/bot/src/handlers/voice/index.ts similarity index 100% rename from packages/bot/src/handlers/voice/mod.ts rename to packages/bot/src/handlers/voice/index.ts diff --git a/packages/bot/src/handlers/webhooks/WEBHOOKS_UPDATE.ts b/packages/bot/src/handlers/webhooks/WEBHOOKS_UPDATE.ts index 5937fe0f4..c2e92a70b 100644 --- a/packages/bot/src/handlers/webhooks/WEBHOOKS_UPDATE.ts +++ b/packages/bot/src/handlers/webhooks/WEBHOOKS_UPDATE.ts @@ -1,7 +1,7 @@ import type { DiscordGatewayPayload, DiscordWebhookUpdate } from '@discordeno/types' import type { Bot } from '../../index.js' -export function handleWebhooksUpdate(bot: Bot, data: DiscordGatewayPayload) { +export async function handleWebhooksUpdate(bot: Bot, data: DiscordGatewayPayload, shardId: number) : Promise { const payload = data.d as DiscordWebhookUpdate bot.events.webhooksUpdate?.({ channelId: bot.transformers.snowflake(payload.channel_id), diff --git a/packages/bot/src/handlers/webhooks/mod.ts b/packages/bot/src/handlers/webhooks/index.ts similarity index 100% rename from packages/bot/src/handlers/webhooks/mod.ts rename to packages/bot/src/handlers/webhooks/index.ts diff --git a/packages/bot/src/index.ts b/packages/bot/src/index.ts index 432d86276..994653bd8 100644 --- a/packages/bot/src/index.ts +++ b/packages/bot/src/index.ts @@ -3,6 +3,6 @@ export * from '@discordeno/rest' export * from '@discordeno/types' export * from '@discordeno/utils' export * from './bot.js' -export * from './handler.js' -export * from './transformer.js' +export * from './handlers.js' +export * from './transformers.js' export * from './utils.js' diff --git a/packages/bot/src/transformer.ts b/packages/bot/src/transformers.ts similarity index 52% rename from packages/bot/src/transformer.ts rename to packages/bot/src/transformers.ts index 759e1627a..d7f1eda3f 100644 --- a/packages/bot/src/transformer.ts +++ b/packages/bot/src/transformers.ts @@ -43,30 +43,29 @@ import type { DiscordVoiceState, DiscordWebhook, DiscordWelcomeScreen, - InteractionResponse, } from '@discordeno/types' -import { bigintToSnowflake, Bot, snowflakeToBigint } from './index.js' -import { Activity, transformActivity } from './transformers/activity' -import { Application, transformApplication } from './transformers/application' -import { ApplicationCommand, transformApplicationCommand } from './transformers/applicationCommand' -import { transformApplicationCommandOption } from './transformers/applicationCommandOption' -import { transformApplicationCommandOptionChoice } from './transformers/applicationCommandOptionChoice' -import { ApplicationCommandPermission, transformApplicationCommandPermission } from './transformers/applicationCommandPermission' -import { Attachment, transformAttachment } from './transformers/attachment' -import { AuditLogEntry, transformAuditLogEntry } from './transformers/auditLogEntry' +import { bigintToSnowflake, snowflakeToBigint, type Bot } from './index.js' +import { transformActivity, type Activity } from './transformers/activity.js' +import { transformApplication, type Application } from './transformers/application.js' +import { transformApplicationCommand, type ApplicationCommand } from './transformers/applicationCommand.js' +import { transformApplicationCommandOption } from './transformers/applicationCommandOption.js' +import { transformApplicationCommandOptionChoice } from './transformers/applicationCommandOptionChoice.js' +import { transformApplicationCommandPermission, type ApplicationCommandPermission } from './transformers/applicationCommandPermission.js' +import { transformAttachment, type Attachment } from './transformers/attachment.js' +import { transformAuditLogEntry, type AuditLogEntry } from './transformers/auditLogEntry.js' import { transformAutoModerationActionExecution, type AutoModerationActionExecution } from './transformers/automodActionExecution.js' -import { AutoModerationRule, transformAutoModerationRule } from './transformers/automodRule' -import { Channel, transformChannel } from './transformers/channel' -import { Component, transformComponent } from './transformers/component' -import { Embed, transformEmbed } from './transformers/embed' -import { Emoji, transformEmoji } from './transformers/emoji' -import { GetGatewayBot, transformGatewayBot } from './transformers/gatewayBot' -import { Guild, transformGuild } from './transformers/guild' -import { Integration, transformIntegration } from './transformers/integration' -import { Interaction, InteractionDataOption, transformInteraction, transformInteractionDataOption } from './transformers/interaction' -import { Invite, transformInvite } from './transformers/invite' -import { Member, transformMember, transformUser, User } from './transformers/member' -import { Message, transformMessage } from './transformers/message' +import { transformAutoModerationRule, type AutoModerationRule } from './transformers/automodRule.js' +import { transformChannel, type Channel } from './transformers/channel.js' +import { transformComponent, type Component } from './transformers/component.js' +import { transformEmbed, type Embed } from './transformers/embed.js' +import { transformEmoji, type Emoji } from './transformers/emoji.js' +import { transformGatewayBot, type GetGatewayBot } from './transformers/gatewayBot.js' +import { transformGuild, type Guild } from './transformers/guild.js' +import { transformIntegration, type Integration } from './transformers/integration.js' +import { transformInteraction, transformInteractionDataOption, type Interaction, type InteractionDataOption } from './transformers/interaction.js' +import { transformInvite, type Invite } from './transformers/invite.js' +import { transformMember, transformUser, type Member, type User } from './transformers/member.js' +import { transformMessage, type Message } from './transformers/message.js' import { transformActivityToDiscordActivity, transformApplicationCommandOptionChoiceToDiscordApplicationCommandOptionChoice, @@ -79,25 +78,25 @@ import { transformMemberToDiscordMember, transformTeamToDiscordTeam, transformUserToDiscordUser, -} from './transformers/mod' -import { PresenceUpdate, transformPresence } from './transformers/presence' -import { transformAllowedMentionsToDiscordAllowedMentions } from './transformers/reverse/allowedMentions' +} from './transformers/index.js' +import { transformPresence, type PresenceUpdate } from './transformers/presence.js' +import { transformAllowedMentionsToDiscordAllowedMentions } from './transformers/reverse/allowedMentions.js' import { transformCreateApplicationCommandToDiscordCreateApplicationCommand } from './transformers/reverse/createApplicationCommand.js' import { transformInteractionResponseToDiscordInteractionResponse } from './transformers/reverse/interactionResponse.js' -import { Role, transformRole } from './transformers/role' -import { ScheduledEvent, transformScheduledEvent } from './transformers/scheduledEvent' -import { StageInstance, transformStageInstance } from './transformers/stageInstance' -import { Sticker, StickerPack, transformSticker, transformStickerPack } from './transformers/sticker' -import { Team, transformTeam } from './transformers/team' -import { Template, transformTemplate } from './transformers/template' -import { ThreadMember, transformThreadMember } from './transformers/threadMember' -import { transformVoiceRegion, VoiceRegions } from './transformers/voiceRegion' -import { transformVoiceState, VoiceState } from './transformers/voiceState' -import { transformWebhook, Webhook } from './transformers/webhook' -import { transformWelcomeScreen, WelcomeScreen } from './transformers/welcomeScreen' -import { GuildWidget, transformWidget } from './transformers/widget' -import { GuildWidgetSettings, transformWidgetSettings } from './transformers/widgetSettings' -import type { DiscordComponent, DiscordInteractionResponse } from './types.js' +import { transformRole, type Role } from './transformers/role.js' +import { transformScheduledEvent, type ScheduledEvent } from './transformers/scheduledEvent.js' +import { transformStageInstance, type StageInstance } from './transformers/stageInstance.js' +import { transformSticker, transformStickerPack, type Sticker, type StickerPack } from './transformers/sticker.js' +import { transformTeam, type Team } from './transformers/team.js' +import { transformTemplate, type Template } from './transformers/template.js' +import { transformThreadMember, type ThreadMember } from './transformers/threadMember.js' +import { transformVoiceRegion, type VoiceRegions } from './transformers/voiceRegion.js' +import { transformVoiceState, type VoiceState } from './transformers/voiceState.js' +import { transformWebhook, type Webhook } from './transformers/webhook.js' +import { transformWelcomeScreen, type WelcomeScreen } from './transformers/welcomeScreen.js' +import { transformWidget, type GuildWidget } from './transformers/widget.js' +import { transformWidgetSettings, type GuildWidgetSettings } from './transformers/widgetSettings.js' +import type { BotInteractionResponse, DiscordComponent, DiscordInteractionResponse } from './typings.js' export interface Transformers { reverse: { @@ -114,7 +113,7 @@ export interface Transformers { applicationCommand: (bot: Bot, payload: ApplicationCommand) => DiscordApplicationCommand applicationCommandOption: (bot: Bot, payload: ApplicationCommandOption) => DiscordApplicationCommandOption applicationCommandOptionChoice: (bot: Bot, payload: ApplicationCommandOptionChoice) => DiscordApplicationCommandOptionChoice - interactionResponse: (bot: Bot, payload: InteractionResponse) => DiscordInteractionResponse + interactionResponse: (bot: Bot, payload: BotInteractionResponse) => DiscordInteractionResponse attachment: (bot: Bot, payload: Attachment) => DiscordAttachment } snowflake: (snowflake: BigString) => bigint @@ -158,64 +157,64 @@ export interface Transformers { template: (bot: Bot, payload: DiscordTemplate) => Template } -export function createTransformers(options: Partial) { +export function createTransformers(options: Partial): Transformers { return { reverse: { - allowedMentions: options.reverse?.allowedMentions || transformAllowedMentionsToDiscordAllowedMentions, - embed: options.reverse?.embed || transformEmbedToDiscordEmbed, - component: options.reverse?.component || transformComponentToDiscordComponent, - activity: options.reverse?.activity || transformActivityToDiscordActivity, - member: options.reverse?.member || transformMemberToDiscordMember, - user: options.reverse?.user || transformUserToDiscordUser, - team: options.reverse?.team || transformTeamToDiscordTeam, - application: options.reverse?.application || transformApplicationToDiscordApplication, - snowflake: options.reverse?.snowflake || bigintToSnowflake, - createApplicationCommand: options.reverse?.createApplicationCommand || transformCreateApplicationCommandToDiscordCreateApplicationCommand, - applicationCommand: options.reverse?.applicationCommand || transformApplicationCommandToDiscordApplicationCommand, - applicationCommandOption: options.reverse?.applicationCommandOption || transformApplicationCommandOptionToDiscordApplicationCommandOption, + allowedMentions: options.reverse?.allowedMentions ?? transformAllowedMentionsToDiscordAllowedMentions, + embed: options.reverse?.embed ?? transformEmbedToDiscordEmbed, + component: options.reverse?.component ?? transformComponentToDiscordComponent, + activity: options.reverse?.activity ?? transformActivityToDiscordActivity, + member: options.reverse?.member ?? transformMemberToDiscordMember, + user: options.reverse?.user ?? transformUserToDiscordUser, + team: options.reverse?.team ?? transformTeamToDiscordTeam, + application: options.reverse?.application ?? transformApplicationToDiscordApplication, + snowflake: options.reverse?.snowflake ?? bigintToSnowflake, + createApplicationCommand: options.reverse?.createApplicationCommand ?? transformCreateApplicationCommandToDiscordCreateApplicationCommand, + applicationCommand: options.reverse?.applicationCommand ?? transformApplicationCommandToDiscordApplicationCommand, + applicationCommandOption: options.reverse?.applicationCommandOption ?? transformApplicationCommandOptionToDiscordApplicationCommandOption, applicationCommandOptionChoice: - options.reverse?.applicationCommandOptionChoice || transformApplicationCommandOptionChoiceToDiscordApplicationCommandOptionChoice, - interactionResponse: options.reverse?.interactionResponse || transformInteractionResponseToDiscordInteractionResponse, - attachment: options.reverse?.attachment || transformAttachmentToDiscordAttachment, + options.reverse?.applicationCommandOptionChoice ?? transformApplicationCommandOptionChoiceToDiscordApplicationCommandOptionChoice, + interactionResponse: options.reverse?.interactionResponse ?? transformInteractionResponseToDiscordInteractionResponse, + attachment: options.reverse?.attachment ?? transformAttachmentToDiscordAttachment, }, - automodRule: options.automodRule || transformAutoModerationRule, - automodActionExecution: options.automodActionExecution || transformAutoModerationActionExecution, - activity: options.activity || transformActivity, - application: options.application || transformApplication, - attachment: options.attachment || transformAttachment, - channel: options.channel || transformChannel, - component: options.component || transformComponent, - embed: options.embed || transformEmbed, - emoji: options.emoji || transformEmoji, - guild: options.guild || transformGuild, - integration: options.integration || transformIntegration, - interaction: options.interaction || transformInteraction, - interactionDataOptions: options.interactionDataOptions || transformInteractionDataOption, - invite: options.invite || transformInvite, - member: options.member || transformMember, - message: options.message || transformMessage, - presence: options.presence || transformPresence, - role: options.role || transformRole, - user: options.user || transformUser, - team: options.team || transformTeam, - voiceState: options.voiceState || transformVoiceState, - snowflake: options.snowflake || snowflakeToBigint, - webhook: options.webhook || transformWebhook, - auditLogEntry: options.auditLogEntry || transformAuditLogEntry, - applicationCommand: options.applicationCommand || transformApplicationCommand, - applicationCommandOption: options.applicationCommandOption || transformApplicationCommandOption, - applicationCommandPermission: options.applicationCommandPermission || transformApplicationCommandPermission, - scheduledEvent: options.scheduledEvent || transformScheduledEvent, - threadMember: options.threadMember || transformThreadMember, - welcomeScreen: options.welcomeScreen || transformWelcomeScreen, - voiceRegion: options.voiceRegion || transformVoiceRegion, - widget: options.widget || transformWidget, - widgetSettings: options.widgetSettings || transformWidgetSettings, - stageInstance: options.stageInstance || transformStageInstance, - sticker: options.sticker || transformSticker, - stickerPack: options.stickerPack || transformStickerPack, - gatewayBot: options.gatewayBot || transformGatewayBot, - applicationCommandOptionChoice: options.applicationCommandOptionChoice || transformApplicationCommandOptionChoice, - template: options.template || transformTemplate, + automodRule: options.automodRule ?? transformAutoModerationRule, + automodActionExecution: options.automodActionExecution ?? transformAutoModerationActionExecution, + activity: options.activity ?? transformActivity, + application: options.application ?? transformApplication, + attachment: options.attachment ?? transformAttachment, + channel: options.channel ?? transformChannel, + component: options.component ?? transformComponent, + embed: options.embed ?? transformEmbed, + emoji: options.emoji ?? transformEmoji, + guild: options.guild ?? transformGuild, + integration: options.integration ?? transformIntegration, + interaction: options.interaction ?? transformInteraction, + interactionDataOptions: options.interactionDataOptions ?? transformInteractionDataOption, + invite: options.invite ?? transformInvite, + member: options.member ?? transformMember, + message: options.message ?? transformMessage, + presence: options.presence ?? transformPresence, + role: options.role ?? transformRole, + user: options.user ?? transformUser, + team: options.team ?? transformTeam, + voiceState: options.voiceState ?? transformVoiceState, + snowflake: options.snowflake ?? snowflakeToBigint, + webhook: options.webhook ?? transformWebhook, + auditLogEntry: options.auditLogEntry ?? transformAuditLogEntry, + applicationCommand: options.applicationCommand ?? transformApplicationCommand, + applicationCommandOption: options.applicationCommandOption ?? transformApplicationCommandOption, + applicationCommandPermission: options.applicationCommandPermission ?? transformApplicationCommandPermission, + scheduledEvent: options.scheduledEvent ?? transformScheduledEvent, + threadMember: options.threadMember ?? transformThreadMember, + welcomeScreen: options.welcomeScreen ?? transformWelcomeScreen, + voiceRegion: options.voiceRegion ?? transformVoiceRegion, + widget: options.widget ?? transformWidget, + widgetSettings: options.widgetSettings ?? transformWidgetSettings, + stageInstance: options.stageInstance ?? transformStageInstance, + sticker: options.sticker ?? transformSticker, + stickerPack: options.stickerPack ?? transformStickerPack, + gatewayBot: options.gatewayBot ?? transformGatewayBot, + applicationCommandOptionChoice: options.applicationCommandOptionChoice ?? transformApplicationCommandOptionChoice, + template: options.template ?? transformTemplate, } } diff --git a/packages/bot/src/transformers/activity.ts b/packages/bot/src/transformers/activity.ts index cb142e6ca..40f4b1722 100644 --- a/packages/bot/src/transformers/activity.ts +++ b/packages/bot/src/transformers/activity.ts @@ -2,6 +2,7 @@ import type { DiscordActivity } from '@discordeno/bot' import type { Bot } from '../index.js' import type { Optionalize } from '../optionalize.js' +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type export function transformActivity(bot: Bot, payload: DiscordActivity) { const activity = { name: payload.name, diff --git a/packages/bot/src/transformers/application.ts b/packages/bot/src/transformers/application.ts index 7cb85ce4e..081c9313c 100644 --- a/packages/bot/src/transformers/application.ts +++ b/packages/bot/src/transformers/application.ts @@ -1,7 +1,8 @@ -import { DiscordApplication, iconHashToBigInt } from '@discordeno/bot' +import { iconHashToBigInt, type DiscordApplication } from '@discordeno/bot' import type { Bot } from '../index.js' import type { Optionalize } from '../optionalize.js' +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type export function transformApplication(bot: Bot, payload: DiscordApplication) { const application = { name: payload.name, @@ -20,7 +21,7 @@ export function transformApplication(bot: Bot, payload: DiscordApplication) { id: bot.transformers.snowflake(payload.id), icon: payload.icon ? iconHashToBigInt(payload.icon) : undefined, owner: payload.owner - ? // @ts-ignore the partial here wont break anything + ? // @ts-expect-error the partial here wont break anything bot.transformers.user(bot, payload.owner) : undefined, team: payload.team ? bot.transformers.team(bot, payload.team) : undefined, diff --git a/packages/bot/src/transformers/applicationCommand.ts b/packages/bot/src/transformers/applicationCommand.ts index 7cae93949..bacdab76a 100644 --- a/packages/bot/src/transformers/applicationCommand.ts +++ b/packages/bot/src/transformers/applicationCommand.ts @@ -2,6 +2,7 @@ import type { DiscordApplicationCommand } from '@discordeno/types' import type { Bot } from '../index.js' import type { Optionalize } from '../optionalize.js' +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type export function transformApplicationCommand(bot: Bot, payload: DiscordApplicationCommand) { const applicationCommand = { id: bot.transformers.snowflake(payload.id), diff --git a/packages/bot/src/transformers/applicationCommandOptionChoice.ts b/packages/bot/src/transformers/applicationCommandOptionChoice.ts index b343e06da..9e0126db4 100644 --- a/packages/bot/src/transformers/applicationCommandOptionChoice.ts +++ b/packages/bot/src/transformers/applicationCommandOptionChoice.ts @@ -2,6 +2,7 @@ import type { DiscordApplicationCommandOptionChoice } from '@discordeno/types' import type { Bot } from '../index.js' import type { Optionalize } from '../optionalize.js' +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type export function transformApplicationCommandOptionChoice(bot: Bot, payload: DiscordApplicationCommandOptionChoice) { const applicationCommandChoice = { name: payload.name, diff --git a/packages/bot/src/transformers/applicationCommandPermission.ts b/packages/bot/src/transformers/applicationCommandPermission.ts index cf1cff30b..50d2cf505 100644 --- a/packages/bot/src/transformers/applicationCommandPermission.ts +++ b/packages/bot/src/transformers/applicationCommandPermission.ts @@ -2,6 +2,7 @@ import type { DiscordGuildApplicationCommandPermissions } from '@discordeno/type import type { Bot } from '../index.js' import type { Optionalize } from '../optionalize.js' +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type export function transformApplicationCommandPermission(bot: Bot, payload: DiscordGuildApplicationCommandPermissions) { const applicationCommandPermission = { id: bot.transformers.snowflake(payload.id), diff --git a/packages/bot/src/transformers/attachment.ts b/packages/bot/src/transformers/attachment.ts index 7fe1bcde7..31fcd990a 100644 --- a/packages/bot/src/transformers/attachment.ts +++ b/packages/bot/src/transformers/attachment.ts @@ -2,6 +2,7 @@ import type { DiscordAttachment } from '@discordeno/types' import type { Bot } from '../index.js' import type { Optionalize } from '../optionalize.js' +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type export function transformAttachment(bot: Bot, payload: DiscordAttachment) { const attachment = { id: bot.transformers.snowflake(payload.id), diff --git a/packages/bot/src/transformers/auditLogEntry.ts b/packages/bot/src/transformers/auditLogEntry.ts index b92b735f9..7473f961e 100644 --- a/packages/bot/src/transformers/auditLogEntry.ts +++ b/packages/bot/src/transformers/auditLogEntry.ts @@ -2,6 +2,7 @@ import type { DiscordAuditLogEntry } from '@discordeno/types' import type { Bot } from '../index.js' import type { Optionalize } from '../optionalize.js' +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type export function transformAuditLogEntry(bot: Bot, payload: DiscordAuditLogEntry) { const auditLogEntry = { id: bot.transformers.snowflake(payload.id), @@ -122,6 +123,8 @@ export function transformAuditLogEntry(bot: Bot, payload: DiscordAuditLogEntry) id: payload.options.id ? bot.transformers.snowflake(payload.options.id) : undefined, type: Number(payload.options.type), roleName: payload.options.role_name, + autoModerationRuleName: payload.options.auto_moderation_rule_name, + autoModerationRuleTriggerType: payload.options.auto_moderation_rule_trigger_type, } : undefined, reason: payload.reason, diff --git a/packages/bot/src/transformers/automodActionExecution.ts b/packages/bot/src/transformers/automodActionExecution.ts index cf9a62c08..c2ff26fd9 100644 --- a/packages/bot/src/transformers/automodActionExecution.ts +++ b/packages/bot/src/transformers/automodActionExecution.ts @@ -2,6 +2,7 @@ import type { DiscordAutoModerationActionExecution } from '@discordeno/types' import type { Bot } from '../index.js' import type { Optionalize } from '../optionalize.js' +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type export function transformAutoModerationActionExecution(bot: Bot, payload: DiscordAutoModerationActionExecution) { const rule = { content: payload.content, diff --git a/packages/bot/src/transformers/automodRule.ts b/packages/bot/src/transformers/automodRule.ts index 7432e8eb1..163e9e298 100644 --- a/packages/bot/src/transformers/automodRule.ts +++ b/packages/bot/src/transformers/automodRule.ts @@ -2,6 +2,7 @@ import type { DiscordAutoModerationRule } from '@discordeno/types' import type { Bot } from '../index.js' import type { Optionalize } from '../optionalize.js' +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type export function transformAutoModerationRule(bot: Bot, payload: DiscordAutoModerationRule) { const rule = { name: payload.name, diff --git a/packages/bot/src/transformers/channel.ts b/packages/bot/src/transformers/channel.ts index aaba4896c..a508a2e29 100644 --- a/packages/bot/src/transformers/channel.ts +++ b/packages/bot/src/transformers/channel.ts @@ -4,21 +4,22 @@ import type { Optionalize } from '../optionalize.js' const Mask = (1n << 64n) - 1n -export function packOverwrites(allow: string, deny: string, id: string, type: number) { +export function packOverwrites(allow: string, deny: string, id: string, type: number): bigint { return pack64(allow, 0) | pack64(deny, 1) | pack64(id, 2) | pack64(type, 3) } -function unpack64(v: bigint, shift: number) { +function unpack64(v: bigint, shift: number): bigint { return (v >> BigInt(shift * 64)) & Mask } -function pack64(v: string | number, shift: number) { +function pack64(v: string | number, shift: number): bigint { const b = BigInt(v) - if (b < 0 || b > Mask) throw new Error('should have been a 64 bit unsigned integer: ' + v) + if (b < 0 || b > Mask) throw new Error('should have been a 64 bit unsigned integer: ' + v.toString()) return b << BigInt(shift * 64) } -export function separateOverwrites(v: bigint) { +export function separateOverwrites(v: bigint): [number, bigint, bigint, bigint] { return [Number(unpack64(v, 3)), unpack64(v, 2), unpack64(v, 0), unpack64(v, 1)] as [number, bigint, bigint, bigint] } +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type export function transformChannel(bot: Bot, payload: { channel: DiscordChannel } & { guildId?: bigint }) { const channel = { // UNTRANSFORMED STUFF HERE @@ -33,10 +34,10 @@ export function transformChannel(bot: Bot, payload: { channel: DiscordChannel } // recipients: payload.channel.recipients?.map((r) => bot.transformers.user(bot, r)), rtcRegion: payload.channel.rtc_region ?? undefined, videoQualityMode: payload.channel.video_quality_mode, - guildId: payload.guildId || (payload.channel.guild_id ? bot.transformers.snowflake(payload.channel.guild_id) : 0n), + guildId: payload.guildId ?? (payload.channel.guild_id ? bot.transformers.snowflake(payload.channel.guild_id) : 0n), lastPinTimestamp: payload.channel.last_pin_timestamp ? Date.parse(payload.channel.last_pin_timestamp) : undefined, permissionOverwrites: payload.channel.permission_overwrites - ? payload.channel.permission_overwrites.map((o) => packOverwrites(o.allow || '0', o.deny || '0', o.id, o.type)) + ? payload.channel.permission_overwrites.map((o) => packOverwrites(o.allow ?? '0', o.deny ?? '0', o.id, o.type)) : [], id: bot.transformers.snowflake(payload.channel.id), diff --git a/packages/bot/src/transformers/component.ts b/packages/bot/src/transformers/component.ts index 064ebbafc..fefc0a6b9 100644 --- a/packages/bot/src/transformers/component.ts +++ b/packages/bot/src/transformers/component.ts @@ -1,8 +1,8 @@ -// import type { DiscordComponent } from '@discordeno/types' import type { ButtonStyles, MessageComponentTypes, SelectOption, TextStyles } from '@discordeno/types' import type { Bot } from '../index.js' +import type { DiscordComponent } from '../typings.js' -export function transformComponent(bot: Bot, payload: any /* TODO: Fix, needs DiscordComponent type */): Component { +export function transformComponent(bot: Bot, payload: DiscordComponent): Component { return { type: payload.type, customId: payload.custom_id, @@ -17,7 +17,6 @@ export function transformComponent(bot: Bot, payload: any /* TODO: Fix, needs Di } : undefined, url: payload.url, - // @ts-expect-error TODO: Fix options: payload.options?.map((option) => ({ label: option.label, value: option.value, @@ -37,7 +36,6 @@ export function transformComponent(bot: Bot, payload: any /* TODO: Fix, needs Di minLength: payload.min_length, maxLength: payload.max_length, value: payload.value, - // @ts-expect-error TODO: Fix components: payload.components?.map((component) => bot.transformers.component(bot, component)), } } @@ -80,7 +78,7 @@ export interface Component { maxValues?: number /** The minimum input length for a text input. Between 0-4000. */ minLength?: number - /**The maximum input length for a text input. Between 1-4000. */ + /** The maximum input length for a text input. Between 1-4000. */ maxLength?: number /** a list of child components */ components?: Component[] diff --git a/packages/bot/src/transformers/embed.ts b/packages/bot/src/transformers/embed.ts index c48728883..2375225b6 100644 --- a/packages/bot/src/transformers/embed.ts +++ b/packages/bot/src/transformers/embed.ts @@ -2,6 +2,7 @@ import type { DiscordEmbed } from '@discordeno/types' import type { Bot } from '../index.js' import type { Optionalize } from '../optionalize.js' +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type export function transformEmbed(bot: Bot, payload: DiscordEmbed) { const embed = { title: payload.title, diff --git a/packages/bot/src/transformers/emoji.ts b/packages/bot/src/transformers/emoji.ts index 4afbe4895..ab0ea76da 100644 --- a/packages/bot/src/transformers/emoji.ts +++ b/packages/bot/src/transformers/emoji.ts @@ -3,10 +3,11 @@ import type { Bot } from '../index.js' import type { Optionalize } from '../optionalize.js' import { EmojiToggles } from './toggles/emoji.js' +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type export function transformEmoji(bot: Bot, payload: DiscordEmoji) { const emoji = { id: payload.id ? bot.transformers.snowflake(payload.id) : undefined, - name: payload.name || undefined, + name: payload.name ?? undefined, roles: payload.roles?.map((id) => bot.transformers.snowflake(id)), user: payload.user ? bot.transformers.user(bot, payload.user) : undefined, toggles: new EmojiToggles(payload), diff --git a/packages/bot/src/transformers/gatewayBot.ts b/packages/bot/src/transformers/gatewayBot.ts index 7c85eace2..7145e208e 100644 --- a/packages/bot/src/transformers/gatewayBot.ts +++ b/packages/bot/src/transformers/gatewayBot.ts @@ -1,6 +1,7 @@ import type { DiscordGetGatewayBot } from '@discordeno/types' import type { Optionalize } from '../optionalize.js' +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type export function transformGatewayBot(payload: DiscordGetGatewayBot) { const gatewayBot = { url: payload.url, diff --git a/packages/bot/src/transformers/guild.ts b/packages/bot/src/transformers/guild.ts index 555e47335..0bebdb60c 100644 --- a/packages/bot/src/transformers/guild.ts +++ b/packages/bot/src/transformers/guild.ts @@ -5,6 +5,7 @@ import type { Optionalize } from '../optionalize.js' import type { Emoji } from '../transformers/emoji.js' import { GuildToggles } from './toggles/guild.js' +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type export function transformGuild(bot: Bot, payload: { guild: DiscordGuild } & { shardId: number }) { const guildId = bot.transformers.snowflake(payload.guild.id) @@ -82,7 +83,7 @@ export function transformGuild(bot: Bot, payload: { guild: DiscordGuild } & { sh }), ), voiceStates: new Collection( - (payload.guild.voice_states || []).map((vs) => bot.transformers.voiceState(bot, { voiceState: vs, guildId })).map((vs) => [vs.userId, vs]), + (payload.guild.voice_states ?? []).map((vs) => bot.transformers.voiceState(bot, { voiceState: vs, guildId })).map((vs) => [vs.userId, vs]), ), id: guildId, diff --git a/packages/bot/src/transformers/mod.ts b/packages/bot/src/transformers/index.ts similarity index 97% rename from packages/bot/src/transformers/mod.ts rename to packages/bot/src/transformers/index.ts index 0931cc1d9..a4e9db236 100644 --- a/packages/bot/src/transformers/mod.ts +++ b/packages/bot/src/transformers/index.ts @@ -19,7 +19,7 @@ export * from './invite.js' export * from './member.js' export * from './message.js' export * from './presence.js' -export * from './reverse/mod.js' +export * from './reverse/index.js' export * from './role.js' export * from './scheduledEvent.js' export * from './stageInstance.js' diff --git a/packages/bot/src/transformers/integration.ts b/packages/bot/src/transformers/integration.ts index 64e06ba69..fb0abee5f 100644 --- a/packages/bot/src/transformers/integration.ts +++ b/packages/bot/src/transformers/integration.ts @@ -1,7 +1,8 @@ import type { DiscordIntegrationCreateUpdate } from '@discordeno/types' -import { Bot, iconHashToBigInt } from '../index.js' +import { iconHashToBigInt, type Bot } from '../index.js' import type { Optionalize } from '../optionalize.js' +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type export function transformIntegration(bot: Bot, payload: DiscordIntegrationCreateUpdate) { const integration = { guildId: bot.transformers.snowflake(payload.guild_id), diff --git a/packages/bot/src/transformers/interaction.ts b/packages/bot/src/transformers/interaction.ts index 35f7159a0..b7b388249 100644 --- a/packages/bot/src/transformers/interaction.ts +++ b/packages/bot/src/transformers/interaction.ts @@ -1,16 +1,17 @@ -import type { ChannelTypes, DiscordAttachment, DiscordInteraction, DiscordInteractionDataOption } from '@discordeno/types' +import type { ChannelTypes, DiscordInteraction, DiscordInteractionDataOption } from '@discordeno/types' import { Collection } from '@discordeno/utils' import type { Bot } from '../index.js' import type { Optionalize } from '../optionalize.js' -import type { DiscordInteractionDataResolved } from '../types.js' +import type { DiscordInteractionDataResolved } from '../typings.js' import type { Attachment } from './attachment.js' import type { Member, User } from './member.js' import type { Message } from './message.js' import type { Role } from './role.js' +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type export function transformInteraction(bot: Bot, payload: DiscordInteraction) { const guildId = payload.guild_id ? bot.transformers.snowflake(payload.guild_id) : undefined - const user = bot.transformers.user(bot, payload.member?.user || payload.user!) + const user = bot.transformers.user(bot, payload.member?.user ?? payload.user!) const interaction = { // UNTRANSFORMED STUFF HERE @@ -49,6 +50,7 @@ export function transformInteraction(bot: Bot, payload: DiscordInteraction) { return interaction as Optionalize } +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type export function transformInteractionDataOption(bot: Bot, option: DiscordInteractionDataOption) { const opt = { name: option.name, @@ -61,6 +63,7 @@ export function transformInteractionDataOption(bot: Bot, option: DiscordInteract return opt as Optionalize } +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type export function transformInteractionDataResolved(bot: Bot, resolved: DiscordInteractionDataResolved, guildId?: bigint) { const transformed: { messages?: Collection @@ -134,7 +137,7 @@ export function transformInteractionDataResolved(bot: Bot, resolved: DiscordInte transformed.attachments = new Collection( Object.entries(resolved.attachments).map(([key, value]) => { const id = bot.transformers.snowflake(key) - return [id, bot.transformers.attachment(bot, value as DiscordAttachment)] + return [id, bot.transformers.attachment(bot, value)] }), ) } diff --git a/packages/bot/src/transformers/invite.ts b/packages/bot/src/transformers/invite.ts index bfc5af6d6..7d9178ee8 100644 --- a/packages/bot/src/transformers/invite.ts +++ b/packages/bot/src/transformers/invite.ts @@ -2,6 +2,7 @@ import type { DiscordInviteCreate } from '@discordeno/types' import type { Bot } from '../index.js' import type { Optionalize } from '../optionalize.js' +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type export function transformInvite(bot: Bot, invite: DiscordInviteCreate) { const transformedInvite = { /** The channel the invite is for */ @@ -24,7 +25,7 @@ export function transformInvite(bot: Bot, invite: DiscordInviteCreate) { targetUser: invite.target_user ? bot.transformers.user(bot, invite.target_user) : undefined, /** The embedded application to open for this voice channel embedded application invite */ targetApplication: invite.target_application - ? // @ts-ignore should not break anything even though its partial. if it does blame wolf :) + ? // @ts-expect-error should not break anything even though its partial. if it does blame wolf :) bot.transformers.application(bot, invite.target_application) : undefined, /** Whether or not the invite is temporary (invited users will be kicked on disconnect unless they're assigned a role) */ diff --git a/packages/bot/src/transformers/member.ts b/packages/bot/src/transformers/member.ts index 507e1effc..16a51de73 100644 --- a/packages/bot/src/transformers/member.ts +++ b/packages/bot/src/transformers/member.ts @@ -5,6 +5,7 @@ import type { Optionalize } from '../optionalize.js' import { MemberToggles } from './toggles/member.js' import { UserToggles } from './toggles/user.js' +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type export function transformUser(bot: Bot, payload: DiscordUser) { const user = { id: bot.transformers.snowflake(payload.id || ''), @@ -22,6 +23,7 @@ export function transformUser(bot: Bot, payload: DiscordUser) { return user as Optionalize } +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type export function transformMember(bot: Bot, payload: DiscordMember, guildId: bigint, userId: bigint) { const member = { id: userId, diff --git a/packages/bot/src/transformers/message.ts b/packages/bot/src/transformers/message.ts index 37af070df..99aad5573 100644 --- a/packages/bot/src/transformers/message.ts +++ b/packages/bot/src/transformers/message.ts @@ -1,17 +1,18 @@ import type { DiscordMessage } from '@discordeno/types' import { CHANNEL_MENTION_REGEX } from '../constants.js' -import { Bot, iconHashToBigInt } from '../index.js' +import { iconHashToBigInt, type Bot } from '../index.js' import type { Optionalize } from '../optionalize.js' import { MemberToggles } from './toggles/member.js' +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type export function transformMessage(bot: Bot, payload: DiscordMessage) { const guildId = payload.guild_id ? bot.transformers.snowflake(payload.guild_id) : undefined const userId = bot.transformers.snowflake(payload.author.id) const message = { // UNTRANSFORMED STUFF HERE - content: payload.content || '', - isFromBot: payload.author.bot || false, + content: payload.content ?? '', + isFromBot: payload.author.bot ?? false, tag: `${payload.author.username}#${payload.author.discriminator}`, timestamp: Date.parse(payload.timestamp), editedTimestamp: payload.edited_timestamp ? Date.parse(payload.edited_timestamp) : undefined, @@ -84,7 +85,7 @@ export function transformMessage(bot: Bot, payload: DiscordMessage) { // Keep any ids tht discord sends ...(payload.mention_channels ?? []).map((m) => bot.transformers.snowflake(m.id)), // Add any other ids that can be validated in a channel mention format - ...(payload.content?.match(CHANNEL_MENTION_REGEX) || []).map((text) => + ...(payload.content?.match(CHANNEL_MENTION_REGEX) ?? []).map((text) => // converts the <#123> into 123 bot.transformers.snowflake(text.substring(2, text.length - 1)), ), diff --git a/packages/bot/src/transformers/presence.ts b/packages/bot/src/transformers/presence.ts index 8a25d8dbb..534d65b3a 100644 --- a/packages/bot/src/transformers/presence.ts +++ b/packages/bot/src/transformers/presence.ts @@ -1,8 +1,9 @@ -import { DiscordPresenceUpdate, PresenceStatus } from '@discordeno/types' -import { Bot, iconHashToBigInt } from '../index.js' +import { PresenceStatus, type DiscordPresenceUpdate } from '@discordeno/types' +import { iconHashToBigInt, type Bot } from '../index.js' import type { Optionalize } from '../optionalize.js' import { UserToggles } from './toggles/user.js' +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type export function transformPresence(bot: Bot, payload: DiscordPresenceUpdate) { const presence = { user: { diff --git a/packages/bot/src/transformers/reverse/application.ts b/packages/bot/src/transformers/reverse/application.ts index 4ea6b65d8..7eef46a0d 100644 --- a/packages/bot/src/transformers/reverse/application.ts +++ b/packages/bot/src/transformers/reverse/application.ts @@ -1,4 +1,4 @@ -import { DiscordApplication, iconBigintToHash } from '@discordeno/bot' +import { iconBigintToHash, type DiscordApplication } from '@discordeno/bot' import type { Bot } from '../../index.js' import type { Application } from '../application.js' diff --git a/packages/bot/src/transformers/reverse/auditLogEntry.ts b/packages/bot/src/transformers/reverse/auditLogEntry.ts index 36f08fc1c..01e7ec7d8 100644 --- a/packages/bot/src/transformers/reverse/auditLogEntry.ts +++ b/packages/bot/src/transformers/reverse/auditLogEntry.ts @@ -13,20 +13,20 @@ export function transformAuditLogEntryToDiscordAuditLogEntry(bot: Bot, payload: return { key: change.key, new_value: ( - change.new as { + change.new as Array<{ id: bigint | undefined name: string | undefined - }[] + }> )?.map((val) => ({ id: val.id ? bot.transformers.reverse.snowflake(val.id) : undefined, name: val.name, })), old_value: ( change.old as - | { + | Array<{ id: bigint | undefined name: string | undefined - }[] + }> | undefined )?.map((val) => ({ id: val?.id ? bot.transformers.reverse.snowflake(val.id) : undefined, @@ -139,10 +139,7 @@ export function transformAuditLogEntryToDiscordAuditLogEntry(bot: Bot, payload: role_name: payload.options.roleName, // make up value to make ts shut up, the orginal value do not persevere in transformer application_id: '', - // TODO: Fix - // @ts-expect-error auto_moderation_rule_name: payload.options.autoModerationRuleName, - // @ts-expect-error auto_moderation_rule_trigger_type: payload.options.autoModerationRuleTriggerType, } : undefined, diff --git a/packages/bot/src/transformers/reverse/component.ts b/packages/bot/src/transformers/reverse/component.ts index 9ac0d522b..d28622dc8 100644 --- a/packages/bot/src/transformers/reverse/component.ts +++ b/packages/bot/src/transformers/reverse/component.ts @@ -1,5 +1,5 @@ import type { Bot } from '../../index.js' -import type { DiscordComponent } from '../../types.js' +import type { DiscordComponent } from '../../typings.js' import type { Component } from '../component.js' export function transformComponentToDiscordComponent(bot: Bot, payload: Component): DiscordComponent { diff --git a/packages/bot/src/transformers/reverse/createApplicationCommand.ts b/packages/bot/src/transformers/reverse/createApplicationCommand.ts index 73a98e6ca..6de459d8a 100644 --- a/packages/bot/src/transformers/reverse/createApplicationCommand.ts +++ b/packages/bot/src/transformers/reverse/createApplicationCommand.ts @@ -1,7 +1,7 @@ import type { CreateApplicationCommand, DiscordCreateApplicationCommand } from '@discordeno/bot' import { calculateBits } from '@discordeno/utils' import type { Bot } from '../../index.js' -import { isContextApplicationCommand } from '../../types.js' +import { isContextApplicationCommand } from '../../typings.js' export function transformCreateApplicationCommandToDiscordCreateApplicationCommand( bot: Bot, diff --git a/packages/bot/src/transformers/reverse/emoji.ts b/packages/bot/src/transformers/reverse/emoji.ts index 5621d10bb..d298ffb35 100644 --- a/packages/bot/src/transformers/reverse/emoji.ts +++ b/packages/bot/src/transformers/reverse/emoji.ts @@ -5,7 +5,7 @@ import type { Emoji } from '../emoji.js' export function transformEmojiToDiscordEmoji(bot: Bot, payload: Emoji): DiscordEmoji { return { id: payload.id ? bot.transformers.reverse.snowflake(payload.id) : undefined, - name: payload.name || undefined, + name: payload.name ?? undefined, roles: payload.roles?.map((id) => bot.transformers.reverse.snowflake(id)), user: payload.user ? bot.transformers.reverse.user(bot, payload.user) : undefined, require_colons: payload.toggles.requireColons, diff --git a/packages/bot/src/transformers/reverse/mod.ts b/packages/bot/src/transformers/reverse/index.ts similarity index 100% rename from packages/bot/src/transformers/reverse/mod.ts rename to packages/bot/src/transformers/reverse/index.ts diff --git a/packages/bot/src/transformers/reverse/interactionResponse.ts b/packages/bot/src/transformers/reverse/interactionResponse.ts index f1a4c586a..a95cb0358 100644 --- a/packages/bot/src/transformers/reverse/interactionResponse.ts +++ b/packages/bot/src/transformers/reverse/interactionResponse.ts @@ -1,5 +1,5 @@ import type { Bot } from '../../index.js' -import type { BotInteractionResponse, DiscordInteractionResponse } from '../../types.js' +import type { BotInteractionResponse, DiscordInteractionResponse } from '../../typings.js' export function transformInteractionResponseToDiscordInteractionResponse(bot: Bot, payload: BotInteractionResponse): DiscordInteractionResponse { // If no mentions are provided, force disable mentions diff --git a/packages/bot/src/transformers/reverse/member.ts b/packages/bot/src/transformers/reverse/member.ts index f76dda277..8a5d5bcaa 100644 --- a/packages/bot/src/transformers/reverse/member.ts +++ b/packages/bot/src/transformers/reverse/member.ts @@ -5,7 +5,7 @@ import type { Member, User } from '../member.js' export function transformUserToDiscordUser(bot: Bot, payload: User): DiscordUser { return { - id: bot.utils.bigintToSnowflake(payload.id), + id: payload.id.toString(), username: payload.username, discriminator: payload.discriminator, avatar: payload.avatar ? iconBigintToHash(payload.avatar) : null, @@ -24,11 +24,11 @@ export function transformUserToDiscordUser(bot: Bot, payload: User): DiscordUser export function transformMemberToDiscordMember(bot: Bot, payload: Member): DiscordMember { return { nick: payload.nick ?? undefined, - roles: payload.roles.map((id) => bot.utils.bigintToSnowflake(id)), + roles: payload.roles.map((id) => id.toString()), joined_at: new Date(payload.joinedAt).toISOString(), premium_since: payload.premiumSince ? new Date(payload.premiumSince).toISOString() : undefined, avatar: payload.avatar ? iconBigintToHash(payload.avatar) : undefined, - permissions: payload.permissions ? bot.utils.bigintToSnowflake(payload.permissions) : undefined, + permissions: payload.permissions?.toString(), communication_disabled_until: payload.communicationDisabledUntil ? new Date(payload.communicationDisabledUntil).toISOString() : undefined, deaf: payload.toggles.deaf, mute: payload.toggles.mute, diff --git a/packages/bot/src/transformers/reverse/presence.ts b/packages/bot/src/transformers/reverse/presence.ts index 568e13796..7e28d4c04 100644 --- a/packages/bot/src/transformers/reverse/presence.ts +++ b/packages/bot/src/transformers/reverse/presence.ts @@ -1,4 +1,4 @@ -import { DiscordPresenceUpdate, PresenceStatus } from '@discordeno/types' +import { PresenceStatus, type DiscordPresenceUpdate } from '@discordeno/types' import type { Bot } from '../../index.js' import type { PresenceUpdate } from '../presence.js' diff --git a/packages/bot/src/transformers/reverse/team.ts b/packages/bot/src/transformers/reverse/team.ts index e9df4d565..17e6cca6f 100644 --- a/packages/bot/src/transformers/reverse/team.ts +++ b/packages/bot/src/transformers/reverse/team.ts @@ -1,16 +1,16 @@ import type { DiscordTeam } from '@discordeno/types' -import { Bot, iconBigintToHash } from '../../index.js' +import { iconBigintToHash, type Bot } from '../../index.js' import type { Team } from '../team.js' export function transformTeamToDiscordTeam(bot: Bot, payload: Team): DiscordTeam { - const id = bot.utils.bigintToSnowflake(payload.id) + const id = payload.id.toString() return { name: payload.name, id, icon: payload.icon ? iconBigintToHash(payload.icon) : null, - owner_user_id: bot.utils.bigintToSnowflake(payload.ownerUserId), + owner_user_id: payload.ownerUserId.toString(), members: payload.members.map((member) => ({ membership_state: member.membershipState, permissions: member.permissions, diff --git a/packages/bot/src/transformers/role.ts b/packages/bot/src/transformers/role.ts index 6d9136c33..fb0845800 100644 --- a/packages/bot/src/transformers/role.ts +++ b/packages/bot/src/transformers/role.ts @@ -1,8 +1,9 @@ import type { DiscordRole } from '@discordeno/types' -import { Bot, iconHashToBigInt } from '../index.js' +import { iconHashToBigInt, type Bot } from '../index.js' import type { Optionalize } from '../optionalize.js' import { RoleToggles } from './toggles/role.js' +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type export function transformRole(bot: Bot, payload: { role: DiscordRole } & { guildId: bigint }) { const role = { name: payload.role.name, diff --git a/packages/bot/src/transformers/scheduledEvent.ts b/packages/bot/src/transformers/scheduledEvent.ts index cdeeeee26..f1061336b 100644 --- a/packages/bot/src/transformers/scheduledEvent.ts +++ b/packages/bot/src/transformers/scheduledEvent.ts @@ -1,7 +1,8 @@ import type { DiscordScheduledEvent } from '@discordeno/types' -import { Bot, iconHashToBigInt } from '../index.js' +import { iconHashToBigInt, type Bot } from '../index.js' import type { Optionalize } from '../optionalize.js' +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type export function transformScheduledEvent(bot: Bot, payload: DiscordScheduledEvent) { const scheduledEvent = { id: bot.transformers.snowflake(payload.id), @@ -18,7 +19,7 @@ export function transformScheduledEvent(bot: Bot, payload: DiscordScheduledEvent privacyLevel: payload.privacy_level, status: payload.status, entityType: payload.entity_type, - userCount: payload.user_count || 0, + userCount: payload.user_count ?? 0, location: payload.entity_metadata?.location, image: payload.image ? iconHashToBigInt(payload.image) : undefined, } diff --git a/packages/bot/src/transformers/stageInstance.ts b/packages/bot/src/transformers/stageInstance.ts index 3ef9c4036..058855e67 100644 --- a/packages/bot/src/transformers/stageInstance.ts +++ b/packages/bot/src/transformers/stageInstance.ts @@ -2,6 +2,7 @@ import type { DiscordStageInstance } from '@discordeno/types' import type { Bot } from '../index.js' import type { Optionalize } from '../optionalize.js' +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type export function transformStageInstance(bot: Bot, payload: DiscordStageInstance) { const stageInstance = { id: bot.transformers.snowflake(payload.id), diff --git a/packages/bot/src/transformers/sticker.ts b/packages/bot/src/transformers/sticker.ts index 0c2f144b3..41a59dca5 100644 --- a/packages/bot/src/transformers/sticker.ts +++ b/packages/bot/src/transformers/sticker.ts @@ -2,17 +2,18 @@ import type { DiscordSticker, DiscordStickerPack } from '@discordeno/types' import type { Bot } from '../index.js' import type { Optionalize } from '../optionalize.js' +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type export function transformSticker(bot: Bot, payload: DiscordSticker) { const sticker = { - id: bot.utils.snowflakeToBigint(payload.id), - packId: payload.pack_id ? bot.utils.snowflakeToBigint(payload.pack_id) : undefined, + id: bot.transformers.snowflake(payload.id), + packId: payload.pack_id ? bot.transformers.snowflake(payload.pack_id) : undefined, name: payload.name, description: payload.description, tags: payload.tags, type: payload.type, formatType: payload.format_type, available: payload.available, - guildId: payload.guild_id ? bot.utils.snowflakeToBigint(payload.guild_id) : undefined, + guildId: payload.guild_id ? bot.transformers.snowflake(payload.guild_id) : undefined, user: payload.user ? bot.transformers.user(bot, payload.user) : undefined, sortValue: payload.sort_value, } @@ -20,6 +21,7 @@ export function transformSticker(bot: Bot, payload: DiscordSticker) { return sticker as Optionalize } +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type export function transformStickerPack(bot: Bot, payload: DiscordStickerPack) { const pack = { id: bot.transformers.snowflake(payload.id), diff --git a/packages/bot/src/transformers/team.ts b/packages/bot/src/transformers/team.ts index cc6d85f2a..bf05b6ee6 100644 --- a/packages/bot/src/transformers/team.ts +++ b/packages/bot/src/transformers/team.ts @@ -1,7 +1,8 @@ import type { DiscordTeam } from '@discordeno/types' -import { Bot, iconHashToBigInt } from '../index.js' +import { iconHashToBigInt, type Bot } from '../index.js' import type { Optionalize } from '../optionalize.js' +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type export function transformTeam(bot: Bot, payload: DiscordTeam) { const id = bot.transformers.snowflake(payload.id) diff --git a/packages/bot/src/transformers/template.ts b/packages/bot/src/transformers/template.ts index 3ed9883dc..db8d9221c 100644 --- a/packages/bot/src/transformers/template.ts +++ b/packages/bot/src/transformers/template.ts @@ -2,6 +2,7 @@ import type { DiscordTemplate } from '@discordeno/types' import type { Bot } from '../index.js' import type { Optionalize } from '../optionalize.js' +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type export function transformTemplate(bot: Bot, payload: DiscordTemplate) { const template = { code: payload.code, diff --git a/packages/bot/src/transformers/threadMember.ts b/packages/bot/src/transformers/threadMember.ts index b444c41f1..b99a241bc 100644 --- a/packages/bot/src/transformers/threadMember.ts +++ b/packages/bot/src/transformers/threadMember.ts @@ -1,8 +1,9 @@ import type { DiscordThreadMember } from '@discordeno/types' import type { Bot } from '../index.js' import type { Optionalize } from '../optionalize.js' -import type { DiscordThreadMemberGuildCreate } from '../types.js' +import type { DiscordThreadMemberGuildCreate } from '../typings.js' +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type export function transformThreadMember(bot: Bot, payload: DiscordThreadMember) { const threadMember = { id: payload.id ? bot.transformers.snowflake(payload.id) : undefined, @@ -14,6 +15,7 @@ export function transformThreadMember(bot: Bot, payload: DiscordThreadMember) { return threadMember as Optionalize } +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type export function transformThreadMemberGuildCreate(bot: Bot, payload: DiscordThreadMemberGuildCreate) { const threadMember = { joinTimestamp: Date.parse(payload.join_timestamp), diff --git a/packages/bot/src/transformers/toggles/ToggleBitfield.ts b/packages/bot/src/transformers/toggles/ToggleBitfield.ts index 8715c161b..985cefdb1 100644 --- a/packages/bot/src/transformers/toggles/ToggleBitfield.ts +++ b/packages/bot/src/transformers/toggles/ToggleBitfield.ts @@ -6,18 +6,18 @@ export class ToggleBitfield { } /** Tests whether or not this bitfield has the permission requested. */ - contains(bits: number) { + contains(bits: number): boolean { return Boolean(this.bitfield & bits); } /** Adds some bits to the bitfield. */ - add(bits: number) { + add(bits: number): this { this.bitfield |= bits; return this; } /** Removes some bits from the bitfield. */ - remove(bits: number) { + remove(bits: number): this { this.bitfield &= ~bits; return this; } @@ -31,18 +31,18 @@ export class ToggleBitfieldBigint { } /** Tests whether or not this bitfield has the permission requested. */ - contains(bits: bigint) { + contains(bits: bigint): boolean { return Boolean(this.bitfield & bits); } /** Adds some bits to the bitfield. */ - add(bits: bigint) { + add(bits: bigint): this { this.bitfield |= bits; return this; } /** Removes some bits from the bitfield. */ - remove(bits: bigint) { + remove(bits: bigint): this { this.bitfield &= ~bits; return this; } diff --git a/packages/bot/src/transformers/toggles/emoji.ts b/packages/bot/src/transformers/toggles/emoji.ts index d83171a09..d4c8aa829 100644 --- a/packages/bot/src/transformers/toggles/emoji.ts +++ b/packages/bot/src/transformers/toggles/emoji.ts @@ -28,34 +28,34 @@ export class EmojiToggles extends ToggleBitfield { } /** Whether this emoji must be wrapped in colons */ - get requireColons() { + get requireColons(): boolean { return this.has('requireColons') } /** Whether this emoji is managed */ - get managed() { + get managed(): boolean { return this.has('managed') } /** Whether this emoji is animated */ - get animated() { + get animated(): boolean { return this.has('animated') } /** Whether this emoji can be used, may be false due to loss of Server Boosts */ - get available() { + get available(): boolean { return this.has('available') } /** Checks whether or not the permissions exist in this */ - has(permissions: EmojiToggleKeys | EmojiToggleKeys[]) { + has(permissions: EmojiToggleKeys | EmojiToggleKeys[]): boolean { if (!Array.isArray(permissions)) return super.contains(EmojiToggle[permissions]) return super.contains(permissions.reduce((a, b) => (a |= EmojiToggle[b]), 0)) } /** Lists all the toggles for the role and whether or not each is true or false. */ - list() { + list(): Record { const json: Record = {} for (const [key, value] of Object.entries(EmojiToggle)) { json[key] = super.contains(value) diff --git a/packages/bot/src/transformers/toggles/guild.ts b/packages/bot/src/transformers/toggles/guild.ts index d1e80098f..ecfba4fe5 100644 --- a/packages/bot/src/transformers/toggles/guild.ts +++ b/packages/bot/src/transformers/toggles/guild.ts @@ -1,4 +1,4 @@ -import { DiscordGuild, GuildFeatures } from '@discordeno/bot' +import { GuildFeatures, type DiscordGuild } from '@discordeno/bot' import { ToggleBitfieldBigint } from './ToggleBitfield.js' const featureNames = [ @@ -93,7 +93,7 @@ export class GuildToggles extends ToggleBitfieldBigint { constructor(guildOrTogglesBigint: DiscordGuild | bigint) { super() - if (typeof guildOrTogglesBigint == 'bigint') this.bitfield = guildOrTogglesBigint + if (typeof guildOrTogglesBigint === 'bigint') this.bitfield = guildOrTogglesBigint else { const guild = guildOrTogglesBigint // Cause discord be smart like that @@ -133,7 +133,7 @@ export class GuildToggles extends ToggleBitfieldBigint { } } - get features() { + get features(): GuildToggleKeys[] { const features: GuildToggleKeys[] = [] for (const key of Object.keys(GuildToggle)) { if (!featureNames.includes(key)) continue @@ -146,135 +146,154 @@ export class GuildToggles extends ToggleBitfieldBigint { } /** Whether the bot is the owner of the guild */ - get owner() { + get owner(): boolean { return this.has('owner') } /** Whether the server widget is enabled */ - get widgetEnabled() { + get widgetEnabled(): boolean { return this.has('widgetEnabled') } /** Whether this is considered a large guild */ - get large() { + get large(): boolean { return this.has('large') } /** Whether this guild is unavailable due to an outage */ - get unavailable() { + get unavailable(): boolean { return this.has('unavailable') } /** Whether the guild has the boost progress bar enabled */ - get premiumProgressBarEnabled() { + get premiumProgressBarEnabled(): boolean { return this.has('premiumProgressBarEnabled') } /** Whether the guild has access to set an invite splash background */ - get inviteSplash() { + get inviteSplash(): boolean { return this.has('inviteSplash') } + /** Whether the guild has access to set 384 kbps bitrate in voice (previously VIP voice servers) */ - get vipRegions() { + get vipRegions(): boolean { return this.has('vipRegions') } + /** Whether the guild has access to set a vanity URL */ - get vanityUrl() { + get vanityUrl(): boolean { return this.has('vanityUrl') } + /** Whether the guild is verified */ - get verified() { + get verified(): boolean { return this.has('verified') } + /** Whether the guild is partnered */ - get partnered() { + get partnered(): boolean { return this.has('partnered') } + /** Whether the guild can enable welcome screen, Membership Screening, stage channels and discovery, and receives community updates */ - get community() { + get community(): boolean { return this.has('community') } + /** Whether the Guild has been set as a support server on the App Directory */ - get developerSupportServer() { + get developerSupportServer(): boolean { return this.has('developerSupportServer') } + /** Whether the guild has access to set an animated guild banner image */ - get animatedBanner() { + get animatedBanner(): boolean { return this.has('animatedBanner') } + /** Whether the guild has access to create news channels */ - get news() { + get news(): boolean { return this.has('news') } + /** Whether the guild is able to be discovered in the directory */ - get discoverable() { + get discoverable(): boolean { return this.has('discoverable') } + /** Whether the guild is able to be featured in the directory */ - get featurable() { + get featurable(): boolean { return this.has('featurable') } + /** Whether the guild has access to set an animated guild icon */ - get animatedIcon() { + get animatedIcon(): boolean { return this.has('animatedIcon') } + /** Whether the guild has access to set a guild banner image */ - get banner() { + get banner(): boolean { return this.has('banner') } + /** Whether the guild has enabled the welcome screen */ - get welcomeScreenEnabled() { + get welcomeScreenEnabled(): boolean { return this.has('welcomeScreenEnabled') } + /** Whether the guild has enabled [Membership Screening](https://discord.com/developers/docs/resources/guild#membership-screening-object) */ - get memberVerificationGateEnabled() { + get memberVerificationGateEnabled(): boolean { return this.has('memberVerificationGateEnabled') } + /** Whether the guild can be previewed before joining via Membership Screening or the directory */ - get previewEnabled() { + get previewEnabled(): boolean { return this.has('previewEnabled') } + /** Whether the guild has enabled ticketed events */ - get ticketedEventsEnabled() { + get ticketedEventsEnabled(): boolean { return this.has('ticketedEventsEnabled') } + /** Whether the guild has enabled monetization */ - get monetizationEnabled() { + get monetizationEnabled(): boolean { return this.has('monetizationEnabled') } + /** Whether the guild has increased custom sticker slots */ - get moreStickers() { + get moreStickers(): boolean { return this.has('moreStickers') } /** Whether the guild has access to create private threads */ - get privateThreads() { + get privateThreads(): boolean { return this.has('privateThreads') } + /** Whether the guild is able to set role icons */ - get roleIcons() { + get roleIcons(): boolean { return this.has('roleIcons') } /** Whether the guild has set up auto moderation rules */ - get autoModeration() { + get autoModeration(): boolean { return this.has('autoModeration') } /** Whether the guild has paused invites, preventing new users from joining */ - get invitesDisabled() { + get invitesDisabled(): boolean { return this.has('invitesDisabled') } /** Checks whether or not the permissions exist in this */ - has(permissions: GuildToggleKeys | GuildToggleKeys[]) { + has(permissions: GuildToggleKeys | GuildToggleKeys[]): boolean { if (!Array.isArray(permissions)) return super.contains(GuildToggle[permissions]) return super.contains(permissions.reduce((a, b) => (a |= GuildToggle[b]), 0n)) } /** Lists all the toggles for the role and whether or not each is true or false. */ - list() { + list(): Record { const json: Record = {} for (const [key, value] of Object.entries(GuildToggle)) { json[key] = super.contains(value) diff --git a/packages/bot/src/transformers/toggles/member.ts b/packages/bot/src/transformers/toggles/member.ts index 5137e1401..765a23e7c 100644 --- a/packages/bot/src/transformers/toggles/member.ts +++ b/packages/bot/src/transformers/toggles/member.ts @@ -25,29 +25,29 @@ export class MemberToggles extends ToggleBitfield { } /** Whether the user belongs to an OAuth2 application */ - get deaf() { + get deaf(): boolean { return this.has('deaf') } /** Whether the user is muted in voice channels */ - get mute() { + get mute(): boolean { return this.has('mute') } /** Whether the user has not yet passed the guild's Membership Screening requirements */ - get pending() { + get pending(): boolean { return this.has('pending') } /** Checks whether or not the permissions exist in this */ - has(permissions: MemberToggleKeys | MemberToggleKeys[]) { + has(permissions: MemberToggleKeys | MemberToggleKeys[]): boolean { if (!Array.isArray(permissions)) return super.contains(MemberToggle[permissions]) return super.contains(permissions.reduce((a, b) => (a |= MemberToggle[b]), 0)) } /** Lists all the toggles for the role and whether or not each is true or false. */ - list() { + list(): Record { const json: Record = {} for (const [key, value] of Object.entries(MemberToggle)) { json[key] = super.contains(value) diff --git a/packages/bot/src/transformers/toggles/role.ts b/packages/bot/src/transformers/toggles/role.ts index d68083521..581156383 100644 --- a/packages/bot/src/transformers/toggles/role.ts +++ b/packages/bot/src/transformers/toggles/role.ts @@ -28,34 +28,34 @@ export class RoleToggles extends ToggleBitfield { } /** If this role is showed separately in the user listing */ - get hoist() { + get hoist(): boolean { return this.has('hoist') } /** Whether this role is managed by an integration */ - get managed() { + get managed(): boolean { return this.has('managed') } /** Whether this role is mentionable */ - get mentionable() { + get mentionable(): boolean { return this.has('mentionable') } /** Whether this is the guilds premium subscriber role */ - get premiumSubscriber() { + get premiumSubscriber(): boolean { return this.has('premiumSubscriber') } /** Checks whether or not the permissions exist in this */ - has(permissions: RoleToggleKeys | RoleToggleKeys[]) { + has(permissions: RoleToggleKeys | RoleToggleKeys[]): boolean { if (!Array.isArray(permissions)) return super.contains(RoleToggle[permissions]) return super.contains(permissions.reduce((a, b) => (a |= RoleToggle[b]), 0)) } /** Lists all the toggles for the role and whether or not each is true or false. */ - list() { + list(): Record { const json: Record = {} for (const [key, value] of Object.entries(RoleToggle)) { json[key] = super.contains(value) diff --git a/packages/bot/src/transformers/toggles/user.ts b/packages/bot/src/transformers/toggles/user.ts index ebe5df6c2..b69ea1928 100644 --- a/packages/bot/src/transformers/toggles/user.ts +++ b/packages/bot/src/transformers/toggles/user.ts @@ -28,34 +28,34 @@ export class UserToggles extends ToggleBitfield { } /** Whether the user belongs to an OAuth2 application */ - get bot() { + get bot(): boolean { return this.has('bot') } /** Whether the user is an Official Discord System user (part of the urgent message system) */ - get system() { + get system(): boolean { return this.has('system') } /** Whether the user has two factor enabled on their account */ - get mfaEnabled() { + get mfaEnabled(): boolean { return this.has('mfaEnabled') } /** Whether the email on this account has been verified */ - get verified() { + get verified(): boolean { return this.has('verified') } /** Checks whether or not the permissions exist in this */ - has(permissions: UserToggleKeys | UserToggleKeys[]) { + has(permissions: UserToggleKeys | UserToggleKeys[]): boolean { if (!Array.isArray(permissions)) return super.contains(UserToggle[permissions]) return super.contains(permissions.reduce((a, b) => (a |= UserToggle[b]), 0)) } /** Lists all the toggles for the role and whether or not each is true or false. */ - list() { + list(): Record { const json: Record = {} for (const [key, value] of Object.entries(UserToggle)) { json[key] = super.contains(value) diff --git a/packages/bot/src/transformers/toggles/voice.ts b/packages/bot/src/transformers/toggles/voice.ts index c34223bcb..4465fe4e8 100644 --- a/packages/bot/src/transformers/toggles/voice.ts +++ b/packages/bot/src/transformers/toggles/voice.ts @@ -37,49 +37,49 @@ export class VoiceStateToggles extends ToggleBitfield { } /** Whether this user is deafened by the server */ - get deaf() { + get deaf(): boolean { return this.has('deaf') } /** Whether this user is muted by the server */ - get mute() { + get mute(): boolean { return this.has('mute') } /** Whether this user is locally deafened */ - get selfDeaf() { + get selfDeaf(): boolean { return this.has('selfDeaf') } /** Whether this user is locally muted */ - get selfMute() { + get selfMute(): boolean { return this.has('selfMute') } /** Whether this user is streaming using "Go Live" */ - get selfStream() { + get selfStream(): boolean { return this.has('selfStream') } /** Whether this user's camera is enabled */ - get selfVideo() { + get selfVideo(): boolean { return this.has('selfVideo') } /** Whether this user is muted by the current user */ - get suppress() { + get suppress(): boolean { return this.has('suppress') } /** Checks whether or not the permissions exist in this */ - has(permissions: VoiceStateToggleKeys | VoiceStateToggleKeys[]) { + has(permissions: VoiceStateToggleKeys | VoiceStateToggleKeys[]): boolean { if (!Array.isArray(permissions)) return super.contains(VoiceStateToggle[permissions]) return super.contains(permissions.reduce((a, b) => (a |= VoiceStateToggle[b]), 0)) } /** Lists all the toggles for the role and whether or not each is true or false. */ - list() { + list(): Record { const json: Record = {} for (const [key, value] of Object.entries(VoiceStateToggle)) { json[key] = super.contains(value) diff --git a/packages/bot/src/transformers/voiceRegion.ts b/packages/bot/src/transformers/voiceRegion.ts index 461ff7954..a0ae7d8f6 100644 --- a/packages/bot/src/transformers/voiceRegion.ts +++ b/packages/bot/src/transformers/voiceRegion.ts @@ -4,6 +4,7 @@ import type { Optionalize } from '../optionalize.js' // TODO: Rename `VoiceRegions` to `VoiceRegion`. +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type export function transformVoiceRegion(bot: Bot, payload: DiscordVoiceRegion) { const voiceRegion = { id: payload.id, diff --git a/packages/bot/src/transformers/voiceState.ts b/packages/bot/src/transformers/voiceState.ts index 0b9bc42d7..4a4d94e9d 100644 --- a/packages/bot/src/transformers/voiceState.ts +++ b/packages/bot/src/transformers/voiceState.ts @@ -3,6 +3,7 @@ import type { Bot } from '../index.js' import type { Optionalize } from '../optionalize.js' import { VoiceStateToggles } from './toggles/voice.js' +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type export function transformVoiceState(bot: Bot, payload: { voiceState: DiscordVoiceState } & { guildId: bigint }) { const voiceState = { toggles: new VoiceStateToggles(payload.voiceState), diff --git a/packages/bot/src/transformers/webhook.ts b/packages/bot/src/transformers/webhook.ts index 45a5cb297..d3f3f2227 100644 --- a/packages/bot/src/transformers/webhook.ts +++ b/packages/bot/src/transformers/webhook.ts @@ -1,7 +1,8 @@ import type { DiscordWebhook } from '@discordeno/types' -import { Bot, iconHashToBigInt } from '../index.js' +import { iconHashToBigInt, type Bot } from '../index.js' import type { Optionalize } from '../optionalize.js' +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type export function transformWebhook(bot: Bot, payload: DiscordWebhook) { const webhook = { id: bot.transformers.snowflake(payload.id), @@ -9,7 +10,7 @@ export function transformWebhook(bot: Bot, payload: DiscordWebhook) { guildId: payload.guild_id ? bot.transformers.snowflake(payload.guild_id) : undefined, channelId: payload.channel_id ? bot.transformers.snowflake(payload.channel_id) : undefined, user: payload.user ? bot.transformers.user(bot, payload.user) : undefined, - name: payload.name || '', + name: payload.name ?? '', avatar: payload.avatar ? iconHashToBigInt(payload.avatar) : undefined, token: payload.token, applicationId: payload.application_id ? bot.transformers.snowflake(payload.application_id) : undefined, @@ -24,7 +25,7 @@ export function transformWebhook(bot: Bot, payload: DiscordWebhook) { sourceChannel: payload.source_channel ? { id: bot.transformers.snowflake(payload.source_channel.id!), - name: payload.source_channel.name || '', + name: payload.source_channel.name ?? '', } : undefined, /** The url used for executing the webhook (returned by the webhooks OAuth2 flow) */ diff --git a/packages/bot/src/transformers/welcomeScreen.ts b/packages/bot/src/transformers/welcomeScreen.ts index 2852be551..63a299f74 100644 --- a/packages/bot/src/transformers/welcomeScreen.ts +++ b/packages/bot/src/transformers/welcomeScreen.ts @@ -2,6 +2,7 @@ import type { DiscordWelcomeScreen } from '@discordeno/types' import type { Bot } from '../index.js' import type { Optionalize } from '../optionalize.js' +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type export function transformWelcomeScreen(bot: Bot, payload: DiscordWelcomeScreen) { const welcomeScreen = { description: payload.description ?? undefined, diff --git a/packages/bot/src/transformers/widget.ts b/packages/bot/src/transformers/widget.ts index c54a30599..42a244678 100644 --- a/packages/bot/src/transformers/widget.ts +++ b/packages/bot/src/transformers/widget.ts @@ -3,6 +3,7 @@ import type { DiscordGuildWidget } from '@discordeno/types' import type { Bot } from '../index.js' import type { Optionalize } from '../optionalize.js' +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type export function transformWidget(bot: Bot, payload: DiscordGuildWidget) { const widget = { id: bot.transformers.snowflake(payload.id), diff --git a/packages/bot/src/transformers/widgetSettings.ts b/packages/bot/src/transformers/widgetSettings.ts index 28568be6a..4b3697043 100644 --- a/packages/bot/src/transformers/widgetSettings.ts +++ b/packages/bot/src/transformers/widgetSettings.ts @@ -2,6 +2,7 @@ import type { DiscordGuildWidgetSettings } from '@discordeno/types' import type { Bot } from '../index.js' import type { Optionalize } from '../optionalize.js' +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type export function transformWidgetSettings(bot: Bot, payload: DiscordGuildWidgetSettings) { const widget = { enabled: payload.enabled, diff --git a/packages/bot/src/types.ts b/packages/bot/src/typings.ts similarity index 86% rename from packages/bot/src/types.ts rename to packages/bot/src/typings.ts index 0e784d462..aabf048f6 100644 --- a/packages/bot/src/types.ts +++ b/packages/bot/src/typings.ts @@ -1,28 +1,28 @@ import { - AllowedMentions, - ApplicationCommandOptionChoice, ApplicationCommandTypes, - ButtonStyles, - CreateApplicationCommand, - CreateContextApplicationCommand, - DiscordAllowedMentions, - DiscordApplicationCommandOptionChoice, - DiscordAttachment, - DiscordChannel, - DiscordEmbed, - DiscordInteractionMember, - DiscordMessage, - DiscordRole, - DiscordSelectOption, - DiscordUser, - FileContent, - InteractionResponseTypes, - MessageComponents, - MessageComponentTypes, - TextStyles, + type AllowedMentions, + type ApplicationCommandOptionChoice, + type ButtonStyles, + type CreateApplicationCommand, + type CreateContextApplicationCommand, + type DiscordAllowedMentions, + type DiscordApplicationCommandOptionChoice, + type DiscordAttachment, + type DiscordChannel, + type DiscordEmbed, + type DiscordInteractionMember, + type DiscordMessage, + type DiscordRole, + type DiscordSelectOption, + type DiscordUser, + type FileContent, + type InteractionResponseTypes, + type MessageComponents, + type MessageComponentTypes, + type TextStyles, } from '@discordeno/types' -import type * as handlers from './handlers/mod.js' -import type { Embed } from './transformers/embed' +import type * as handlers from './handlers/index.js' +import type { Embed } from './transformers/embed.js' export function isContextApplicationCommand(command: CreateApplicationCommand): command is CreateContextApplicationCommand { return command.type === ApplicationCommandTypes.Message || command.type === ApplicationCommandTypes.User @@ -79,7 +79,7 @@ export interface DiscordComponent { max_values?: number /** The minimum input length for a text input. Between 0-4000. */ min_length?: number - /**The maximum input length for a text input. Between 1-4000. */ + /** The maximum input length for a text input. Between 1-4000. */ max_length?: number /** a list of child components */ components?: DiscordComponent[] @@ -101,7 +101,7 @@ export interface BotInteractionCallbackData { /** True if this is a TTS message */ tts?: boolean /** Embedded `rich` content (up to 6000 characters) */ - embeds?: Array + embeds?: Embed[] /** Allowed mentions for the message */ allowedMentions?: AllowedMentions /** The contents of the file being sent */ @@ -118,11 +118,6 @@ export interface BotInteractionCallbackData { choices?: ApplicationCommandOptionChoice[] } -export interface DiscordInteractionResponse { - type: InteractionResponseTypes - data?: DiscordInteractionCallbackData -} - export interface DiscordInteractionDataResolved { /** The Ids and Message objects */ messages?: Record @@ -147,6 +142,12 @@ export interface DiscordThreadMemberGuildCreate { export interface BotGatewayHandlerOptions { READY: typeof handlers.handleReady + APPLICATION_COMMAND_PERMISSIONS_UPDATE: typeof handlers.handleApplicationCommandPermissionsUpdate + AUTO_MODERATION_ACTION_EXECUTION: typeof handlers.handleAutoModerationActionExecution + AUTO_MODERATION_RULE_CREATE: typeof handlers.handleAutoModerationRuleCreate + AUTO_MODERATION_RULE_DELETE: typeof handlers.handleAutoModerationRuleDelete + AUTO_MODERATION_RULE_UPDATE: typeof handlers.handleAutoModerationRuleUpdate + CHANNEL_CREATE: typeof handlers.handleChannelCreate CHANNEL_DELETE: typeof handlers.handleChannelDelete CHANNEL_PINS_UPDATE: typeof handlers.handleChannelPinsUpdate @@ -178,6 +179,7 @@ export interface BotGatewayHandlerOptions { GUILD_SCHEDULED_EVENT_UPDATE: typeof handlers.handleGuildScheduledEventUpdate GUILD_SCHEDULED_EVENT_USER_ADD: typeof handlers.handleGuildScheduledEventUserAdd GUILD_SCHEDULED_EVENT_USER_REMOVE: typeof handlers.handleGuildScheduledEventUserRemove + GUILD_STICKERS_UPDATE: typeof handlers.handleGuildStickersUpdate GUILD_UPDATE: typeof handlers.handleGuildUpdate INTERACTION_CREATE: typeof handlers.handleInteractionCreate INVITE_CREATE: typeof handlers.handleInviteCreate diff --git a/packages/rest/tests/e2e/guild.spec.ts b/packages/rest/tests/e2e/guild.spec.ts index 1ad321619..7689557d8 100644 --- a/packages/rest/tests/e2e/guild.spec.ts +++ b/packages/rest/tests/e2e/guild.spec.ts @@ -110,4 +110,15 @@ describe('Manage Guilds', async () => { it('Get vanity URL', async () => { await expect(rest.getVanityUrl(e2ecache.guild.id)).to.eventually.rejected }) + + // Get a welcome screen + // it('Get welcome screen', async () => { + // const screen = await rest.getWelcomeScreen(e2ecache.guild.id) + // await rest.editWelcomeScreen(e2ecache.guild.id, { + // enabled: true, + // description: 'some description', + // }) + + + // }) }) diff --git a/packages/rest/tests/e2e/message.spec.ts b/packages/rest/tests/e2e/message.spec.ts index 68b42604d..4dd4487fb 100644 --- a/packages/rest/tests/e2e/message.spec.ts +++ b/packages/rest/tests/e2e/message.spec.ts @@ -128,27 +128,26 @@ describe('Manage reactions', async () => { }) }) -describe("Manage pins", () => { -it('Pin, get, and unpin messages', async () => { - const channel = await rest.createChannel(e2ecache.guild.id, { name: 'pinning' }) - const message = await rest.sendMessage(channel.id, { content: 'pin me' }) - const message2 = await rest.sendMessage(channel.id, { content: 'pin me 2' }) +describe('Manage pins', () => { + it('Pin, get, and unpin messages', async () => { + const channel = await rest.createChannel(e2ecache.guild.id, { name: 'pinning' }) + const message = await rest.sendMessage(channel.id, { content: 'pin me' }) + const message2 = await rest.sendMessage(channel.id, { content: 'pin me 2' }) - await rest.pinMessage(channel.id, message.id) - await rest.pinMessage(channel.id, message2.id, 'with a reason') + await rest.pinMessage(channel.id, message.id) + await rest.pinMessage(channel.id, message2.id, 'with a reason') - const pins = await rest.getPinnedMessages(channel.id) - expect(pins.length).to.equal(2) - expect(pins.some(p => p.id === message.id)).to.equal(true) + const pins = await rest.getPinnedMessages(channel.id) + expect(pins.length).to.equal(2) + expect(pins.some((p) => p.id === message.id)).to.equal(true) - await rest.unpinMessage(channel.id, message.id) - await rest.unpinMessage(channel.id, message2.id, 'with a reason') + await rest.unpinMessage(channel.id, message.id) + await rest.unpinMessage(channel.id, message2.id, 'with a reason') - const unpinned = await rest.getPinnedMessages(channel.id) - expect(unpinned.length).to.equal(0) + const unpinned = await rest.getPinnedMessages(channel.id) + expect(unpinned.length).to.equal(0) + }) }) -}) - describe('Rate limit manager testing', () => { it('Send 10 messages to 1 channel', async () => { diff --git a/packages/types/src/shared.ts b/packages/types/src/shared.ts index fed53662b..ccce3e39b 100644 --- a/packages/types/src/shared.ts +++ b/packages/types/src/shared.ts @@ -700,6 +700,7 @@ export type GatewayDispatchEventNames = | 'THREAD_LIST_SYNC' | 'THREAD_MEMBER_UPDATE' | 'THREAD_MEMBERS_UPDATE' + | 'GUILD_AUDIT_LOG_ENTRY_CREATE' | 'GUILD_CREATE' | 'GUILD_UPDATE' | 'GUILD_DELETE' diff --git a/packages/utils/package.json b/packages/utils/package.json index 0ca9c8ada..88f3f59d0 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -16,7 +16,7 @@ "fmt": "eslint --fix \"src/**/*.ts*\"", "lint": "eslint \"src/**/*.ts*\"", "test:unit-coverage": "c8 mocha --no-warnings 'tests/**/*.spec.ts'", - "test:unit": "c8 --r lcov mocha --no-warnings 'tests/**/*.spec.ts' && node ../../scripts/coveragePathFixing.js utils", + "test:unit": "c8 --r lcov mocha --no-warnings 'tests/**/bucket.spec.ts' && node ../../scripts/coveragePathFixing.js utils", "test:deno-unit": "swc tests --delete-dir-on-start -C jsc.minify.mangle=false --out-dir denoTestsDist && node ../../scripts/fixDenoTestExtension.js && deno test -A --import-map ../../denoImportMap.json denoTestsDist", "test:unit:watch": "mocha --no-warnings --watch --parallel 'tests/**/*.spec.ts'", "test:type": "tsc --noEmit", diff --git a/packages/utils/src/bucket.ts b/packages/utils/src/bucket.ts index 05a8ba0c4..d522a676e 100644 --- a/packages/utils/src/bucket.ts +++ b/packages/utils/src/bucket.ts @@ -28,6 +28,22 @@ export class LeakyBucket implements LeakyBucketOptions { return this.max < this.used ? 0 : this.max - this.used } + /** Refills the bucket as needed. */ + refillBucket(): void { + console.log('refilling bucket'); + logger.info(`[LeakyBucket] Timeout for leaky bucket requests executed. Refilling bucket.`) + // Lower the used amount by the refill amount + this.used = this.refillAmount > this.used ? 0 : this.used - this.refillAmount + // Reset the refillsAt timestamp since it just got refilled + this.refillsAt = undefined + + if (this.used > 0) { + if (this.timeoutId) clearTimeout(this.timeoutId) + this.timeoutId = setTimeout(() => this.refillBucket, this.refillInterval) + this.refillsAt = Date.now() + this.refillInterval + } + } + /** Begin processing the queue. */ async processQueue(): Promise { logger.debug('[Gateway] Processing queue') @@ -49,13 +65,8 @@ export class LeakyBucket implements LeakyBucketOptions { // Create a new timeout for this request if none exists. if (!this.timeoutId) { logger.debug(`[LeakyBucket] Creating new timeout for leaky bucket requests.`) - this.timeoutId = setTimeout(() => { - logger.debug(`[LeakyBucket] Timeout for leaky bucket requests executed. Refilling bucket.`) - // Lower the used amount by the refill amount - this.used -= this.refillAmount - // Reset the refillsAt timestamp since it just got refilled - this.refillsAt = undefined - }, this.refillInterval) + + this.timeoutId = setTimeout(() => this.refillBucket, this.refillInterval) // Set the time for when this refill will occur. this.refillsAt = Date.now() + this.refillInterval } diff --git a/packages/utils/tests/bucket.spec.ts b/packages/utils/tests/bucket.spec.ts index 6275306df..df1a8a8dc 100644 --- a/packages/utils/tests/bucket.spec.ts +++ b/packages/utils/tests/bucket.spec.ts @@ -62,5 +62,26 @@ describe('bucket.ts', () => { }) expect(bucket.queue).to.deep.equal([]) }) + + it('idk', async () => { + const bucket = new LeakyBucket({ + max: 2, + refillInterval: 500, + refillAmount: 2, + }) + + const now = Date.now() + await bucket.acquire() + + console.log((Date.now() - now), bucket.used, bucket.remaining) + await clock.tickAsync(1000) + console.log((Date.now() - now), bucket.used, bucket.remaining) + + await bucket.acquire() + + console.log((Date.now() - now), bucket.used, bucket.remaining) + await clock.tickAsync(1000) + console.log((Date.now() - now), bucket.used, bucket.remaining) + }) }) })