From 27fc12ec34073662c70a7efd7b54fb80541d92b5 Mon Sep 17 00:00:00 2001 From: Fleny Date: Sat, 20 Jul 2024 23:52:21 +0200 Subject: [PATCH] feat(cli)!: CLI generated types (#3453) * Move transformers types to a single file * Add script to test TS Compiler api capabilities Remove nested objects where possible * Use Partial and DiscordOverwrite instead of objects in AuditLogChange * Fix typescript errors * Remove interfaces.json It is a generated file from the test script, not something that should be commited * Start work on the test generation script The TS version got bumped to 5.5.3 * Fix any type, use node16 module resolution "node" is a deprecated alias for "node10", node16 is the recommended Add code to check for type errors when getting the types from the interfaces Fix errors when TS tries to find the files that the root tsconfig.json handles * remove some useless compile options in TSApiTest * Add jsdoc parsing JSDoc tags with the next right after are not supported * fix small format issue * Fix ApplicationCommandPermissions todo * Fix CI error * Simplify parseDocumentation * get type directly from the sourceFile * remove hasUndefinedUnion as it is no longer used * fix discordeno bin file name * Update the yarn lockfile * Merge scripts into one * Use `@internal` instead of `@private` + `@deprecated` * work on .d.ts files * Process interface members once * Move emit/preEmit diagnostics to a unit test they can take quite a while, even 3-4 seconds, so running in the CLI every time does not seem ideal * test: add build:types to test:unit dependencies This is a test commit, it will provably get reversed. The scope is to see what CI does with this * add find-up to deno import map * add typescript to the deno import map * Add node:assert to deno import map * check for this.timeout that exists deno does not have the timeout * add build:type to deno-unit * Temp hack to work-around the script deno tests * Test with bun running the test as well * fix turbo deps for unit tests * remove test scripts * Update CI to use build:type cache * Apply code review suggestion Co-authored-by: LTS20050703 * Add code to modify the interface member * use an actual config The config source is still a dummy object for now * Search and use discordeno.config.js file * provide config from cli options * Handle props in base objects The dependencies of an object need to be declared/updated manually, it would be painful to fix this in such a way that would be something that Typescript can give us from the compiler API * add some tests for desired proprieties * also check for a .mjs config file * Add support for .ts config files We use the typescript compiler to emit an in-memory version of the config file, import it and then remove it. It does not do bundling so if the config imports local files it will not work. Also the file is not type-checked as it would slow down the config loading * remove compiler host, use callback on program.emit * fix deno ci error * add node:fs/promises to deno import map --------- Co-authored-by: LTS20050703 --- .github/workflows/lib-check.yml | 12 +- .github/workflows/other-runtime-unit-test.yml | 12 + .github/workflows/unit-test.yml | 6 + denoImportMap.json | 6 + package.json | 1 + .../benchmarks/src/benchmarks/transformers.ts | 16 +- packages/bot/src/bot.ts | 44 +- packages/bot/src/helpers.ts | 66 +- packages/bot/src/transformers.ts | 1859 +++++++++-------- packages/bot/src/transformers/activity.ts | 35 +- packages/bot/src/transformers/application.ts | 42 +- .../src/transformers/applicationCommand.ts | 19 +- .../transformers/applicationCommandOption.ts | 36 +- .../applicationCommandOptionChoice.ts | 10 +- .../applicationCommandPermission.ts | 22 +- packages/bot/src/transformers/attachment.ts | 39 +- .../bot/src/transformers/auditLogEntry.ts | 124 +- .../transformers/automodActionExecution.ts | 25 +- packages/bot/src/transformers/automodRule.ts | 38 +- .../src/transformers/avatarDecorationData.ts | 9 +- packages/bot/src/transformers/channel.ts | 153 +- packages/bot/src/transformers/component.ts | 47 +- packages/bot/src/transformers/embed.ts | 51 +- packages/bot/src/transformers/emoji.ts | 29 +- packages/bot/src/transformers/entitlement.ts | 27 +- packages/bot/src/transformers/gatewayBot.ts | 13 +- packages/bot/src/transformers/guild.ts | 125 +- packages/bot/src/transformers/index.ts | 1 + packages/bot/src/transformers/integration.ts | 33 +- packages/bot/src/transformers/interaction.ts | 168 +- packages/bot/src/transformers/invite.ts | 44 +- packages/bot/src/transformers/member.ts | 57 +- packages/bot/src/transformers/message.ts | 233 +-- packages/bot/src/transformers/onboarding.ts | 59 +- packages/bot/src/transformers/poll.ts | 81 +- packages/bot/src/transformers/presence.ts | 12 +- .../bot/src/transformers/reverse/activity.ts | 3 +- .../src/transformers/reverse/application.ts | 3 +- .../reverse/applicationCommand.ts | 3 +- .../reverse/applicationCommandOption.ts | 3 +- .../reverse/applicationCommandOptionChoice.ts | 3 +- .../reverse/applicationCommandPermission.ts | 5 +- .../src/transformers/reverse/attachment.ts | 3 +- .../src/transformers/reverse/auditLogEntry.ts | 3 +- .../bot/src/transformers/reverse/component.ts | 3 +- .../bot/src/transformers/reverse/embed.ts | 3 +- .../bot/src/transformers/reverse/emoji.ts | 3 +- .../src/transformers/reverse/gatewayBot.ts | 2 +- .../bot/src/transformers/reverse/member.ts | 3 +- .../bot/src/transformers/reverse/presence.ts | 3 +- packages/bot/src/transformers/reverse/team.ts | 3 +- .../transformers/reverse/widgetSettings.ts | 3 +- packages/bot/src/transformers/role.ts | 90 +- .../bot/src/transformers/scheduledEvent.ts | 45 +- packages/bot/src/transformers/sku.ts | 19 +- .../bot/src/transformers/stageInstance.ts | 15 +- .../src/transformers/stageInviteInstance.ts | 13 +- packages/bot/src/transformers/sticker.ts | 38 +- packages/bot/src/transformers/team.ts | 17 +- packages/bot/src/transformers/template.ts | 16 +- packages/bot/src/transformers/threadMember.ts | 13 +- packages/bot/src/transformers/types.ts | 1651 +++++++++++++++ packages/bot/src/transformers/user.ts | 56 +- packages/bot/src/transformers/voiceRegion.ts | 10 +- packages/bot/src/transformers/voiceState.ts | 11 +- packages/bot/src/transformers/webhook.ts | 32 +- .../bot/src/transformers/welcomeScreen.ts | 12 +- packages/bot/src/transformers/widget.ts | 22 +- .../bot/src/transformers/widgetSettings.ts | 7 +- packages/bot/src/typings.ts | 3 +- packages/discordeno/bin/discordeno.js | 1 + packages/discordeno/bin/disocrdeno.js | 1 - packages/discordeno/package.json | 10 +- packages/discordeno/src/bin/config.ts | 88 + .../src/bin/generate/desiredProperty.ts | 115 + .../discordeno/src/bin/generate/emitter.ts | 55 + .../discordeno/src/bin/generate/typescript.ts | 123 ++ packages/discordeno/src/bin/index.ts | 43 +- packages/discordeno/src/index.ts | 1 + packages/discordeno/tests/generate.spec.ts | 91 + packages/rest/src/types.ts | 4 +- packages/tsconfig/base.json | 6 +- packages/types/src/discord.ts | 49 +- packages/types/src/discordeno.ts | 11 - packages/types/src/shared.ts | 2 + scripts/fixDenoTestExtension.js | 1 - turbo.json | 6 +- yarn.lock | 65 +- 88 files changed, 3496 insertions(+), 2849 deletions(-) create mode 100644 packages/bot/src/transformers/types.ts create mode 100644 packages/discordeno/bin/discordeno.js delete mode 100755 packages/discordeno/bin/disocrdeno.js create mode 100644 packages/discordeno/src/bin/config.ts create mode 100644 packages/discordeno/src/bin/generate/desiredProperty.ts create mode 100644 packages/discordeno/src/bin/generate/emitter.ts create mode 100644 packages/discordeno/src/bin/generate/typescript.ts create mode 100644 packages/discordeno/tests/generate.spec.ts diff --git a/.github/workflows/lib-check.yml b/.github/workflows/lib-check.yml index 650697247..d6bcaa0a8 100644 --- a/.github/workflows/lib-check.yml +++ b/.github/workflows/lib-check.yml @@ -135,7 +135,7 @@ jobs: # Not using matrix because test later on cant needs a specific job bot-unit-test: name: Bot - needs: build-dist + needs: [build-dist, build-type-and-test] uses: ./.github/workflows/unit-test.yml with: package: bot @@ -157,7 +157,7 @@ jobs: discordeno-unit-test: name: Discordeno - needs: build-dist + needs: [build-dist, build-type-and-test] uses: ./.github/workflows/unit-test.yml with: package: discordeno @@ -170,7 +170,7 @@ jobs: gateway-unit-test: name: Gateway - needs: build-dist + needs: [build-dist, build-type-and-test] uses: ./.github/workflows/unit-test.yml with: package: gateway @@ -189,7 +189,7 @@ jobs: rest-unit-test: name: Rest - needs: build-dist + needs: [build-dist, build-type-and-test] uses: ./.github/workflows/unit-test.yml with: package: rest @@ -211,7 +211,7 @@ jobs: types-unit-test: name: Types - needs: build-dist + needs: [build-dist, build-type-and-test] uses: ./.github/workflows/unit-test.yml with: package: types @@ -224,7 +224,7 @@ jobs: utils-unit-test: name: Utils - needs: build-dist + needs: [build-dist, build-type-and-test] uses: ./.github/workflows/unit-test.yml with: package: utils diff --git a/.github/workflows/other-runtime-unit-test.yml b/.github/workflows/other-runtime-unit-test.yml index 71a987fee..3f2919cc5 100644 --- a/.github/workflows/other-runtime-unit-test.yml +++ b/.github/workflows/other-runtime-unit-test.yml @@ -41,6 +41,12 @@ jobs: with: path: .turbo key: ${{ runner.os }}-turbo-build-${{ github.sha }} + - name: Build type cache + if: steps.turbo-cache.outputs.cache-hit != 'true' + uses: actions/cache@v3 + with: + path: .turbo + key: ${{ runner.os }}-turbo-build:type-${{ github.sha }} - name: Deno cache uses: actions/cache@v3 with: @@ -85,6 +91,12 @@ jobs: with: path: .turbo key: ${{ runner.os }}-turbo-build-${{ github.sha }} + - name: Build type cache + if: steps.turbo-cache.outputs.cache-hit != 'true' + uses: actions/cache@v3 + with: + path: .turbo + key: ${{ runner.os }}-turbo-build:type-${{ github.sha }} - name: Bun Unit Test run: yarn test:bun-unit --cache-dir=".turbo" --filter=./packages/${{ inputs.package }} timeout-minutes: 1 diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index d8b7d57e0..60006f837 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -38,6 +38,12 @@ jobs: with: path: .turbo key: ${{ runner.os }}-turbo-build-${{ github.sha }} + - name: Build type cache + if: steps.turbo-cache.outputs.cache-hit != 'true' + uses: actions/cache@v3 + with: + path: .turbo + key: ${{ runner.os }}-turbo-build:type-${{ github.sha }} - name: Unit Test run: yarn test:unit --cache-dir=".turbo" --filter=./packages/${{ inputs.package }} timeout-minutes: 1 diff --git a/denoImportMap.json b/denoImportMap.json index 610822702..504718bf8 100644 --- a/denoImportMap.json +++ b/denoImportMap.json @@ -2,16 +2,22 @@ "imports": { "node:buffer": "https://deno.land/std@0.176.0/node/buffer.ts", "node:fs": "https://deno.land/std@0.176.0/node/fs.ts", + "node:fs/promises": "https://deno.land/std@0.176.0/node/fs/promises.ts", "node:events": "https://deno.land/std@0.176.0/node/events.ts", "tweetnacl": "npm:tweetnacl", "ws": "npm:ws", "mocha": "https://deno.land/std@0.168.0/testing/bdd.ts", "chai": "https://cdn.skypack.dev/chai@4.3.4?dts", "sinon": "https://cdn.skypack.dev/sinon@15.0.0?dts", + "find-up": "npm:find-up", + "typescript": "npm:typescript", "chai-as-promised": "npm:chai-as-promised", "benchmark": "npm:benchmark", "dotenv": "npm:dotenv", "node:zlib": "https://deno.land/std@0.176.0/node/zlib.ts", + "node:assert": "https://deno.land/std@0.176.0/node/assert.ts", + "node:path": "https://deno.land/std@0.176.0/node/path.ts", + "node:url": "https://deno.land/std@0.176.0/node/url.ts", "@discordeno/utils": "./packages/utils/dist/esm/index.js", "@discordeno/types": "./packages/types/dist/esm/index.js", "@discordeno/rest": "./packages/rest/dist/esm/index.js", diff --git a/package.json b/package.json index 5efa184ac..efc99b41a 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "devDependencies": { "@biomejs/biome": "^1.8.0", "chokidar-cli": "^3.0.0", + "discordeno": "19.0.0-alpha.1", "husky": "^9.0.11", "lint-staged": "^15.2.7", "turbo": "^2.0.6", diff --git a/packages/benchmarks/src/benchmarks/transformers.ts b/packages/benchmarks/src/benchmarks/transformers.ts index 1f415ed5b..6d4a18a04 100644 --- a/packages/benchmarks/src/benchmarks/transformers.ts +++ b/packages/benchmarks/src/benchmarks/transformers.ts @@ -40,18 +40,18 @@ bot.transformers.desiredProperties.message.editedTimestamp = true bot.transformers.desiredProperties.message.embeds = true bot.transformers.desiredProperties.message.guildId = true bot.transformers.desiredProperties.message.id = true -bot.transformers.desiredProperties.message.interaction.id = true -bot.transformers.desiredProperties.message.interaction.member = true -bot.transformers.desiredProperties.message.interaction.name = true -bot.transformers.desiredProperties.message.interaction.user = true -bot.transformers.desiredProperties.message.interaction.type = true +bot.transformers.desiredProperties.messageInteraction.id = true +bot.transformers.desiredProperties.messageInteraction.member = true +bot.transformers.desiredProperties.messageInteraction.name = true +bot.transformers.desiredProperties.messageInteraction.user = true +bot.transformers.desiredProperties.messageInteraction.type = true bot.transformers.desiredProperties.message.member = true bot.transformers.desiredProperties.message.mentionedChannelIds = true bot.transformers.desiredProperties.message.mentionedRoleIds = true bot.transformers.desiredProperties.message.mentions = true -bot.transformers.desiredProperties.message.messageReference.messageId = true -bot.transformers.desiredProperties.message.messageReference.channelId = true -bot.transformers.desiredProperties.message.messageReference.guildId = true +bot.transformers.desiredProperties.messageReference.messageId = true +bot.transformers.desiredProperties.messageReference.channelId = true +bot.transformers.desiredProperties.messageReference.guildId = true bot.transformers.desiredProperties.message.nonce = true bot.transformers.desiredProperties.message.reactions = true bot.transformers.desiredProperties.message.stickerItems = true diff --git a/packages/bot/src/bot.ts b/packages/bot/src/bot.ts index 4a9dec632..819b203ce 100644 --- a/packages/bot/src/bot.ts +++ b/packages/bot/src/bot.ts @@ -7,26 +7,28 @@ import { type Collection, createLogger, getBotIdFromToken, type logger } from '@ import { createBotGatewayHandlers } from './handlers.js' import { type BotHelpers, createBotHelpers } from './helpers.js' import { type Transformers, createTransformers } 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 { Entitlement } from './transformers/entitlement.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 } 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 { User } from './transformers/user.js' -import type { VoiceState } from './transformers/voiceState.js' +import type { + AuditLogEntry, + AutoModerationActionExecution, + AutoModerationRule, + Channel, + Emoji, + Entitlement, + Guild, + GuildApplicationCommandPermissions, + Integration, + Interaction, + Invite, + Member, + Message, + PresenceUpdate, + Role, + ScheduledEvent, + Sticker, + ThreadMember, + User, + VoiceState, +} from './transformers/index.js' import type { BotGatewayHandlerOptions } from './typings.js' /** @@ -161,7 +163,7 @@ export interface Bot { export interface EventHandlers { debug: (text: string, ...args: any[]) => unknown - applicationCommandPermissionsUpdate: (command: ApplicationCommandPermission) => unknown + applicationCommandPermissionsUpdate: (command: GuildApplicationCommandPermissions) => unknown guildAuditLogEntryCreate: (log: AuditLogEntry, guildId: bigint) => unknown automodRuleCreate: (rule: AutoModerationRule) => unknown automodRuleUpdate: (rule: AutoModerationRule) => unknown diff --git a/packages/bot/src/helpers.ts b/packages/bot/src/helpers.ts index e903be572..ea24c3cc8 100644 --- a/packages/bot/src/helpers.ts +++ b/packages/bot/src/helpers.ts @@ -2,11 +2,11 @@ import type { CreateWebhook } from '@discordeno/rest' import type { AddDmRecipientOptions, AddGuildMemberOptions, - ApplicationCommandPermissions, AtLeastOne, BeginGuildPrune, BigString, CamelizedDiscordAccessTokenResponse, + CamelizedDiscordApplicationCommandPermissions, CamelizedDiscordApplicationRoleConnection, CamelizedDiscordArchivedThreads, CamelizedDiscordAuditLog, @@ -94,31 +94,34 @@ import type { } from '@discordeno/types' import { snakelize } from '@discordeno/utils' import type { Bot } from './bot.js' -import type { Application } from './transformers/application.js' -import type { ApplicationCommand } from './transformers/applicationCommand.js' -import type { ApplicationCommandPermission } from './transformers/applicationCommandPermission.js' -import type { AutoModerationRule } from './transformers/automodRule.js' -import type { Channel } from './transformers/channel.js' -import type { Emoji } from './transformers/emoji.js' -import { type Entitlement } from './transformers/entitlement.js' -import type { Guild } from './transformers/guild.js' -import type { Integration } from './transformers/integration.js' -import type { Invite } from './transformers/invite.js' -import type { Member } from './transformers/member.js' -import type { Message } from './transformers/message.js' -import type { GuildOnboarding } from './transformers/onboarding.js' -import type { Role } from './transformers/role.js' -import type { ScheduledEvent } from './transformers/scheduledEvent.js' -import type { Sku } from './transformers/sku.js' -import type { StageInstance } from './transformers/stageInstance.js' -import type { Sticker, StickerPack } from './transformers/sticker.js' -import type { Template } from './transformers/template.js' -import type { ThreadMember } from './transformers/threadMember.js' -import type { User } from './transformers/user.js' -import type { Webhook } from './transformers/webhook.js' -import type { WelcomeScreen } from './transformers/welcomeScreen.js' -import type { GuildWidget } from './transformers/widget.js' -import type { GuildWidgetSettings } from './transformers/widgetSettings.js' +import type { + Application, + ApplicationCommand, + AutoModerationRule, + Channel, + Emoji, + Entitlement, + Guild, + GuildApplicationCommandPermissions, + GuildOnboarding, + GuildWidget, + GuildWidgetSettings, + Integration, + Invite, + Member, + Message, + Role, + ScheduledEvent, + Sku, + StageInstance, + Sticker, + StickerPack, + Template, + ThreadMember, + User, + Webhook, + WelcomeScreen, +} from './transformers/index.js' export function createBotHelpers(bot: Bot): BotHelpers { return { @@ -740,8 +743,8 @@ export interface BotHelpers { guildId: BigString, commandId: BigString, bearerToken: string, - options: ApplicationCommandPermissions[], - ) => Promise + options: CamelizedDiscordApplicationCommandPermissions[], + ) => Promise editAutomodRule: ( guildId: BigString, ruleId: BigString, @@ -791,8 +794,11 @@ export interface BotHelpers { guildId: BigString, commandId: BigString, options?: GetApplicationCommandPermissionOptions, - ) => Promise - getApplicationCommandPermissions: (guildId: BigString, options?: GetApplicationCommandPermissionOptions) => Promise + ) => Promise + getApplicationCommandPermissions: ( + guildId: BigString, + options?: GetApplicationCommandPermissionOptions, + ) => Promise getAuditLog: (guildId: BigString, options?: GetGuildAuditLog) => Promise getAutomodRule: (guildId: BigString, ruleId: BigString) => Promise getAutomodRules: (guildId: BigString) => Promise diff --git a/packages/bot/src/transformers.ts b/packages/bot/src/transformers.ts index 0f8a06cc1..10a6700b6 100644 --- a/packages/bot/src/transformers.ts +++ b/packages/bot/src/transformers.ts @@ -53,81 +53,130 @@ import type { DiscordVoiceState, DiscordWebhook, DiscordWelcomeScreen, + RecursivePartial, } from '@discordeno/types' import { logger } from '@discordeno/utils' -import { type Bot, bigintToSnowflake, snowflakeToBigint } from './index.js' -import { type Activity, transformActivity } from './transformers/activity.js' -import { type Application, transformApplication } from './transformers/application.js' -import { type ApplicationCommand, transformApplicationCommand } from './transformers/applicationCommand.js' -import { type ApplicationCommandOption, transformApplicationCommandOption } from './transformers/applicationCommandOption.js' -import { type ApplicationCommandOptionChoice, transformApplicationCommandOptionChoice } from './transformers/applicationCommandOptionChoice.js' -import { type ApplicationCommandPermission, transformApplicationCommandPermission } from './transformers/applicationCommandPermission.js' -import { type Attachment, transformAttachment } from './transformers/attachment.js' -import { type AuditLogEntry, transformAuditLogEntry } from './transformers/auditLogEntry.js' -import { type AutoModerationActionExecution, transformAutoModerationActionExecution } from './transformers/automodActionExecution.js' -import { type AutoModerationRule, transformAutoModerationRule } from './transformers/automodRule.js' -import { type Channel, type ForumTag, transformChannel, transformForumTag } from './transformers/channel.js' -import { type Component, transformComponent } from './transformers/component.js' -import { type Embed, transformEmbed } from './transformers/embed.js' -import { type DefaultReactionEmoji, type Emoji, transformDefaultReactionEmoji, transformEmoji } from './transformers/emoji.js' -import { type Entitlement, transformEntitlement } from './transformers/entitlement.js' -import { type GetGatewayBot, transformGatewayBot } from './transformers/gatewayBot.js' -import { type Guild, transformGuild } from './transformers/guild.js' +import type { Bot } from './bot.js' import { + type Activity, + type Application, + type ApplicationCommand, + type ApplicationCommandOption, + type ApplicationCommandOptionChoice, + type Attachment, + type AuditLogEntry, + type AutoModerationActionExecution, + type AutoModerationRule, type AvatarDecorationData, - transformActivityToDiscordActivity, - transformApplicationCommandOptionChoiceToDiscordApplicationCommandOptionChoice, - transformApplicationCommandOptionToDiscordApplicationCommandOption, - transformApplicationCommandToDiscordApplicationCommand, - transformApplicationToDiscordApplication, - transformAttachmentToDiscordAttachment, - transformAvatarDecorationData, - transformComponentToDiscordComponent, - transformEmbedToDiscordEmbed, - transformMemberToDiscordMember, - transformTeamToDiscordTeam, - transformUserToDiscordUser, -} from './transformers/index.js' -import { type Integration, transformIntegration } from './transformers/integration.js' -import { type Interaction, type InteractionDataOption, transformInteraction, transformInteractionDataOption } from './transformers/interaction.js' -import { type Invite, transformInvite } from './transformers/invite.js' -import { type Member, transformMember } from './transformers/member.js' -import { + type Channel, + type Component, + type DefaultReactionEmoji, + type Embed, + type Emoji, + type Entitlement, + type ForumTag, + type GetGatewayBot, + type Guild, + type GuildApplicationCommandPermissions, + type GuildOnboarding, + type GuildWidget, + type GuildWidgetSettings, + type Integration, + type Interaction, + type InteractionDataOption, + type Invite, + type InviteStageInstance, + type Member, type Message, type MessageCall, type MessageInteractionMetadata, + type Poll, + type PollMedia, + type PresenceUpdate, + type Role, + type ScheduledEvent, + type Sku, + type StageInstance, + type Sticker, + type StickerPack, + type Team, + type Template, + type ThreadMember, + type ThreadMemberGuildCreate, + type User, + type VoiceRegion, + type VoiceState, + type Webhook, + type WelcomeScreen, + transformActivity, + transformActivityToDiscordActivity, + transformApplication, + transformApplicationCommand, + transformApplicationCommandOption, + transformApplicationCommandOptionChoice, + transformApplicationCommandOptionChoiceToDiscordApplicationCommandOptionChoice, + transformApplicationCommandOptionToDiscordApplicationCommandOption, + transformApplicationCommandPermission, + transformApplicationCommandToDiscordApplicationCommand, + transformApplicationToDiscordApplication, + transformAttachment, + transformAttachmentToDiscordAttachment, + transformAuditLogEntry, + transformAutoModerationActionExecution, + transformAutoModerationRule, + transformAvatarDecorationData, + transformChannel, + transformComponent, + transformComponentToDiscordComponent, + transformDefaultReactionEmoji, + transformEmbed, + transformEmbedToDiscordEmbed, + transformEmoji, + transformEntitlement, + transformForumTag, + transformGatewayBot, + transformGuild, + transformGuildOnboarding, + transformIntegration, + transformInteraction, + transformInteractionDataOption, + transformInvite, + transformInviteStageInstance, + transformMember, + transformMemberToDiscordMember, transformMessage, transformMessageCall, transformMessageInteractionMetadata, -} from './transformers/message.js' -import { type GuildOnboarding, transformGuildOnboarding } from './transformers/onboarding.js' -import { type Poll, type PollMedia, transformPoll, transformPollMedia } from './transformers/poll.js' -import { type PresenceUpdate, transformPresence } 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 { type Role, transformRole } from './transformers/role.js' -import { type ScheduledEvent, transformScheduledEvent } from './transformers/scheduledEvent.js' -import { type Sku, transformSku } from './transformers/sku.js' -import { type StageInstance, transformStageInstance } from './transformers/stageInstance.js' -import { type InviteStageInstance, transformInviteStageInstance } from './transformers/stageInviteInstance.js' -import { type Sticker, type StickerPack, transformSticker, transformStickerPack } from './transformers/sticker.js' -import { type Team, transformTeam } from './transformers/team.js' -import { type Template, transformTemplate } from './transformers/template.js' -import { - type ThreadMember, - type ThreadMemberGuildCreate, + transformPoll, + transformPollMedia, + transformPresence, + transformRole, + transformScheduledEvent, + transformSku, + transformStageInstance, + transformSticker, + transformStickerPack, + transformTeam, + transformTeamToDiscordTeam, + transformTemplate, transformThreadMember, transformThreadMemberGuildCreate, -} from './transformers/threadMember.js' -import { type User, transformUser } from './transformers/user.js' -import { type VoiceRegion, transformVoiceRegion } from './transformers/voiceRegion.js' -import { type VoiceState, transformVoiceState } from './transformers/voiceState.js' -import { type Webhook, transformWebhook } from './transformers/webhook.js' -import { type WelcomeScreen, transformWelcomeScreen } from './transformers/welcomeScreen.js' -import { type GuildWidget, transformWidget } from './transformers/widget.js' -import { type GuildWidgetSettings, transformWidgetSettings } from './transformers/widgetSettings.js' + transformUser, + transformUserToDiscordUser, + transformVoiceRegion, + transformVoiceState, + transformWebhook, + transformWelcomeScreen, + transformWidget, + transformWidgetSettings, +} from './transformers/index.js' +import { + transformAllowedMentionsToDiscordAllowedMentions, + transformCreateApplicationCommandToDiscordCreateApplicationCommand, + transformInteractionResponseToDiscordInteractionResponse, +} from './transformers/reverse/index.js' import type { BotInteractionResponse, DiscordComponent, DiscordInteractionResponse, DiscordThreadMemberGuildCreate } from './typings.js' +import { bigintToSnowflake, snowflakeToBigint } from './utils.js' export interface Transformers { customizers: { @@ -163,7 +212,7 @@ export interface Transformers { applicationCommandPermission: ( bot: Bot, payload: DiscordGuildApplicationCommandPermissions, - applicationCommandPermission: ApplicationCommandPermission, + applicationCommandPermission: GuildApplicationCommandPermissions, ) => any scheduledEvent: (bot: Bot, payload: DiscordScheduledEvent, scheduledEvent: ScheduledEvent) => any threadMember: (bot: Bot, payload: DiscordThreadMember, threadMember: ThreadMember) => any @@ -190,416 +239,7 @@ export interface Transformers { pollMedia: (bot: Bot, payload: DiscordPollMedia, pollMedia: PollMedia) => any avatarDecorationData: (bot: Bot, payload: DiscordAvatarDecorationData, avatarDecorationData: AvatarDecorationData) => any } - desiredProperties: { - attachment: { - id: boolean - filename: boolean - title: boolean - contentType: boolean - size: boolean - url: boolean - proxyUrl: boolean - height: boolean - width: boolean - ephemeral: boolean - description: boolean - duration_secs: boolean - waveform: boolean - flags: boolean - } - channel: { - type: boolean - position: boolean - name: boolean - topic: boolean - nsfw: boolean - bitrate: boolean - userLimit: boolean - rateLimitPerUser: boolean - rtcRegion: boolean - videoQualityMode: boolean - guildId: boolean - lastPinTimestamp: boolean - permissionOverwrites: boolean - id: boolean - permissions: boolean - lastMessageId: boolean - ownerId: boolean - applicationId: boolean - managed: boolean - parentId: boolean - memberCount: boolean - messageCount: boolean - archiveTimestamp: boolean - defaultAutoArchiveDuration: boolean - autoArchiveDuration: boolean - botIsMember: boolean - archived: boolean - locked: boolean - invitable: boolean - createTimestamp: boolean - newlyCreated: boolean - flags: boolean - recipients: boolean - icon: boolean - member: boolean - totalMessageSent: boolean - availableTags: boolean - appliedTags: boolean - defaultReactionEmoji: boolean - defaultThreadRateLimitPerUser: boolean - defaultSortOrder: boolean - defaultForumLayout: boolean - } - forumTag: { - id: boolean - name: boolean - moderated: boolean - emojiId: boolean - emojiName: boolean - } - emoji: { - id: boolean - name: boolean - roles: boolean - user: boolean - } - defaultReactionEmoji: { - emojiId: boolean - emojiName: boolean - } - guild: { - afkTimeout: boolean - approximateMemberCount: boolean - approximatePresenceCount: boolean - defaultMessageNotifications: boolean - description: boolean - explicitContentFilter: boolean - maxMembers: boolean - maxPresences: boolean - maxVideoChannelUsers: boolean - mfaLevel: boolean - name: boolean - nsfwLevel: boolean - preferredLocale: boolean - premiumSubscriptionCount: boolean - premiumTier: boolean - toggles: boolean - stageInstances: boolean - channels: boolean - members: boolean - roles: boolean - emojis: boolean - stickers: boolean - threads: boolean - voiceStates: boolean - large: boolean - owner: boolean - widgetEnabled: boolean - unavailable: boolean - iconHash: boolean - presences: boolean - systemChannelFlags: boolean - vanityUrlCode: boolean - verificationLevel: boolean - welcomeScreen: boolean - discoverySplash: boolean - joinedAt: boolean - memberCount: boolean - shardId: boolean - icon: boolean - banner: boolean - splash: boolean - id: boolean - ownerId: boolean - permissions: boolean - afkChannelId: boolean - widgetChannelId: boolean - applicationId: boolean - systemChannelId: boolean - rulesChannelId: boolean - publicUpdatesChannelId: boolean - premiumProgressBarEnabled: boolean - safetyAlertsChannelId: boolean - } - interaction: { - id: boolean - applicationId: boolean - type: boolean - guild: boolean - guildId: boolean - channel: boolean - channelId: boolean - member: boolean - user: boolean - token: boolean - version: boolean - message: boolean - data: boolean - locale: boolean - guildLocale: boolean - appPermissions: boolean - authorizingIntegrationOwners: boolean - context: boolean - } - invite: { - type: boolean - channelId: boolean - code: boolean - createdAt: boolean - guildId: boolean - inviter: boolean - maxAge: boolean - maxUses: boolean - targetType: boolean - targetUser: boolean - targetApplication: boolean - temporary: boolean - uses: boolean - approximateMemberCount: boolean - approximatePresenceCount: boolean - guildScheduledEvent: boolean - stageInstance: boolean - expiresAt: boolean - } - member: { - id: boolean - guildId: boolean - user: boolean - nick: boolean - roles: boolean - joinedAt: boolean - premiumSince: boolean - avatar: boolean - permissions: boolean - communicationDisabledUntil: boolean - deaf: boolean - mute: boolean - pending: boolean - flags: boolean - avatarDecorationData: boolean - } - message: { - activity: boolean - application: boolean - applicationId: boolean - attachments: boolean - author: boolean - channelId: boolean - components: boolean - content: boolean - editedTimestamp: boolean - embeds: boolean - guildId: boolean - id: boolean - interactionMetadata: { - id: boolean - type: boolean - user: boolean - authorizingIntegrationOwners: boolean - originalResponseMessageId: boolean - interactedMessageId: boolean - triggeringInteractionMetadata: boolean - } - interaction: { - id: boolean - member: boolean - name: boolean - user: boolean - type: boolean - } - member: boolean - mentionedChannelIds: boolean - mentionedRoleIds: boolean - mentions: boolean - messageReference: { - messageId: boolean - channelId: boolean - guildId: boolean - } - nonce: boolean - reactions: boolean - stickerItems: boolean - thread: boolean - type: boolean - webhookId: boolean - poll: boolean - call: { - participants: boolean - endedTimestamp: boolean - } - } - role: { - name: boolean - guildId: boolean - position: boolean - color: boolean - id: boolean - botId: boolean - integrationId: boolean - permissions: boolean - icon: boolean - unicodeEmoji: boolean - mentionable: boolean - hoist: boolean - managed: boolean - subscriptionListingId: boolean - flags: boolean - } - scheduledEvent: { - id: boolean - guildId: boolean - channelId: boolean - creatorId: boolean - scheduledStartTime: boolean - scheduledEndTime: boolean - entityId: boolean - creator: boolean - name: boolean - description: boolean - privacyLevel: boolean - status: boolean - entityType: boolean - userCount: boolean - location: boolean - image: boolean - } - stageInstance: { - id: boolean - guildId: boolean - channelId: boolean - topic: boolean - guildScheduledEventId: boolean - } - inviteStageInstance: { - members: boolean - participantCount: boolean - speakerCount: boolean - topic: boolean - } - sticker: { - id: boolean - packId: boolean - name: boolean - description: boolean - tags: boolean - type: boolean - formatType: boolean - available: boolean - guildId: boolean - user: boolean - sortValue: boolean - } - user: { - username: boolean - globalName: boolean - locale: boolean - flags: boolean - premiumType: boolean - publicFlags: boolean - accentColor: boolean - id: boolean - discriminator: boolean - avatar: boolean - bot: boolean - system: boolean - mfaEnabled: boolean - verified: boolean - email: boolean - banner: boolean - avatarDecorationData: boolean - } - avatarDecorationData: { - asset: boolean - skuId: boolean - } - webhook: { - id: boolean - type: boolean - guildId: boolean - channelId: boolean - user: boolean - name: boolean - avatar: boolean - token: boolean - applicationId: boolean - sourceGuild: boolean - sourceChannel: boolean - url: boolean - } - guildOnboarding: { - guildId: boolean - prompts: { - id: boolean - type: boolean - options: { - id: boolean - channelIds: boolean - roleIds: boolean - emoji: boolean - title: boolean - description: boolean - } - title: boolean - singleSelect: boolean - required: boolean - inOnboarding: boolean - } - defaultChannelIds: boolean - enabled: boolean - mode: boolean - } - entitlement: { - id: boolean - skuId: boolean - userId: boolean - guildId: boolean - applicationId: boolean - type: boolean - deleted: boolean - startsAt: boolean - endsAt: boolean - consumed: boolean - } - sku: { - id: boolean - type: boolean - applicationId: boolean - name: boolean - slug: boolean - flags: boolean - } - voiceState: { - requestToSpeakTimestamp: boolean - channelId: boolean - guildId: boolean - toggles: boolean - sessionId: boolean - userId: boolean - } - poll: { - question: boolean - answers: { - answerId: boolean - pollMedia: boolean - } - expiry: boolean - allowMultiselect: boolean - layoutType: boolean - results: { - isFinalized: boolean - answerCounts: { - id: boolean - count: boolean - meVoted: boolean - } - } - } - pollMedia: { - text: boolean - emoji: boolean - } - } + desiredProperties: TransformersDesiredProprieties reverse: { allowedMentions: (bot: Bot, payload: AllowedMentions) => DiscordAllowedMentions embed: (bot: Bot, payload: Embed) => DiscordEmbed @@ -648,7 +288,7 @@ export interface Transformers { auditLogEntry: (bot: Bot, payload: DiscordAuditLogEntry) => AuditLogEntry applicationCommand: (bot: Bot, payload: DiscordApplicationCommand) => ApplicationCommand applicationCommandOption: (bot: Bot, payload: DiscordApplicationCommandOption) => ApplicationCommandOption - applicationCommandPermission: (bot: Bot, payload: DiscordGuildApplicationCommandPermissions) => ApplicationCommandPermission + applicationCommandPermission: (bot: Bot, payload: DiscordGuildApplicationCommandPermissions) => GuildApplicationCommandPermissions scheduledEvent: (bot: Bot, payload: DiscordScheduledEvent) => ScheduledEvent threadMember: (bot: Bot, payload: DiscordThreadMember) => ThreadMember threadMemberGuildCreate: (bot: Bot, payload: DiscordThreadMemberGuildCreate) => ThreadMemberGuildCreate @@ -671,6 +311,417 @@ export interface Transformers { avatarDecorationData: (bot: Bot, payload: DiscordAvatarDecorationData) => AvatarDecorationData } +export interface TransformersDesiredProprieties { + attachment: { + id: boolean + filename: boolean + title: boolean + contentType: boolean + size: boolean + url: boolean + proxyUrl: boolean + height: boolean + width: boolean + ephemeral: boolean + description: boolean + duration_secs: boolean + waveform: boolean + flags: boolean + } + channel: { + type: boolean + position: boolean + name: boolean + topic: boolean + nsfw: boolean + bitrate: boolean + userLimit: boolean + rateLimitPerUser: boolean + rtcRegion: boolean + videoQualityMode: boolean + guildId: boolean + lastPinTimestamp: boolean + permissionOverwrites: boolean + id: boolean + permissions: boolean + lastMessageId: boolean + ownerId: boolean + applicationId: boolean + managed: boolean + parentId: boolean + memberCount: boolean + messageCount: boolean + archiveTimestamp: boolean + defaultAutoArchiveDuration: boolean + autoArchiveDuration: boolean + botIsMember: boolean + archived: boolean + locked: boolean + invitable: boolean + createTimestamp: boolean + newlyCreated: boolean + flags: boolean + recipients: boolean + icon: boolean + member: boolean + totalMessageSent: boolean + availableTags: boolean + appliedTags: boolean + defaultReactionEmoji: boolean + defaultThreadRateLimitPerUser: boolean + defaultSortOrder: boolean + defaultForumLayout: boolean + } + forumTag: { + id: boolean + name: boolean + moderated: boolean + emojiId: boolean + emojiName: boolean + } + emoji: { + id: boolean + name: boolean + roles: boolean + user: boolean + } + defaultReactionEmoji: { + emojiId: boolean + emojiName: boolean + } + guild: { + afkTimeout: boolean + approximateMemberCount: boolean + approximatePresenceCount: boolean + defaultMessageNotifications: boolean + description: boolean + explicitContentFilter: boolean + maxMembers: boolean + maxPresences: boolean + maxVideoChannelUsers: boolean + mfaLevel: boolean + name: boolean + nsfwLevel: boolean + preferredLocale: boolean + premiumSubscriptionCount: boolean + premiumTier: boolean + toggles: boolean + stageInstances: boolean + channels: boolean + members: boolean + roles: boolean + emojis: boolean + stickers: boolean + threads: boolean + voiceStates: boolean + large: boolean + owner: boolean + widgetEnabled: boolean + unavailable: boolean + iconHash: boolean + presences: boolean + systemChannelFlags: boolean + vanityUrlCode: boolean + verificationLevel: boolean + welcomeScreen: boolean + discoverySplash: boolean + joinedAt: boolean + memberCount: boolean + shardId: boolean + icon: boolean + banner: boolean + splash: boolean + id: boolean + ownerId: boolean + permissions: boolean + afkChannelId: boolean + widgetChannelId: boolean + applicationId: boolean + systemChannelId: boolean + rulesChannelId: boolean + publicUpdatesChannelId: boolean + premiumProgressBarEnabled: boolean + safetyAlertsChannelId: boolean + } + interaction: { + id: boolean + applicationId: boolean + type: boolean + guild: boolean + guildId: boolean + channel: boolean + channelId: boolean + member: boolean + user: boolean + token: boolean + version: boolean + message: boolean + data: boolean + locale: boolean + guildLocale: boolean + appPermissions: boolean + authorizingIntegrationOwners: boolean + context: boolean + } + invite: { + type: boolean + channelId: boolean + code: boolean + createdAt: boolean + guildId: boolean + inviter: boolean + maxAge: boolean + maxUses: boolean + targetType: boolean + targetUser: boolean + targetApplication: boolean + temporary: boolean + uses: boolean + approximateMemberCount: boolean + approximatePresenceCount: boolean + guildScheduledEvent: boolean + stageInstance: boolean + expiresAt: boolean + } + member: { + id: boolean + guildId: boolean + user: boolean + nick: boolean + roles: boolean + joinedAt: boolean + premiumSince: boolean + avatar: boolean + permissions: boolean + communicationDisabledUntil: boolean + flags: boolean + toggles: boolean + avatarDecorationData: boolean + } + message: { + activity: boolean + application: boolean + applicationId: boolean + attachments: boolean + author: boolean + channelId: boolean + components: boolean + content: boolean + editedTimestamp: boolean + embeds: boolean + guildId: boolean + id: boolean + interactionMetadata: boolean + interaction: boolean + member: boolean + mentionedChannelIds: boolean + mentionedRoleIds: boolean + mentions: boolean + messageReference: boolean + nonce: boolean + reactions: boolean + stickerItems: boolean + thread: boolean + type: boolean + webhookId: boolean + poll: boolean + call: boolean + } + messageInteractionMetadata: { + id: boolean + type: boolean + user: boolean + authorizingIntegrationOwners: boolean + originalResponseMessageId: boolean + interactedMessageId: boolean + triggeringInteractionMetadata: boolean + } + messageInteraction: { + id: boolean + member: boolean + name: boolean + user: boolean + type: boolean + } + messageReference: { + messageId: boolean + channelId: boolean + guildId: boolean + } + messageCall: { + participants: boolean + endedTimestamp: boolean + } + role: { + name: boolean + guildId: boolean + position: boolean + color: boolean + id: boolean + permissions: boolean + icon: boolean + unicodeEmoji: boolean + flags: boolean + tags: boolean + toggles: boolean + } + scheduledEvent: { + id: boolean + guildId: boolean + channelId: boolean + creatorId: boolean + scheduledStartTime: boolean + scheduledEndTime: boolean + entityId: boolean + creator: boolean + name: boolean + description: boolean + privacyLevel: boolean + status: boolean + entityType: boolean + userCount: boolean + location: boolean + image: boolean + } + stageInstance: { + id: boolean + guildId: boolean + channelId: boolean + topic: boolean + guildScheduledEventId: boolean + } + inviteStageInstance: { + members: boolean + participantCount: boolean + speakerCount: boolean + topic: boolean + } + sticker: { + id: boolean + packId: boolean + name: boolean + description: boolean + tags: boolean + type: boolean + formatType: boolean + available: boolean + guildId: boolean + user: boolean + sortValue: boolean + } + user: { + username: boolean + globalName: boolean + locale: boolean + flags: boolean + premiumType: boolean + publicFlags: boolean + accentColor: boolean + id: boolean + discriminator: boolean + avatar: boolean + email: boolean + banner: boolean + avatarDecorationData: boolean + toggles: boolean + } + avatarDecorationData: { + asset: boolean + skuId: boolean + } + webhook: { + id: boolean + type: boolean + guildId: boolean + channelId: boolean + user: boolean + name: boolean + avatar: boolean + token: boolean + applicationId: boolean + sourceGuild: boolean + sourceChannel: boolean + url: boolean + } + guildOnboarding: { + guildId: boolean + prompts: boolean + defaultChannelIds: boolean + enabled: boolean + mode: boolean + } + guildOnboardingPrompt: { + id: boolean + type: boolean + options: boolean + title: boolean + singleSelect: boolean + required: boolean + inOnboarding: boolean + } + guildOnboardingPromptOption: { + id: boolean + channelIds: boolean + roleIds: boolean + emoji: boolean + title: boolean + description: boolean + } + entitlement: { + id: boolean + skuId: boolean + userId: boolean + guildId: boolean + applicationId: boolean + type: boolean + deleted: boolean + startsAt: boolean + endsAt: boolean + consumed: boolean + } + sku: { + id: boolean + type: boolean + applicationId: boolean + name: boolean + slug: boolean + flags: boolean + } + voiceState: { + requestToSpeakTimestamp: boolean + channelId: boolean + guildId: boolean + toggles: boolean + sessionId: boolean + userId: boolean + } + poll: { + question: boolean + answers: boolean + expiry: boolean + allowMultiselect: boolean + layoutType: boolean + results: boolean + } + pollAnswer: { + answerId: boolean + pollMedia: boolean + } + pollResult: { + isFinalized: boolean + answerCounts: boolean + } + pollAnswerCount: { + id: boolean + count: boolean + meVoted: boolean + } + pollMedia: { + text: boolean + emoji: boolean + } +} + export interface CreateTransformerOptions { defaultDesiredPropertiesValue: boolean logger?: Pick @@ -841,416 +892,7 @@ export function createTransformers(options: Partial, opts?: Create return avatarDecorationData }, }, - desiredProperties: { - attachment: { - id: opts?.defaultDesiredPropertiesValue ?? false, - filename: opts?.defaultDesiredPropertiesValue ?? false, - title: opts?.defaultDesiredPropertiesValue ?? false, - contentType: opts?.defaultDesiredPropertiesValue ?? false, - size: opts?.defaultDesiredPropertiesValue ?? false, - url: opts?.defaultDesiredPropertiesValue ?? false, - proxyUrl: opts?.defaultDesiredPropertiesValue ?? false, - height: opts?.defaultDesiredPropertiesValue ?? false, - width: opts?.defaultDesiredPropertiesValue ?? false, - ephemeral: opts?.defaultDesiredPropertiesValue ?? false, - description: opts?.defaultDesiredPropertiesValue ?? false, - duration_secs: opts?.defaultDesiredPropertiesValue ?? false, - waveform: opts?.defaultDesiredPropertiesValue ?? false, - flags: opts?.defaultDesiredPropertiesValue ?? false, - }, - channel: { - type: opts?.defaultDesiredPropertiesValue ?? false, - position: opts?.defaultDesiredPropertiesValue ?? false, - name: opts?.defaultDesiredPropertiesValue ?? false, - topic: opts?.defaultDesiredPropertiesValue ?? false, - nsfw: opts?.defaultDesiredPropertiesValue ?? false, - bitrate: opts?.defaultDesiredPropertiesValue ?? false, - userLimit: opts?.defaultDesiredPropertiesValue ?? false, - rateLimitPerUser: opts?.defaultDesiredPropertiesValue ?? false, - rtcRegion: opts?.defaultDesiredPropertiesValue ?? false, - videoQualityMode: opts?.defaultDesiredPropertiesValue ?? false, - guildId: opts?.defaultDesiredPropertiesValue ?? false, - lastPinTimestamp: opts?.defaultDesiredPropertiesValue ?? false, - permissionOverwrites: opts?.defaultDesiredPropertiesValue ?? false, - id: opts?.defaultDesiredPropertiesValue ?? false, - permissions: opts?.defaultDesiredPropertiesValue ?? false, - lastMessageId: opts?.defaultDesiredPropertiesValue ?? false, - ownerId: opts?.defaultDesiredPropertiesValue ?? false, - applicationId: opts?.defaultDesiredPropertiesValue ?? false, - managed: opts?.defaultDesiredPropertiesValue ?? false, - parentId: opts?.defaultDesiredPropertiesValue ?? false, - memberCount: opts?.defaultDesiredPropertiesValue ?? false, - messageCount: opts?.defaultDesiredPropertiesValue ?? false, - archiveTimestamp: opts?.defaultDesiredPropertiesValue ?? false, - defaultAutoArchiveDuration: opts?.defaultDesiredPropertiesValue ?? false, - autoArchiveDuration: opts?.defaultDesiredPropertiesValue ?? false, - botIsMember: opts?.defaultDesiredPropertiesValue ?? false, - archived: opts?.defaultDesiredPropertiesValue ?? false, - locked: opts?.defaultDesiredPropertiesValue ?? false, - invitable: opts?.defaultDesiredPropertiesValue ?? false, - createTimestamp: opts?.defaultDesiredPropertiesValue ?? false, - newlyCreated: opts?.defaultDesiredPropertiesValue ?? false, - flags: opts?.defaultDesiredPropertiesValue ?? false, - appliedTags: opts?.defaultDesiredPropertiesValue ?? false, - availableTags: opts?.defaultDesiredPropertiesValue ?? false, - defaultForumLayout: opts?.defaultDesiredPropertiesValue ?? false, - defaultReactionEmoji: opts?.defaultDesiredPropertiesValue ?? false, - defaultSortOrder: opts?.defaultDesiredPropertiesValue ?? false, - defaultThreadRateLimitPerUser: opts?.defaultDesiredPropertiesValue ?? false, - icon: opts?.defaultDesiredPropertiesValue ?? false, - member: opts?.defaultDesiredPropertiesValue ?? false, - recipients: opts?.defaultDesiredPropertiesValue ?? false, - totalMessageSent: opts?.defaultDesiredPropertiesValue ?? false, - }, - forumTag: { - emojiId: opts?.defaultDesiredPropertiesValue ?? false, - emojiName: opts?.defaultDesiredPropertiesValue ?? false, - id: opts?.defaultDesiredPropertiesValue ?? false, - moderated: opts?.defaultDesiredPropertiesValue ?? false, - name: opts?.defaultDesiredPropertiesValue ?? false, - }, - emoji: { - id: opts?.defaultDesiredPropertiesValue ?? false, - name: opts?.defaultDesiredPropertiesValue ?? false, - roles: opts?.defaultDesiredPropertiesValue ?? false, - user: opts?.defaultDesiredPropertiesValue ?? false, - }, - defaultReactionEmoji: { - emojiId: opts?.defaultDesiredPropertiesValue ?? false, - emojiName: opts?.defaultDesiredPropertiesValue ?? false, - }, - guild: { - afkTimeout: opts?.defaultDesiredPropertiesValue ?? false, - approximateMemberCount: opts?.defaultDesiredPropertiesValue ?? false, - approximatePresenceCount: opts?.defaultDesiredPropertiesValue ?? false, - defaultMessageNotifications: opts?.defaultDesiredPropertiesValue ?? false, - description: opts?.defaultDesiredPropertiesValue ?? false, - explicitContentFilter: opts?.defaultDesiredPropertiesValue ?? false, - maxMembers: opts?.defaultDesiredPropertiesValue ?? false, - maxPresences: opts?.defaultDesiredPropertiesValue ?? false, - maxVideoChannelUsers: opts?.defaultDesiredPropertiesValue ?? false, - mfaLevel: opts?.defaultDesiredPropertiesValue ?? false, - name: opts?.defaultDesiredPropertiesValue ?? false, - channels: opts?.defaultDesiredPropertiesValue ?? false, - emojis: opts?.defaultDesiredPropertiesValue ?? false, - iconHash: opts?.defaultDesiredPropertiesValue ?? false, - large: opts?.defaultDesiredPropertiesValue ?? false, - members: opts?.defaultDesiredPropertiesValue ?? false, - owner: opts?.defaultDesiredPropertiesValue ?? false, - presences: opts?.defaultDesiredPropertiesValue ?? false, - roles: opts?.defaultDesiredPropertiesValue ?? false, - stickers: opts?.defaultDesiredPropertiesValue ?? false, - threads: opts?.defaultDesiredPropertiesValue ?? false, - toggles: opts?.defaultDesiredPropertiesValue ?? false, - unavailable: opts?.defaultDesiredPropertiesValue ?? false, - voiceStates: opts?.defaultDesiredPropertiesValue ?? false, - widgetEnabled: opts?.defaultDesiredPropertiesValue ?? false, - nsfwLevel: opts?.defaultDesiredPropertiesValue ?? false, - preferredLocale: opts?.defaultDesiredPropertiesValue ?? false, - premiumSubscriptionCount: opts?.defaultDesiredPropertiesValue ?? false, - premiumTier: opts?.defaultDesiredPropertiesValue ?? false, - stageInstances: opts?.defaultDesiredPropertiesValue ?? false, - systemChannelFlags: opts?.defaultDesiredPropertiesValue ?? false, - vanityUrlCode: opts?.defaultDesiredPropertiesValue ?? false, - verificationLevel: opts?.defaultDesiredPropertiesValue ?? false, - welcomeScreen: opts?.defaultDesiredPropertiesValue ?? false, - discoverySplash: opts?.defaultDesiredPropertiesValue ?? false, - joinedAt: opts?.defaultDesiredPropertiesValue ?? false, - memberCount: opts?.defaultDesiredPropertiesValue ?? false, - shardId: opts?.defaultDesiredPropertiesValue ?? false, - icon: opts?.defaultDesiredPropertiesValue ?? false, - banner: opts?.defaultDesiredPropertiesValue ?? false, - splash: opts?.defaultDesiredPropertiesValue ?? false, - id: opts?.defaultDesiredPropertiesValue ?? false, - ownerId: opts?.defaultDesiredPropertiesValue ?? false, - permissions: opts?.defaultDesiredPropertiesValue ?? false, - afkChannelId: opts?.defaultDesiredPropertiesValue ?? false, - widgetChannelId: opts?.defaultDesiredPropertiesValue ?? false, - applicationId: opts?.defaultDesiredPropertiesValue ?? false, - systemChannelId: opts?.defaultDesiredPropertiesValue ?? false, - rulesChannelId: opts?.defaultDesiredPropertiesValue ?? false, - publicUpdatesChannelId: opts?.defaultDesiredPropertiesValue ?? false, - premiumProgressBarEnabled: opts?.defaultDesiredPropertiesValue ?? false, - safetyAlertsChannelId: opts?.defaultDesiredPropertiesValue ?? false, - }, - interaction: { - id: opts?.defaultDesiredPropertiesValue ?? false, - applicationId: opts?.defaultDesiredPropertiesValue ?? false, - type: opts?.defaultDesiredPropertiesValue ?? false, - guild: opts?.defaultDesiredPropertiesValue ?? false, - guildId: opts?.defaultDesiredPropertiesValue ?? false, - channel: opts?.defaultDesiredPropertiesValue ?? false, - channelId: opts?.defaultDesiredPropertiesValue ?? false, - member: opts?.defaultDesiredPropertiesValue ?? false, - user: opts?.defaultDesiredPropertiesValue ?? false, - token: opts?.defaultDesiredPropertiesValue ?? false, - version: opts?.defaultDesiredPropertiesValue ?? false, - message: opts?.defaultDesiredPropertiesValue ?? false, - data: opts?.defaultDesiredPropertiesValue ?? false, - locale: opts?.defaultDesiredPropertiesValue ?? false, - guildLocale: opts?.defaultDesiredPropertiesValue ?? false, - appPermissions: opts?.defaultDesiredPropertiesValue ?? false, - authorizingIntegrationOwners: opts?.defaultDesiredPropertiesValue ?? false, - context: opts?.defaultDesiredPropertiesValue ?? false, - }, - invite: { - type: opts?.defaultDesiredPropertiesValue ?? false, - channelId: opts?.defaultDesiredPropertiesValue ?? false, - code: opts?.defaultDesiredPropertiesValue ?? false, - createdAt: opts?.defaultDesiredPropertiesValue ?? false, - guildId: opts?.defaultDesiredPropertiesValue ?? false, - inviter: opts?.defaultDesiredPropertiesValue ?? false, - maxAge: opts?.defaultDesiredPropertiesValue ?? false, - maxUses: opts?.defaultDesiredPropertiesValue ?? false, - targetType: opts?.defaultDesiredPropertiesValue ?? false, - targetUser: opts?.defaultDesiredPropertiesValue ?? false, - targetApplication: opts?.defaultDesiredPropertiesValue ?? false, - temporary: opts?.defaultDesiredPropertiesValue ?? false, - uses: opts?.defaultDesiredPropertiesValue ?? false, - approximateMemberCount: opts?.defaultDesiredPropertiesValue ?? false, - approximatePresenceCount: opts?.defaultDesiredPropertiesValue ?? false, - guildScheduledEvent: opts?.defaultDesiredPropertiesValue ?? false, - stageInstance: opts?.defaultDesiredPropertiesValue ?? false, - expiresAt: opts?.defaultDesiredPropertiesValue ?? false, - }, - member: { - id: opts?.defaultDesiredPropertiesValue ?? false, - guildId: opts?.defaultDesiredPropertiesValue ?? false, - user: opts?.defaultDesiredPropertiesValue ?? false, - nick: opts?.defaultDesiredPropertiesValue ?? false, - roles: opts?.defaultDesiredPropertiesValue ?? false, - joinedAt: opts?.defaultDesiredPropertiesValue ?? false, - premiumSince: opts?.defaultDesiredPropertiesValue ?? false, - avatar: opts?.defaultDesiredPropertiesValue ?? false, - permissions: opts?.defaultDesiredPropertiesValue ?? false, - communicationDisabledUntil: opts?.defaultDesiredPropertiesValue ?? false, - deaf: opts?.defaultDesiredPropertiesValue ?? false, - mute: opts?.defaultDesiredPropertiesValue ?? false, - pending: opts?.defaultDesiredPropertiesValue ?? false, - flags: opts?.defaultDesiredPropertiesValue ?? false, - avatarDecorationData: opts?.defaultDesiredPropertiesValue ?? false, - }, - message: { - activity: opts?.defaultDesiredPropertiesValue ?? false, - application: opts?.defaultDesiredPropertiesValue ?? false, - applicationId: opts?.defaultDesiredPropertiesValue ?? false, - attachments: opts?.defaultDesiredPropertiesValue ?? false, - author: opts?.defaultDesiredPropertiesValue ?? false, - channelId: opts?.defaultDesiredPropertiesValue ?? false, - components: opts?.defaultDesiredPropertiesValue ?? false, - content: opts?.defaultDesiredPropertiesValue ?? false, - editedTimestamp: opts?.defaultDesiredPropertiesValue ?? false, - embeds: opts?.defaultDesiredPropertiesValue ?? false, - guildId: opts?.defaultDesiredPropertiesValue ?? false, - id: opts?.defaultDesiredPropertiesValue ?? false, - interactionMetadata: { - id: opts?.defaultDesiredPropertiesValue ?? false, - type: opts?.defaultDesiredPropertiesValue ?? false, - user: opts?.defaultDesiredPropertiesValue ?? false, - authorizingIntegrationOwners: opts?.defaultDesiredPropertiesValue ?? false, - originalResponseMessageId: opts?.defaultDesiredPropertiesValue ?? false, - interactedMessageId: opts?.defaultDesiredPropertiesValue ?? false, - triggeringInteractionMetadata: opts?.defaultDesiredPropertiesValue ?? false, - }, - interaction: { - id: opts?.defaultDesiredPropertiesValue ?? false, - member: opts?.defaultDesiredPropertiesValue ?? false, - name: opts?.defaultDesiredPropertiesValue ?? false, - type: opts?.defaultDesiredPropertiesValue ?? false, - user: opts?.defaultDesiredPropertiesValue ?? false, - }, - member: opts?.defaultDesiredPropertiesValue ?? false, - mentionedChannelIds: opts?.defaultDesiredPropertiesValue ?? false, - mentionedRoleIds: opts?.defaultDesiredPropertiesValue ?? false, - mentions: opts?.defaultDesiredPropertiesValue ?? false, - messageReference: { - messageId: opts?.defaultDesiredPropertiesValue ?? false, - channelId: opts?.defaultDesiredPropertiesValue ?? false, - guildId: opts?.defaultDesiredPropertiesValue ?? false, - }, - nonce: opts?.defaultDesiredPropertiesValue ?? false, - reactions: opts?.defaultDesiredPropertiesValue ?? false, - stickerItems: opts?.defaultDesiredPropertiesValue ?? false, - thread: opts?.defaultDesiredPropertiesValue ?? false, - type: opts?.defaultDesiredPropertiesValue ?? false, - webhookId: opts?.defaultDesiredPropertiesValue ?? false, - poll: opts?.defaultDesiredPropertiesValue ?? false, - call: { - participants: opts?.defaultDesiredPropertiesValue ?? false, - endedTimestamp: opts?.defaultDesiredPropertiesValue ?? false, - }, - }, - role: { - name: opts?.defaultDesiredPropertiesValue ?? false, - guildId: opts?.defaultDesiredPropertiesValue ?? false, - position: opts?.defaultDesiredPropertiesValue ?? false, - color: opts?.defaultDesiredPropertiesValue ?? false, - id: opts?.defaultDesiredPropertiesValue ?? false, - botId: opts?.defaultDesiredPropertiesValue ?? false, - integrationId: opts?.defaultDesiredPropertiesValue ?? false, - permissions: opts?.defaultDesiredPropertiesValue ?? false, - icon: opts?.defaultDesiredPropertiesValue ?? false, - unicodeEmoji: opts?.defaultDesiredPropertiesValue ?? false, - mentionable: opts?.defaultDesiredPropertiesValue ?? false, - hoist: opts?.defaultDesiredPropertiesValue ?? false, - managed: opts?.defaultDesiredPropertiesValue ?? false, - subscriptionListingId: opts?.defaultDesiredPropertiesValue ?? false, - flags: opts?.defaultDesiredPropertiesValue ?? false, - }, - scheduledEvent: { - id: opts?.defaultDesiredPropertiesValue ?? false, - guildId: opts?.defaultDesiredPropertiesValue ?? false, - channelId: opts?.defaultDesiredPropertiesValue ?? false, - creatorId: opts?.defaultDesiredPropertiesValue ?? false, - scheduledStartTime: opts?.defaultDesiredPropertiesValue ?? false, - scheduledEndTime: opts?.defaultDesiredPropertiesValue ?? false, - entityId: opts?.defaultDesiredPropertiesValue ?? false, - creator: opts?.defaultDesiredPropertiesValue ?? false, - name: opts?.defaultDesiredPropertiesValue ?? false, - description: opts?.defaultDesiredPropertiesValue ?? false, - privacyLevel: opts?.defaultDesiredPropertiesValue ?? false, - status: opts?.defaultDesiredPropertiesValue ?? false, - entityType: opts?.defaultDesiredPropertiesValue ?? false, - userCount: opts?.defaultDesiredPropertiesValue ?? false, - location: opts?.defaultDesiredPropertiesValue ?? false, - image: opts?.defaultDesiredPropertiesValue ?? false, - }, - stageInstance: { - id: opts?.defaultDesiredPropertiesValue ?? false, - guildId: opts?.defaultDesiredPropertiesValue ?? false, - channelId: opts?.defaultDesiredPropertiesValue ?? false, - topic: opts?.defaultDesiredPropertiesValue ?? false, - guildScheduledEventId: opts?.defaultDesiredPropertiesValue ?? false, - }, - inviteStageInstance: { - members: opts?.defaultDesiredPropertiesValue ?? false, - participantCount: opts?.defaultDesiredPropertiesValue ?? false, - speakerCount: opts?.defaultDesiredPropertiesValue ?? false, - topic: opts?.defaultDesiredPropertiesValue ?? false, - }, - sticker: { - id: opts?.defaultDesiredPropertiesValue ?? false, - packId: opts?.defaultDesiredPropertiesValue ?? false, - name: opts?.defaultDesiredPropertiesValue ?? false, - description: opts?.defaultDesiredPropertiesValue ?? false, - tags: opts?.defaultDesiredPropertiesValue ?? false, - type: opts?.defaultDesiredPropertiesValue ?? false, - formatType: opts?.defaultDesiredPropertiesValue ?? false, - available: opts?.defaultDesiredPropertiesValue ?? false, - guildId: opts?.defaultDesiredPropertiesValue ?? false, - user: opts?.defaultDesiredPropertiesValue ?? false, - sortValue: opts?.defaultDesiredPropertiesValue ?? false, - }, - user: { - username: opts?.defaultDesiredPropertiesValue ?? false, - globalName: opts?.defaultDesiredPropertiesValue ?? false, - locale: opts?.defaultDesiredPropertiesValue ?? false, - flags: opts?.defaultDesiredPropertiesValue ?? false, - premiumType: opts?.defaultDesiredPropertiesValue ?? false, - publicFlags: opts?.defaultDesiredPropertiesValue ?? false, - accentColor: opts?.defaultDesiredPropertiesValue ?? false, - id: opts?.defaultDesiredPropertiesValue ?? false, - discriminator: opts?.defaultDesiredPropertiesValue ?? false, - avatar: opts?.defaultDesiredPropertiesValue ?? false, - bot: opts?.defaultDesiredPropertiesValue ?? false, - system: opts?.defaultDesiredPropertiesValue ?? false, - mfaEnabled: opts?.defaultDesiredPropertiesValue ?? false, - verified: opts?.defaultDesiredPropertiesValue ?? false, - email: opts?.defaultDesiredPropertiesValue ?? false, - banner: opts?.defaultDesiredPropertiesValue ?? false, - avatarDecorationData: opts?.defaultDesiredPropertiesValue ?? false, - }, - avatarDecorationData: { - asset: opts?.defaultDesiredPropertiesValue ?? false, - skuId: opts?.defaultDesiredPropertiesValue ?? false, - }, - webhook: { - id: opts?.defaultDesiredPropertiesValue ?? false, - type: opts?.defaultDesiredPropertiesValue ?? false, - guildId: opts?.defaultDesiredPropertiesValue ?? false, - channelId: opts?.defaultDesiredPropertiesValue ?? false, - user: opts?.defaultDesiredPropertiesValue ?? false, - name: opts?.defaultDesiredPropertiesValue ?? false, - avatar: opts?.defaultDesiredPropertiesValue ?? false, - token: opts?.defaultDesiredPropertiesValue ?? false, - applicationId: opts?.defaultDesiredPropertiesValue ?? false, - sourceGuild: opts?.defaultDesiredPropertiesValue ?? false, - sourceChannel: opts?.defaultDesiredPropertiesValue ?? false, - url: opts?.defaultDesiredPropertiesValue ?? false, - }, - guildOnboarding: { - defaultChannelIds: opts?.defaultDesiredPropertiesValue ?? false, - enabled: opts?.defaultDesiredPropertiesValue ?? false, - guildId: opts?.defaultDesiredPropertiesValue ?? false, - mode: opts?.defaultDesiredPropertiesValue ?? false, - prompts: { - id: opts?.defaultDesiredPropertiesValue ?? false, - inOnboarding: opts?.defaultDesiredPropertiesValue ?? false, - options: { - channelIds: opts?.defaultDesiredPropertiesValue ?? false, - description: opts?.defaultDesiredPropertiesValue ?? false, - emoji: opts?.defaultDesiredPropertiesValue ?? false, - id: opts?.defaultDesiredPropertiesValue ?? false, - roleIds: opts?.defaultDesiredPropertiesValue ?? false, - title: opts?.defaultDesiredPropertiesValue ?? false, - }, - required: opts?.defaultDesiredPropertiesValue ?? false, - singleSelect: opts?.defaultDesiredPropertiesValue ?? false, - title: opts?.defaultDesiredPropertiesValue ?? false, - type: opts?.defaultDesiredPropertiesValue ?? false, - }, - }, - entitlement: { - id: opts?.defaultDesiredPropertiesValue ?? false, - skuId: opts?.defaultDesiredPropertiesValue ?? false, - userId: opts?.defaultDesiredPropertiesValue ?? false, - guildId: opts?.defaultDesiredPropertiesValue ?? false, - applicationId: opts?.defaultDesiredPropertiesValue ?? false, - type: opts?.defaultDesiredPropertiesValue ?? false, - deleted: opts?.defaultDesiredPropertiesValue ?? false, - startsAt: opts?.defaultDesiredPropertiesValue ?? false, - endsAt: opts?.defaultDesiredPropertiesValue ?? false, - consumed: opts?.defaultDesiredPropertiesValue ?? false, - }, - sku: { - id: opts?.defaultDesiredPropertiesValue ?? false, - type: opts?.defaultDesiredPropertiesValue ?? false, - applicationId: opts?.defaultDesiredPropertiesValue ?? false, - name: opts?.defaultDesiredPropertiesValue ?? false, - slug: opts?.defaultDesiredPropertiesValue ?? false, - flags: opts?.defaultDesiredPropertiesValue ?? false, - }, - voiceState: { - requestToSpeakTimestamp: opts?.defaultDesiredPropertiesValue ?? false, - channelId: opts?.defaultDesiredPropertiesValue ?? false, - guildId: opts?.defaultDesiredPropertiesValue ?? false, - toggles: opts?.defaultDesiredPropertiesValue ?? false, - sessionId: opts?.defaultDesiredPropertiesValue ?? false, - userId: opts?.defaultDesiredPropertiesValue ?? false, - }, - poll: { - question: opts?.defaultDesiredPropertiesValue ?? false, - answers: { - answerId: opts?.defaultDesiredPropertiesValue ?? false, - pollMedia: opts?.defaultDesiredPropertiesValue ?? false, - }, - expiry: opts?.defaultDesiredPropertiesValue ?? false, - layoutType: opts?.defaultDesiredPropertiesValue ?? false, - allowMultiselect: opts?.defaultDesiredPropertiesValue ?? false, - results: { - isFinalized: opts?.defaultDesiredPropertiesValue ?? false, - answerCounts: { - id: opts?.defaultDesiredPropertiesValue ?? false, - count: opts?.defaultDesiredPropertiesValue ?? false, - meVoted: opts?.defaultDesiredPropertiesValue ?? false, - }, - }, - }, - pollMedia: { - text: opts?.defaultDesiredPropertiesValue ?? false, - emoji: opts?.defaultDesiredPropertiesValue ?? false, - }, - }, + desiredProperties: createDesiredProprietiesObject({}, opts?.defaultDesiredPropertiesValue ?? false), reverse: { allowedMentions: options.reverse?.allowedMentions ?? transformAllowedMentionsToDiscordAllowedMentions, embed: options.reverse?.embed ?? transformEmbedToDiscordEmbed, @@ -1322,3 +964,452 @@ export function createTransformers(options: Partial, opts?: Create avatarDecorationData: options.avatarDecorationData ?? transformAvatarDecorationData, } } + +export function createDesiredProprietiesObject( + desiredProperties: RecursivePartial, + defaultValue = false, +): TransformersDesiredProprieties { + return { + attachment: { + id: defaultValue, + filename: defaultValue, + title: defaultValue, + contentType: defaultValue, + size: defaultValue, + url: defaultValue, + proxyUrl: defaultValue, + height: defaultValue, + width: defaultValue, + ephemeral: defaultValue, + description: defaultValue, + duration_secs: defaultValue, + waveform: defaultValue, + flags: defaultValue, + ...desiredProperties.attachment, + }, + channel: { + type: defaultValue, + position: defaultValue, + name: defaultValue, + topic: defaultValue, + nsfw: defaultValue, + bitrate: defaultValue, + userLimit: defaultValue, + rateLimitPerUser: defaultValue, + rtcRegion: defaultValue, + videoQualityMode: defaultValue, + guildId: defaultValue, + lastPinTimestamp: defaultValue, + permissionOverwrites: defaultValue, + id: defaultValue, + permissions: defaultValue, + lastMessageId: defaultValue, + ownerId: defaultValue, + applicationId: defaultValue, + managed: defaultValue, + parentId: defaultValue, + memberCount: defaultValue, + messageCount: defaultValue, + archiveTimestamp: defaultValue, + defaultAutoArchiveDuration: defaultValue, + autoArchiveDuration: defaultValue, + botIsMember: defaultValue, + archived: defaultValue, + locked: defaultValue, + invitable: defaultValue, + createTimestamp: defaultValue, + newlyCreated: defaultValue, + flags: defaultValue, + appliedTags: defaultValue, + availableTags: defaultValue, + defaultForumLayout: defaultValue, + defaultReactionEmoji: defaultValue, + defaultSortOrder: defaultValue, + defaultThreadRateLimitPerUser: defaultValue, + icon: defaultValue, + member: defaultValue, + recipients: defaultValue, + totalMessageSent: defaultValue, + ...desiredProperties.channel, + }, + forumTag: { + emojiId: defaultValue, + emojiName: defaultValue, + id: defaultValue, + moderated: defaultValue, + name: defaultValue, + ...desiredProperties.forumTag, + }, + emoji: { + id: defaultValue, + name: defaultValue, + roles: defaultValue, + user: defaultValue, + ...desiredProperties.emoji, + }, + defaultReactionEmoji: { + emojiId: defaultValue, + emojiName: defaultValue, + ...desiredProperties.defaultReactionEmoji, + }, + guild: { + afkTimeout: defaultValue, + approximateMemberCount: defaultValue, + approximatePresenceCount: defaultValue, + defaultMessageNotifications: defaultValue, + description: defaultValue, + explicitContentFilter: defaultValue, + maxMembers: defaultValue, + maxPresences: defaultValue, + maxVideoChannelUsers: defaultValue, + mfaLevel: defaultValue, + name: defaultValue, + channels: defaultValue, + emojis: defaultValue, + iconHash: defaultValue, + large: defaultValue, + members: defaultValue, + owner: defaultValue, + presences: defaultValue, + roles: defaultValue, + stickers: defaultValue, + threads: defaultValue, + toggles: defaultValue, + unavailable: defaultValue, + voiceStates: defaultValue, + widgetEnabled: defaultValue, + nsfwLevel: defaultValue, + preferredLocale: defaultValue, + premiumSubscriptionCount: defaultValue, + premiumTier: defaultValue, + stageInstances: defaultValue, + systemChannelFlags: defaultValue, + vanityUrlCode: defaultValue, + verificationLevel: defaultValue, + welcomeScreen: defaultValue, + discoverySplash: defaultValue, + joinedAt: defaultValue, + memberCount: defaultValue, + shardId: defaultValue, + icon: defaultValue, + banner: defaultValue, + splash: defaultValue, + id: defaultValue, + ownerId: defaultValue, + permissions: defaultValue, + afkChannelId: defaultValue, + widgetChannelId: defaultValue, + applicationId: defaultValue, + systemChannelId: defaultValue, + rulesChannelId: defaultValue, + publicUpdatesChannelId: defaultValue, + premiumProgressBarEnabled: defaultValue, + safetyAlertsChannelId: defaultValue, + ...desiredProperties.guild, + }, + interaction: { + id: defaultValue, + applicationId: defaultValue, + type: defaultValue, + guild: defaultValue, + guildId: defaultValue, + channel: defaultValue, + channelId: defaultValue, + member: defaultValue, + user: defaultValue, + token: defaultValue, + version: defaultValue, + message: defaultValue, + data: defaultValue, + locale: defaultValue, + guildLocale: defaultValue, + appPermissions: defaultValue, + authorizingIntegrationOwners: defaultValue, + context: defaultValue, + ...desiredProperties.interaction, + }, + invite: { + type: defaultValue, + channelId: defaultValue, + code: defaultValue, + createdAt: defaultValue, + guildId: defaultValue, + inviter: defaultValue, + maxAge: defaultValue, + maxUses: defaultValue, + targetType: defaultValue, + targetUser: defaultValue, + targetApplication: defaultValue, + temporary: defaultValue, + uses: defaultValue, + approximateMemberCount: defaultValue, + approximatePresenceCount: defaultValue, + guildScheduledEvent: defaultValue, + stageInstance: defaultValue, + expiresAt: defaultValue, + ...desiredProperties.invite, + }, + member: { + id: defaultValue, + guildId: defaultValue, + user: defaultValue, + nick: defaultValue, + roles: defaultValue, + joinedAt: defaultValue, + premiumSince: defaultValue, + avatar: defaultValue, + permissions: defaultValue, + communicationDisabledUntil: defaultValue, + flags: defaultValue, + toggles: defaultValue, + avatarDecorationData: defaultValue, + ...desiredProperties.member, + }, + message: { + activity: defaultValue, + application: defaultValue, + applicationId: defaultValue, + attachments: defaultValue, + author: defaultValue, + channelId: defaultValue, + components: defaultValue, + content: defaultValue, + editedTimestamp: defaultValue, + embeds: defaultValue, + guildId: defaultValue, + id: defaultValue, + interactionMetadata: defaultValue, + interaction: defaultValue, + member: defaultValue, + mentionedChannelIds: defaultValue, + mentionedRoleIds: defaultValue, + mentions: defaultValue, + messageReference: defaultValue, + nonce: defaultValue, + reactions: defaultValue, + stickerItems: defaultValue, + thread: defaultValue, + type: defaultValue, + webhookId: defaultValue, + poll: defaultValue, + call: defaultValue, + ...desiredProperties.message, + }, + messageInteractionMetadata: { + id: defaultValue, + type: defaultValue, + user: defaultValue, + authorizingIntegrationOwners: defaultValue, + originalResponseMessageId: defaultValue, + interactedMessageId: defaultValue, + triggeringInteractionMetadata: defaultValue, + ...desiredProperties.messageInteractionMetadata, + }, + messageInteraction: { + id: defaultValue, + member: defaultValue, + name: defaultValue, + type: defaultValue, + user: defaultValue, + ...desiredProperties.messageInteraction, + }, + messageReference: { + messageId: defaultValue, + channelId: defaultValue, + guildId: defaultValue, + ...desiredProperties.messageReference, + }, + messageCall: { + participants: defaultValue, + endedTimestamp: defaultValue, + ...desiredProperties.messageCall, + }, + role: { + name: defaultValue, + guildId: defaultValue, + position: defaultValue, + color: defaultValue, + id: defaultValue, + permissions: defaultValue, + icon: defaultValue, + unicodeEmoji: defaultValue, + flags: defaultValue, + tags: defaultValue, + toggles: defaultValue, + ...desiredProperties.role, + }, + scheduledEvent: { + id: defaultValue, + guildId: defaultValue, + channelId: defaultValue, + creatorId: defaultValue, + scheduledStartTime: defaultValue, + scheduledEndTime: defaultValue, + entityId: defaultValue, + creator: defaultValue, + name: defaultValue, + description: defaultValue, + privacyLevel: defaultValue, + status: defaultValue, + entityType: defaultValue, + userCount: defaultValue, + location: defaultValue, + image: defaultValue, + ...desiredProperties.scheduledEvent, + }, + stageInstance: { + id: defaultValue, + guildId: defaultValue, + channelId: defaultValue, + topic: defaultValue, + guildScheduledEventId: defaultValue, + ...desiredProperties.stageInstance, + }, + inviteStageInstance: { + members: defaultValue, + participantCount: defaultValue, + speakerCount: defaultValue, + topic: defaultValue, + ...desiredProperties.inviteStageInstance, + }, + sticker: { + id: defaultValue, + packId: defaultValue, + name: defaultValue, + description: defaultValue, + tags: defaultValue, + type: defaultValue, + formatType: defaultValue, + available: defaultValue, + guildId: defaultValue, + user: defaultValue, + sortValue: defaultValue, + ...desiredProperties.sticker, + }, + user: { + username: defaultValue, + globalName: defaultValue, + locale: defaultValue, + flags: defaultValue, + premiumType: defaultValue, + publicFlags: defaultValue, + accentColor: defaultValue, + id: defaultValue, + discriminator: defaultValue, + avatar: defaultValue, + email: defaultValue, + banner: defaultValue, + avatarDecorationData: defaultValue, + toggles: defaultValue, + ...desiredProperties.user, + }, + avatarDecorationData: { + asset: defaultValue, + skuId: defaultValue, + ...desiredProperties.avatarDecorationData, + }, + webhook: { + id: defaultValue, + type: defaultValue, + guildId: defaultValue, + channelId: defaultValue, + user: defaultValue, + name: defaultValue, + avatar: defaultValue, + token: defaultValue, + applicationId: defaultValue, + sourceGuild: defaultValue, + sourceChannel: defaultValue, + url: defaultValue, + ...desiredProperties.webhook, + }, + guildOnboarding: { + defaultChannelIds: defaultValue, + enabled: defaultValue, + guildId: defaultValue, + mode: defaultValue, + prompts: defaultValue, + ...desiredProperties.guildOnboarding, + }, + guildOnboardingPrompt: { + id: defaultValue, + inOnboarding: defaultValue, + options: defaultValue, + required: defaultValue, + singleSelect: defaultValue, + title: defaultValue, + type: defaultValue, + ...desiredProperties.guildOnboardingPrompt, + }, + guildOnboardingPromptOption: { + channelIds: defaultValue, + description: defaultValue, + emoji: defaultValue, + id: defaultValue, + roleIds: defaultValue, + title: defaultValue, + ...desiredProperties.guildOnboardingPromptOption, + }, + entitlement: { + id: defaultValue, + skuId: defaultValue, + userId: defaultValue, + guildId: defaultValue, + applicationId: defaultValue, + type: defaultValue, + deleted: defaultValue, + startsAt: defaultValue, + endsAt: defaultValue, + consumed: defaultValue, + ...desiredProperties.entitlement, + }, + sku: { + id: defaultValue, + type: defaultValue, + applicationId: defaultValue, + name: defaultValue, + slug: defaultValue, + flags: defaultValue, + ...desiredProperties.sku, + }, + voiceState: { + requestToSpeakTimestamp: defaultValue, + channelId: defaultValue, + guildId: defaultValue, + toggles: defaultValue, + sessionId: defaultValue, + userId: defaultValue, + ...desiredProperties.voiceState, + }, + poll: { + question: defaultValue, + answers: defaultValue, + expiry: defaultValue, + layoutType: defaultValue, + allowMultiselect: defaultValue, + results: defaultValue, + ...desiredProperties.poll, + }, + pollAnswer: { + answerId: defaultValue, + pollMedia: defaultValue, + ...desiredProperties.pollAnswer, + }, + pollResult: { + isFinalized: defaultValue, + answerCounts: defaultValue, + ...desiredProperties.pollResult, + }, + pollAnswerCount: { + id: defaultValue, + count: defaultValue, + meVoted: defaultValue, + ...desiredProperties.pollAnswerCount, + }, + pollMedia: { + text: defaultValue, + emoji: defaultValue, + ...desiredProperties.pollMedia, + }, + } +} diff --git a/packages/bot/src/transformers/activity.ts b/packages/bot/src/transformers/activity.ts index ea7075f21..0e70d0f36 100644 --- a/packages/bot/src/transformers/activity.ts +++ b/packages/bot/src/transformers/activity.ts @@ -1,4 +1,4 @@ -import type { ActivityTypes, Bot, DiscordActivity } from '../index.js' +import type { Activity, Bot, DiscordActivity } from '../index.js' export function transformActivity(bot: Bot, payload: DiscordActivity): Activity { const activity = { @@ -35,36 +35,3 @@ export function transformActivity(bot: Bot, payload: DiscordActivity): Activity return bot.transformers.customizers.activity(bot, payload, activity) } - -export interface Activity { - join?: string - flags?: number - applicationId?: bigint - spectate?: string - url?: string - startedAt?: number - endedAt?: number - details?: string - state?: string - emoji?: { - id?: bigint - animated?: boolean - name: string - } - partyId?: string - partyCurrentSize?: number - partyMaxSize?: number - largeImage?: string - largeText?: string - smallImage?: string - smallText?: string - match?: string - instance?: boolean - buttons?: Array<{ - url: string - label: string - }> - name: string - type: ActivityTypes - createdAt: number -} diff --git a/packages/bot/src/transformers/application.ts b/packages/bot/src/transformers/application.ts index 3e9595f84..26db7bf42 100644 --- a/packages/bot/src/transformers/application.ts +++ b/packages/bot/src/transformers/application.ts @@ -1,13 +1,9 @@ import { - type ApplicationFlags, + type Application, type Bot, type DiscordApplication, DiscordApplicationIntegrationType, type DiscordUser, - type Guild, - type OAuth2Scope, - type Team, - type User, iconHashToBigInt, } from '../index.js' @@ -64,39 +60,3 @@ export function transformApplication(bot: Bot, payload: { application: DiscordAp return bot.transformers.customizers.application(bot, payload.application, application) } - -export interface Application { - flags?: ApplicationFlags - icon?: bigint - rpcOrigins?: string[] - termsOfServiceUrl?: string - privacyPolicyUrl?: string - primarySkuId?: string - slug?: string - coverImage?: bigint - owner?: User - team?: Team - guildId?: bigint - guild?: Guild - id: bigint - name: string - description: string - botPublic: boolean - botRequireCodeGrant: boolean - verifyKey: string - approximateGuildCount?: number - bot?: User - redirectUris?: string[] - interactionsEndpointUrl?: string - integrationTypesConfig?: Partial> -} - -export interface ApplicationIntegrationTypeConfiguration { - /** Install params for each installation context's default in-app authorization link */ - oauth2InstallParams?: { - /** Scopes to add the application to the server with */ - scopes: OAuth2Scope[] - /** Permissions to request for the bot role */ - permissions: bigint - } -} diff --git a/packages/bot/src/transformers/applicationCommand.ts b/packages/bot/src/transformers/applicationCommand.ts index 859edf940..1bea8987e 100644 --- a/packages/bot/src/transformers/applicationCommand.ts +++ b/packages/bot/src/transformers/applicationCommand.ts @@ -1,5 +1,5 @@ -import type { ApplicationCommandTypes, DiscordApplicationCommand, Locales } from '@discordeno/types' -import type { ApplicationCommandOption, Bot } from '../index.js' +import type { DiscordApplicationCommand } from '@discordeno/types' +import type { ApplicationCommand, Bot } from '../index.js' export function transformApplicationCommand(bot: Bot, payload: DiscordApplicationCommand): ApplicationCommand { const applicationCommand = { @@ -20,18 +20,3 @@ export function transformApplicationCommand(bot: Bot, payload: DiscordApplicatio return bot.transformers.customizers.applicationCommand(bot, payload, applicationCommand) } - -export interface ApplicationCommand { - options?: ApplicationCommandOption[] - description?: string - guildId?: bigint - nameLocalizations?: Record - descriptionLocalizations?: Record - defaultMemberPermissions?: bigint - type?: ApplicationCommandTypes - version?: string - id: bigint - name: string - applicationId: bigint - dmPermission: boolean -} diff --git a/packages/bot/src/transformers/applicationCommandOption.ts b/packages/bot/src/transformers/applicationCommandOption.ts index 4a22c0b37..0b0144241 100644 --- a/packages/bot/src/transformers/applicationCommandOption.ts +++ b/packages/bot/src/transformers/applicationCommandOption.ts @@ -1,6 +1,5 @@ -import type { ApplicationCommandOptionTypes, ChannelTypes, DiscordApplicationCommandOption, Localization } from '@discordeno/types' -import type { Bot } from '../index.js' -import type { ApplicationCommandOptionChoice } from './applicationCommandOptionChoice.js' +import type { DiscordApplicationCommandOption } from '@discordeno/types' +import type { ApplicationCommandOption, Bot } from '../index.js' export function transformApplicationCommandOption(bot: Bot, payload: DiscordApplicationCommandOption): ApplicationCommandOption { const applicationCommandOption = { @@ -22,34 +21,3 @@ export function transformApplicationCommandOption(bot: Bot, payload: DiscordAppl return bot.transformers.customizers.applicationCommandOption(bot, payload, applicationCommandOption) } - -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 index 4f2f940e9..40114e512 100644 --- a/packages/bot/src/transformers/applicationCommandOptionChoice.ts +++ b/packages/bot/src/transformers/applicationCommandOptionChoice.ts @@ -1,5 +1,5 @@ -import type { DiscordApplicationCommandOptionChoice, Locales } from '@discordeno/types' -import type { Bot } from '../index.js' +import type { DiscordApplicationCommandOptionChoice } from '@discordeno/types' +import type { ApplicationCommandOptionChoice, Bot } from '../index.js' export function transformApplicationCommandOptionChoice(bot: Bot, payload: DiscordApplicationCommandOptionChoice): ApplicationCommandOptionChoice { const applicationCommandOptionChoice = { @@ -10,9 +10,3 @@ export function transformApplicationCommandOptionChoice(bot: Bot, payload: Disco return bot.transformers.customizers.applicationCommandOptionChoice(bot, payload, applicationCommandOptionChoice) } - -export interface ApplicationCommandOptionChoice { - nameLocalizations?: Record - name: string - value: string | number -} diff --git a/packages/bot/src/transformers/applicationCommandPermission.ts b/packages/bot/src/transformers/applicationCommandPermission.ts index 19da84d81..8e8453398 100644 --- a/packages/bot/src/transformers/applicationCommandPermission.ts +++ b/packages/bot/src/transformers/applicationCommandPermission.ts @@ -1,7 +1,10 @@ -import type { ApplicationCommandPermissionTypes, DiscordGuildApplicationCommandPermissions } from '@discordeno/types' -import type { Bot } from '../index.js' +import type { DiscordGuildApplicationCommandPermissions } from '@discordeno/types' +import type { Bot, GuildApplicationCommandPermissions } from '../index.js' -export function transformApplicationCommandPermission(bot: Bot, payload: DiscordGuildApplicationCommandPermissions): ApplicationCommandPermission { +export function transformApplicationCommandPermission( + bot: Bot, + payload: DiscordGuildApplicationCommandPermissions, +): GuildApplicationCommandPermissions { const applicationCommandPermission = { id: bot.transformers.snowflake(payload.id), applicationId: bot.transformers.snowflake(payload.application_id), @@ -11,18 +14,7 @@ export function transformApplicationCommandPermission(bot: Bot, payload: Discord type: perm.type, permission: perm.permission, })), - } as ApplicationCommandPermission + } as GuildApplicationCommandPermissions return bot.transformers.customizers.applicationCommandPermission(bot, payload, applicationCommandPermission) } - -export interface ApplicationCommandPermission { - id: bigint - guildId: bigint - applicationId: bigint - permissions: Array<{ - id: bigint - type: ApplicationCommandPermissionTypes - permission: boolean - }> -} diff --git a/packages/bot/src/transformers/attachment.ts b/packages/bot/src/transformers/attachment.ts index d3fd18faa..996cdb06c 100644 --- a/packages/bot/src/transformers/attachment.ts +++ b/packages/bot/src/transformers/attachment.ts @@ -1,5 +1,5 @@ -import type { AttachmentFlags, DiscordAttachment } from '@discordeno/types' -import type { Bot } from '../index.js' +import type { DiscordAttachment } from '@discordeno/types' +import type { Attachment, Bot } from '../index.js' export function transformAttachment(bot: Bot, payload: DiscordAttachment): Attachment { const props = bot.transformers.desiredProperties.attachment @@ -22,38 +22,3 @@ export function transformAttachment(bot: Bot, payload: DiscordAttachment): Attac return bot.transformers.customizers.attachment(bot, payload, attachment) } - -export interface Attachment { - /** Name of file attached */ - filename: string - /** The title of the file */ - title?: string - /** The attachment's [media type](https://en.wikipedia.org/wiki/Media_type) */ - contentType?: string - /** Size of file in bytes */ - size: number - /** Source url of file */ - url: string - /** A proxied url of file */ - proxyUrl: string - /** Attachment id */ - id: bigint - /** description for the file (max 1024 characters) */ - description?: string - /** Height of file (if image) */ - height?: number - /** Width of file (if image) */ - width?: number - /** - * whether this attachment is ephemeral. - * Ephemeral attachments will automatically be removed after a set period of time. - * Ephemeral attachments on messages are guaranteed to be available as long as the message itself exists. - */ - ephemeral?: boolean - /** The duration of the audio file for a voice message */ - duration_secs?: number - /** A base64 encoded bytearray representing a sampled waveform for a voice message */ - waveform?: string - /** Attachment flags combined as a bitfield */ - flags?: AttachmentFlags -} diff --git a/packages/bot/src/transformers/auditLogEntry.ts b/packages/bot/src/transformers/auditLogEntry.ts index 1945dd303..eb880529c 100644 --- a/packages/bot/src/transformers/auditLogEntry.ts +++ b/packages/bot/src/transformers/auditLogEntry.ts @@ -1,5 +1,5 @@ -import type { AuditLogEvents, DiscordAuditLogEntry, OverwriteTypes } from '@discordeno/types' -import { type Bot, iconHashToBigInt } from '../index.js' +import type { DiscordAuditLogEntry } from '@discordeno/types' +import { type AuditLogEntry, type Bot, iconHashToBigInt } from '../index.js' export function transformAuditLogEntry(bot: Bot, payload: DiscordAuditLogEntry): AuditLogEntry { const auditLogEntry = { @@ -136,123 +136,3 @@ export function transformAuditLogEntry(bot: Bot, payload: DiscordAuditLogEntry): return bot.transformers.customizers.auditLogEntry(bot, payload, auditLogEntry) } - -export interface AuditLogEntry { - id: bigint - userId?: bigint - reason?: string - changes?: Array<{ - new?: - | string - | number - | bigint - | boolean - | Array<{ - allow?: string - deny?: string - id: string - type: OverwriteTypes - }> - | Array<{ - id?: bigint - name?: string - }> - old?: - | string - | number - | bigint - | boolean - | Array<{ - allow?: string - deny?: string - id: string - type: OverwriteTypes - }> - | Array<{ - id?: bigint - name?: string - }> - key: - | 'id' - | 'name' - | 'description' - | 'type' - | 'permissions' - | 'locked' - | 'invitable' - | 'nsfw' - | 'archived' - | 'position' - | 'topic' - | 'bitrate' - | 'default_auto_archive_duration' - | 'auto_archive_duration' - | 'allow' - | 'deny' - | 'channel_id' - | 'deaf' - | 'mute' - | 'status' - | 'nick' - | 'communication_disabled_until' - | 'color' - | 'permission_overwrites' - | 'user_limit' - | 'rate_limit_per_user' - | 'owner_id' - | 'application_id' - | 'hoist' - | 'mentionable' - | 'location' - | 'verification_level' - | 'default_message_notifications' - | 'explicit_content_filter' - | 'preferred_locale' - | 'afk_timeout' - | 'afk_channel_id' - | 'system_channel_id' - | 'widget_enabled' - | 'mfa_level' - | 'vanity_url_code' - | 'icon_hash' - | 'widget_channel_id' - | 'rules_channel_id' - | 'public_updates_channel_id' - | 'code' - | 'region' - | 'privacy_level' - | 'entity_type' - | 'enable_emoticons' - | 'expire_behavior' - | 'expire_grace_period' - | 'uses' - | 'max_uses' - | 'max_age' - | 'temporary' - | 'discovery_splash_hash' - | 'banner_hash' - | 'image_hash' - | 'splash_hash' - | 'inviter_id' - | 'avatar_hash' - | 'command_id' - | 'prune_delete_days' - | '$add' - | '$remove' - }> - targetId?: bigint - actionType: AuditLogEvents - options?: { - id?: bigint - channelId?: bigint - messageId?: bigint - type: number - count: number - deleteMemberDays: number - membersRemoved: number - roleName: string - autoModerationRuleName: string - autoModerationRuleTriggerType: string - integrationType: string - } -} diff --git a/packages/bot/src/transformers/automodActionExecution.ts b/packages/bot/src/transformers/automodActionExecution.ts index dbd96ecea..232250c61 100644 --- a/packages/bot/src/transformers/automodActionExecution.ts +++ b/packages/bot/src/transformers/automodActionExecution.ts @@ -1,5 +1,5 @@ -import type { AutoModerationActionType, AutoModerationTriggerTypes, DiscordAutoModerationActionExecution } from '@discordeno/types' -import type { Bot } from '../index.js' +import type { DiscordAutoModerationActionExecution } from '@discordeno/types' +import type { AutoModerationActionExecution, Bot } from '../index.js' export function transformAutoModerationActionExecution(bot: Bot, payload: DiscordAutoModerationActionExecution): AutoModerationActionExecution { const rule = { @@ -25,24 +25,3 @@ export function transformAutoModerationActionExecution(bot: Bot, payload: Discor return bot.transformers.customizers.automodActionExecution(bot, payload, rule) } - -export interface AutoModerationActionExecution { - channelId?: bigint - messageId?: bigint - alertSystemMessageId?: bigint - guildId: bigint - userId: bigint - content: string - action: { - type: AutoModerationActionType - metadata: { - customMessage?: string - durationSeconds?: number - channelId?: bigint - } - } - ruleTriggerType: AutoModerationTriggerTypes - ruleId: bigint - matchedKeyword: string - matchedContent: string -} diff --git a/packages/bot/src/transformers/automodRule.ts b/packages/bot/src/transformers/automodRule.ts index 40b8ffdba..2788c189e 100644 --- a/packages/bot/src/transformers/automodRule.ts +++ b/packages/bot/src/transformers/automodRule.ts @@ -1,11 +1,5 @@ -import type { - AutoModerationActionType, - AutoModerationEventTypes, - AutoModerationTriggerTypes, - DiscordAutoModerationRule, - DiscordAutoModerationRuleTriggerMetadataPresets, -} from '@discordeno/types' -import type { Bot } from '../index.js' +import type { DiscordAutoModerationRule } from '@discordeno/types' +import type { AutoModerationRule, Bot } from '../index.js' export function transformAutoModerationRule(bot: Bot, payload: DiscordAutoModerationRule): AutoModerationRule { const rule = { @@ -41,31 +35,3 @@ export function transformAutoModerationRule(bot: Bot, payload: DiscordAutoModera return bot.transformers.customizers.automodRule(bot, payload, rule) } - -export interface AutoModerationRule { - triggerMetadata?: { - keywordFilter?: string[] - presets?: DiscordAutoModerationRuleTriggerMetadataPresets[] - allowList?: string[] - mentionTotalLimit?: number - regexPatterns: string[] - } - - id: bigint - name: string - guildId: bigint - eventType: AutoModerationEventTypes - triggerType: AutoModerationTriggerTypes - enabled: boolean - creatorId: bigint - exemptRoles: bigint[] - exemptChannels: bigint[] - actions: Array<{ - type: AutoModerationActionType - metadata?: { - channelId?: bigint - customMessage?: string - durationSeconds?: number - } - }> -} diff --git a/packages/bot/src/transformers/avatarDecorationData.ts b/packages/bot/src/transformers/avatarDecorationData.ts index 20c267e41..4bb22ad2f 100644 --- a/packages/bot/src/transformers/avatarDecorationData.ts +++ b/packages/bot/src/transformers/avatarDecorationData.ts @@ -1,4 +1,4 @@ -import { type Bot, type DiscordAvatarDecorationData, iconHashToBigInt } from '../index.js' +import { type AvatarDecorationData, type Bot, type DiscordAvatarDecorationData, iconHashToBigInt } from '../index.js' export function transformAvatarDecorationData(bot: Bot, payload: DiscordAvatarDecorationData): AvatarDecorationData { const data = {} as AvatarDecorationData @@ -9,10 +9,3 @@ export function transformAvatarDecorationData(bot: Bot, payload: DiscordAvatarDe return data } - -export interface AvatarDecorationData { - /** the avatar decoration hash */ - asset: bigint - /** id of the avatar decoration's SKU */ - skuId: bigint -} diff --git a/packages/bot/src/transformers/channel.ts b/packages/bot/src/transformers/channel.ts index 3416e6bc3..6f4105018 100644 --- a/packages/bot/src/transformers/channel.ts +++ b/packages/bot/src/transformers/channel.ts @@ -1,14 +1,5 @@ -import type { - BigString, - ChannelTypes, - DiscordChannel, - DiscordForumTag, - ForumLayout, - OverwriteReadable, - SortOrderTypes, - VideoQualityModes, -} from '@discordeno/types' -import { type Bot, type DefaultReactionEmoji, type ThreadMember, type User, calculatePermissions, iconHashToBigInt } from '../index.js' +import type { BigString, DiscordChannel, DiscordForumTag } from '@discordeno/types' +import { type Bot, type Channel, type ForumTag, calculatePermissions, iconHashToBigInt } from '../index.js' import { Permissions } from './toggles/Permissions.js' import { ChannelToggles } from './toggles/channel.js' @@ -29,7 +20,7 @@ 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] } -export const baseChannel: Partial & BaseChannel = { +export const baseChannel = { get archived() { return !!this.toggles?.archived }, @@ -66,12 +57,12 @@ export const baseChannel: Partial & BaseChannel = { archiveTimestamp: this.internalThreadMetadata?.archiveTimestamp, createTimestamp: this.internalThreadMetadata?.createTimestamp, autoArchiveDuration: this.internalThreadMetadata?.autoArchiveDuration, - locked: this.locked, - invitable: this.invitable, - archived: this.archived, + locked: !!this.toggles?.locked, + invitable: !!this.toggles?.invitable, + archived: !!this.toggles?.archived, } }, -} +} as Channel export function transformChannel(bot: Bot, payload: { channel: DiscordChannel } & { guildId?: BigString }): Channel { const channel = Object.create(baseChannel) as Channel @@ -142,133 +133,3 @@ export function transformForumTag(bot: Bot, payload: DiscordForumTag): ForumTag return bot.transformers.customizers.forumTag(bot, payload, forumTag) } - -export interface BaseChannel { - /** Whether the channel is nsfw */ - nsfw: boolean - /** Thread-specific fields not needed by other channels */ - threadMetadata?: { - /** Timestamp when the thread's archive status was last changed, used for calculating recent activity */ - archiveTimestamp?: number - /** Timestamp when the thread was created; only populated for threads created after 2022-01-09 */ - createTimestamp?: number - /** Duration in minutes to automatically archive the thread after recent activity */ - autoArchiveDuration?: 60 | 1440 | 4320 | 10080 - /** When a thread is locked, only users with `MANAGE_THREADS` can unarchive it */ - locked: boolean - /** whether non-moderators can add other non-moderators to a thread; only available on private threads */ - invitable: boolean - /** Whether the thread is archived */ - archived: boolean - } - /** When a thread is created this will be true on that channel payload for the thread. */ - newlyCreated: boolean - /** When a thread is locked, only users with `MANAGE_THREADS` can unarchive it */ - locked: boolean - /** whether non-moderators can add other non-moderators to a thread; only available on private threads */ - invitable: boolean - /** Whether the thread is archived */ - archived: boolean - /** for group DM channels: whether the channel is managed by an application via the `gdm.join` OAuth2 scope */ - managed: boolean - /** Explicit permission overwrites for members and roles. */ - permissionOverwrites: OverwriteReadable[] -} - -export interface Channel extends BaseChannel { - /** The id of the channel */ - id: bigint - /** The compressed form of all the boolean values on this channel. */ - toggles: ChannelToggles - /** The type of channel */ - type: ChannelTypes - /** The id of the guild */ - guildId?: bigint - /** Sorting position of the channel */ - position?: number - /** The name of the channel (1-100 characters) */ - name?: string - /** The channel topic (0-4096 characters for GUILD_FORUM channels, 0-1024 characters for all others) */ - topic?: string - /** The id of the last message sent in this channel (may not point to an existing or valid message) */ - lastMessageId?: bigint - /** The bitrate (in bits) of the voice or stage channel */ - bitrate?: number - /** The user limit of the voice or stage channel */ - userLimit?: number - /** Amount of seconds a user has to wait before sending another message (0-21600); bots, as well as users with the permission `manage_messages` or `manage_channel`, are unaffected */ - rateLimitPerUser?: number - /** Id of the creator of the thread */ - ownerId?: bigint - /** For guild channels: Id of the parent category for a channel (each parent category can contain up to 50 channels), for threads: id of the text channel this thread was created */ - parentId?: bigint - /** When the last pinned message was pinned. This may be null in events such as GUILD_CREATE when a message is not pinned. */ - lastPinTimestamp?: number - /** Voice region id for the voice or stage channel, automatic when set to null */ - rtcRegion?: string - /** The camera video quality mode of the voice channel, 1 when not present */ - videoQualityMode?: VideoQualityModes - /** An approximate count of messages in a thread, stops counting at 50 */ - messageCount?: number - /** An approximate count of users in a thread, stops counting at 50 */ - memberCount?: number - /** - * Thread-specific fields not needed by other channels. - * @deprecated Use channel.threadMetadata - * @private This field is an internal field, subject to breaking changes. - */ - internalThreadMetadata?: { - /** Timestamp when the thread's archive status was last changed, used for calculating recent activity */ - archiveTimestamp: number - /** Timestamp when the thread was created; only populated for threads created after 2022-01-09 */ - createTimestamp?: number - /** Duration in minutes to automatically archive the thread after recent activity */ - autoArchiveDuration: 60 | 1440 | 4320 | 10080 - } - /** Thread member object for the current user, if they have joined the thread, only included on certain API endpoints */ - member?: ThreadMember - /** Default duration for newly created threads, in minutes, to automatically archive the thread after recent activity, can be set to: 60, 1440, 4320, 10080 */ - defaultAutoArchiveDuration?: number - /** computed permissions for the invoking user in the channel, including overwrites, only included when part of the resolved data received on a slash command interaction. This does not include implicit permissions, which may need to be checked separately. */ - permissions?: Permissions - /** The flags of the channel */ - flags?: number - /** - * Explicit permission overwrites for members and roles - * @deprecated Use channel.permissionOverwrites - * @private This is for internal use only, and prone to breaking changes. - */ - internalOverwrites?: bigint[] - /** The recipients of a group dm */ - recipients?: User[] - /** Icon hash of the group dm */ - icon?: bigint - /** Application id of the group DM creator if it is bot-created */ - applicationId?: bigint - /** Number of messages ever sent in a thread, it's similar to `message_count` on message creation, but will not decrement the number when a message is deleted */ - totalMessageSent?: number - /** The set of tags that can be used in a `GUILD_FORUM` or a `GUILD_MEDIA` channel */ - availableTags?: ForumTag[] - /** The IDs of the set of tags that have been applied to a thread in a `GUILD_FORUM` or a `GUILD_MEDIA` channel */ - appliedTags?: bigint[] - /** The emoji to show in the add reaction button on a thread in a `GUILD_FORUM` or a `GUILD_MEDIA` channel */ - defaultReactionEmoji?: DefaultReactionEmoji - /** the initial `rateLimitPerUser` to set on newly created threads in a channel. this field is copied to the thread at creation time and does not live update. */ - defaultThreadRateLimitPerUser?: number - /** The default sort order type used to order posts in `GUILD_FORUM` and `GUILD_MEDIA` channels. Defaults to null, which indicates a preferred sort order hasn't been set by a channel admin */ - defaultSortOrder?: SortOrderTypes | null - defaultForumLayout?: ForumLayout -} - -export interface ForumTag { - /** The id of the tag */ - id: bigint - /** The name of the tag (0-20 characters) */ - name: string - /** Whether this tag can only be added to or removed from threads by a member with the MANAGE_THREADS permission */ - moderated: boolean - /** The id of a guild's custom emoji At most one of emoji_id and emoji_name may be set. */ - emojiId: bigint - /** The unicode character of the emoji */ - emojiName: string | null -} diff --git a/packages/bot/src/transformers/component.ts b/packages/bot/src/transformers/component.ts index 0b9bfa1a0..fdd093e97 100644 --- a/packages/bot/src/transformers/component.ts +++ b/packages/bot/src/transformers/component.ts @@ -1,5 +1,4 @@ -import type { ButtonStyles, ChannelTypes, MessageComponentTypes, SelectOption, TextStyles } from '@discordeno/types' -import type { Bot } from '../index.js' +import type { Bot, Component } from '../index.js' import type { DiscordComponent } from '../typings.js' export function transformComponent(bot: Bot, payload: DiscordComponent): Component { @@ -42,47 +41,3 @@ export function transformComponent(bot: Bot, payload: DiscordComponent): Compone return bot.transformers.customizers.component(bot, payload, component) } - -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 - /** List of channel types to include in a channel select menu options list */ - channelTypes?: ChannelTypes[] - /** 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 index 7850e78d8..9b02be6c4 100644 --- a/packages/bot/src/transformers/embed.ts +++ b/packages/bot/src/transformers/embed.ts @@ -1,5 +1,5 @@ -import type { DiscordEmbed, EmbedTypes } from '@discordeno/types' -import type { Bot } from '../index.js' +import type { DiscordEmbed } from '@discordeno/types' +import type { Bot, Embed } from '../index.js' export function transformEmbed(bot: Bot, payload: DiscordEmbed): Embed { const embed = { @@ -54,50 +54,3 @@ export function transformEmbed(bot: Bot, payload: DiscordEmbed): Embed { return bot.transformers.customizers.embed(bot, payload, embed) } - -export interface Embed { - description?: string - type?: EmbedTypes - url?: string - image?: { - proxyUrl?: string - height?: number - width?: number - url: string - } - video?: { - url?: string - proxyUrl?: string - height?: number - width?: number - } - title?: string - timestamp?: number - color?: number - footer?: { - iconUrl?: string - proxyIconUrl?: string - text: string - } - thumbnail?: { - proxyUrl?: string - height?: number - width?: number - url: string - } - provider?: { - name?: string - url?: string - } - author?: { - url?: string - iconUrl?: string - proxyIconUrl?: string - name: string - } - fields?: Array<{ - inline?: boolean - name: string - value: string - }> -} diff --git a/packages/bot/src/transformers/emoji.ts b/packages/bot/src/transformers/emoji.ts index d66cddd20..4c369ab63 100644 --- a/packages/bot/src/transformers/emoji.ts +++ b/packages/bot/src/transformers/emoji.ts @@ -1,5 +1,5 @@ import type { DiscordDefaultReactionEmoji, DiscordEmoji } from '@discordeno/types' -import type { Bot, User } from '../index.js' +import type { Bot, DefaultReactionEmoji, Emoji } from '../index.js' import { EmojiToggles } from './toggles/emoji.js' export function transformEmoji(bot: Bot, payload: DiscordEmoji): Emoji { @@ -25,30 +25,3 @@ export function transformDefaultReactionEmoji(bot: Bot, payload: DiscordDefaultR return bot.transformers.customizers.defaultReactionEmoji(bot, payload, defaultReactionEmoji) } - -export interface Emoji { - /** Emoji name (can only be null in reaction emoji objects) */ - name?: string - /** Emoji id */ - id?: bigint - /** Roles allowed to use this emoji */ - roles?: bigint[] - /** User that created this emoji */ - user?: User - /** Whether this emoji must be wrapped in colons */ - requireColons?: boolean - /** Whether this emoji is managed */ - managed?: boolean - /** Whether this emoji is animated */ - animated?: boolean - /** Whether this emoji can be used, may be false due to loss of Server Boosts */ - available?: boolean - toggles: EmojiToggles -} - -export interface DefaultReactionEmoji { - /** The id of a guild's custom emoji */ - emojiId: bigint - /** The unicode character of the emoji */ - emojiName?: string -} diff --git a/packages/bot/src/transformers/entitlement.ts b/packages/bot/src/transformers/entitlement.ts index cf8a6d857..ddbd559ae 100644 --- a/packages/bot/src/transformers/entitlement.ts +++ b/packages/bot/src/transformers/entitlement.ts @@ -1,5 +1,5 @@ -import type { DiscordEntitlement, DiscordEntitlementType } from '@discordeno/types' -import type { Bot } from '../index.js' +import type { DiscordEntitlement } from '@discordeno/types' +import type { Bot, Entitlement } from '../index.js' export function transformEntitlement(bot: Bot, payload: DiscordEntitlement): Entitlement { const props = bot.transformers.desiredProperties.entitlement @@ -18,26 +18,3 @@ export function transformEntitlement(bot: Bot, payload: DiscordEntitlement): Ent return bot.transformers.customizers.entitlement(bot, payload, entitlement) } - -export interface Entitlement { - /** ID of the entitlement */ - id: bigint - /** ID of the SKU */ - skuId: bigint - /** ID of the user that is granted access to the entitlement's sku */ - userId?: bigint - /** ID of the guild that is granted access to the entitlement's sku */ - guildId?: bigint - /** ID of the parent application */ - applicationId: bigint - /** Type of entitlement */ - type: DiscordEntitlementType - /** Entitlement was deleted */ - deleted: boolean - /** Start date at which the entitlement is valid. Not present when using test entitlements */ - startsAt?: number - /** Date at which the entitlement is no longer valid. Not present when using test entitlements */ - endsAt?: number - /** For consumable items, whether or not the entitlement has been consumed */ - consumed?: boolean -} diff --git a/packages/bot/src/transformers/gatewayBot.ts b/packages/bot/src/transformers/gatewayBot.ts index 2965f1bb8..4908ddca7 100644 --- a/packages/bot/src/transformers/gatewayBot.ts +++ b/packages/bot/src/transformers/gatewayBot.ts @@ -1,5 +1,5 @@ import type { DiscordGetGatewayBot } from '@discordeno/types' -import type { Bot } from '../index.js' +import type { Bot, GetGatewayBot } from '../index.js' export function transformGatewayBot(bot: Bot, payload: DiscordGetGatewayBot): GetGatewayBot { const gatewayBot = { @@ -15,14 +15,3 @@ export function transformGatewayBot(bot: Bot, payload: DiscordGetGatewayBot): Ge return bot.transformers.customizers.gatewayBot(bot, payload, gatewayBot) } - -export interface GetGatewayBot { - url: string - shards: number - sessionStartLimit: { - total: number - remaining: number - resetAfter: number - maxConcurrency: number - } -} diff --git a/packages/bot/src/transformers/guild.ts b/packages/bot/src/transformers/guild.ts index ec48b7f08..653569244 100644 --- a/packages/bot/src/transformers/guild.ts +++ b/packages/bot/src/transformers/guild.ts @@ -1,18 +1,6 @@ -import { - ChannelTypes, - type DefaultMessageNotificationLevels, - type DiscordGuild, - type DiscordPresenceUpdate, - type ExplicitContentFilterLevels, - type GuildNsfwLevel, - type MfaLevels, - type PremiumTiers, - type SystemChannelFlags, - type VerificationLevels, -} from '@discordeno/types' +import { ChannelTypes, type DiscordGuild, type DiscordPresenceUpdate } from '@discordeno/types' import { Collection, iconHashToBigInt } from '@discordeno/utils' -import type { Bot, Channel, GuildFeatureKeys, Member, PresenceUpdate, Role, StageInstance, Sticker, VoiceState, WelcomeScreen } from '../index.js' -import type { Emoji } from '../transformers/emoji.js' +import type { Bot, Channel, Guild } from '../index.js' import { GuildToggles } from './toggles/guild.js' const baseGuild = { @@ -150,112 +138,3 @@ export function transformGuild(bot: Bot, payload: { guild: DiscordGuild } & { sh return bot.transformers.customizers.guild(bot, payload.guild, guild) } - -export interface Guild { - /** Guild name (2-100 characters, excluding trailing and leading whitespace) */ - name: string - /** True if the user is the owner of the guild */ - owner: boolean | undefined - /** Afk timeout in seconds */ - afkTimeout: number - /** True if the server widget is enabled */ - widgetEnabled?: boolean - /** Verification level required for the guild */ - verificationLevel: VerificationLevels - /** Default message notifications level */ - defaultMessageNotifications: DefaultMessageNotificationLevels - /** Explicit content filter level */ - explicitContentFilter: ExplicitContentFilterLevels - /** Enabled guild features */ - features: GuildFeatureKeys[] - /** Required MFA level for the guild */ - mfaLevel: MfaLevels - /** System channel flags */ - systemChannelFlags: SystemChannelFlags - /** True if this is considered a large guild */ - large?: boolean - /** True if this guild is unavailable due to an outage */ - unavailable?: boolean - /** Total number of members in this guild */ - memberCount: number - /** The maximum number of presences for the guild (the default value, currently 25000, is in effect when null is returned) */ - maxPresences?: number - /** The maximum number of members for the guild */ - maxMembers?: number - /** The vanity url code for the guild */ - vanityUrlCode?: string - /** The description of a guild */ - description?: string - toggles: GuildToggles - shardId: number - /** Premium tier (Server Boost level) */ - premiumTier: PremiumTiers - /** The number of boosts this guild currently has */ - premiumSubscriptionCount?: number - /** The maximum amount of users in a video channel */ - maxVideoChannelUsers?: number - /** Maximum amount of users in a stage video channel */ - maxStageVideoChannelUsers?: number - /** Approximate number of members in this guild, returned from the GET /guilds/id endpoint when with_counts is true */ - approximateMemberCount?: number - /** Approximate number of non-offline members in this guild, returned from the GET /guilds/id endpoint when with_counts is true */ - approximatePresenceCount?: number - /** Guild NSFW level */ - nsfwLevel: GuildNsfwLevel - /** Whether the guild has the boost progress bar enabled */ - premiumProgressBarEnabled: boolean - /** Guild id */ - id: bigint - /** Icon hash */ - icon?: bigint - /** Icon hash, returned when in the template object */ - iconHash?: bigint - /** Splash hash */ - splash?: bigint - /** Discovery splash hash; only present for guilds with the "DISCOVERABLE" feature */ - discoverySplash?: bigint - /** Id of the owner */ - ownerId: bigint - /** Total permissions for the user in the guild (excludes overwrites and implicit permissions) */ - permissions: bigint - /** Id of afk channel */ - afkChannelId?: bigint - /** The channel id that the widget will generate an invite to, or null if set to no invite */ - widgetChannelId?: bigint - /** Roles in the guild */ - roles: Collection - /** Custom guild emojis */ - emojis: Collection - /** Application id of the guild creator if it is bot-created */ - applicationId?: bigint - /** The id of the channel where guild notices such as welcome messages and boost events are posted */ - systemChannelId?: bigint - /** The id of the channel where community guilds can display rules and/or guidelines */ - rulesChannelId?: bigint - /** When this guild was joined at */ - joinedAt?: number - /** States of members currently in voice channels; lacks the guild_id key */ - voiceStates: Collection - /** Users in the guild */ - members: Collection - /** Channels in the guild */ - channels: Collection - /** All active threads in the guild that the current user has permission to view */ - threads: Collection - /** Presences of the members in the guild, will only include non-offline members if the size is greater than large threshold */ - presences?: PresenceUpdate[] - /** Banner hash */ - banner?: bigint - /** The preferred locale of a Community guild; used in server discovery and notices from Discord; defaults to "en-US" */ - preferredLocale: string - /** The id of the channel where admins and moderators of Community guilds receive notices from Discord */ - publicUpdatesChannelId?: bigint - /** The welcome screen of a Community guild, shown to new members, returned in an Invite's guild object */ - welcomeScreen?: WelcomeScreen - /** Stage instances in the guild */ - stageInstances?: StageInstance[] - /** Custom guild stickers */ - stickers?: Collection - /** The id of the channel where admins and moderators of Community guilds receive safety alerts from Discord */ - safetyAlertsChannelId?: bigint -} diff --git a/packages/bot/src/transformers/index.ts b/packages/bot/src/transformers/index.ts index e111dad95..4347f7564 100644 --- a/packages/bot/src/transformers/index.ts +++ b/packages/bot/src/transformers/index.ts @@ -35,6 +35,7 @@ export * from './team.js' export * from './template.js' export * from './threadMember.js' export * from './toggles/index.js' +export * from './types.js' export * from './user.js' export * from './voiceRegion.js' export * from './voiceState.js' diff --git a/packages/bot/src/transformers/integration.ts b/packages/bot/src/transformers/integration.ts index 60470f2fa..d1ad892e9 100644 --- a/packages/bot/src/transformers/integration.ts +++ b/packages/bot/src/transformers/integration.ts @@ -1,5 +1,5 @@ -import type { DiscordIntegrationCreateUpdate, IntegrationExpireBehaviors, OAuth2Scope } from '@discordeno/types' -import { type Bot, type User, iconHashToBigInt } from '../index.js' +import type { DiscordIntegrationCreateUpdate } from '@discordeno/types' +import { type Bot, type Integration, iconHashToBigInt } from '../index.js' export function transformIntegration(bot: Bot, payload: DiscordIntegrationCreateUpdate): Integration { const integration = { @@ -35,32 +35,3 @@ export function transformIntegration(bot: Bot, payload: DiscordIntegrationCreate return bot.transformers.customizers.integration(bot, payload, integration) } - -export interface Integration { - user?: User - enabled?: boolean - syncing?: boolean - roleId?: bigint - enableEmoticons?: boolean - expireBehavior?: IntegrationExpireBehaviors - expireGracePeriod?: number - syncedAt?: number - subscriberCount?: number - revoked?: boolean - application?: { - bot?: User - icon?: bigint - id: bigint - name: string - description: string - } - id: bigint - name: string - guildId: bigint - type: 'twitch' | 'youtube' | 'discord' - account: { - id: bigint - name: string - } - scopes: OAuth2Scope[] -} diff --git a/packages/bot/src/transformers/interaction.ts b/packages/bot/src/transformers/interaction.ts index 98ba6f4b9..6a152a450 100644 --- a/packages/bot/src/transformers/interaction.ts +++ b/packages/bot/src/transformers/interaction.ts @@ -1,142 +1,25 @@ import { - type ApplicationCommandOptionTypes, - type ApplicationCommandTypes, - type BigString, type ChannelTypes, + DiscordApplicationIntegrationType, type DiscordInteraction, type DiscordInteractionDataOption, - type InteractionCallbackData, InteractionResponseTypes, InteractionTypes, - type MessageComponentTypes, MessageFlags, } from '@discordeno/types' import { Collection } from '@discordeno/utils' import { type Bot, - type Channel, - type Component, - DiscordApplicationIntegrationType, type DiscordChannel, - type DiscordInteractionContextType, - type Guild, + type Interaction, + type InteractionDataOption, + type InteractionDataResolved, + type Member, + type Message, } from '../index.js' import type { DiscordInteractionDataResolved } from '../typings.js' -import type { Attachment } from './attachment.js' -import type { Member } from './member.js' -import type { Message } from './message.js' -import type { Role } from './role.js' -import type { User } from './user.js' -export interface Interaction extends BaseInteraction { - /** The bot object */ - bot: Bot - /** Whether or not this interaction has been responded to. */ - acknowledged: boolean - /** Id of the interaction */ - id: bigint - /** Id of the application this interaction is for */ - applicationId: bigint - /** The type of interaction */ - type: InteractionTypes - /** Guild that the interaction was sent from */ - guild: Guild - /** The guild it was sent from */ - guildId?: bigint - /** The channel it was sent from */ - channel: Partial - /** - * The ID of channel it was sent from - * - * @remarks - * It is recommended that you begin using this channel field to identify the source channel of the interaction as they may deprecate the existing channel_id field in the future. - */ - channelId?: bigint - /** Guild member data for the invoking user, including permissions */ - member?: Member - /** User object for the invoking user, if invoked in a DM */ - user: User - /** A continuation token for responding to the interaction */ - token: string - /** Read-only property, always `1` */ - version: 1 - /** For the message the button was attached to */ - message?: Message - /** the command data payload */ - data?: { - type?: ApplicationCommandTypes - componentType?: MessageComponentTypes - customId?: string - components?: Component[] - values?: string[] - name: string - resolved?: InteractionDataResolved - options?: InteractionDataOption[] - id?: bigint - targetId?: bigint - // guildId?: bigint - } - /** The selected language of the invoking user */ - locale?: string - /** The guild's preferred locale, if invoked in a guild */ - guildLocale?: string - /** The computed permissions for a bot or app in the context of a specific interaction (including channel overwrites) */ - appPermissions: bigint - /** Mapping of installation contexts that the interaction was authorized for to related user or guild IDs. */ - authorizingIntegrationOwners: Partial> - /** Context where the interaction was triggered from */ - context?: DiscordInteractionContextType -} - -export interface BaseInteraction { - /** - * Sends a response to an interaction. - * - * @remarks - * This will send a {@link InteractionResponseTypes.ChannelMessageWithSource}, {@link InteractionResponseTypes.ApplicationCommandAutocompleteResult} or {@link InteractionResponseTypes.Modal} response based on the type of the interaction you are responding to. - * - * If the interaction has been already acknowledged, indicated by {@link Interaction.acknowledged}, it will send a followup message instead. - * - * Uses `interaction.type`, `interaction.token` and `interaction.id`, missing one of these in the desired proprieties may cause unexpected behavior. - */ - respond: (response: string | InteractionCallbackData, options?: { isPrivate?: boolean }) => Promise - /** - * Edit the original response of an interaction or a followup if the message id is provided. - * - * @remarks - * This will edit the original interaction response or, if the interaction has not yet been acknowledged and the type of the interaction is {@link InteractionTypes.MessageComponent} it will instead send a {@link InteractionResponseTypes.UpdateMessage} response instead. - * - * Uses `interaction.type`, `interaction.token` and `interaction.id`, missing one of these in the desired proprieties may cause unexpected behavior. - */ - edit: (response: string | InteractionCallbackData, messageId?: BigString) => Promise - /** - * Defer the interaction for updating the referenced message at a later time with {@link edit}. - * - * @remarks - * This will send a {@link InteractionResponseTypes.DeferredUpdateMessage} response. - * - * Uses `interaction.type`, `interaction.token` and `interaction.id`, missing one of these in the desired proprieties may cause unexpected behavior. - */ - deferEdit: () => Promise - /** - * Defer the interaction for updating the response at a later time with {@link edit}. - * - * @remarks - * This will send a {@link InteractionResponseTypes.DeferredChannelMessageWithSource} response. - * - * Uses `interaction.type`, `interaction.token` and `interaction.id`, missing one of these in the desired proprieties may cause unexpected behavior. - */ - defer: (isPrivate?: boolean) => Promise - /** - * Delete the original interaction response or a followup if the message id is provided. - * - * @remarks - * Uses `interaction.type` and `interaction.token`, missing one of these in the desired proprieties may cause unexpected behavior. - */ - delete: (messageId?: BigString) => Promise -} - -const baseInteraction: Partial & BaseInteraction = { +const baseInteraction = { async respond(response, options) { let type = InteractionResponseTypes.ChannelMessageWithSource @@ -149,14 +32,14 @@ const baseInteraction: Partial & BaseInteraction = { if (type === InteractionResponseTypes.ChannelMessageWithSource && options?.isPrivate) response.flags = MessageFlags.Ephemeral // Since this has already been given a response, any further responses must be followups. - if (this.acknowledged) return await this.bot!.helpers.sendFollowupMessage(this.token!, response) + if (this.acknowledged) return await this.bot.helpers.sendFollowupMessage(this.token, response) // Modals cannot be chained if (this.type === InteractionTypes.ModalSubmit && type === InteractionResponseTypes.Modal) throw new Error('Cannot respond to a modal interaction with another modal.') this.acknowledged = true - return await this.bot!.helpers.sendInteractionResponse(this.id!, this.token!, { type, data: response }) + return await this.bot.helpers.sendInteractionResponse(this.id, this.token, { type, data: response }) }, async edit(response, messageId) { if (this.type === InteractionTypes.ApplicationCommandAutocomplete) throw new Error('Cannot edit an autocomplete interaction.') @@ -165,7 +48,7 @@ const baseInteraction: Partial & BaseInteraction = { if (typeof response === 'string') response = { content: response } if (messageId) { - return await this.bot?.helpers.editFollowupMessage(this.token!, messageId, response) + return await this.bot?.helpers.editFollowupMessage(this.token, messageId, response) } if (!this.acknowledged) { @@ -173,10 +56,10 @@ const baseInteraction: Partial & BaseInteraction = { throw new Error("This interaction has not been responded to yet and this isn't a MessageComponent interaction.") this.acknowledged = true - return await this.bot!.helpers.sendInteractionResponse(this.id!, this.token!, { type: InteractionResponseTypes.UpdateMessage, data: response }) + return await this.bot.helpers.sendInteractionResponse(this.id, this.token, { type: InteractionResponseTypes.UpdateMessage, data: response }) } - return await this.bot!.helpers.editOriginalInteractionResponse(this.token!, response) + return await this.bot.helpers.editOriginalInteractionResponse(this.token, response) }, async deferEdit() { if (this.type === InteractionTypes.ApplicationCommandAutocomplete) throw new Error('Cannot edit an autocomplete interaction.') @@ -186,13 +69,13 @@ const baseInteraction: Partial & BaseInteraction = { throw new Error("Cannot defer to then edit an interaction that isn't a MessageComponent interaction.") this.acknowledged = true - return await this.bot!.helpers.sendInteractionResponse(this.id!, this.token!, { type: InteractionResponseTypes.DeferredUpdateMessage }) + return await this.bot.helpers.sendInteractionResponse(this.id, this.token, { type: InteractionResponseTypes.DeferredUpdateMessage }) }, async defer(isPrivate) { if (this.acknowledged) throw new Error('Cannot defer an already responded interaction.') this.acknowledged = true - return await this.bot!.helpers.sendInteractionResponse(this.id!, this.token!, { + return await this.bot.helpers.sendInteractionResponse(this.id, this.token, { type: InteractionResponseTypes.DeferredChannelMessageWithSource, data: { flags: isPrivate ? MessageFlags.Ephemeral : undefined, @@ -202,10 +85,10 @@ const baseInteraction: Partial & BaseInteraction = { async delete(messageId) { if (this.type === InteractionTypes.ApplicationCommandAutocomplete) throw new Error('Cannot delete an autocomplete interaction') - if (messageId) return await this.bot?.helpers.deleteFollowupMessage(this.token!, messageId) - else return await this.bot?.helpers.deleteOriginalInteractionResponse(this.token!) + if (messageId) return await this.bot?.helpers.deleteFollowupMessage(this.token, messageId) + else return await this.bot?.helpers.deleteOriginalInteractionResponse(this.token) }, -} +} as Interaction export function transformInteraction(bot: Bot, payload: { interaction: DiscordInteraction; shardId: number }): Interaction { const guildId = payload.interaction.guild_id ? bot.transformers.snowflake(payload.interaction.guild_id) : undefined @@ -354,20 +237,3 @@ export function transformInteractionDataResolved(bot: Bot, resolved: DiscordInte return transformed } - -export interface InteractionDataResolved { - messages?: Collection - users?: Collection - members?: Collection - roles?: Collection - channels?: Collection - attachments?: Collection -} - -export interface InteractionDataOption { - name: string - type: ApplicationCommandOptionTypes - value?: string | number | boolean - options?: InteractionDataOption[] - focused?: boolean -} diff --git a/packages/bot/src/transformers/invite.ts b/packages/bot/src/transformers/invite.ts index 08eb253ad..4358fbec3 100644 --- a/packages/bot/src/transformers/invite.ts +++ b/packages/bot/src/transformers/invite.ts @@ -1,6 +1,5 @@ -import type { DiscordApplication, DiscordInviteCreate, DiscordInviteMetadata, DiscordInviteType } from '@discordeno/types' -import { type Application, type Bot, type ScheduledEvent, type User, isInviteWithMetadata } from '../index.js' -import type { InviteStageInstance } from './stageInviteInstance.js' +import type { DiscordApplication, DiscordInviteCreate, DiscordInviteMetadata } from '@discordeno/types' +import { type Bot, type Invite, isInviteWithMetadata } from '../index.js' export function transformInvite(bot: Bot, payload: { invite: DiscordInviteCreate | DiscordInviteMetadata; shardId: number }): Invite { const props = bot.transformers.desiredProperties.invite @@ -47,42 +46,3 @@ export function transformInvite(bot: Bot, payload: { invite: DiscordInviteCreate return bot.transformers.customizers.invite(bot, payload.invite, invite) } - -export interface Invite { - /** The type of invite */ - type: DiscordInviteType - /** The channel the invite is for */ - channelId: bigint - /** The unique invite code */ - code: string - /** The time at which the invite was created */ - createdAt: number - /** The guild of the invite */ - guildId?: bigint - /** The user that created the invite */ - inviter?: User - /** How long the invite is valid for (in seconds) */ - maxAge: number - /** The maximum number of times the invite can be used */ - maxUses: number - /** The type of target for this voice channel invite */ - targetType: number - /** The target user for this invite */ - targetUser: User - /** The embedded application to open for this voice channel embedded application invite */ - targetApplication?: Application - /** Whether or not the invite is temporary (invited users will be kicked on disconnect unless they're assigned a role) */ - temporary: boolean - /** How many times the invite has been used (always will be 0) */ - uses: number - /** Approximate count of online members (only present when target_user is set) */ - approximateMemberCount: number - /** Stage instance data if there is a public Stage instance in the Stage channel this invite is for */ - stageInstance?: InviteStageInstance - /** The expiration date of this invite, returned from the GET /invites/code endpoint when with_expiration is true */ - expiresAt?: number - /** guild scheduled event data */ - guildScheduledEvent?: ScheduledEvent - /** Approximate count of online members (only present when target_user is set) */ - approximatePresenceCount?: number -} diff --git a/packages/bot/src/transformers/member.ts b/packages/bot/src/transformers/member.ts index 317421ad0..23ed9cf97 100644 --- a/packages/bot/src/transformers/member.ts +++ b/packages/bot/src/transformers/member.ts @@ -1,12 +1,11 @@ import { type BigString, type DiscordMember } from '@discordeno/types' import { iconHashToBigInt } from '@discordeno/utils' import type { Bot } from '../bot.js' -import type { AvatarDecorationData } from './avatarDecorationData.js' import { Permissions } from './toggles/Permissions.js' import { MemberToggles } from './toggles/member.js' -import type { User } from './user.js' +import type { Member } from './types.js' -const baseMember: Partial & BaseMember = { +const baseMember = { get deaf() { return !!this.toggles?.has('deaf') }, @@ -31,7 +30,7 @@ const baseMember: Partial & BaseMember = { get completedOnboarding() { return !!this.toggles?.completedOnboarding }, -} +} as Member export function transformMember(bot: Bot, payload: DiscordMember, guildId: BigString, userId: BigString): Member { const member: Member = Object.create(baseMember) @@ -48,57 +47,9 @@ export function transformMember(bot: Bot, payload: DiscordMember, guildId: BigSt member.communicationDisabledUntil = Date.parse(payload.communication_disabled_until) if (props.avatar && payload.avatar) member.avatar = iconHashToBigInt(payload.avatar) if (props.permissions && payload.permissions) member.permissions = new Permissions(payload.permissions) - if (props.deaf || props.mute || props.pending || props.flags) { - member.toggles = new MemberToggles(payload) - } + if (props.toggles) member.toggles = new MemberToggles(payload) if (props.avatarDecorationData && payload.avatar_decoration_data) member.avatarDecorationData = bot.transformers.avatarDecorationData(bot, payload.avatar_decoration_data) return bot.transformers.customizers.member(bot, payload, member) } - -export interface BaseMember { - /** Whether the user is deafened in voice channels */ - deaf?: boolean - /** Whether the user is muted in voice channels */ - mute?: boolean - /** Whether the user has not yet passed the guild's Membership Screening requirements */ - pending?: boolean - /** Member has left and rejoined the guild */ - didRejoin?: boolean - /** Member has completed onboarding */ - startedOnboarding?: boolean - /** Member is exempt from guild verification requirements */ - bypassesVerification?: boolean - /** Member has started onboarding */ - completedOnboarding?: boolean - /** Guild member flags */ - flags: number -} - -export interface Member extends BaseMember { - /** The user id of the member. */ - id: bigint - /** The compressed form of all the boolean values on this user. */ - toggles?: MemberToggles - /** The guild id where this member is. */ - guildId: bigint - /** The user this guild member represents */ - user?: User - /** This users guild nickname */ - nick?: string - /** The members custom avatar for this server. */ - avatar?: bigint - /** Array of role object ids */ - roles: bigint[] - /** When the user joined the guild */ - joinedAt: number - /** When the user started boosting the guild */ - premiumSince?: number - /** The permissions this member has in the guild. Only present on interaction events. */ - permissions?: Permissions - /** when the user's timeout will expire and the user will be able to communicate in the guild again (set null to remove timeout), null or a time in the past if the user is not timed out */ - communicationDisabledUntil?: number - /** data for the member's guild avatar decoration */ - avatarDecorationData: AvatarDecorationData -} diff --git a/packages/bot/src/transformers/message.ts b/packages/bot/src/transformers/message.ts index 25a84cc75..62c2677a9 100644 --- a/packages/bot/src/transformers/message.ts +++ b/packages/bot/src/transformers/message.ts @@ -3,24 +3,15 @@ import { type DiscordMessage, type DiscordMessageCall, type DiscordMessageInteractionMetadata, - type InteractionTypes, - type MessageActivityTypes, MessageFlags, - type MessageTypes, - type StickerFormatTypes, } from '@discordeno/types' import { CHANNEL_MENTION_REGEX } from '../constants.js' -import { type Bot, type Poll, snowflakeToTimestamp } from '../index.js' -import type { Attachment } from './attachment.js' -import type { Channel } from './channel.js' -import type { Component } from './component.js' -import type { Embed } from './embed.js' -import type { Emoji } from './emoji.js' -import type { Member } from './member.js' +import { type Bot, type Message, type MessageCall, type MessageInteractionMetadata, snowflakeToTimestamp } from '../index.js' import { ToggleBitfield } from './toggles/ToggleBitfield.js' -import type { User } from './user.js' -const baseMessage: Partial & MessageBase = { +const EMPTY_STRING = '' + +const baseMessage = { get crossposted() { return this.flags?.contains(MessageFlags.Crossposted) ?? false }, @@ -131,153 +122,7 @@ const baseMessage: Partial & MessageBase = { if (value) this.flags.add(MessageFlags.Urgent) else this.flags.remove(MessageFlags.Urgent) }, -} - -export interface MessageBase { - /** Holds all the boolean values on this message. */ - bitfield?: ToggleBitfield - /** Whether this message has been published to subscribed channels (via Channel Following) */ - crossposted: boolean - /** Whether this message is only visible to the user who invoked the Interaction */ - ephemeral: boolean - /** Whether this message failed to mention some roles and add their members to the thread */ - failedToMentionSomeRolesInThread: boolean - /** Message flags combined as a bitfield */ - flags?: ToggleBitfield - /** Whether this message has an associated thread, with the same id as the message */ - hasThread: boolean - /** Whether this message originated from a message in another channel (via Channel Following) */ - isCrosspost: boolean - /** Whether this message is an Interaction Response and the bot is "thinking" */ - loading: boolean - /** The ids of the users who were mentioned in this message. */ - mentionedUserIds: bigint[] - /** Whether this message mentions everyone */ - mentionEveryone: boolean - /** Whether this message is pinned */ - pinned: boolean - /** Whether the source message for this crosspost has been deleted (via Channel Following) */ - sourceMessageDeleted: boolean - /** Whether do not include any embeds when serializing this message */ - suppressEmbeds: boolean - /** Whether this message will not trigger push and desktop notifications */ - suppressNotifications: boolean - /** The timestamp in milliseconds when this message was created */ - timestamp: number - /** Whether this was a TTS message. */ - tts: boolean - /** Whether this message came from the urgent message system */ - urgent: boolean -} - -export interface Message extends MessageBase { - /** Sent with Rich Presence-related chat embeds */ - activity?: { - /** Type of message activity */ - type: MessageActivityTypes - /** party_id from a Rich Presence event */ - partyId?: string - } - /** if the message is an Interaction or application-owned webhook, this is the id of the application */ - applicationId?: bigint - /** Any attached files on this message. */ - attachments?: Attachment[] - /** The author of this message (not guaranteed to be a valid user) Note: The author object follows the structure of the user object, but is only a valid user in the case where the message is generated by a user or bot user. If the message is generated by a webhook, the author object corresponds to the webhook's id, username, and avatar. You can tell if a message is generated by a webhook by checking for the webhook_id on the message object. */ - author: User - /** id of the channel the message was sent in */ - channelId: bigint - /** The components related to this message */ - components: Component[] - /** Contents of the message */ - content: string - /** The timestamp in milliseconds when this message was edited last. */ - editedTimestamp?: number - /** Any embedded content */ - embeds?: Embed[] - /** id of the guild the message was sent in Note: For MESSAGE_CREATE and MESSAGE_UPDATE events, the message object may not contain a guild_id or member field since the events are sent directly to the receiving user and the bot who sent the message, rather than being sent through the guild like non-ephemeral messages. */ - guildId?: bigint - /** id of the message */ - id: bigint - /** sent if the message is sent as a result of an interaction */ - interactionMetadata?: MessageInteractionMetadata - /** - * Sent if the message is a response to an Interaction - * - * @deprecated Deprecated in favor of {@link interactionMetadata} - */ - interaction?: { - /** Id of the interaction */ - id: bigint - /** The member who invoked the interaction in the guild */ - member?: Member - /** The name of the ApplicationCommand including the name of the subcommand/subcommand group */ - name: string - /** The type of interaction */ - type: InteractionTypes - /** The user who invoked the interaction */ - user: User - } - /** Member properties for this message's author Note: The member object exists in MESSAGE_CREATE and MESSAGE_UPDATE events from text-based guild channels. This allows bots to obtain real-time member data without requiring bots to store member state in memory. */ - member?: Member - /** Users specifically mentioned in the message Note: The user objects in the mentions array will only have the partial member field present in MESSAGE_CREATE and MESSAGE_UPDATE events from text-based guild channels. */ - mentions?: User[] - /** Channels specifically mentioned in this message Note: Not all channel mentions in a message will appear in mention_channels. Only textual channels that are visible to everyone in a discoverable guild will ever be included. Only crossposted messages (via Channel Following) currently include mention_channels at all. If no mentions in the message meet these requirements, this field will not be sent. */ - mentionedChannelIds?: bigint[] - /** Roles specifically mentioned in this message */ - mentionedRoleIds?: bigint[] - /** Data showing the source of a crossposted channel follow add, pin or reply message */ - messageReference?: { - /** id of the originating message's channel Note: channel_id is optional when creating a reply, but will always be present when receiving an event/response that includes this data model. */ - channelId?: bigint - /** id of the originating message's guild */ - guildId?: bigint - /** id of the originating message */ - messageId?: bigint - } - /** Used for validating a message was sent */ - nonce?: string | number - /** Reactions on this message. */ - reactions?: Array<{ - /** Whether the current user reacted using this emoji */ - me: boolean - /** Whether the current user super-reacted using this emoji */ - meBurst: boolean - /** Times this emoji has been used to react */ - count: number - /** Reaction count details object */ - countDetails: { - /** Count of super reactions */ - burst: number - /** Count of normal reactions */ - normal: number - } - /** Emoji information */ - emoji: Emoji - /** HEX colors used for super reaction */ - burstColors: string[] - }> - /** Sent if the message contains stickers */ - stickerItems?: Array<{ - /** The id of this sticker. */ - id: bigint - /** The name of this sticker. */ - name: string - /** The type of this stickers format. */ - formatType: StickerFormatTypes - }> - /** Type of message */ - type: MessageTypes - /** The thread that was started from this message, includes thread member object */ - thread?: Channel - /** If the message is generated by a webhook, this is the webhook's id */ - webhookId?: bigint - /** A poll! */ - poll?: Poll - /** The call associated with the message */ - call?: MessageCall -} - -const EMPTY_STRING = '' +} as Message export function transformMessage(bot: Bot, payload: DiscordMessage): Message { const guildId = payload.guild_id ? bot.transformers.snowflake(payload.guild_id) : undefined @@ -300,33 +145,30 @@ export function transformMessage(bot: Bot, payload: DiscordMessage): Message { if (props.embeds && payload.embeds?.length) message.embeds = payload.embeds.map((embed) => bot.transformers.embed(bot, embed)) if (props.guildId && guildId) message.guildId = guildId if (props.id && payload.id) message.id = bot.transformers.snowflake(payload.id) - if (payload.interaction_metadata) message.interactionMetadata = transformMessageInteractionMetadata(bot, payload.interaction_metadata) - if (payload.interaction) { + if (props.interactionMetadata && payload.interaction_metadata) + message.interactionMetadata = transformMessageInteractionMetadata(bot, payload.interaction_metadata) + if (props.interaction && payload.interaction) { const interaction = {} as NonNullable - let edited = false - if (props.interaction.id) { + const messageInteractionProps = bot.transformers.desiredProperties.messageInteraction + + if (messageInteractionProps.id) { interaction.id = bot.transformers.snowflake(payload.interaction.id) - edited = true } - if (props.interaction.member && payload.interaction.member) { + if (messageInteractionProps.member && payload.interaction.member) { // @ts-expect-error TODO: partial - check why this is partial and handle as needed interaction.member = bot.transformers.member(bot, payload.interaction.member, guildId, payload.interaction.user.id) - edited = true } - if (props.interaction.name) { + if (messageInteractionProps.name) { interaction.name = payload.interaction.name - edited = true } - if (props.interaction.type) { + if (messageInteractionProps.type) { interaction.type = payload.interaction.type - edited = true } - if (props.interaction.user) { + if (messageInteractionProps.user) { interaction.user = bot.transformers.user(bot, payload.interaction.user) - edited = true } - if (edited) message.interaction = interaction + message.interaction = interaction } if (props.member && guildId && payload.member) message.member = bot.transformers.member(bot, payload.member, guildId, userId) if (payload.mention_everyone) message.mentionEveryone = true @@ -344,24 +186,21 @@ export function transformMessage(bot: Bot, payload: DiscordMessage): Message { if (props.mentionedRoleIds && payload.mention_roles?.length) message.mentionedRoleIds = payload.mention_roles.map((id) => bot.transformers.snowflake(id)) if (props.mentions && payload.mentions?.length) message.mentions = payload.mentions.map((user) => bot.transformers.user(bot, user)) - if (payload.message_reference) { + if (props.messageReference && payload.message_reference) { const reference = {} as NonNullable - let edited = false + const messageReferenceProps = bot.transformers.desiredProperties.messageReference - if (props.messageReference.channelId && payload.message_reference.channel_id) { + if (messageReferenceProps.channelId && payload.message_reference.channel_id) { reference.channelId = bot.transformers.snowflake(payload.message_reference.channel_id) - edited = true } - if (props.messageReference.guildId && payload.message_reference.guild_id) { + if (messageReferenceProps.guildId && payload.message_reference.guild_id) { reference.guildId = bot.transformers.snowflake(payload.message_reference.guild_id) - edited = true } - if (props.messageReference.messageId && payload.message_reference.message_id) { + if (messageReferenceProps.messageId && payload.message_reference.message_id) { reference.messageId = bot.transformers.snowflake(payload.message_reference.message_id) - edited = true } - if (edited) message.messageReference = reference + message.messageReference = reference } if (props.nonce && payload.nonce) message.nonce = payload.nonce if (payload.pinned) message.pinned = true @@ -395,7 +234,7 @@ export function transformMessage(bot: Bot, payload: DiscordMessage): Message { } export function transformMessageInteractionMetadata(bot: Bot, payload: DiscordMessageInteractionMetadata): MessageInteractionMetadata { - const props = bot.transformers.desiredProperties.message.interactionMetadata + const props = bot.transformers.desiredProperties.messageInteractionMetadata const metadata = {} as MessageInteractionMetadata if (props.id) metadata.id = bot.transformers.snowflake(payload.id) @@ -424,34 +263,10 @@ export function transformMessageInteractionMetadata(bot: Bot, payload: DiscordMe export function transformMessageCall(bot: Bot, payload: DiscordMessageCall): MessageCall { const call = {} as MessageCall - const props = bot.transformers.desiredProperties.message.call + const props = bot.transformers.desiredProperties.messageCall if (props.participants && payload.participants) call.participants = payload.participants.map((x) => bot.transformers.snowflake(x)) if (props.endedTimestamp && payload.ended_timestamp) call.endedTimestamp = Date.parse(payload.ended_timestamp) return bot.transformers.customizers.messageCall(bot, payload, call) } - -export interface MessageInteractionMetadata { - /** Id of the interaction */ - id: bigint - /** The type of interaction */ - type: InteractionTypes - /** User who triggered the interaction */ - user: User - /** IDs for installation context(s) related to an interaction */ - authorizingIntegrationOwners: Partial> - /** ID of the original response message, present only on follow-up messages */ - originalResponseMessageId?: bigint - /** ID of the message that contained interactive component, present only on messages created from component interactions */ - interactedMessageId?: bigint - /** Metadata for the interaction that was used to open the modal, present only on modal submit interactions */ - triggeringInteractionMetadata?: MessageInteractionMetadata -} - -export interface MessageCall { - /** Array of user object ids that participated in the call */ - participants: bigint[] - /** Time when call ended */ - endedTimestamp: number -} diff --git a/packages/bot/src/transformers/onboarding.ts b/packages/bot/src/transformers/onboarding.ts index 5956704a7..0b1ee2831 100644 --- a/packages/bot/src/transformers/onboarding.ts +++ b/packages/bot/src/transformers/onboarding.ts @@ -1,11 +1,5 @@ -import type { - DiscordGuildOnboarding, - DiscordGuildOnboardingMode, - DiscordGuildOnboardingPrompt, - DiscordGuildOnboardingPromptOption, - DiscordGuildOnboardingPromptType, -} from '@discordeno/types' -import { type Bot, type Emoji } from '../index.js' +import type { DiscordGuildOnboarding, DiscordGuildOnboardingPrompt, DiscordGuildOnboardingPromptOption } from '@discordeno/types' +import { type Bot, type GuildOnboarding, type GuildOnboardingPrompt, type GuildOnboardingPromptOption } from '../index.js' export function transformGuildOnboarding(bot: Bot, payload: DiscordGuildOnboarding): GuildOnboarding { const props = bot.transformers.desiredProperties.guildOnboarding @@ -22,7 +16,7 @@ export function transformGuildOnboarding(bot: Bot, payload: DiscordGuildOnboardi } export function transformGuildOnboardingPrompt(bot: Bot, payload: DiscordGuildOnboardingPrompt): GuildOnboardingPrompt { - const props = bot.transformers.desiredProperties.guildOnboarding.prompts + const props = bot.transformers.desiredProperties.guildOnboardingPrompt const prompt = {} as GuildOnboardingPrompt if (props.id && payload.id) prompt.id = bot.transformers.snowflake(prompt.id) @@ -37,7 +31,7 @@ export function transformGuildOnboardingPrompt(bot: Bot, payload: DiscordGuildOn } export function transformGuildOnboardingPromptOption(bot: Bot, payload: DiscordGuildOnboardingPromptOption): GuildOnboardingPromptOption { - const props = bot.transformers.desiredProperties.guildOnboarding.prompts.options + const props = bot.transformers.desiredProperties.guildOnboardingPromptOption const option = {} as GuildOnboardingPromptOption if (props.id && payload.id) option.id = bot.transformers.snowflake(payload.id) @@ -49,48 +43,3 @@ export function transformGuildOnboardingPromptOption(bot: Bot, payload: DiscordG return option } - -export interface GuildOnboarding { - /** ID of the guild this onboarding is part of */ - guildId: bigint - /** Prompts shown during onboarding and in customize community */ - prompts: GuildOnboardingPrompt[] - /** Channel IDs that members get opted into automatically */ - defaultChannelIds: bigint[] - /** Whether onboarding is enabled in the guild */ - enabled: boolean - /** Current mode of onboarding */ - mode: DiscordGuildOnboardingMode -} - -export interface GuildOnboardingPrompt { - /** ID of the prompt */ - id: bigint - /** Type of prompt */ - type: DiscordGuildOnboardingPromptType - /** Options available within the prompt */ - options: GuildOnboardingPromptOption[] - /** Title of the prompt */ - title: string - /** Indicates whether users are limited to selecting one option for the prompt */ - singleSelect: boolean - /** Indicates whether the prompt is required before a user completes the onboarding flow */ - required: boolean - /** Indicates whether the prompt is present in the onboarding flow. If `false`, the prompt will only appear in the Channels & Roles tab */ - inOnboarding: boolean -} - -export interface GuildOnboardingPromptOption { - /** ID of the prompt option */ - id: bigint - /** IDs for channels a member is added to when the option is selected */ - channelIds: bigint[] - /** IDs for roles assigned to a member when the option is selected */ - roleIds: bigint[] - /** Emoji of the option */ - emoji: Emoji - /** Title of the option */ - title: string - /** Description of the option */ - description: string | undefined -} diff --git a/packages/bot/src/transformers/poll.ts b/packages/bot/src/transformers/poll.ts index fff538e94..d8200be22 100644 --- a/packages/bot/src/transformers/poll.ts +++ b/packages/bot/src/transformers/poll.ts @@ -1,5 +1,5 @@ -import type { DiscordEmoji, DiscordPoll, DiscordPollLayoutType, DiscordPollMedia } from '@discordeno/types' -import type { Bot, Emoji } from '../index.js' +import type { DiscordEmoji, DiscordPoll, DiscordPollMedia } from '@discordeno/types' +import type { Bot, Poll, PollMedia, PollResult } from '../index.js' export function transformPoll(bot: Bot, payload: DiscordPoll): Poll { const props = bot.transformers.desiredProperties.poll @@ -13,9 +13,10 @@ export function transformPoll(bot: Bot, payload: DiscordPoll): Poll { if (props.layoutType) poll.layoutType = payload.layout_type if (props.results && payload.results) { poll.results = {} as PollResult + const pollResultProps = bot.transformers.desiredProperties.pollResult - if (props.results.isFinalized && payload.results.is_finalized) poll.results.isFinalized = payload.results.is_finalized - if (props.results.answerCounts && payload.results.answer_counts) + if (pollResultProps.isFinalized && payload.results.is_finalized) poll.results.isFinalized = payload.results.is_finalized + if (pollResultProps.answerCounts && payload.results.answer_counts) poll.results.answerCounts = payload.results.answer_counts.map((x) => ({ id: x.id, count: x.count, meVoted: x.me_voted })) } @@ -31,75 +32,3 @@ export function transformPollMedia(bot: Bot, payload: DiscordPollMedia): PollMed return bot.transformers.customizers.pollMedia(bot, payload, pollMedia) } - -export interface Poll { - /** The question of the poll. Only `text` is supported. */ - question: PollMedia - /** Each of the answers available in the poll. There is a maximum of 10 answers per poll. */ - answers: PollAnswer[] - /** - * The time when the poll ends. - * - * @remarks - * `expiry` is marked as nullable to support non-expiring polls in the future, but all polls have an expiry currently. - */ - expiry: number | null - /** Whether a user can select multiple answers */ - allowMultiselect: boolean - /** The layout type of the poll */ - layoutType: DiscordPollLayoutType - /** - * The results of the poll - * - * @remarks - * This value will not be sent by discord under specific conditions where they don't fetch them on their backend. When this value is missing it should be interpreted as "Unknown results" and not as "No results" - * The results may not be totally accurate while the poll has not ended. When it ends discord will re-calculate all the results and set {@link DiscordPollResult.is_finalized} to true - */ - results?: PollResult -} - -export interface PollMedia { - /** - * The text of the field - * - * @remarks - * `text` should always be non-null for both questions and answers, but this is subject to changes. - * The maximum length of `text` is 300 for the question, and 55 for any answer. - */ - text?: string - /** - * The emoji of the field - * - * @remarks - * When creating a poll answer with an emoji, one only needs to send either the `id` (custom emoji) or `name` (default emoji) as the only field. - */ - emoji?: Partial -} - -export interface PollAnswer { - /** - * The id of the answer - * - * @remarks - * This id labels each answer. It starts at 1 and goes up sequentially. Discord recommend against depending on this sequence as it is an implementation detail. - */ - answerId: number - /** The data of the answer */ - pollMedia: PollMedia -} - -export interface PollResult { - /** Whether the votes have been precisely counted */ - isFinalized: boolean - /** The counts for each answer */ - answerCounts: PollAnswerCount[] -} - -export interface PollAnswerCount { - /** The {@link PollAnswer.answerId | answerId} */ - id: number - /** The number of votes for this answer */ - count: number - /** Whether the current user voted for this answer */ - meVoted: boolean -} diff --git a/packages/bot/src/transformers/presence.ts b/packages/bot/src/transformers/presence.ts index 4f49751a7..76964ca57 100644 --- a/packages/bot/src/transformers/presence.ts +++ b/packages/bot/src/transformers/presence.ts @@ -1,5 +1,5 @@ import { type DiscordPresenceUpdate, PresenceStatus } from '@discordeno/types' -import type { Activity, Bot, User } from '../index.js' +import type { Bot, PresenceUpdate } from '../index.js' export function transformPresence(bot: Bot, payload: DiscordPresenceUpdate): PresenceUpdate { const presence = { @@ -14,13 +14,3 @@ export function transformPresence(bot: Bot, payload: DiscordPresenceUpdate): Pre return bot.transformers.customizers.presence(bot, payload, presence) } - -export interface PresenceUpdate { - desktop?: string - mobile?: string - web?: string - user: User - guildId: bigint - status: PresenceStatus - activities: Activity[] -} diff --git a/packages/bot/src/transformers/reverse/activity.ts b/packages/bot/src/transformers/reverse/activity.ts index cc10b32ee..4b93db220 100644 --- a/packages/bot/src/transformers/reverse/activity.ts +++ b/packages/bot/src/transformers/reverse/activity.ts @@ -1,5 +1,4 @@ -import type { Bot, DiscordActivity } from '../../index.js' -import type { Activity } from '../activity.js' +import type { Activity, Bot, DiscordActivity } from '../../index.js' export function transformActivityToDiscordActivity(_bot: Bot, payload: Activity): DiscordActivity { return { diff --git a/packages/bot/src/transformers/reverse/application.ts b/packages/bot/src/transformers/reverse/application.ts index f91397b8f..a260a4db1 100644 --- a/packages/bot/src/transformers/reverse/application.ts +++ b/packages/bot/src/transformers/reverse/application.ts @@ -1,5 +1,4 @@ -import { type Bot, type DiscordApplication, iconBigintToHash } from '../../index.js' -import type { Application } from '../application.js' +import { type Application, type Bot, type DiscordApplication, iconBigintToHash } from '../../index.js' export function transformApplicationToDiscordApplication(bot: Bot, payload: Application): DiscordApplication { return { diff --git a/packages/bot/src/transformers/reverse/applicationCommand.ts b/packages/bot/src/transformers/reverse/applicationCommand.ts index 182289ed3..e9b1f1322 100644 --- a/packages/bot/src/transformers/reverse/applicationCommand.ts +++ b/packages/bot/src/transformers/reverse/applicationCommand.ts @@ -1,5 +1,4 @@ -import type { Bot, DiscordApplicationCommand } from '../../index.js' -import type { ApplicationCommand } from '../applicationCommand.js' +import type { ApplicationCommand, Bot, DiscordApplicationCommand } from '../../index.js' export function transformApplicationCommandToDiscordApplicationCommand(bot: Bot, payload: ApplicationCommand): DiscordApplicationCommand { return { diff --git a/packages/bot/src/transformers/reverse/applicationCommandOption.ts b/packages/bot/src/transformers/reverse/applicationCommandOption.ts index 5b374c43f..026584dce 100644 --- a/packages/bot/src/transformers/reverse/applicationCommandOption.ts +++ b/packages/bot/src/transformers/reverse/applicationCommandOption.ts @@ -1,5 +1,4 @@ -import type { Bot, DiscordApplicationCommandOption } from '../../index.js' -import type { ApplicationCommandOption } from '../applicationCommandOption.js' +import type { ApplicationCommandOption, Bot, DiscordApplicationCommandOption } from '../../index.js' export function transformApplicationCommandOptionToDiscordApplicationCommandOption( bot: Bot, diff --git a/packages/bot/src/transformers/reverse/applicationCommandOptionChoice.ts b/packages/bot/src/transformers/reverse/applicationCommandOptionChoice.ts index 7e9be0f1d..634a0113c 100644 --- a/packages/bot/src/transformers/reverse/applicationCommandOptionChoice.ts +++ b/packages/bot/src/transformers/reverse/applicationCommandOptionChoice.ts @@ -1,5 +1,4 @@ -import type { Bot, Camelize, DiscordApplicationCommandOptionChoice } from '../../index.js' -import type { ApplicationCommandOptionChoice } from '../applicationCommandOptionChoice.js' +import type { ApplicationCommandOptionChoice, Bot, Camelize, DiscordApplicationCommandOptionChoice } from '../../index.js' export function transformApplicationCommandOptionChoiceToDiscordApplicationCommandOptionChoice( _bot: Bot, diff --git a/packages/bot/src/transformers/reverse/applicationCommandPermission.ts b/packages/bot/src/transformers/reverse/applicationCommandPermission.ts index ff0348806..50102077a 100644 --- a/packages/bot/src/transformers/reverse/applicationCommandPermission.ts +++ b/packages/bot/src/transformers/reverse/applicationCommandPermission.ts @@ -1,9 +1,8 @@ -import type { Bot, DiscordGuildApplicationCommandPermissions } from '../../index.js' -import type { ApplicationCommandPermission } from '../applicationCommandPermission.js' +import type { Bot, DiscordGuildApplicationCommandPermissions, GuildApplicationCommandPermissions } from '../../index.js' export function transformApplicationCommandPermissionToDiscordApplicationCommandPermission( bot: Bot, - payload: ApplicationCommandPermission, + payload: GuildApplicationCommandPermissions, ): DiscordGuildApplicationCommandPermissions { return { id: bot.transformers.reverse.snowflake(payload.id), diff --git a/packages/bot/src/transformers/reverse/attachment.ts b/packages/bot/src/transformers/reverse/attachment.ts index 402864def..ceb94f347 100644 --- a/packages/bot/src/transformers/reverse/attachment.ts +++ b/packages/bot/src/transformers/reverse/attachment.ts @@ -1,5 +1,4 @@ -import type { Bot, DiscordAttachment } from '../../index.js' -import type { Attachment } from '../attachment.js' +import type { Attachment, Bot, DiscordAttachment } from '../../index.js' export function transformAttachmentToDiscordAttachment(bot: Bot, payload: Attachment): DiscordAttachment { return { diff --git a/packages/bot/src/transformers/reverse/auditLogEntry.ts b/packages/bot/src/transformers/reverse/auditLogEntry.ts index 2c315df94..269ab2127 100644 --- a/packages/bot/src/transformers/reverse/auditLogEntry.ts +++ b/packages/bot/src/transformers/reverse/auditLogEntry.ts @@ -1,6 +1,5 @@ import type { DiscordAuditLogEntry } from '@discordeno/types' -import { type Bot, iconBigintToHash } from '../../index.js' -import type { AuditLogEntry } from '../auditLogEntry.js' +import { type AuditLogEntry, type Bot, iconBigintToHash } from '../../index.js' export function transformAuditLogEntryToDiscordAuditLogEntry(bot: Bot, payload: AuditLogEntry): DiscordAuditLogEntry { return { diff --git a/packages/bot/src/transformers/reverse/component.ts b/packages/bot/src/transformers/reverse/component.ts index 7180eaf5b..442b23bae 100644 --- a/packages/bot/src/transformers/reverse/component.ts +++ b/packages/bot/src/transformers/reverse/component.ts @@ -1,6 +1,5 @@ -import type { Bot } from '../../index.js' +import type { Bot, Component } from '../../index.js' import type { DiscordComponent } from '../../typings.js' -import type { Component } from '../component.js' export function transformComponentToDiscordComponent(bot: Bot, payload: Component): DiscordComponent { return { diff --git a/packages/bot/src/transformers/reverse/embed.ts b/packages/bot/src/transformers/reverse/embed.ts index 07706322f..997d19cfe 100644 --- a/packages/bot/src/transformers/reverse/embed.ts +++ b/packages/bot/src/transformers/reverse/embed.ts @@ -1,6 +1,5 @@ import type { DiscordEmbed } from '@discordeno/types' -import type { Bot } from '../../index.js' -import type { Embed } from '../embed.js' +import type { Bot, Embed } from '../../index.js' export function transformEmbedToDiscordEmbed(_bot: Bot, payload: Embed): DiscordEmbed { return { diff --git a/packages/bot/src/transformers/reverse/emoji.ts b/packages/bot/src/transformers/reverse/emoji.ts index d298ffb35..3a0bf6dc3 100644 --- a/packages/bot/src/transformers/reverse/emoji.ts +++ b/packages/bot/src/transformers/reverse/emoji.ts @@ -1,6 +1,5 @@ import type { DiscordEmoji } from '@discordeno/types' -import type { Bot } from '../../index.js' -import type { Emoji } from '../emoji.js' +import type { Bot, Emoji } from '../../index.js' export function transformEmojiToDiscordEmoji(bot: Bot, payload: Emoji): DiscordEmoji { return { diff --git a/packages/bot/src/transformers/reverse/gatewayBot.ts b/packages/bot/src/transformers/reverse/gatewayBot.ts index 58352eb59..e444c1be3 100644 --- a/packages/bot/src/transformers/reverse/gatewayBot.ts +++ b/packages/bot/src/transformers/reverse/gatewayBot.ts @@ -1,5 +1,5 @@ import type { DiscordGetGatewayBot } from '@discordeno/types' -import type { GetGatewayBot } from '../gatewayBot.js' +import type { GetGatewayBot } from '../types.js' export function transformGatewayBotToDiscordGatewayBot(payload: GetGatewayBot): DiscordGetGatewayBot { return { diff --git a/packages/bot/src/transformers/reverse/member.ts b/packages/bot/src/transformers/reverse/member.ts index b4d90034d..306366d92 100644 --- a/packages/bot/src/transformers/reverse/member.ts +++ b/packages/bot/src/transformers/reverse/member.ts @@ -1,8 +1,7 @@ import type { DiscordMember, DiscordUser } from '@discordeno/types' import { iconBigintToHash } from '@discordeno/utils' import type { Bot } from '../../bot.js' -import type { Member } from '../member.js' -import type { User } from '../user.js' +import type { Member, User } from '../types.js' export function transformUserToDiscordUser(_bot: Bot, payload: User): DiscordUser { return { diff --git a/packages/bot/src/transformers/reverse/presence.ts b/packages/bot/src/transformers/reverse/presence.ts index db717e5f1..1c3cc29c7 100644 --- a/packages/bot/src/transformers/reverse/presence.ts +++ b/packages/bot/src/transformers/reverse/presence.ts @@ -1,6 +1,5 @@ import { type DiscordPresenceUpdate, PresenceStatus } from '@discordeno/types' -import type { Bot } from '../../index.js' -import type { PresenceUpdate } from '../presence.js' +import type { Bot, PresenceUpdate } from '../../index.js' export const reverseStatusTypes = Object.freeze({ 0: 'online', diff --git a/packages/bot/src/transformers/reverse/team.ts b/packages/bot/src/transformers/reverse/team.ts index 5fc017811..81af4a2e5 100644 --- a/packages/bot/src/transformers/reverse/team.ts +++ b/packages/bot/src/transformers/reverse/team.ts @@ -1,6 +1,5 @@ import type { DiscordTeam } from '@discordeno/types' -import { type Bot, iconBigintToHash } from '../../index.js' -import type { Team } from '../team.js' +import { type Bot, type Team, iconBigintToHash } from '../../index.js' export function transformTeamToDiscordTeam(bot: Bot, payload: Team): DiscordTeam { const id = payload.id.toString() diff --git a/packages/bot/src/transformers/reverse/widgetSettings.ts b/packages/bot/src/transformers/reverse/widgetSettings.ts index c41190575..5a9ccb0fe 100644 --- a/packages/bot/src/transformers/reverse/widgetSettings.ts +++ b/packages/bot/src/transformers/reverse/widgetSettings.ts @@ -1,6 +1,5 @@ import type { DiscordGuildWidgetSettings } from '@discordeno/types' -import type { Bot } from '../../index.js' -import type { GuildWidgetSettings } from '../widgetSettings.js' +import type { Bot, GuildWidgetSettings } from '../../index.js' export function transformWidgetSettingsToDiscordWidgetSettings(_bot: Bot, payload: GuildWidgetSettings): DiscordGuildWidgetSettings { return { diff --git a/packages/bot/src/transformers/role.ts b/packages/bot/src/transformers/role.ts index a91f7c05a..40a653b93 100644 --- a/packages/bot/src/transformers/role.ts +++ b/packages/bot/src/transformers/role.ts @@ -1,9 +1,9 @@ -import type { BigString, DiscordRole, RoleFlags } from '@discordeno/types' -import { type Bot, iconHashToBigInt } from '../index.js' +import type { BigString, DiscordRole } from '@discordeno/types' +import { type Bot, type Role, iconHashToBigInt } from '../index.js' import { Permissions } from './toggles/Permissions.js' import { RoleToggles } from './toggles/role.js' -const baseRole: Partial & BaseRole = { +const baseRole = { get tags() { return { botId: this.internalTags?.botId, @@ -38,7 +38,7 @@ const baseRole: Partial & BaseRole = { get guildConnections() { return !!this.toggles?.has('guildConnections') }, -} +} as Role export function transformRole(bot: Bot, payload: { role: DiscordRole } & { guildId: BigString }): Role { const role: Role = Object.create(baseRole) @@ -52,88 +52,16 @@ export function transformRole(bot: Bot, payload: { role: DiscordRole } & { guild if (props.icon && payload.role.icon) role.icon = iconHashToBigInt(payload.role.icon) if (props.unicodeEmoji && payload.role.unicode_emoji) role.unicodeEmoji = payload.role.unicode_emoji if (props.flags) role.flags = payload.role.flags - if ((props.botId || props.integrationId || props.subscriptionListingId) && payload.role.tags) { + if (props.tags && payload.role.tags) { role.internalTags = {} - if (props.botId && payload.role.tags.bot_id) role.internalTags.botId = bot.transformers.snowflake(payload.role.tags.bot_id) - if (props.integrationId && payload.role.tags.integration_id) - role.internalTags.integrationId = bot.transformers.snowflake(payload.role.tags.integration_id) - if (props.subscriptionListingId && payload.role.tags.subscription_listing_id) + if (payload.role.tags.bot_id) role.internalTags.botId = bot.transformers.snowflake(payload.role.tags.bot_id) + if (payload.role.tags.integration_id) role.internalTags.integrationId = bot.transformers.snowflake(payload.role.tags.integration_id) + if (payload.role.tags.subscription_listing_id) role.internalTags.subscriptionListingId = bot.transformers.snowflake(payload.role.tags.subscription_listing_id) } - if (props.hoist || props.managed || props.mentionable) { + if (props.toggles) { role.toggles = new RoleToggles(payload.role) } return bot.transformers.customizers.role(bot, payload.role, role) } - -export interface BaseRole { - /** The tags this role has */ - tags?: { - /** The id of the bot this role belongs to */ - botId?: bigint - /** The id of the integration this role belongs to */ - integrationId?: bigint - /** Id of this role's subscription sku and listing. */ - subscriptionListingId?: bigint - /** Whether this role is available for purchase. */ - availableForPurchase?: boolean - /** Whether this is a guild's linked role */ - guildConnections?: boolean - /** Whether this is the guild's premium subscriber role */ - premiumSubscriber?: boolean - } - /** If this role is showed separately in the user listing */ - hoist: boolean - /** Whether this role is managed by an integration */ - managed: boolean - /** Whether this role is mentionable */ - mentionable: boolean - /** Whether this is the guilds premium subscriber role */ - premiumSubscriber: boolean - /** Whether this role is available for purchase. */ - availableForPurchase: boolean - /** Whether this is a guild's linked role. */ - guildConnections: boolean -} - -export interface Role extends BaseRole { - /** Role id */ - id: bigint - /** The guild id where this role is located. */ - guildId: bigint - /** The compressed version of the boolean values on this role. */ - toggles?: RoleToggles - /** If this role is showed separately in the user listing */ - hoist: boolean - /** Permission bit set */ - permissions: Permissions - /** Whether this role is managed by an integration */ - managed: boolean - /** Whether this role is mentionable */ - mentionable: boolean - /** - * Use role.tags - * @deprecated this is not deprecated, but this is here to prevent users from using this as this is an internal value open to breaking changes. - */ - internalTags?: { - /** The id of the bot this role belongs to */ - botId?: bigint - /** The id of the integration this role belongs to */ - integrationId?: bigint - /** Id of this role's subscription sku and listing. */ - subscriptionListingId?: bigint - } - /** the role emoji hash */ - icon?: bigint - /** Role name */ - name: string - /** Integer representation of hexadecimal color code */ - color: number - /** Position of this role */ - position: number - /** role unicode emoji */ - unicodeEmoji?: string - /** Role flags combined as a bitfield */ - flags: RoleFlags -} diff --git a/packages/bot/src/transformers/scheduledEvent.ts b/packages/bot/src/transformers/scheduledEvent.ts index 3ed42f30f..8cd7b09cb 100644 --- a/packages/bot/src/transformers/scheduledEvent.ts +++ b/packages/bot/src/transformers/scheduledEvent.ts @@ -1,11 +1,5 @@ -import type { - DiscordScheduledEvent, - DiscordScheduledEventEntityMetadata, - ScheduledEventEntityType, - ScheduledEventPrivacyLevel, - ScheduledEventStatus, -} from '@discordeno/types' -import { type Bot, type User, iconHashToBigInt } from '../index.js' +import type { DiscordScheduledEvent } from '@discordeno/types' +import { type Bot, type ScheduledEvent, iconHashToBigInt } from '../index.js' export function transformScheduledEvent(bot: Bot, payload: DiscordScheduledEvent): ScheduledEvent { const props = bot.transformers.desiredProperties.scheduledEvent @@ -30,38 +24,3 @@ export function transformScheduledEvent(bot: Bot, payload: DiscordScheduledEvent return bot.transformers.customizers.scheduledEvent(bot, payload, scheduledEvent) } - -export interface ScheduledEvent { - /** the id of the scheduled event */ - id: bigint - /** the guild id which the scheduled event belongs to */ - guildId: bigint - /** the channel id in which the scheduled event will be hosted if specified */ - channelId?: bigint - /** the id of the user that created the scheduled event */ - creatorId?: bigint - /** the name of the scheduled event */ - name: string - /** the description of the scheduled event */ - description?: string - /** the time the scheduled event will start */ - scheduledStartTime: number - /** the time the scheduled event will end if it does end. */ - scheduledEndTime?: number - /** the privacy level of the scheduled event */ - privacyLevel: ScheduledEventPrivacyLevel - /** the status of the scheduled event */ - status: ScheduledEventStatus - /** the type of hosting entity associated with a scheduled event */ - entityType: ScheduledEventEntityType - /** any additional id of the hosting entity associated with event */ - entityId?: bigint - /** the location for the scheduled event */ - location?: DiscordScheduledEventEntityMetadata['location'] - /** the user that created the scheduled event */ - creator?: User - /** the number of users subscribed to the scheduled event */ - userCount?: number - /** the cover image hash of the scheduled event */ - image?: bigint -} diff --git a/packages/bot/src/transformers/sku.ts b/packages/bot/src/transformers/sku.ts index 76436fa3c..e04555dff 100644 --- a/packages/bot/src/transformers/sku.ts +++ b/packages/bot/src/transformers/sku.ts @@ -1,5 +1,5 @@ -import type { DiscordSku, DiscordSkuType, SkuFlags } from '@discordeno/types' -import type { Bot } from '../index.js' +import type { DiscordSku } from '@discordeno/types' +import type { Bot, Sku } from '../index.js' export function transformSku(bot: Bot, payload: DiscordSku): Sku { const props = bot.transformers.desiredProperties.sku @@ -14,18 +14,3 @@ export function transformSku(bot: Bot, payload: DiscordSku): Sku { return bot.transformers.customizers.sku(bot, payload, sku) } - -export interface Sku { - /** ID of SKU */ - id: bigint - /** Type of SKU */ - type: DiscordSkuType - /** ID of the parent application */ - applicationId: bigint - /** Customer-facing name of your premium offering */ - name: string - /** System-generated URL slug based on the SKU's name */ - slug: string - /** SKU flags combined as a bitfield */ - flags: SkuFlags -} diff --git a/packages/bot/src/transformers/stageInstance.ts b/packages/bot/src/transformers/stageInstance.ts index cdcd41f0a..f7f6a4d1d 100644 --- a/packages/bot/src/transformers/stageInstance.ts +++ b/packages/bot/src/transformers/stageInstance.ts @@ -1,5 +1,5 @@ import type { DiscordStageInstance } from '@discordeno/types' -import type { Bot } from '../index.js' +import type { Bot, StageInstance } from '../index.js' export function transformStageInstance(bot: Bot, payload: DiscordStageInstance): StageInstance { const props = bot.transformers.desiredProperties.stageInstance @@ -14,16 +14,3 @@ export function transformStageInstance(bot: Bot, payload: DiscordStageInstance): return bot.transformers.customizers.stageInstance(bot, payload, stageInstance) } - -export interface StageInstance { - /** The topic of the Stage instance (1-120 characters) */ - topic: string - /** The id of this Stage instance */ - id: bigint - /** The guild id of the associated Stage channel */ - guildId: bigint - /** The id of the associated Stage channel */ - channelId: bigint - /** The id of the scheduled event for this Stage instance */ - guildScheduledEventId?: bigint -} diff --git a/packages/bot/src/transformers/stageInviteInstance.ts b/packages/bot/src/transformers/stageInviteInstance.ts index a91836b15..4aaf22461 100644 --- a/packages/bot/src/transformers/stageInviteInstance.ts +++ b/packages/bot/src/transformers/stageInviteInstance.ts @@ -1,5 +1,5 @@ import type { BigString, DiscordInviteStageInstance, DiscordMember } from '@discordeno/types' -import type { Bot, Member } from '../index.js' +import type { Bot, InviteStageInstance } from '../index.js' export function transformInviteStageInstance(bot: Bot, payload: DiscordInviteStageInstance & { guildId: BigString }): InviteStageInstance { const props = bot.transformers.desiredProperties.inviteStageInstance @@ -21,14 +21,3 @@ export function transformInviteStageInstance(bot: Bot, payload: DiscordInviteSta return bot.transformers.customizers.inviteStageInstance(bot, payload, inviteStageInstance) } - -export interface InviteStageInstance { - /** The members speaking in the Stage */ - members: Partial[] - /** The number of users in the Stage */ - participantCount: number - /** The number of users speaking in the Stage */ - speakerCount: number - /** The topic of the Stage instance (1-120 characters) */ - topic: string -} diff --git a/packages/bot/src/transformers/sticker.ts b/packages/bot/src/transformers/sticker.ts index 24e0023f3..610222778 100644 --- a/packages/bot/src/transformers/sticker.ts +++ b/packages/bot/src/transformers/sticker.ts @@ -1,5 +1,5 @@ -import type { DiscordSticker, DiscordStickerPack, StickerFormatTypes, StickerTypes } from '@discordeno/types' -import type { Bot, User } from '../index.js' +import type { DiscordSticker, DiscordStickerPack } from '@discordeno/types' +import type { Bot, Sticker, StickerPack } from '../index.js' export function transformSticker(bot: Bot, payload: DiscordSticker): Sticker { const props = bot.transformers.desiredProperties.sticker @@ -33,37 +33,3 @@ export function transformStickerPack(bot: Bot, payload: DiscordStickerPack): Sti return bot.transformers.customizers.stickerPack(bot, payload, pack) } - -export interface Sticker { - /** [Id of the sticker](https://discord.com/developers/docs/reference#image-formatting) */ - id: bigint - /** Id of the pack the sticker is from */ - packId?: bigint - /** Name of the sticker */ - name: string - /** Description of the sticker */ - description: string - /** a unicode emoji representing the sticker's expression */ - tags: string - /** [type of sticker](https://discord.com/developers/docs/resources/sticker#sticker-object-sticker-types) */ - type: StickerTypes - /** [Type of sticker format](https://discord.com/developers/docs/resources/sticker#sticker-object-sticker-format-types) */ - formatType: StickerFormatTypes - /** Whether or not the sticker is available */ - available?: boolean - /** Id of the guild that owns this sticker */ - guildId?: bigint - /** The user that uploaded the sticker */ - user?: User - /** A sticker's sort order within a pack */ - sortValue?: number -} -export interface StickerPack { - coverStickerId?: bigint - bannerAssetId?: bigint - id: bigint - name: string - description: string - stickers: Sticker[] - skuId: bigint -} diff --git a/packages/bot/src/transformers/team.ts b/packages/bot/src/transformers/team.ts index 63df457d9..32c4743f7 100644 --- a/packages/bot/src/transformers/team.ts +++ b/packages/bot/src/transformers/team.ts @@ -1,5 +1,5 @@ -import type { DiscordTeam, DiscordTeamMemberRole, TeamMembershipStates } from '@discordeno/types' -import { type Bot, type User, iconHashToBigInt } from '../index.js' +import type { DiscordTeam } from '@discordeno/types' +import { type Bot, type Team, iconHashToBigInt } from '../index.js' export function transformTeam(bot: Bot, payload: DiscordTeam): Team { const id = bot.transformers.snowflake(payload.id) @@ -19,16 +19,3 @@ export function transformTeam(bot: Bot, payload: DiscordTeam): Team { return bot.transformers.customizers.team(bot, payload, team) } - -export interface Team { - icon?: bigint | undefined - id: bigint - name: string - ownerUserId: bigint - members: Array<{ - membershipState: TeamMembershipStates - teamId: bigint - user: User - role: DiscordTeamMemberRole - }> -} diff --git a/packages/bot/src/transformers/template.ts b/packages/bot/src/transformers/template.ts index 6b1545603..9ccfcbf70 100644 --- a/packages/bot/src/transformers/template.ts +++ b/packages/bot/src/transformers/template.ts @@ -1,5 +1,5 @@ import type { DiscordTemplate } from '@discordeno/types' -import type { Bot, User } from '../index.js' +import type { Bot, Template } from '../index.js' export function transformTemplate(bot: Bot, payload: DiscordTemplate): Template { const template = { @@ -18,17 +18,3 @@ export function transformTemplate(bot: Bot, payload: DiscordTemplate): Template return bot.transformers.customizers.template(bot, payload, template) } - -export interface Template { - description?: string | null - isDirty?: boolean - name: string - creatorId: bigint - createdAt: number - code: string - usageCount: number - creator: User - updatedAt: number - sourceGuildId: bigint - serializedSourceGuild: NonNullable -} diff --git a/packages/bot/src/transformers/threadMember.ts b/packages/bot/src/transformers/threadMember.ts index bb1cd11ac..66d79e51d 100644 --- a/packages/bot/src/transformers/threadMember.ts +++ b/packages/bot/src/transformers/threadMember.ts @@ -1,5 +1,5 @@ import type { DiscordThreadMember } from '@discordeno/types' -import type { Bot } from '../index.js' +import type { Bot, ThreadMember, ThreadMemberGuildCreate } from '../index.js' import type { DiscordThreadMemberGuildCreate } from '../typings.js' export function transformThreadMember(bot: Bot, payload: DiscordThreadMember): ThreadMember { @@ -20,14 +20,3 @@ export function transformThreadMemberGuildCreate(bot: Bot, payload: DiscordThrea return bot.transformers.customizers.threadMemberGuildCreate(bot, payload, threadMember) } - -export interface ThreadMember { - id?: bigint - userId?: bigint - flags: number - joinTimestamp: number -} - -export interface ThreadMemberGuildCreate { - joinTimestamp: number -} diff --git a/packages/bot/src/transformers/types.ts b/packages/bot/src/transformers/types.ts new file mode 100644 index 000000000..3d27da602 --- /dev/null +++ b/packages/bot/src/transformers/types.ts @@ -0,0 +1,1651 @@ +import type { + ActivityTypes, + ApplicationCommandOptionTypes, + ApplicationCommandPermissionTypes, + ApplicationCommandTypes, + ApplicationFlags, + AttachmentFlags, + AuditLogEvents, + AutoModerationActionType, + AutoModerationEventTypes, + AutoModerationTriggerTypes, + BigString, + ButtonStyles, + ChannelTypes, + DefaultMessageNotificationLevels, + DiscordApplicationIntegrationType, + DiscordAutoModerationRuleTriggerMetadataPresets, + DiscordEntitlementType, + DiscordGuildOnboardingMode, + DiscordGuildOnboardingPromptType, + DiscordInteractionContextType, + DiscordInviteType, + DiscordOverwrite, + DiscordPollLayoutType, + DiscordSkuType, + DiscordTeamMemberRole, + DiscordTemplateSerializedSourceGuild, + EmbedTypes, + ExplicitContentFilterLevels, + ForumLayout, + GuildNsfwLevel, + IntegrationExpireBehaviors, + InteractionCallbackData, + InteractionTypes, + Locales, + Localization, + MessageActivityTypes, + MessageComponentTypes, + MessageTypes, + MfaLevels, + OAuth2Scope, + OverwriteReadable, + PremiumTiers, + PremiumTypes, + PresenceStatus, + RoleFlags, + ScheduledEventEntityType, + ScheduledEventPrivacyLevel, + ScheduledEventStatus, + SelectOption, + SkuFlags, + SortOrderTypes, + StickerFormatTypes, + StickerTypes, + SystemChannelFlags, + TeamMembershipStates, + TextStyles, + VerificationLevels, + VideoQualityModes, + WebhookTypes, +} from '@discordeno/types' +import type { Collection } from '@discordeno/utils' +import type { + Bot, + ChannelToggles, + EmojiToggles, + GuildFeatureKeys, + GuildToggles, + MemberToggles, + Permissions, + RoleToggles, + ToggleBitfield, + UserToggles, + VoiceStateToggles, +} from '../index.js' + +export interface Activity { + join?: string + flags?: number + applicationId?: bigint + spectate?: string + url?: string + startedAt?: number + endedAt?: number + details?: string + state?: string + emoji?: ActivityEmoji + partyId?: string + partyCurrentSize?: number + partyMaxSize?: number + largeImage?: string + largeText?: string + smallImage?: string + smallText?: string + match?: string + instance?: boolean + buttons?: ActivityButton[] + name: string + type: ActivityTypes + createdAt: number +} + +export interface ActivityEmoji { + id?: bigint + animated?: boolean + name: string +} + +export interface ActivityButton { + url: string + label: string +} + +export interface Application { + flags?: ApplicationFlags + icon?: bigint + rpcOrigins?: string[] + termsOfServiceUrl?: string + privacyPolicyUrl?: string + primarySkuId?: string + slug?: string + coverImage?: bigint + owner?: User + team?: Team + guildId?: bigint + guild?: Guild + id: bigint + name: string + description: string + botPublic: boolean + botRequireCodeGrant: boolean + verifyKey: string + approximateGuildCount?: number + bot?: User + redirectUris?: string[] + interactionsEndpointUrl?: string + integrationTypesConfig?: Partial> +} + +export interface ApplicationIntegrationTypeConfiguration { + /** Install params for each installation context's default in-app authorization link */ + oauth2InstallParams?: ApplicationInstallParams +} + +export interface ApplicationInstallParams { + /** Scopes to add the application to the server with */ + scopes: OAuth2Scope[] + /** Permissions to request for the bot role */ + permissions: bigint +} + +export interface ApplicationCommand { + options?: ApplicationCommandOption[] + description?: string + guildId?: bigint + nameLocalizations?: Record + descriptionLocalizations?: Record + defaultMemberPermissions?: bigint + type?: ApplicationCommandTypes + version?: string + id: bigint + name: string + applicationId: bigint + dmPermission: boolean +} + +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 +} + +export interface ApplicationCommandOptionChoice { + nameLocalizations?: Record + name: string + value: string | number +} + +export interface GuildApplicationCommandPermissions { + id: bigint + guildId: bigint + applicationId: bigint + permissions: ApplicationCommandPermissions[] +} + +export interface ApplicationCommandPermissions { + /** The id of the role or user */ + id: bigint + /** Role or User */ + type: ApplicationCommandPermissionTypes + /** `true` to allow, `false`, to disallow */ + permission: boolean +} + +export interface Attachment { + /** Name of file attached */ + filename: string + /** The title of the file */ + title?: string + /** The attachment's [media type](https://en.wikipedia.org/wiki/Media_type) */ + contentType?: string + /** Size of file in bytes */ + size: number + /** Source url of file */ + url: string + /** A proxied url of file */ + proxyUrl: string + /** Attachment id */ + id: bigint + /** description for the file (max 1024 characters) */ + description?: string + /** Height of file (if image) */ + height?: number + /** Width of file (if image) */ + width?: number + /** whether this attachment is ephemeral. Ephemeral attachments will automatically be removed after a set period of time. Ephemeral attachments on messages are guaranteed to be available as long as the message itself exists. */ + ephemeral?: boolean + /** The duration of the audio file for a voice message */ + duration_secs?: number + /** A base64 encoded bytearray representing a sampled waveform for a voice message */ + waveform?: string + /** Attachment flags combined as a bitfield */ + flags?: AttachmentFlags +} + +export interface AuditLogEntry { + id: bigint + userId?: bigint + reason?: string + changes?: AuditLogChange[] + targetId?: bigint + actionType: AuditLogEvents + options?: OptionalAuditEntryInfo +} + +export interface AuditLogChange { + new?: string | number | bigint | boolean | DiscordOverwrite[] | Partial[] + old?: string | number | bigint | boolean | DiscordOverwrite[] | Partial[] + key: + | 'id' + | 'name' + | 'description' + | 'type' + | 'permissions' + | 'locked' + | 'invitable' + | 'nsfw' + | 'archived' + | 'position' + | 'topic' + | 'bitrate' + | 'default_auto_archive_duration' + | 'auto_archive_duration' + | 'allow' + | 'deny' + | 'channel_id' + | 'deaf' + | 'mute' + | 'status' + | 'nick' + | 'communication_disabled_until' + | 'color' + | 'permission_overwrites' + | 'user_limit' + | 'rate_limit_per_user' + | 'owner_id' + | 'application_id' + | 'hoist' + | 'mentionable' + | 'location' + | 'verification_level' + | 'default_message_notifications' + | 'explicit_content_filter' + | 'preferred_locale' + | 'afk_timeout' + | 'afk_channel_id' + | 'system_channel_id' + | 'widget_enabled' + | 'mfa_level' + | 'vanity_url_code' + | 'icon_hash' + | 'widget_channel_id' + | 'rules_channel_id' + | 'public_updates_channel_id' + | 'code' + | 'region' + | 'privacy_level' + | 'entity_type' + | 'enable_emoticons' + | 'expire_behavior' + | 'expire_grace_period' + | 'uses' + | 'max_uses' + | 'max_age' + | 'temporary' + | 'discovery_splash_hash' + | 'banner_hash' + | 'image_hash' + | 'splash_hash' + | 'inviter_id' + | 'avatar_hash' + | 'command_id' + | 'prune_delete_days' + | '$add' + | '$remove' +} + +export interface OptionalAuditEntryInfo { + id?: bigint + channelId?: bigint + messageId?: bigint + type: number + count: number + deleteMemberDays: number + membersRemoved: number + roleName: string + autoModerationRuleName: string + autoModerationRuleTriggerType: string + integrationType: string +} + +export interface AutoModerationActionExecution { + channelId?: bigint + messageId?: bigint + alertSystemMessageId?: bigint + guildId: bigint + userId: bigint + content: string + action: AutoModerationAction + ruleTriggerType: AutoModerationTriggerTypes + ruleId: bigint + matchedKeyword: string + matchedContent: string +} + +export interface AutoModerationAction { + type: AutoModerationActionType + metadata: AutoModerationActionMetadata +} + +export interface AutoModerationActionMetadata { + customMessage?: string + durationSeconds?: number + channelId?: bigint +} + +export interface AutoModerationRule { + triggerMetadata?: AutoModerationRuleTriggerMetadata + id: bigint + name: string + guildId: bigint + eventType: AutoModerationEventTypes + triggerType: AutoModerationTriggerTypes + enabled: boolean + creatorId: bigint + exemptRoles: bigint[] + exemptChannels: bigint[] + actions: AutoModerationAction[] +} + +export interface AutoModerationRuleTriggerMetadata { + keywordFilter?: string[] + presets?: DiscordAutoModerationRuleTriggerMetadataPresets[] + allowList?: string[] + mentionTotalLimit?: number + regexPatterns: string[] +} + +export interface AvatarDecorationData { + /** the avatar decoration hash */ + asset: bigint + /** id of the avatar decoration's SKU */ + skuId: bigint +} + +export interface Channel { + /** The id of the channel */ + id: bigint + /** The compressed form of all the boolean values on this channel. */ + toggles: ChannelToggles + /** The type of channel */ + type: ChannelTypes + /** The id of the guild */ + guildId?: bigint + /** Sorting position of the channel */ + position?: number + /** The name of the channel (1-100 characters) */ + name?: string + /** The channel topic (0-4096 characters for GUILD_FORUM channels, 0-1024 characters for all others) */ + topic?: string + /** The id of the last message sent in this channel (may not point to an existing or valid message) */ + lastMessageId?: bigint + /** The bitrate (in bits) of the voice or stage channel */ + bitrate?: number + /** The user limit of the voice or stage channel */ + userLimit?: number + /** Amount of seconds a user has to wait before sending another message (0-21600); bots, as well as users with the permission `manage_messages` or `manage_channel`, are unaffected */ + rateLimitPerUser?: number + /** Id of the creator of the thread */ + ownerId?: bigint + /** For guild channels: Id of the parent category for a channel (each parent category can contain up to 50 channels), for threads: id of the text channel this thread was created */ + parentId?: bigint + /** When the last pinned message was pinned. This may be null in events such as GUILD_CREATE when a message is not pinned. */ + lastPinTimestamp?: number + /** Voice region id for the voice or stage channel, automatic when set to null */ + rtcRegion?: string + /** The camera video quality mode of the voice channel, 1 when not present */ + videoQualityMode?: VideoQualityModes + /** An approximate count of messages in a thread, stops counting at 50 */ + messageCount?: number + /** An approximate count of users in a thread, stops counting at 50 */ + memberCount?: number + /** + * Thread-specific fields not needed by other channels. + * + * @internal + * This field is an internal field, subject to breaking changes. + */ + internalThreadMetadata?: InternalChannelThreadMetadata + member?: ThreadMember + /** Default duration for newly created threads, in minutes, to automatically archive the thread after recent activity, can be set to: 60, 1440, 4320, 10080 */ + defaultAutoArchiveDuration?: number + /** computed permissions for the invoking user in the channel, including overwrites, only included when part of the resolved data received on a slash command interaction. This does not include implicit permissions, which may need to be checked separately. */ + permissions?: Permissions + /** The flags of the channel */ + flags?: number + /** + * Explicit permission overwrites for members and roles + * + * @internal + * Use channel.permissionOverwrites. This is for internal use only, and prone to breaking changes. + */ + internalOverwrites?: bigint[] + /** The recipients of a group dm */ + recipients?: User[] + /** Icon hash of the group dm */ + icon?: bigint + /** Application id of the group DM creator if it is bot-created */ + applicationId?: bigint + /** Number of messages ever sent in a thread, it's similar to `message_count` on message creation, but will not decrement the number when a message is deleted */ + totalMessageSent?: number + /** The set of tags that can be used in a `GUILD_FORUM` or a `GUILD_MEDIA` channel */ + availableTags?: ForumTag[] + /** The IDs of the set of tags that have been applied to a thread in a `GUILD_FORUM` or a `GUILD_MEDIA` channel */ + appliedTags?: bigint[] + /** The emoji to show in the add reaction button on a thread in a `GUILD_FORUM` or a `GUILD_MEDIA` channel */ + defaultReactionEmoji?: DefaultReactionEmoji + /** the initial `rateLimitPerUser` to set on newly created threads in a channel. this field is copied to the thread at creation time and does not live update. */ + defaultThreadRateLimitPerUser?: number + /** The default sort order type used to order posts in `GUILD_FORUM` and `GUILD_MEDIA` channels. Defaults to null, which indicates a preferred sort order hasn't been set by a channel admin */ + defaultSortOrder?: SortOrderTypes | null + defaultForumLayout?: ForumLayout + /** Whether the channel is nsfw */ + nsfw: boolean + /** Thread-specific fields not needed by other channels */ + threadMetadata?: ChannelThreadMetadata + /** When a thread is created this will be true on that channel payload for the thread. */ + newlyCreated: boolean + /** When a thread is locked, only users with `MANAGE_THREADS` can unarchive it */ + locked: boolean + /** whether non-moderators can add other non-moderators to a thread; only available on private threads */ + invitable: boolean + /** Whether the thread is archived */ + archived: boolean + /** for group DM channels: whether the channel is managed by an application via the `gdm.join` OAuth2 scope */ + managed: boolean + /** Explicit permission overwrites for members and roles. */ + permissionOverwrites: OverwriteReadable[] +} + +export interface ForumTag { + /** The id of the tag */ + id: bigint + /** The name of the tag (0-20 characters) */ + name: string + /** Whether this tag can only be added to or removed from threads by a member with the MANAGE_THREADS permission */ + moderated: boolean + /** The id of a guild's custom emoji At most one of emoji_id and emoji_name may be set. */ + emojiId: bigint + /** The unicode character of the emoji */ + emojiName: string | null +} + +/** + * @internal + * This is for internal purposes only, and subject to breaking changes + */ +export interface InternalChannelThreadMetadata { + /** Timestamp when the thread's archive status was last changed, used for calculating recent activity */ + archiveTimestamp: number + /** Timestamp when the thread was created; only populated for threads created after 2022-01-09 */ + createTimestamp?: number + /** Duration in minutes to automatically archive the thread after recent activity */ + autoArchiveDuration: 60 | 1440 | 4320 | 10080 +} + +export interface ChannelThreadMetadata { + /** Timestamp when the thread's archive status was last changed, used for calculating recent activity */ + archiveTimestamp?: number + /** Timestamp when the thread was created; only populated for threads created after 2022-01-09 */ + createTimestamp?: number + /** Duration in minutes to automatically archive the thread after recent activity */ + autoArchiveDuration?: 60 | 1440 | 4320 | 10080 + /** When a thread is locked, only users with `MANAGE_THREADS` can unarchive it */ + locked: boolean + /** whether non-moderators can add other non-moderators to a thread; only available on private threads */ + invitable: boolean + /** Whether the thread is archived */ + archived: boolean +} + +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?: Pick, 'id' | 'name' | 'animated'> + /** 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 + /** List of channel types to include in a channel select menu options list */ + channelTypes?: ChannelTypes[] + /** 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[] +} + +export interface Embed { + description?: string + type?: EmbedTypes + url?: string + image?: EmbedImage + video?: EmbedVideo + title?: string + timestamp?: number + color?: number + footer?: EmbedFooter + thumbnail?: EmbedThumbnail + provider?: EmbedProvider + author?: EmbedAuthor + fields?: EmbedField[] +} + +export interface EmbedImage { + proxyUrl?: string + height?: number + width?: number + url: string +} + +export interface EmbedVideo { + url?: string + proxyUrl?: string + height?: number + width?: number +} + +export interface EmbedFooter { + iconUrl?: string + proxyIconUrl?: string + text: string +} + +export interface EmbedThumbnail { + proxyUrl?: string + height?: number + width?: number + url: string +} + +export interface EmbedProvider { + name?: string + url?: string +} + +export interface EmbedAuthor { + url?: string + iconUrl?: string + proxyIconUrl?: string + name: string +} + +export interface EmbedField { + inline?: boolean + name: string + value: string +} + +export interface Emoji { + /** Emoji name (can only be null in reaction emoji objects) */ + name?: string + /** Emoji id */ + id?: bigint + /** Roles allowed to use this emoji */ + roles?: bigint[] + /** User that created this emoji */ + user?: User + /** Whether this emoji must be wrapped in colons */ + requireColons?: boolean + /** Whether this emoji is managed */ + managed?: boolean + /** Whether this emoji is animated */ + animated?: boolean + /** Whether this emoji can be used, may be false due to loss of Server Boosts */ + available?: boolean + toggles: EmojiToggles +} + +export interface DefaultReactionEmoji { + /** The id of a guild's custom emoji */ + emojiId: bigint + /** The unicode character of the emoji */ + emojiName?: string +} + +export interface Entitlement { + /** ID of the entitlement */ + id: bigint + /** ID of the SKU */ + skuId: bigint + /** ID of the user that is granted access to the entitlement's sku */ + userId?: bigint + /** ID of the guild that is granted access to the entitlement's sku */ + guildId?: bigint + /** ID of the parent application */ + applicationId: bigint + /** Type of entitlement */ + type: DiscordEntitlementType + /** Entitlement was deleted */ + deleted: boolean + /** Start date at which the entitlement is valid. Not present when using test entitlements */ + startsAt?: number + /** Date at which the entitlement is no longer valid. Not present when using test entitlements */ + endsAt?: number + /** For consumable items, whether or not the entitlement has been consumed */ + consumed?: boolean +} + +export interface GetGatewayBot { + url: string + shards: number + sessionStartLimit: SessionStartLimit +} + +export interface SessionStartLimit { + total: number + remaining: number + resetAfter: number + maxConcurrency: number +} + +export interface Guild { + /** Guild name (2-100 characters, excluding trailing and leading whitespace) */ + name: string + /** True if the user is the owner of the guild */ + owner?: boolean + /** Afk timeout in seconds */ + afkTimeout: number + /** True if the server widget is enabled */ + widgetEnabled?: boolean + /** Verification level required for the guild */ + verificationLevel: VerificationLevels + /** Default message notifications level */ + defaultMessageNotifications: DefaultMessageNotificationLevels + /** Explicit content filter level */ + explicitContentFilter: ExplicitContentFilterLevels + /** Enabled guild features */ + features: GuildFeatureKeys[] + /** Required MFA level for the guild */ + mfaLevel: MfaLevels + /** System channel flags */ + systemChannelFlags: SystemChannelFlags + /** True if this is considered a large guild */ + large?: boolean + /** True if this guild is unavailable due to an outage */ + unavailable?: boolean + /** Total number of members in this guild */ + memberCount: number + /** The maximum number of presences for the guild (the default value, currently 25000, is in effect when null is returned) */ + maxPresences?: number + /** The maximum number of members for the guild */ + maxMembers?: number + /** The vanity url code for the guild */ + vanityUrlCode?: string + /** The description of a guild */ + description?: string + toggles: GuildToggles + shardId: number + /** Premium tier (Server Boost level) */ + premiumTier: PremiumTiers + /** The number of boosts this guild currently has */ + premiumSubscriptionCount?: number + /** The maximum amount of users in a video channel */ + maxVideoChannelUsers?: number + /** Maximum amount of users in a stage video channel */ + maxStageVideoChannelUsers?: number + /** Approximate number of members in this guild, returned from the GET /guilds/id endpoint when with_counts is true */ + approximateMemberCount?: number + /** Approximate number of non-offline members in this guild, returned from the GET /guilds/id endpoint when with_counts is true */ + approximatePresenceCount?: number + /** Guild NSFW level */ + nsfwLevel: GuildNsfwLevel + /** Whether the guild has the boost progress bar enabled */ + premiumProgressBarEnabled: boolean + /** Guild id */ + id: bigint + /** Icon hash */ + icon?: bigint + /** Icon hash, returned when in the template object */ + iconHash?: bigint + /** Splash hash */ + splash?: bigint + /** Discovery splash hash; only present for guilds with the "DISCOVERABLE" feature */ + discoverySplash?: bigint + /** Id of the owner */ + ownerId: bigint + /** Total permissions for the user in the guild (excludes overwrites and implicit permissions) */ + permissions: bigint + /** Id of afk channel */ + afkChannelId?: bigint + /** The channel id that the widget will generate an invite to, or null if set to no invite */ + widgetChannelId?: bigint + /** Roles in the guild */ + roles: Collection + /** Custom guild emojis */ + emojis: Collection + /** Application id of the guild creator if it is bot-created */ + applicationId?: bigint + /** The id of the channel where guild notices such as welcome messages and boost events are posted */ + systemChannelId?: bigint + /** The id of the channel where community guilds can display rules and/or guidelines */ + rulesChannelId?: bigint + /** When this guild was joined at */ + joinedAt?: number + /** States of members currently in voice channels; lacks the guild_id key */ + voiceStates: Collection + /** Users in the guild */ + members: Collection + /** Channels in the guild */ + channels: Collection + /** All active threads in the guild that the current user has permission to view */ + threads: Collection + /** Presences of the members in the guild, will only include non-offline members if the size is greater than large threshold */ + presences?: PresenceUpdate[] + /** Banner hash */ + banner?: bigint + /** The preferred locale of a Community guild; used in server discovery and notices from Discord; defaults to "en-US" */ + preferredLocale: string + /** The id of the channel where admins and moderators of Community guilds receive notices from Discord */ + publicUpdatesChannelId?: bigint + /** The welcome screen of a Community guild, shown to new members, returned in an Invite's guild object */ + welcomeScreen?: WelcomeScreen + /** Stage instances in the guild */ + stageInstances?: StageInstance[] + /** Custom guild stickers */ + stickers?: Collection + /** The id of the channel where admins and moderators of Community guilds receive safety alerts from Discord */ + safetyAlertsChannelId?: bigint +} + +export interface Integration { + user?: User + enabled?: boolean + syncing?: boolean + roleId?: bigint + enableEmoticons?: boolean + expireBehavior?: IntegrationExpireBehaviors + expireGracePeriod?: number + syncedAt?: number + subscriberCount?: number + revoked?: boolean + application?: IntegrationApplication + id: bigint + name: string + guildId: bigint + type: 'twitch' | 'youtube' | 'discord' + account: IntegrationAccount + scopes: OAuth2Scope[] +} + +export interface IntegrationApplication { + bot?: User + icon?: bigint + id: bigint + name: string + description: string +} + +export interface IntegrationAccount { + id: bigint + name: string +} + +export interface Interaction { + /** The bot object */ + bot: Bot + /** Whether or not this interaction has been responded to. */ + acknowledged: boolean + /** Id of the interaction */ + id: bigint + /** Id of the application this interaction is for */ + applicationId: bigint + /** The type of interaction */ + type: InteractionTypes + /** Guild that the interaction was sent from */ + guild: Guild + /** The guild it was sent from */ + guildId?: bigint + /** The channel it was sent from */ + channel: Partial + /** + * The ID of channel it was sent from + * + * @remarks + * It is recommended that you begin using this channel field to identify the source channel of the interaction as they may deprecate the existing channel_id field in the future. + */ + channelId?: bigint + /** Guild member data for the invoking user, including permissions */ + member?: Member + /** User object for the invoking user, if invoked in a DM */ + user: User + /** A continuation token for responding to the interaction */ + token: string + /** Read-only property, always `1` */ + version: 1 + /** For the message the button was attached to */ + message?: Message + /** the command data payload */ + data?: InteractionData + locale?: string + /** The guild's preferred locale, if invoked in a guild */ + guildLocale?: string + /** The computed permissions for a bot or app in the context of a specific interaction (including channel overwrites) */ + appPermissions: bigint + /** Mapping of installation contexts that the interaction was authorized for to related user or guild IDs. */ + authorizingIntegrationOwners: Partial> + /** Context where the interaction was triggered from */ + context?: DiscordInteractionContextType + /** + * Sends a response to an interaction. + * + * @remarks + * This will send a ChannelMessageWithSource, ApplicationCommandAutocompleteResult or Modal response based on the type of the interaction you are responding to. + * + * If the interaction has been already acknowledged, indicated by {@link Interaction.acknowledged}, it will send a followup message instead. + */ + respond: (response: string | InteractionCallbackData, options?: { isPrivate?: boolean }) => Promise + /** + * Edit the original response of an interaction or a followup if the message id is provided. + * + * @remarks + * This will edit the original interaction response or, if the interaction has not yet been acknowledged and the type of the interaction is MessageComponent it will instead send a UpdateMessage response instead. + */ + edit: (response: string | InteractionCallbackData, messageId?: BigString) => Promise + /** + * Defer the interaction for updating the referenced message at a later time with {@link edit}. + * + * @remarks + * This will send a DeferredUpdateMessage response. + */ + deferEdit: () => Promise + /** + * Defer the interaction for updating the response at a later time with {@link edit}. + * + * @remarks + * This will send a DeferredChannelMessageWithSource response. + */ + defer: (isPrivate?: boolean) => Promise + /** Delete the original interaction response or a followup if the message id is provided. */ + delete: (messageId?: BigString) => Promise +} + +export interface InteractionData { + type?: ApplicationCommandTypes + componentType?: MessageComponentTypes + customId?: string + components?: Component[] + values?: string[] + name: string + resolved?: InteractionDataResolved + options?: InteractionDataOption[] + id?: bigint + targetId?: bigint +} + +export interface InteractionDataResolved { + messages?: Collection + users?: Collection + members?: Collection + roles?: Collection + channels?: Collection + attachments?: Collection +} + +export interface InteractionDataOption { + name: string + type: ApplicationCommandOptionTypes + value?: string | number | boolean + options?: InteractionDataOption[] + focused?: boolean +} + +export interface Invite { + /** The type of invite */ + type: DiscordInviteType + /** The channel the invite is for */ + channelId: bigint + /** The unique invite code */ + code: string + /** The time at which the invite was created */ + createdAt: number + /** The guild of the invite */ + guildId?: bigint + /** The user that created the invite */ + inviter?: User + /** How long the invite is valid for (in seconds) */ + maxAge: number + /** The maximum number of times the invite can be used */ + maxUses: number + /** The type of target for this voice channel invite */ + targetType: number + /** The target user for this invite */ + targetUser: User + /** The embedded application to open for this voice channel embedded application invite */ + targetApplication?: Application + /** Whether or not the invite is temporary (invited users will be kicked on disconnect unless they're assigned a role) */ + temporary: boolean + /** How many times the invite has been used (always will be 0) */ + uses: number + /** Approximate count of online members (only present when target_user is set) */ + approximateMemberCount: number + /** Stage instance data if there is a public Stage instance in the Stage channel this invite is for */ + stageInstance?: InviteStageInstance + /** The expiration date of this invite, returned from the GET /invites/code endpoint when with_expiration is true */ + expiresAt?: number + /** guild scheduled event data */ + guildScheduledEvent?: ScheduledEvent + /** Approximate count of online members (only present when target_user is set) */ + approximatePresenceCount?: number +} + +export interface Member { + /** The user id of the member. */ + id: bigint + /** The compressed form of all the boolean values on this user. */ + toggles?: MemberToggles + /** The guild id where this member is. */ + guildId: bigint + /** The user this guild member represents */ + user?: User + /** This users guild nickname */ + nick?: string + /** The members custom avatar for this server. */ + avatar?: bigint + /** Array of role object ids */ + roles: bigint[] + /** When the user joined the guild */ + joinedAt: number + /** When the user started boosting the guild */ + premiumSince?: number + /** The permissions this member has in the guild. Only present on interaction events. */ + permissions?: Permissions + /** when the user's timeout will expire and the user will be able to communicate in the guild again (set null to remove timeout), null or a time in the past if the user is not timed out */ + communicationDisabledUntil?: number + /** data for the member's guild avatar decoration */ + avatarDecorationData: AvatarDecorationData + /** Whether the user is deafened in voice channels */ + deaf?: boolean + /** Whether the user is muted in voice channels */ + mute?: boolean + /** Whether the user has not yet passed the guild's Membership Screening requirements */ + pending?: boolean + /** Member has left and rejoined the guild */ + didRejoin?: boolean + /** Member has completed onboarding */ + startedOnboarding?: boolean + /** Member is exempt from guild verification requirements */ + bypassesVerification?: boolean + /** Member has started onboarding */ + completedOnboarding?: boolean + /** Guild member flags */ + flags: number +} + +export interface Message { + /** Sent with Rich Presence-related chat embeds */ + activity?: MessageActivity + applicationId?: bigint + /** Any attached files on this message. */ + attachments?: Attachment[] + /** The author of this message (not guaranteed to be a valid user) Note: The author object follows the structure of the user object, but is only a valid user in the case where the message is generated by a user or bot user. If the message is generated by a webhook, the author object corresponds to the webhook's id, username, and avatar. You can tell if a message is generated by a webhook by checking for the webhook_id on the message object. */ + author: User + /** id of the channel the message was sent in */ + channelId: bigint + /** The components related to this message */ + components: Component[] + /** Contents of the message */ + content: string + /** The timestamp in milliseconds when this message was edited last. */ + editedTimestamp?: number + /** Any embedded content */ + embeds?: Embed[] + /** id of the guild the message was sent in Note: For MESSAGE_CREATE and MESSAGE_UPDATE events, the message object may not contain a guild_id or member field since the events are sent directly to the receiving user and the bot who sent the message, rather than being sent through the guild like non-ephemeral messages. */ + guildId?: bigint + /** id of the message */ + id: bigint + /** sent if the message is sent as a result of an interaction */ + interactionMetadata?: MessageInteractionMetadata + /** + * Sent if the message is a response to an Interaction + * + * @deprecated + * Deprecated in favor of {@link interactionMetadata} + */ + interaction?: MessageInteraction + member?: Member + /** Users specifically mentioned in the message Note: The user objects in the mentions array will only have the partial member field present in MESSAGE_CREATE and MESSAGE_UPDATE events from text-based guild channels. */ + mentions?: User[] + /** Channels specifically mentioned in this message Note: Not all channel mentions in a message will appear in mention_channels. Only textual channels that are visible to everyone in a discoverable guild will ever be included. Only crossposted messages (via Channel Following) currently include mention_channels at all. If no mentions in the message meet these requirements, this field will not be sent. */ + mentionedChannelIds?: bigint[] + /** Roles specifically mentioned in this message */ + mentionedRoleIds?: bigint[] + /** Data showing the source of a crossposted channel follow add, pin or reply message */ + messageReference?: MessageReference + nonce?: string | number + /** Reactions on this message. */ + reactions?: Reaction[] + /** Sent if the message contains stickers */ + stickerItems?: Pick[] + /** Type of message */ + type: MessageTypes + /** The thread that was started from this message, includes thread member object */ + thread?: Channel + /** If the message is generated by a webhook, this is the webhook's id */ + webhookId?: bigint + /** A poll! */ + poll?: Poll + /** The call associated with the message */ + call?: MessageCall + /** Holds all the boolean values on this message. */ + bitfield?: ToggleBitfield + /** Whether this message has been published to subscribed channels (via Channel Following) */ + crossposted: boolean + /** Whether this message is only visible to the user who invoked the Interaction */ + ephemeral: boolean + /** Whether this message failed to mention some roles and add their members to the thread */ + failedToMentionSomeRolesInThread: boolean + /** Message flags combined as a bitfield */ + flags?: ToggleBitfield + /** Whether this message has an associated thread, with the same id as the message */ + hasThread: boolean + /** Whether this message originated from a message in another channel (via Channel Following) */ + isCrosspost: boolean + /** Whether this message is an Interaction Response and the bot is "thinking" */ + loading: boolean + /** The ids of the users who were mentioned in this message. */ + mentionedUserIds: bigint[] + /** Whether this message mentions everyone */ + mentionEveryone: boolean + /** Whether this message is pinned */ + pinned: boolean + /** Whether the source message for this crosspost has been deleted (via Channel Following) */ + sourceMessageDeleted: boolean + /** Whether do not include any embeds when serializing this message */ + suppressEmbeds: boolean + /** Whether this message will not trigger push and desktop notifications */ + suppressNotifications: boolean + /** The timestamp in milliseconds when this message was created */ + timestamp: number + /** Whether this was a TTS message. */ + tts: boolean + /** Whether this message came from the urgent message system */ + urgent: boolean +} + +export interface MessageActivity { + /** Type of message activity */ + type: MessageActivityTypes + /** party_id from a Rich Presence event */ + partyId?: string +} + +export interface MessageInteraction { + /** Id of the interaction */ + id: bigint + /** The member who invoked the interaction in the guild */ + member?: Member + /** The name of the ApplicationCommand including the name of the subcommand/subcommand group */ + name: string + /** The type of interaction */ + type: InteractionTypes + /** The user who invoked the interaction */ + user: User +} + +export interface MessageReference { + /** id of the originating message's channel Note: channel_id is optional when creating a reply, but will always be present when receiving an event/response that includes this data model. */ + channelId?: bigint + /** id of the originating message's guild */ + guildId?: bigint + /** id of the originating message */ + messageId?: bigint +} + +export interface MessageInteractionMetadata { + /** Id of the interaction */ + id: bigint + /** The type of interaction */ + type: InteractionTypes + /** User who triggered the interaction */ + user: User + /** IDs for installation context(s) related to an interaction */ + authorizingIntegrationOwners: Partial> + /** ID of the original response message, present only on follow-up messages */ + originalResponseMessageId?: bigint + /** ID of the message that contained interactive component, present only on messages created from component interactions */ + interactedMessageId?: bigint + /** Metadata for the interaction that was used to open the modal, present only on modal submit interactions */ + triggeringInteractionMetadata?: MessageInteractionMetadata +} + +export interface MessageCall { + /** Array of user object ids that participated in the call */ + participants: bigint[] + /** Time when call ended */ + endedTimestamp: number +} + +export interface Reaction { + /** Whether the current user reacted using this emoji */ + me: boolean + /** Whether the current user super-reacted using this emoji */ + meBurst: boolean + /** Times this emoji has been used to react */ + count: number + /** Reaction count details object */ + countDetails: ReactionCountDetails + emoji: Partial + /** HEX colors used for super reaction */ + burstColors: string[] +} + +export interface ReactionCountDetails { + /** Count of super reactions */ + burst: number + /** Count of normal reactions */ + normal: number +} + +export interface GuildOnboarding { + /** ID of the guild this onboarding is part of */ + guildId: bigint + /** Prompts shown during onboarding and in customize community */ + prompts: GuildOnboardingPrompt[] + /** Channel IDs that members get opted into automatically */ + defaultChannelIds: bigint[] + /** Whether onboarding is enabled in the guild */ + enabled: boolean + /** Current mode of onboarding */ + mode: DiscordGuildOnboardingMode +} + +export interface GuildOnboardingPrompt { + /** ID of the prompt */ + id: bigint + /** Type of prompt */ + type: DiscordGuildOnboardingPromptType + /** Options available within the prompt */ + options: GuildOnboardingPromptOption[] + /** Title of the prompt */ + title: string + /** Indicates whether users are limited to selecting one option for the prompt */ + singleSelect: boolean + /** Indicates whether the prompt is required before a user completes the onboarding flow */ + required: boolean + /** Indicates whether the prompt is present in the onboarding flow. If `false`, the prompt will only appear in the Channels & Roles tab */ + inOnboarding: boolean +} + +export interface GuildOnboardingPromptOption { + /** ID of the prompt option */ + id: bigint + /** IDs for channels a member is added to when the option is selected */ + channelIds: bigint[] + /** IDs for roles assigned to a member when the option is selected */ + roleIds: bigint[] + /** Emoji of the option */ + emoji: Emoji + /** Title of the option */ + title: string + /** Description of the option */ + description?: string +} + +export interface Poll { + /** The question of the poll. Only `text` is supported. */ + question: PollMedia + /** Each of the answers available in the poll. There is a maximum of 10 answers per poll. */ + answers: PollAnswer[] + /** + * The time when the poll ends. + * + * @remarks + * `expiry` is marked as nullable to support non-expiring polls in the future, but all polls have an expiry currently. + */ + expiry: number | null + /** Whether a user can select multiple answers */ + allowMultiselect: boolean + /** The layout type of the poll */ + layoutType: DiscordPollLayoutType + /** + * The results of the poll + * + * @remarks + * This value will not be sent by discord under specific conditions where they don't fetch them on their backend. When this value is missing it should be interpreted as "Unknown results" and not as "No results" + * The results may not be totally accurate while the poll has not ended. When it ends discord will re-calculate all the results and set is_finalized to true + */ + results?: PollResult +} + +export interface PollMedia { + /** + * The text of the field + * + * @remarks + * `text` should always be non-null for both questions and answers, but this is subject to changes. + * The maximum length of `text` is 300 for the question, and 55 for any answer. + */ + text?: string + /** + * The emoji of the field + * + * @remarks + * When creating a poll answer with an emoji, one only needs to send either the `id` (custom emoji) or `name` (default emoji) as the only field. + */ + emoji?: Partial +} + +export interface PollAnswer { + /** + * The id of the answer + * + * @remarks + * This id labels each answer. It starts at 1 and goes up sequentially. Discord recommend against depending on this sequence as it is an implementation detail. + */ + answerId: number + /** The data of the answer */ + pollMedia: PollMedia +} + +export interface PollResult { + /** Whether the votes have been precisely counted */ + isFinalized: boolean + /** The counts for each answer */ + answerCounts: PollAnswerCount[] +} + +export interface PollAnswerCount { + /** The {@link PollAnswer.answerId | answerId} */ + id: number + /** The number of votes for this answer */ + count: number + /** Whether the current user voted for this answer */ + meVoted: boolean +} + +export interface PresenceUpdate { + desktop?: string + mobile?: string + web?: string + user: User + guildId: bigint + status: PresenceStatus + activities: Activity[] +} + +export interface Role { + /** Role id */ + id: bigint + /** The guild id where this role is located. */ + guildId: bigint + /** The compressed version of the boolean values on this role. */ + toggles?: RoleToggles + /** If this role is showed separately in the user listing */ + hoist: boolean + /** Permission bit set */ + permissions: Permissions + /** Whether this role is managed by an integration */ + managed: boolean + /** Whether this role is mentionable */ + mentionable: boolean + /** + * Role tags + * + * @internal + * Use role.tags. This is for internal use only, and prone to breaking changes. + */ + internalTags?: InternalRoleTags + icon?: bigint + /** Role name */ + name: string + /** Integer representation of hexadecimal color code */ + color: number + /** Position of this role */ + position: number + /** role unicode emoji */ + unicodeEmoji?: string + /** Role flags combined as a bitfield */ + flags: RoleFlags + /** The tags this role has */ + tags?: RoleTags + premiumSubscriber: boolean + /** Whether this role is available for purchase. */ + availableForPurchase: boolean + /** Whether this is a guild's linked role. */ + guildConnections: boolean +} + +/** + * @internal + * This is for internal purposes only, and subject to breaking changes + */ +export interface InternalRoleTags { + /** The id of the bot this role belongs to */ + botId?: bigint + /** The id of the integration this role belongs to */ + integrationId?: bigint + /** Id of this role's subscription sku and listing. */ + subscriptionListingId?: bigint +} + +export interface RoleTags { + /** The id of the bot this role belongs to */ + botId?: bigint + /** The id of the integration this role belongs to */ + integrationId?: bigint + /** Id of this role's subscription sku and listing. */ + subscriptionListingId?: bigint + /** Whether this role is available for purchase. */ + availableForPurchase?: boolean + /** Whether this is a guild's linked role */ + guildConnections?: boolean + /** Whether this is the guild's premium subscriber role */ + premiumSubscriber?: boolean +} + +export interface ScheduledEvent { + /** the id of the scheduled event */ + id: bigint + /** the guild id which the scheduled event belongs to */ + guildId: bigint + /** the channel id in which the scheduled event will be hosted if specified */ + channelId?: bigint + /** the id of the user that created the scheduled event */ + creatorId?: bigint + /** the name of the scheduled event */ + name: string + /** the description of the scheduled event */ + description?: string + /** the time the scheduled event will start */ + scheduledStartTime: number + /** the time the scheduled event will end if it does end. */ + scheduledEndTime?: number + /** the privacy level of the scheduled event */ + privacyLevel: ScheduledEventPrivacyLevel + /** the status of the scheduled event */ + status: ScheduledEventStatus + /** the type of hosting entity associated with a scheduled event */ + entityType: ScheduledEventEntityType + /** any additional id of the hosting entity associated with event */ + entityId?: bigint + /** the location for the scheduled event */ + location?: string + /** the user that created the scheduled event */ + creator?: User + /** the number of users subscribed to the scheduled event */ + userCount?: number + /** the cover image hash of the scheduled event */ + image?: bigint +} + +export interface Sku { + /** ID of SKU */ + id: bigint + /** Type of SKU */ + type: DiscordSkuType + /** ID of the parent application */ + applicationId: bigint + /** Customer-facing name of your premium offering */ + name: string + /** System-generated URL slug based on the SKU's name */ + slug: string + /** SKU flags combined as a bitfield */ + flags: SkuFlags +} + +export interface StageInstance { + /** The topic of the Stage instance (1-120 characters) */ + topic: string + /** The id of this Stage instance */ + id: bigint + /** The guild id of the associated Stage channel */ + guildId: bigint + /** The id of the associated Stage channel */ + channelId: bigint + /** The id of the scheduled event for this Stage instance */ + guildScheduledEventId?: bigint +} + +export interface InviteStageInstance { + /** The members speaking in the Stage */ + members: Partial[] + /** The number of users in the Stage */ + participantCount: number + /** The number of users speaking in the Stage */ + speakerCount: number + /** The topic of the Stage instance (1-120 characters) */ + topic: string +} + +export interface Sticker { + /** [Id of the sticker](https://discord.com/developers/docs/reference#image-formatting) */ + id: bigint + /** Id of the pack the sticker is from */ + packId?: bigint + /** Name of the sticker */ + name: string + /** Description of the sticker */ + description: string + /** a unicode emoji representing the sticker's expression */ + tags: string + /** [type of sticker](https://discord.com/developers/docs/resources/sticker#sticker-object-sticker-types) */ + type: StickerTypes + /** [Type of sticker format](https://discord.com/developers/docs/resources/sticker#sticker-object-sticker-format-types) */ + formatType: StickerFormatTypes + /** Whether or not the sticker is available */ + available?: boolean + /** Id of the guild that owns this sticker */ + guildId?: bigint + /** The user that uploaded the sticker */ + user?: User + /** A sticker's sort order within a pack */ + sortValue?: number +} + +export interface StickerPack { + coverStickerId?: bigint + bannerAssetId?: bigint + id: bigint + name: string + description: string + stickers: Sticker[] + skuId: bigint +} + +export interface Team { + icon?: bigint + id: bigint + name: string + ownerUserId: bigint + members: TeamMember[] +} + +export interface TeamMember { + membershipState: TeamMembershipStates + teamId: bigint + user: User + role: DiscordTeamMemberRole +} + +export interface Template { + description?: string | null + isDirty?: boolean + name: string + creatorId: bigint + createdAt: number + code: string + usageCount: number + creator: User + updatedAt: number + sourceGuildId: bigint + serializedSourceGuild: DiscordTemplateSerializedSourceGuild +} + +export interface ThreadMember { + id?: bigint + userId?: bigint + flags: number + joinTimestamp: number +} + +export interface ThreadMemberGuildCreate { + joinTimestamp: number +} + +export interface User { + /** Compressed version of all the booleans on a user. */ + toggles?: UserToggles + /** The user's username, not unique across the platform */ + username: string + /** The user's display name, if it is set. For bots, this is the application name */ + globalName?: string + /** The user's chosen language option */ + locale?: string + /** The flags on a user's account */ + flags?: ToggleBitfield + /** The type of Nitro subscription on a user's account */ + premiumType?: PremiumTypes + /** The public flags on a user's account */ + publicFlags?: ToggleBitfield + /** the user's banner color encoded as an integer representation of hexadecimal color code */ + accentColor?: number + /** The user's id */ + id: bigint + /** The user's discord-tag */ + discriminator: string + /** The user's avatar hash */ + avatar?: bigint + /** The user's email */ + email?: string + /** the user's banner, or null if unset */ + banner?: bigint + /** data for the user's avatar decoration */ + avatarDecorationData?: AvatarDecorationData + /** The user tag in the form of username#discriminator */ + tag: string + /** Whether the user belongs to an OAuth2 application */ + bot: boolean + /** Whether the user is an Official Discord System user (part of the urgent message system) */ + system: boolean + /** Whether the user has two factor enabled on their account */ + mfaEnabled: boolean + /** Whether the email on this account has been verified */ + verified: boolean +} + +export interface VoiceRegion { + id: string + name: string + custom: boolean + optimal: boolean + deprecated: boolean +} + +export interface VoiceState { + requestToSpeakTimestamp?: number + channelId?: bigint + guildId: bigint + toggles: VoiceStateToggles + sessionId: string + userId: bigint +} + +export interface Webhook { + /** The type of the webhook */ + type: WebhookTypes + /** The secure token of the webhook (returned for Incoming Webhooks) */ + token?: string + /** The url used for executing the webhook (returned by the webhooks OAuth2 flow) */ + url?: string + /** The id of the webhook */ + id: bigint + /** The guild id this webhook is for */ + guildId?: bigint + /** The channel id this webhook is for */ + channelId?: bigint + /** The user this webhook was created by (not returned when getting a webhook with its token) */ + user?: User + /** The default name of the webhook */ + name?: string + /** The default user avatar hash of the webhook */ + avatar?: bigint + /** The bot/OAuth2 application that created this webhook */ + applicationId?: bigint + /** The guild of the channel that this webhook is following (returned for Channel Follower Webhooks) */ + sourceGuild?: Partial + /** The channel that this webhook is following (returned for Channel Follower Webhooks) */ + sourceChannel?: Partial +} + +export interface WelcomeScreen { + description?: string + welcomeChannels: WelcomeScreenChannel[] +} + +export interface WelcomeScreenChannel { + channelId: bigint + description: string + emojiId?: bigint + emojiName?: string +} + +export interface GuildWidget { + id: bigint + name: string + members: Partial[] + channels: Partial[] + instant_invite: string + presenceCount: number +} + +export interface GuildWidgetSettings { + channelId?: string + enabled: boolean +} diff --git a/packages/bot/src/transformers/user.ts b/packages/bot/src/transformers/user.ts index 3418bcfe9..897794423 100644 --- a/packages/bot/src/transformers/user.ts +++ b/packages/bot/src/transformers/user.ts @@ -1,8 +1,8 @@ -import type { DiscordUser, PremiumTypes } from '@discordeno/types' +import type { DiscordUser } from '@discordeno/types' import { iconHashToBigInt } from '@discordeno/utils' -import { type AvatarDecorationData, type Bot, ToggleBitfield, UserToggles } from '../index.js' +import { type Bot, ToggleBitfield, type User, UserToggles } from '../index.js' -const baseUser: Partial & BaseUser = { +const baseUser = { get tag() { return `${this.username}#${this.discriminator}` }, @@ -18,15 +18,13 @@ const baseUser: Partial & BaseUser = { get verified() { return !!this.toggles?.has('verified') }, -} +} as User export function transformUser(bot: Bot, payload: DiscordUser): User { const user: User = Object.create(baseUser) const props = bot.transformers.desiredProperties.user - if (props.bot || props.system || props.mfaEnabled || props.verified) { - user.toggles = new UserToggles(payload) - } + if (props.toggles) user.toggles = new UserToggles(payload) if (props.flags) user.flags = new ToggleBitfield(payload.flags) if (props.publicFlags) user.publicFlags = new ToggleBitfield(payload.public_flags) if (props.id && payload.id) user.id = bot.transformers.snowflake(payload.id) @@ -44,47 +42,3 @@ export function transformUser(bot: Bot, payload: DiscordUser): User { return bot.transformers.customizers.user(bot, payload, user) } - -export interface BaseUser { - /** The user tag in the form of username#discriminator */ - tag: string - /** Whether the user belongs to an OAuth2 application */ - bot: boolean - /** Whether the user is an Official Discord System user (part of the urgent message system) */ - system: boolean - /** Whether the user has two factor enabled on their account */ - mfaEnabled: boolean - /** Whether the email on this account has been verified */ - verified: boolean -} - -export interface User extends BaseUser { - /** Compressed version of all the booleans on a user. */ - toggles?: UserToggles - /** The user's username, not unique across the platform */ - username: string - /** The user's display name, if it is set. For bots, this is the application name */ - globalName?: string - /** The user's chosen language option */ - locale?: string - /** The flags on a user's account */ - flags?: ToggleBitfield - /** The type of Nitro subscription on a user's account */ - premiumType?: PremiumTypes - /** The public flags on a user's account */ - publicFlags?: ToggleBitfield - /** the user's banner color encoded as an integer representation of hexadecimal color code */ - accentColor?: number - /** The user's id */ - id: bigint - /** The user's discord-tag */ - discriminator: string - /** The user's avatar hash */ - avatar?: bigint - /** The user's email */ - email?: string - /** the user's banner, or null if unset */ - banner?: bigint - /** data for the user's avatar decoration */ - avatarDecorationData?: AvatarDecorationData -} diff --git a/packages/bot/src/transformers/voiceRegion.ts b/packages/bot/src/transformers/voiceRegion.ts index 67e3aee37..69df66b3f 100644 --- a/packages/bot/src/transformers/voiceRegion.ts +++ b/packages/bot/src/transformers/voiceRegion.ts @@ -1,5 +1,5 @@ import type { DiscordVoiceRegion } from '@discordeno/types' -import type { Bot } from '../index.js' +import type { Bot, VoiceRegion } from '../index.js' export function transformVoiceRegion(bot: Bot, payload: DiscordVoiceRegion): VoiceRegion { const voiceRegion = { @@ -12,11 +12,3 @@ export function transformVoiceRegion(bot: Bot, payload: DiscordVoiceRegion): Voi return bot.transformers.customizers.voiceRegion(bot, payload, voiceRegion) } - -export interface VoiceRegion { - id: string - name: string - custom: boolean - optimal: boolean - deprecated: boolean -} diff --git a/packages/bot/src/transformers/voiceState.ts b/packages/bot/src/transformers/voiceState.ts index ac0d8f9aa..d91e049ca 100644 --- a/packages/bot/src/transformers/voiceState.ts +++ b/packages/bot/src/transformers/voiceState.ts @@ -1,5 +1,5 @@ import type { DiscordVoiceState } from '@discordeno/types' -import type { Bot } from '../index.js' +import type { Bot, VoiceState } from '../index.js' import { VoiceStateToggles } from './toggles/voice.js' export function transformVoiceState(bot: Bot, payload: { voiceState: DiscordVoiceState } & { guildId: bigint }): VoiceState { @@ -16,12 +16,3 @@ export function transformVoiceState(bot: Bot, payload: { voiceState: DiscordVoic return bot.transformers.customizers.voiceState(bot, payload.voiceState, voiceState) } - -export interface VoiceState { - requestToSpeakTimestamp?: number - channelId?: bigint - guildId: bigint - toggles: VoiceStateToggles - sessionId: string - userId: bigint -} diff --git a/packages/bot/src/transformers/webhook.ts b/packages/bot/src/transformers/webhook.ts index 0d650c240..0bbfe58c5 100644 --- a/packages/bot/src/transformers/webhook.ts +++ b/packages/bot/src/transformers/webhook.ts @@ -1,5 +1,5 @@ -import type { DiscordWebhook, WebhookTypes } from '@discordeno/types' -import { type Bot, type Channel, type Guild, type User, iconHashToBigInt } from '../index.js' +import type { DiscordWebhook } from '@discordeno/types' +import { type Bot, type Webhook, iconHashToBigInt } from '../index.js' export function transformWebhook(bot: Bot, payload: DiscordWebhook): Webhook { const props = bot.transformers.desiredProperties.webhook @@ -29,31 +29,3 @@ export function transformWebhook(bot: Bot, payload: DiscordWebhook): Webhook { return bot.transformers.customizers.webhook(bot, payload, webhook) } - -export interface Webhook { - /** The type of the webhook */ - type: WebhookTypes - /** The secure token of the webhook (returned for Incoming Webhooks) */ - token?: string - /** The url used for executing the webhook (returned by the webhooks OAuth2 flow) */ - url?: string - - /** The id of the webhook */ - id: bigint - /** The guild id this webhook is for */ - guildId?: bigint - /** The channel id this webhook is for */ - channelId?: bigint - /** The user this webhook was created by (not returned when getting a webhook with its token) */ - user?: User - /** The default name of the webhook */ - name?: string - /** The default user avatar hash of the webhook */ - avatar?: bigint - /** The bot/OAuth2 application that created this webhook */ - applicationId?: bigint - /** The guild of the channel that this webhook is following (returned for Channel Follower Webhooks) */ - sourceGuild?: Partial - /** The channel that this webhook is following (returned for Channel Follower Webhooks) */ - sourceChannel?: Partial -} diff --git a/packages/bot/src/transformers/welcomeScreen.ts b/packages/bot/src/transformers/welcomeScreen.ts index a8aef7849..d2d55b0b9 100644 --- a/packages/bot/src/transformers/welcomeScreen.ts +++ b/packages/bot/src/transformers/welcomeScreen.ts @@ -1,5 +1,5 @@ import type { DiscordWelcomeScreen } from '@discordeno/types' -import type { Bot } from '../index.js' +import type { Bot, WelcomeScreen } from '../index.js' export function transformWelcomeScreen(bot: Bot, payload: DiscordWelcomeScreen): WelcomeScreen { const welcomeScreen = { @@ -14,13 +14,3 @@ export function transformWelcomeScreen(bot: Bot, payload: DiscordWelcomeScreen): return bot.transformers.customizers.welcomeScreen(bot, payload, welcomeScreen) } - -export interface WelcomeScreen { - description?: string - welcomeChannels: Array<{ - channelId: bigint - description: string - emojiId?: bigint - emojiName?: string - }> -} diff --git a/packages/bot/src/transformers/widget.ts b/packages/bot/src/transformers/widget.ts index fe85af4de..b9ad5c2bb 100644 --- a/packages/bot/src/transformers/widget.ts +++ b/packages/bot/src/transformers/widget.ts @@ -1,5 +1,5 @@ import type { DiscordGuildWidget } from '@discordeno/types' -import { type Bot, iconHashToBigInt } from '../index.js' +import { type Bot, type GuildWidget, iconHashToBigInt } from '../index.js' export function transformWidget(bot: Bot, payload: DiscordGuildWidget): GuildWidget { const widget = { @@ -24,23 +24,3 @@ export function transformWidget(bot: Bot, payload: DiscordGuildWidget): GuildWid return bot.transformers.customizers.widget(bot, payload, widget) } - -export interface GuildWidget { - id: bigint - name: string - members: Array<{ - id: bigint - username: string - discriminator: string - avatar?: bigint - status: string - avatarUrl: string - }> - channels: Array<{ - id: bigint - name: string - position: number - }> - instant_invite: string - presenceCount: number -} diff --git a/packages/bot/src/transformers/widgetSettings.ts b/packages/bot/src/transformers/widgetSettings.ts index 5ca558c80..6a1b269ac 100644 --- a/packages/bot/src/transformers/widgetSettings.ts +++ b/packages/bot/src/transformers/widgetSettings.ts @@ -1,5 +1,5 @@ import type { DiscordGuildWidgetSettings } from '@discordeno/types' -import type { Bot } from '../index.js' +import type { Bot, GuildWidgetSettings } from '../index.js' export function transformWidgetSettings(bot: Bot, payload: DiscordGuildWidgetSettings): GuildWidgetSettings { const widget = { @@ -9,8 +9,3 @@ export function transformWidgetSettings(bot: Bot, payload: DiscordGuildWidgetSet return bot.transformers.customizers.widgetSettings(bot, payload, widget) } - -export interface GuildWidgetSettings { - channelId?: string - enabled: boolean -} diff --git a/packages/bot/src/typings.ts b/packages/bot/src/typings.ts index 2e02546f7..8f0325f2f 100644 --- a/packages/bot/src/typings.ts +++ b/packages/bot/src/typings.ts @@ -22,8 +22,7 @@ import { type TextStyles, } from '@discordeno/types' import type * as handlers from './handlers/index.js' -import type { ApplicationCommandOptionChoice } from './transformers/applicationCommandOptionChoice.js' -import type { Embed } from './transformers/embed.js' +import type { ApplicationCommandOptionChoice, Embed } from './transformers/index.js' export function isContextApplicationCommand(command: CreateApplicationCommand): command is CreateContextApplicationCommand { return command.type === ApplicationCommandTypes.Message || command.type === ApplicationCommandTypes.User diff --git a/packages/discordeno/bin/discordeno.js b/packages/discordeno/bin/discordeno.js new file mode 100644 index 000000000..bc92202e8 --- /dev/null +++ b/packages/discordeno/bin/discordeno.js @@ -0,0 +1 @@ +import('../dist/esm/bin/index.js') diff --git a/packages/discordeno/bin/disocrdeno.js b/packages/discordeno/bin/disocrdeno.js deleted file mode 100755 index 7b12c5199..000000000 --- a/packages/discordeno/bin/disocrdeno.js +++ /dev/null @@ -1 +0,0 @@ -import('../dist/bin/index.js') diff --git a/packages/discordeno/package.json b/packages/discordeno/package.json index cb9194e38..e878f3a0a 100644 --- a/packages/discordeno/package.json +++ b/packages/discordeno/package.json @@ -7,7 +7,7 @@ "require": "./dist/cjs/index.cjs", "types": "./dist/types/index.d.ts" }, - "bin": "./bin/disocrdeno.js", + "bin": "./bin/discordeno.js", "types": "./dist/types/index.d.ts", "type": "module", "license": "Apache-2.0", @@ -24,6 +24,7 @@ "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 discordeno", "test:deno-unit": "swc --strip-leading-paths tests --delete-dir-on-start --out-dir denoTestsDist && node ../../scripts/fixDenoTestExtension.js && deno test -A --import-map ../../denoImportMap.json denoTestsDist", + "test:bun-unit": "node ../../scripts/fixBunTestExtension.js && bun test bunTestsDist", "test:unit:watch": "mocha --no-warnings --watch --parallel 'tests/**/*.spec.ts'", "test:type": "tsc --noEmit", "test:test-type": "tsc --project tests/tsconfig.json" @@ -34,7 +35,9 @@ "@discordeno/rest": "19.0.0-alpha.1", "@discordeno/types": "19.0.0-beta.1", "@discordeno/utils": "19.0.0-beta.1", - "commander": "^12.1.0" + "commander": "^12.1.0", + "find-up": "^7.0.0", + "typescript": "^5.5.3" }, "devDependencies": { "@biomejs/biome": "^1.8.0", @@ -49,7 +52,6 @@ "mocha": "^10.5.1", "sinon": "^18.0.0", "ts-node": "^10.9.2", - "tsconfig": "*", - "typescript": "^5.5.3" + "tsconfig": "*" } } diff --git a/packages/discordeno/src/bin/config.ts b/packages/discordeno/src/bin/config.ts new file mode 100644 index 000000000..fdd4aa4fc --- /dev/null +++ b/packages/discordeno/src/bin/config.ts @@ -0,0 +1,88 @@ +import { unlink, writeFile } from 'node:fs/promises' +import { dirname } from 'node:path' +import { pathToFileURL } from 'node:url' +import { type TransformersDesiredProprieties, createDesiredProprietiesObject, gray } from '@discordeno/bot' +import type { RecursivePartial } from '@discordeno/types' +import { findUp } from 'find-up' +import ts from 'typescript' + +export enum DesiredProprietiesBehavior { + Remove, + TypeAsNever, +} + +export const typescriptOptions: ts.CompilerOptions = { + target: ts.ScriptTarget.ES2022, + module: ts.ModuleKind.Node16, + moduleResolution: ts.ModuleResolutionKind.Node16, + skipLibCheck: true, + skipDefaultLibCheck: true, + strict: true, +} + +export function defineConfig(config: RecursivePartial): DiscordenoConfig { + return { + desiredProperties: { + behavior: config.desiredProperties?.behavior ?? DesiredProprietiesBehavior.TypeAsNever, + properties: createDesiredProprietiesObject(config.desiredProperties?.properties ?? {}), + }, + } +} + +export async function findConfig(path?: string): Promise { + const fileToSearch = path ?? ['discordeno.config.js', 'discordeno.config.mjs', 'discordeno.config.ts', 'discordeno.config.mts'] + + const file = await findUp(fileToSearch, { allowSymlinks: true, type: 'file' }) + + if (!file) { + throw new Error('Could not find the config file, please pass the config file explicitly') + } + + console.log(gray(`Found config file at: ${file}`)) + + const module = await importConfig(file) + const config = module.default + + if (!config || typeof config !== 'object') { + throw new Error("The config could not be found or it isn't an object") + } + + return config +} + +async function importConfig(file: string) { + if (!file.endsWith('.ts') && !file.endsWith('.mts')) { + // We need to convert to a file:// url to prevent a nodejs error on Windows + return import(pathToFileURL(file).href) + } + + // for .ts files we need to build them, write them to disk (for relative imports) and then remove them + + const fileName = `${dirname(file)}/discordeno-${Date.now()}.config.mjs` + + try { + await writeFile(fileName, buildConfig(file)) + + // We need to convert to a file:// url to prevent a nodejs error on Windows + return await import(pathToFileURL(fileName).href) + } finally { + await unlink(fileName) + } +} + +function buildConfig(path: string) { + const createdFiles: Record = {} + + const program = ts.createProgram([path], typescriptOptions) + program.emit(undefined, (file, text) => (createdFiles[file] = text)) + + const outFileName = path.replaceAll('\\', '/').replace(/\.m?[tj]s/i, '.js') + return createdFiles[outFileName] +} + +export interface DiscordenoConfig { + desiredProperties: { + behavior: DesiredProprietiesBehavior + properties: RecursivePartial + } +} diff --git a/packages/discordeno/src/bin/generate/desiredProperty.ts b/packages/discordeno/src/bin/generate/desiredProperty.ts new file mode 100644 index 000000000..6c4817f55 --- /dev/null +++ b/packages/discordeno/src/bin/generate/desiredProperty.ts @@ -0,0 +1,115 @@ +import type { DiscordenoConfig } from '../config.js' + +/** Mapping to all the dependencies a specific getter has */ +const computedDesiredProprieties = { + channel: { + archived: ['toggles'], + invitable: ['toggles'], + locked: ['toggles'], + nsfw: ['toggles'], + newlyCreated: ['toggles'], + managed: ['toggles'], + threadMetadata: ['toggles', 'archiveTimestamp', 'createTimestamp', 'autoArchiveDuration'], + }, + guild: { + threads: ['channels'], + features: ['toggles'], + }, + interaction: { + respond: ['type', 'token', 'id'], + edit: ['type', 'token', 'id'], + deferEdit: ['type', 'token', 'id'], + defer: ['type', 'token', 'id'], + delete: ['type', 'token'], + }, + member: { + deaf: ['toggles'], + mute: ['toggles'], + pending: ['toggles'], + flags: ['toggles'], + didRejoin: ['toggles'], + startedOnboarding: ['toggles'], + bypassesVerification: ['toggles'], + completedOnboarding: ['toggles'], + }, + message: { + crossposted: ['flags'], + ephemeral: ['flags'], + failedToMentionSomeRolesInThread: ['flags'], + hasThread: ['flags'], + isCrosspost: ['flags'], + loading: ['flags'], + mentionedUserIds: ['mentions'], + mentionEveryone: ['bitfield'], + pinned: ['bitfield'], + sourceMessageDeleted: ['flags'], + suppressEmbeds: ['flags'], + suppressNotifications: ['flags'], + timestamp: ['id'], + tts: ['bitfield'], + urgent: ['flags'], + }, + role: { + tags: ['tags', 'toggles'], + hoist: ['toggles'], + managed: ['toggles'], + mentionable: ['toggles'], + premiumSubscriber: ['toggles'], + availableForPurchase: ['toggles'], + guildConnections: ['toggles'], + }, + user: { + tag: ['username', 'discriminator'], + bot: ['toggles'], + system: ['toggles'], + mfaEnabled: ['toggles'], + verified: ['toggles'], + }, +} + +export function isPropertyDesired(config: DiscordenoConfig, interfaceName: string, memberName: string): boolean { + const desiredProperties = config.desiredProperties.properties + + const name = pascalCaseToCamelCase(interfaceName) + + const interfaceProps = desiredProperties[name as keyof typeof desiredProperties] + const computedProps = computedDesiredProprieties[name as keyof typeof computedDesiredProprieties] + + // This interface does not support desired proprieties, so we include them + if (!interfaceProps) { + return true + } + + const isPropDesired = interfaceProps[memberName as keyof typeof interfaceProps] ?? false + + // If this interface has some computed props, and this member is one of the ones that is in fact computed, check it's dependencies + if (computedProps) { + const dependencies: string[] = computedProps[memberName as keyof typeof computedProps] + + if (dependencies) { + return dependencies.every((x) => { + // To avoid an infinite loop we need to check that we don't call isPropertyDesired on this same member + if (x === memberName) return isPropDesired + + return isPropertyDesired(config, interfaceName, x) + }) + } + } + + return isPropDesired +} + +export function getPropertyDependencies(interfaceName: string, memberName: string): string[] | undefined { + const name = pascalCaseToCamelCase(interfaceName) + const computedProps = computedDesiredProprieties[name as keyof typeof computedDesiredProprieties] + + if (!computedProps) return undefined + + return computedProps[memberName as keyof typeof computedProps] +} + +function pascalCaseToCamelCase(str: string) { + if (str.length === 0) return str + + return `${str[0].toLowerCase()}${str.slice(1)}` +} diff --git a/packages/discordeno/src/bin/generate/emitter.ts b/packages/discordeno/src/bin/generate/emitter.ts new file mode 100644 index 000000000..4546342f9 --- /dev/null +++ b/packages/discordeno/src/bin/generate/emitter.ts @@ -0,0 +1,55 @@ +import type { WriteStream } from 'node:fs' +import type ts from 'typescript' + +export function writeInterfaceMember(stream: WriteStream, name: string, type: string, optional: boolean) { + stream.write(` ${name}${optional ? '?' : ''}: ${type}\n`) +} + +export function writeJSDoc(stream: WriteStream, docs: ts.SymbolDisplayPart[], jsDocTags: ts.JSDocTagInfo[], ident = ''): void { + const withDocs = docs.length > 0 + const withJSdoc = jsDocTags.length > 0 + + if (!withDocs && !withJSdoc) return + + stream.write(`${ident}/**`) + + if (withDocs && withJSdoc) { + stream.write(`\n${ident} *`) + } + + if (withDocs) { + writeSymbolDisplayParts(stream, docs, ident) + } + + for (const jsDoc of jsDocTags) { + if (withDocs) { + stream.write(`\n${ident} *`) + } + + stream.write(`\n${ident} *`) + stream.write(` @${jsDoc.name}\n${ident} *`) + + if (jsDoc.text) { + writeSymbolDisplayParts(stream, jsDoc.text, ident) + } + } + + if (withJSdoc) { + stream.write(`\n${ident}`) + } + + stream.write(' */\n') +} + +function writeSymbolDisplayParts(stream: WriteStream, documentation: ts.SymbolDisplayPart[], ident: string): void { + const docs = documentation.reduce((acc, cur) => `${acc}${cur.kind === 'linkText' ? ' | ' : ''}${cur.text}`, '') + const splitted = docs.split('\n') + + stream.write(' ') + stream.write(splitted[0]) + + for (const text of splitted.slice(1)) { + stream.write(`\n${ident} * `) + stream.write(text) + } +} diff --git a/packages/discordeno/src/bin/generate/typescript.ts b/packages/discordeno/src/bin/generate/typescript.ts new file mode 100644 index 000000000..120e57ad4 --- /dev/null +++ b/packages/discordeno/src/bin/generate/typescript.ts @@ -0,0 +1,123 @@ +import assert from 'node:assert' +import { type WriteStream, createWriteStream } from 'node:fs' +import ts from 'typescript' +import { DesiredProprietiesBehavior, type DiscordenoConfig, typescriptOptions } from '../config.js' +import { getPropertyDependencies, isPropertyDesired } from './desiredProperty.js' +import { writeInterfaceMember, writeJSDoc } from './emitter.js' + +export const autoGeneratedNote = '// \n' + +export function generateNewFile(config: DiscordenoConfig, fileName: string, outFile: string) { + const program = ts.createProgram([fileName], typescriptOptions) + + // The type checker will give us find more about symbols + const checker = program.getTypeChecker() + const sourceFile = program.getSourceFile(fileName) + + if (!sourceFile) { + throw new Error('Cannot process a undefined file') + } + + const stream = createWriteStream(outFile, 'utf-8') + stream.write(autoGeneratedNote) + + ts.forEachChild(sourceFile, (node) => processChild(stream, config, checker, node)) +} + +function processChild(writeStream: WriteStream, config: DiscordenoConfig, checker: ts.TypeChecker, node: ts.Node): void { + if (ts.isImportDeclaration(node)) { + processImportNode(node, writeStream) + return + } + + if (ts.isInterfaceDeclaration(node)) { + processInterfaceDeclarationNode(node, config, checker, writeStream) + return + } +} + +function processInterfaceDeclarationNode(node: ts.InterfaceDeclaration, config: DiscordenoConfig, checker: ts.TypeChecker, writeStream: WriteStream) { + const symbol = checker.getSymbolAtLocation(node.name) + if (!symbol) return + + assert(symbol.members) + + const interfaceName = symbol.getName() + + writeStream.write('\n') + writeJSDoc(writeStream, symbol.getDocumentationComment(checker), symbol.getJsDocTags(checker)) + writeStream.write(`export interface ${interfaceName} {\n`) + + // Generate the interface in the output file + for (const member of symbol.members.values()) { + const memberName = member.getName() + const valueDeclaration = member.valueDeclaration + assert(valueDeclaration) + + const valueDeclarationChildren = valueDeclaration.getChildren() + const typeNode = valueDeclarationChildren.find((x) => ts.isTypeNode(x)) + assert(typeNode) + + // Since we are getting the type directly from the sourceFile it may have a trailing space, so we remove them + const typeText = typeNode.getFullText().trim() + const jsDoc = member.getJsDocTags(checker) + const docs = member.getDocumentationComment(checker) + const isOptional = !!(member.getFlags() & ts.SymbolFlags.Optional) + const isInternal = !!jsDoc.find((x) => x.name === 'internal') + + // If the propriety is internal then we don't want to apply the desired propriety logic to it + if (isInternal || isPropertyDesired(config, interfaceName, memberName)) { + writeJSDoc(writeStream, docs, jsDoc, ' ') + writeInterfaceMember(writeStream, memberName, typeText, isOptional) + + continue + } + + // The property is undesired + handleUndesiredProperty(writeStream, config, docs, jsDoc, interfaceName, memberName, typeText, isOptional) + } + + writeStream.write('}\n') +} + +function processImportNode(node: ts.ImportDeclaration, writeStream: WriteStream) { + let importText = node.getFullText().trim() + + // We manually add the newline afterwards, so we need to remove it from here + if (importText.startsWith('\n')) { + importText = importText.substring(1) + } + + writeStream.write(importText) + writeStream.write('\n') +} + +function handleUndesiredProperty( + stream: WriteStream, + config: DiscordenoConfig, + docs: ts.SymbolDisplayPart[], + jsDoc: ts.JSDocTagInfo[], + interfaceName: string, + memberName: string, + typeText: string, + isOptional: boolean, +) { + if (config.desiredProperties.behavior === DesiredProprietiesBehavior.Remove) return + + const dependencies = getPropertyDependencies(interfaceName, memberName) + + const additionalJsDocTag: ts.JSDocTagInfo = { + name: 'remarks', + text: [ + { + kind: 'text', + text: `This property is not desired according to your Desired Properties configuration.\n\nOriginal type: ${typeText}${dependencies ? `\n\nThis value requires other values to be enabled, those are: ${dependencies.join(', ')}` : ''}`, + }, + ], + } + + jsDoc.push(additionalJsDocTag) + + writeJSDoc(stream, docs, jsDoc, ' ') + writeInterfaceMember(stream, memberName, 'never', isOptional) +} diff --git a/packages/discordeno/src/bin/index.ts b/packages/discordeno/src/bin/index.ts index 39d8f68f2..ab3835257 100644 --- a/packages/discordeno/src/bin/index.ts +++ b/packages/discordeno/src/bin/index.ts @@ -1,4 +1,9 @@ +import { readFile, rename, stat } from 'node:fs/promises' import { Command } from 'commander' +import { findUp } from 'find-up' +import { findConfig } from './config.js' +import { autoGeneratedNote, generateNewFile } from './generate/typescript.js' + const program = new Command() program.name('discordeno').description('CLI to discordeno utilities').version('0.1.0') @@ -6,6 +11,42 @@ program.name('discordeno').description('CLI to discordeno utilities').version('0 program .command('generate') .description('Generate types/schema for discordeno') - .action(() => {}) + .option('-c, --config [path]', 'Path to the config file') + .action(async (options) => { + const config = await findConfig(options.config) + + const typesFile = await findUp('node_modules/@discordeno/bot/dist/types/transformers/types.d.ts', { allowSymlinks: true, type: 'file' }) + + if (!typesFile) { + throw new Error('Could not find @discordeno/bot transformer types file.') + } + + // We use a .old file to preserve the original file in case we need it in the future + // The reason for this is because when we write the updated .d.ts file we may lose some type information, so we still need the original file + // However if a user updates the package version we want to use the updated version, so for this reason we check for "// " at the beginning of the file + + const oldTypesFile = typesFile.replace('.d.ts', '.old.d.ts') + + const typesFileContent = await readFile(typesFile, 'utf-8') + const startFile = typesFileContent.slice(0, autoGeneratedNote.length) + + // If we found that the current types.d.ts file has been auto generated then use the .old one + const usingOldFile = startFile === autoGeneratedNote + + const fileToUse = usingOldFile ? oldTypesFile : typesFile + const fileToUseStat = await stat(fileToUse).catch(() => null) + + // If somehow the file we decided to use does not exist we error out + if (!fileToUseStat) { + throw new Error('Could not find a valid file to use') + } + + // If we are using the .d.ts file rename it to .old.d.ts so we can use it a later point + if (!usingOldFile) { + await rename(typesFile, oldTypesFile) + } + + generateNewFile(config, oldTypesFile, typesFile) + }) program.parse() diff --git a/packages/discordeno/src/index.ts b/packages/discordeno/src/index.ts index 32cd6dc65..57ed04717 100644 --- a/packages/discordeno/src/index.ts +++ b/packages/discordeno/src/index.ts @@ -1 +1,2 @@ export * from '@discordeno/bot' +export * from './bin/config.js' diff --git a/packages/discordeno/tests/generate.spec.ts b/packages/discordeno/tests/generate.spec.ts new file mode 100644 index 000000000..c1dd735ad --- /dev/null +++ b/packages/discordeno/tests/generate.spec.ts @@ -0,0 +1,91 @@ +import { expect } from 'chai' +import { findUp } from 'find-up' +import { describe, it } from 'mocha' +import ts from 'typescript' +import { typescriptOptions } from '../src/bin/config.js' +import { getPropertyDependencies, isPropertyDesired } from '../src/bin/generate/desiredProperty.js' +import { defineConfig } from '../src/index.js' + +describe('discordeno generate', () => { + it('will emit without errors', async function () { + // Mocha will crash if this takes more then 2s + // Deno does not have the timeout function + // Bun does not give a this object at all + if (this?.timeout) { + // we set the timeout to 20s, typescript can be slow at doing the entire type checking + this.timeout(20_000) + } + + const typesFile = await findUp('packages/bot/dist/types/transformers/types.d.ts', { + allowSymlinks: true, + }) + + expect(typesFile).to.exist + + if (!typesFile) { + throw new Error('Transformers types file not found!') + } + + const program = ts.createProgram([typesFile], { + ...typescriptOptions, + noEmit: true, + }) + + // Check if typescript is producing type errors for the program + const emitResult = program.emit() + const allDiagnostics = ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics) + + expect(allDiagnostics).to.be.an('array').that.is.empty + }) + + it('can get propriety dependencies', () => { + const deps = getPropertyDependencies('member', 'mute') + + expect(deps).to.have.members(['toggles']) + }) + + it('can get desired status for a prop', () => { + const config = defineConfig({ + desiredProperties: { + properties: { + channel: { + id: true, + }, + }, + }, + }) + + // desired + const idProp = isPropertyDesired(config, 'channel', 'id') + expect(idProp).to.be.equal(true) + + // not desired + const nameProp = isPropertyDesired(config, 'channel', 'name') + expect(nameProp).to.be.equal(false) + }) + + it('can get computed desired status for a prop', () => { + const config = defineConfig({ + desiredProperties: { + properties: { + interaction: { + type: true, + token: true, + }, + }, + }, + }) + + // missing all deps + const threadMetadata = isPropertyDesired(config, 'channel', 'threadMetadata') + expect(threadMetadata).to.be.equal(false) + + // missing one dep + const respond = isPropertyDesired(config, 'interaction', 'respond') + expect(respond).to.be.equal(false) + + // having all deps + const interactionDelete = isPropertyDesired(config, 'interaction', 'delete') + expect(interactionDelete).to.be.equal(true) + }) +}) diff --git a/packages/rest/src/types.ts b/packages/rest/src/types.ts index 21f0c9d1c..f8a3e4c57 100644 --- a/packages/rest/src/types.ts +++ b/packages/rest/src/types.ts @@ -1,7 +1,6 @@ import type { AddDmRecipientOptions, AddGuildMemberOptions, - ApplicationCommandPermissions, AtLeastOne, BeginGuildPrune, BigString, @@ -10,6 +9,7 @@ import type { CamelizedDiscordActiveThreads, CamelizedDiscordApplication, CamelizedDiscordApplicationCommand, + CamelizedDiscordApplicationCommandPermissions, CamelizedDiscordApplicationRoleConnection, CamelizedDiscordArchivedThreads, CamelizedDiscordAuditLog, @@ -1013,7 +1013,7 @@ export interface RestManager { guildId: BigString, commandId: BigString, bearerToken: string, - options: ApplicationCommandPermissions[], + options: CamelizedDiscordApplicationCommandPermissions[], ) => Promise /** * Edits an automod rule. diff --git a/packages/tsconfig/base.json b/packages/tsconfig/base.json index 23dc3f1d7..2777b0999 100644 --- a/packages/tsconfig/base.json +++ b/packages/tsconfig/base.json @@ -2,8 +2,8 @@ "$schema": "https://json.schemastore.org/tsconfig", "display": "Default", "compilerOptions": { - "target": "es2022", - "module": "es2022", + "target": "ES2022", + "module": "Node16", "rootDir": "${configDir}/src", "outDir": "${configDir}/dist", "tsBuildInfoFile": "${configDir}/dist/.tsbuildinfo", @@ -14,7 +14,7 @@ "forceConsistentCasingInFileNames": true, "inlineSources": false, "isolatedModules": true, - "moduleResolution": "node", + "moduleResolution": "Node16", "noUnusedLocals": false, "noUnusedParameters": false, "preserveWatchOutput": true, diff --git a/packages/types/src/discord.ts b/packages/types/src/discord.ts index c5fb4ceb2..ec5a99b55 100644 --- a/packages/types/src/discord.ts +++ b/packages/types/src/discord.ts @@ -2836,31 +2836,34 @@ export interface DiscordTemplate { /** The Id of the guild this template is based on */ source_guild_id: string /** The guild snapshot this template contains */ - serialized_source_guild: Omit< - PickPartial< - DiscordGuild, - | 'name' - | 'description' - | 'verification_level' - | 'default_message_notifications' - | 'explicit_content_filter' - | 'preferred_locale' - | 'afk_timeout' - | 'channels' - | 'afk_channel_id' - | 'system_channel_id' - | 'system_channel_flags' - >, - 'roles' - > & { - roles: Array< - Omit, 'id'> & { id: number } - > - } - /** Whether the template has un-synced changes */ + serialized_source_guild: DiscordTemplateSerializedSourceGuild is_dirty: boolean | null } +export type DiscordTemplateSerializedSourceGuild = Omit< + PickPartial< + DiscordGuild, + | 'name' + | 'description' + | 'verification_level' + | 'default_message_notifications' + | 'explicit_content_filter' + | 'preferred_locale' + | 'afk_timeout' + | 'channels' + | 'afk_channel_id' + | 'system_channel_id' + | 'system_channel_flags' + >, + 'roles' +> & { + roles: Array< + Omit, 'id'> & { + id: number + } + > +} + /** https://discord.com/developers/docs/topics/gateway#guild-member-add */ export interface DiscordGuildMemberAdd extends DiscordMemberWithUser { /** id of the guild */ @@ -3385,7 +3388,7 @@ export interface DiscordGuildOnboardingPromptOption { /** Title of the option */ title: string /** Description of the option */ - description: string | undefined + description: string | null } /** https://discord.com/developers/docs/resources/guild#guild-onboarding-object-prompt-types */ diff --git a/packages/types/src/discordeno.ts b/packages/types/src/discordeno.ts index 845985e21..9f46b08b5 100644 --- a/packages/types/src/discordeno.ts +++ b/packages/types/src/discordeno.ts @@ -23,7 +23,6 @@ import type { } from './discord.js' import type { AllowedMentionsTypes, - ApplicationCommandPermissionTypes, ApplicationCommandTypes, ApplicationFlags, AuditLogEvents, @@ -1167,16 +1166,6 @@ export interface EditMessage { components?: MessageComponents } -/** https://discord.com/developers/docs/interactions/application-commands#edit-application-command-permissions */ -export interface ApplicationCommandPermissions { - /** The id of the role or user */ - id: string - /** Role or User */ - type: ApplicationCommandPermissionTypes - /** `true` to allow, `false`, to disallow */ - permission: boolean -} - /** Additional proprieties for https://discord.com/developers/docs/interactions/application-commands#get-guild-application-command-permissions and https://discord.com/developers/docs/interactions/application-commands#get-guild-application-command-permissions */ export interface GetApplicationCommandPermissionOptions { /** Access token of the user. Requires the `applications.commands.permissions.update` scope */ diff --git a/packages/types/src/shared.ts b/packages/types/src/shared.ts index b2acec17b..e2da1cb3d 100644 --- a/packages/types/src/shared.ts +++ b/packages/types/src/shared.ts @@ -1162,3 +1162,5 @@ export type Snakelize = T extends any[] : T export type PickPartial = { [P in keyof T]?: T[P] | undefined } & { [P in K]: T[P] } + +export type RecursivePartial = T extends object ? { [K in keyof T]?: RecursivePartial } : Partial diff --git a/scripts/fixDenoTestExtension.js b/scripts/fixDenoTestExtension.js index bce37bfee..98d1aeef1 100644 --- a/scripts/fixDenoTestExtension.js +++ b/scripts/fixDenoTestExtension.js @@ -14,7 +14,6 @@ for await (const dir of dirs) { `denoTestsDist${dir}/${file.slice(-8) === '.spec.js' ? `${file.slice(0, -7)}test.js` : file}`, content .replace(/src\//g, 'dist/esm/') - .replace(/\.ts/g, '.js') .replace(/describe\.skip/g, 'describe.ignore') .replace(/it\.skip/g, 'it.ignore'), ) diff --git a/turbo.json b/turbo.json index 307dfe912..2935773ec 100644 --- a/turbo.json +++ b/turbo.json @@ -14,7 +14,7 @@ "outputs": ["coverage/**"] }, "test:unit": { - "dependsOn": ["^build"], + "dependsOn": ["^build", "build", "build:type"], "outputs": ["coverage/**"] }, "test:integration": { @@ -25,11 +25,11 @@ "dependsOn": ["^build:type"] }, "test:deno-unit": { - "dependsOn": ["build", "^build"], + "dependsOn": ["^build", "build", "build:type"], "outputs": ["denoTestsDist/**"] }, "test:bun-unit": { - "dependsOn": ["^build"], + "dependsOn": ["^build", "build", "build:type"], "outputs": ["bunTestsDist/**"] }, "test:e2e": { diff --git a/yarn.lock b/yarn.lock index 84396c624..8a669c6b1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1524,6 +1524,7 @@ __metadata: dependencies: "@biomejs/biome": "npm:^1.8.0" chokidar-cli: "npm:^3.0.0" + discordeno: "npm:19.0.0-alpha.1" husky: "npm:^9.0.11" lint-staged: "npm:^15.2.7" turbo: "npm:^2.0.6" @@ -1533,7 +1534,7 @@ __metadata: languageName: unknown linkType: soft -"discordeno@workspace:packages/discordeno": +"discordeno@npm:19.0.0-alpha.1, discordeno@workspace:packages/discordeno": version: 0.0.0-use.local resolution: "discordeno@workspace:packages/discordeno" dependencies: @@ -1552,13 +1553,14 @@ __metadata: c8: "npm:^9.1.0" chai: "npm:^5.1.1" commander: "npm:^12.1.0" + find-up: "npm:^7.0.0" mocha: "npm:^10.5.1" sinon: "npm:^18.0.0" ts-node: "npm:^10.9.2" tsconfig: "npm:*" typescript: "npm:^5.5.3" bin: - discordeno: ./bin/disocrdeno.js + discordeno: ./bin/discordeno.js languageName: unknown linkType: soft @@ -1813,6 +1815,17 @@ __metadata: languageName: node linkType: hard +"find-up@npm:^7.0.0": + version: 7.0.0 + resolution: "find-up@npm:7.0.0" + dependencies: + locate-path: "npm:^7.2.0" + path-exists: "npm:^5.0.0" + unicorn-magic: "npm:^0.1.0" + checksum: 7e6b08fbc05a10677e25e74bb0a020054a86b31d1806c5e6a9e32e75472bbf177210bc16e5f97453be8bda7ae2e3d97669dbb2901f8c30b39ce53929cbea6746 + languageName: node + linkType: hard + "find-versions@npm:^5.0.0": version: 5.1.0 resolution: "find-versions@npm:5.1.0" @@ -2426,6 +2439,15 @@ __metadata: languageName: node linkType: hard +"locate-path@npm:^7.2.0": + version: 7.2.0 + resolution: "locate-path@npm:7.2.0" + dependencies: + p-locate: "npm:^6.0.0" + checksum: 1c6d269d4efec555937081be964e8a9b4a136319c79ca1d45ac6382212a8466113c75bd89e44521ca8ecd1c47fb08523b56eee5c0712bc7d14fec5f729deeb42 + languageName: node + linkType: hard + "lodash.debounce@npm:^4.0.8": version: 4.0.8 resolution: "lodash.debounce@npm:4.0.8" @@ -3046,6 +3068,15 @@ __metadata: languageName: node linkType: hard +"p-limit@npm:^4.0.0": + version: 4.0.0 + resolution: "p-limit@npm:4.0.0" + dependencies: + yocto-queue: "npm:^1.0.0" + checksum: 01d9d70695187788f984226e16c903475ec6a947ee7b21948d6f597bed788e3112cc7ec2e171c1d37125057a5f45f3da21d8653e04a3a793589e12e9e80e756b + languageName: node + linkType: hard + "p-locate@npm:^3.0.0": version: 3.0.0 resolution: "p-locate@npm:3.0.0" @@ -3064,6 +3095,15 @@ __metadata: languageName: node linkType: hard +"p-locate@npm:^6.0.0": + version: 6.0.0 + resolution: "p-locate@npm:6.0.0" + dependencies: + p-limit: "npm:^4.0.0" + checksum: 2bfe5234efa5e7a4e74b30a5479a193fdd9236f8f6b4d2f3f69e3d286d9a7d7ab0c118a2a50142efcf4e41625def635bd9332d6cbf9cc65d85eb0718c579ab38 + languageName: node + linkType: hard + "p-map@npm:^4.0.0": version: 4.0.0 resolution: "p-map@npm:4.0.0" @@ -3094,6 +3134,13 @@ __metadata: languageName: node linkType: hard +"path-exists@npm:^5.0.0": + version: 5.0.0 + resolution: "path-exists@npm:5.0.0" + checksum: 8ca842868cab09423994596eb2c5ec2a971c17d1a3cb36dbf060592c730c725cd524b9067d7d2a1e031fef9ba7bd2ac6dc5ec9fb92aa693265f7be3987045254 + languageName: node + linkType: hard + "path-is-absolute@npm:^1.0.0": version: 1.0.1 resolution: "path-is-absolute@npm:1.0.1" @@ -3983,6 +4030,13 @@ __metadata: languageName: node linkType: hard +"unicorn-magic@npm:^0.1.0": + version: 0.1.0 + resolution: "unicorn-magic@npm:0.1.0" + checksum: 9b4d0e9809807823dc91d0920a4a4c0cff2de3ebc54ee87ac1ee9bc75eafd609b09d1f14495e0173aef26e01118706196b6ab06a75fe0841028b3983a8af313f + languageName: node + linkType: hard + "unique-filename@npm:^2.0.0": version: 2.0.1 resolution: "unique-filename@npm:2.0.1" @@ -4276,3 +4330,10 @@ __metadata: checksum: f77b3d8d00310def622123df93d4ee654fc6a0096182af8bd60679ddcdfb3474c56c6c7190817c84a2785648cdee9d721c0154eb45698c62176c322fb46fc700 languageName: node linkType: hard + +"yocto-queue@npm:^1.0.0": + version: 1.1.1 + resolution: "yocto-queue@npm:1.1.1" + checksum: f2e05b767ed3141e6372a80af9caa4715d60969227f38b1a4370d60bffe153c9c5b33a862905609afc9b375ec57cd40999810d20e5e10229a204e8bde7ef255c + languageName: node + linkType: hard