diff --git a/package.json b/package.json index 80aced5b9..ccceb4dfd 100644 --- a/package.json +++ b/package.json @@ -33,8 +33,8 @@ "prepack:esm": "rollup-type-bundler -d dist/esm -t .mts" }, "dependencies": { - "@discordjs/builders": "^1.8.2", - "@sapphire/discord-utilities": "^3.4.0", + "@discordjs/builders": "^1.9.0", + "@sapphire/discord-utilities": "^3.4.1", "@sapphire/discord.js-utilities": "^7.3.0", "@sapphire/lexure": "^1.1.7", "@sapphire/pieces": "^4.3.1", @@ -60,7 +60,7 @@ "@vitest/coverage-v8": "^2.0.5", "concurrently": "^8.2.2", "cz-conventional-changelog": "^3.3.0", - "discord.js": "^14.15.3", + "discord.js": "^14.16.1", "esbuild-plugin-file-path-extensions": "^2.1.2", "esbuild-plugin-version-injector": "^1.2.1", "eslint": "^8.57.0", diff --git a/src/lib/utils/application-commands/compute-differences/contexts.ts b/src/lib/utils/application-commands/compute-differences/contexts.ts new file mode 100644 index 000000000..31cd7a112 --- /dev/null +++ b/src/lib/utils/application-commands/compute-differences/contexts.ts @@ -0,0 +1,54 @@ +import type { InteractionContextType } from 'discord.js'; +import type { CommandDifference } from './_shared'; + +export function* checkInteractionContextTypes( + existingContexts?: InteractionContextType[], + newContexts?: InteractionContextType[] +): Generator { + // 0. No existing contexts and now we have contexts + if (!existingContexts && newContexts?.length) { + yield { + key: 'contexts', + original: 'no contexts present', + expected: 'contexts present' + }; + } + // 1. Existing contexts and now we have no contexts + else if (existingContexts?.length && !newContexts?.length) { + yield { + key: 'contexts', + original: 'contexts present', + expected: 'no contexts present' + }; + } + // 2. Maybe changes in order or additions, log + else if (newContexts?.length) { + let index = 0; + + for (const newContext of newContexts) { + const currentIndex = index++; + + if (existingContexts![currentIndex] !== newContext) { + yield { + key: `contexts[${currentIndex}]`, + original: `contexts type ${existingContexts?.[currentIndex]}`, + expected: `contexts type ${newContext}` + }; + } + } + + if (index < existingContexts!.length) { + let type: InteractionContextType; + + while ((type = existingContexts![index]) !== undefined) { + yield { + key: `contexts[${index}]`, + original: `context ${type} present`, + expected: `no context present` + }; + + index++; + } + } + } +} diff --git a/src/lib/utils/application-commands/compute-differences/integration_types.ts b/src/lib/utils/application-commands/compute-differences/integration_types.ts new file mode 100644 index 000000000..675d29503 --- /dev/null +++ b/src/lib/utils/application-commands/compute-differences/integration_types.ts @@ -0,0 +1,54 @@ +import type { ApplicationIntegrationType } from 'discord.js'; +import type { CommandDifference } from './_shared'; + +export function* checkIntegrationTypes( + existingIntegrationTypes?: ApplicationIntegrationType[], + newIntegrationTypes?: ApplicationIntegrationType[] +): Generator { + // 0. No existing integration types and now we have integration types + if (!existingIntegrationTypes?.length && newIntegrationTypes?.length) { + yield { + key: 'integrationTypes', + original: 'no integration types present', + expected: 'integration types present' + }; + } + // 1. Existing integration types and now we have no integration types + else if (existingIntegrationTypes?.length && !newIntegrationTypes?.length) { + yield { + key: 'integrationTypes', + original: 'integration types present', + expected: 'no integration types present' + }; + } + // 2. Maybe changes in order or additions, log + else if (newIntegrationTypes?.length) { + let index = 0; + + for (const newIntegrationType of newIntegrationTypes) { + const currentIndex = index++; + + if (existingIntegrationTypes![currentIndex] !== newIntegrationType) { + yield { + key: `integrationTypes[${currentIndex}]`, + original: `integration type ${existingIntegrationTypes?.[currentIndex]}`, + expected: `integration type ${newIntegrationType}` + }; + } + } + + if (index < existingIntegrationTypes!.length) { + let type: ApplicationIntegrationType; + + while ((type = existingIntegrationTypes![index]) !== undefined) { + yield { + key: `integrationTypes[${index}]`, + original: `integration type ${type} present`, + expected: 'no integration type present' + }; + + index++; + } + } + } +} diff --git a/src/lib/utils/application-commands/computeDifferences.ts b/src/lib/utils/application-commands/computeDifferences.ts index 8305fcfd3..19f17658f 100644 --- a/src/lib/utils/application-commands/computeDifferences.ts +++ b/src/lib/utils/application-commands/computeDifferences.ts @@ -12,6 +12,8 @@ import { checkDMPermission } from './compute-differences/dm_permission'; import { checkLocalizations } from './compute-differences/localizations'; import { checkName } from './compute-differences/name'; import { checkOptions } from './compute-differences/options'; +import { checkIntegrationTypes } from './compute-differences/integration_types'; +import { checkInteractionContextTypes } from './compute-differences/contexts'; /** * @returns `true` if there are differences, `false` otherwise @@ -61,6 +63,12 @@ export function* getCommandDifferences( originalLocalizedDescriptions: originalLocalizedNames, expectedLocalizedDescriptions: expectedLocalizedNames }); + + // Check integration types + yield* checkIntegrationTypes(existingCommand.integration_types, casted.integration_types); + + // Check contexts + yield* checkInteractionContextTypes(existingCommand.contexts, casted.contexts); } return; @@ -106,5 +114,11 @@ export function* getCommandDifferences( expectedLocalizedDescriptions }); + // Check integration types + yield* checkIntegrationTypes(existingCommand.integration_types, casted.integration_types); + + // Check contexts + yield* checkInteractionContextTypes(existingCommand.contexts, casted.contexts); + yield* checkOptions(existingCommand.options, casted.options); } diff --git a/src/lib/utils/application-commands/normalizeInputs.ts b/src/lib/utils/application-commands/normalizeInputs.ts index 1705d2f96..4c13ea804 100644 --- a/src/lib/utils/application-commands/normalizeInputs.ts +++ b/src/lib/utils/application-commands/normalizeInputs.ts @@ -15,7 +15,9 @@ import { import { ApplicationCommand, PermissionsBitField, + type ApplicationIntegrationType, type ChatInputApplicationCommandData, + type InteractionContextType, type MessageApplicationCommandData, type UserApplicationCommandData } from 'discord.js'; @@ -71,7 +73,9 @@ export function normalizeChatInputCommand( description_localizations: command.descriptionLocalizations, type: ApplicationCommandType.ChatInput, dm_permission: command.dmPermission, - nsfw: command.nsfw + nsfw: command.nsfw, + integration_types: command.integrationTypes as ApplicationIntegrationType[] | undefined, + contexts: command.contexts as InteractionContextType[] | undefined }; if (typeof command.defaultMemberPermissions !== 'undefined') { @@ -108,7 +112,9 @@ export function normalizeContextMenuCommand( name_localizations: command.nameLocalizations, type: command.type, dm_permission: command.dmPermission, - nsfw: command.nsfw + nsfw: command.nsfw, + integration_types: command.integrationTypes as ApplicationIntegrationType[] | undefined, + contexts: command.contexts as InteractionContextType[] | undefined }; if (typeof command.defaultMemberPermissions !== 'undefined') { @@ -125,7 +131,9 @@ export function convertApplicationCommandToApiData(command: ApplicationCommand): name_localizations: command.nameLocalizations, dm_permission: command.dmPermission, nsfw: command.nsfw, - default_member_permissions: command.defaultMemberPermissions?.bitfield.toString() ?? null + default_member_permissions: command.defaultMemberPermissions?.bitfield.toString() ?? null, + integration_types: command.integrationTypes, + contexts: command.contexts } as RESTPostAPIApplicationCommandsJSONBody; if (command.type === ApplicationCommandType.ChatInput) { diff --git a/src/optional-listeners/message-command-listeners/CoreMessageCommandTyping.ts b/src/optional-listeners/message-command-listeners/CoreMessageCommandTyping.ts index e72d73b2e..01bbb6a2b 100644 --- a/src/optional-listeners/message-command-listeners/CoreMessageCommandTyping.ts +++ b/src/optional-listeners/message-command-listeners/CoreMessageCommandTyping.ts @@ -1,5 +1,5 @@ import { isStageChannel } from '@sapphire/discord.js-utilities'; -import type { Message } from 'discord.js'; +import { ChannelType, type Message } from 'discord.js'; import { Listener } from '../../lib/structures/Listener'; import type { MessageCommand } from '../../lib/types/CommandTypes'; import { Events, type MessageCommandRunPayload } from '../../lib/types/Events'; @@ -15,6 +15,10 @@ export class CoreListener extends Listener { return; } + if (message.channel.type === ChannelType.GroupDM) { + return; + } + try { await message.channel.sendTyping(); } catch (error) { diff --git a/src/optional-listeners/message-command-listeners/CorePreMessageParser.ts b/src/optional-listeners/message-command-listeners/CorePreMessageParser.ts index 4c8da2464..00c9200ae 100644 --- a/src/optional-listeners/message-command-listeners/CorePreMessageParser.ts +++ b/src/optional-listeners/message-command-listeners/CorePreMessageParser.ts @@ -1,5 +1,5 @@ import { isDMChannel } from '@sapphire/discord.js-utilities'; -import { PermissionFlagsBits, PermissionsBitField, type Message } from 'discord.js'; +import { ChannelType, PermissionFlagsBits, PermissionsBitField, type Message } from 'discord.js'; import { Listener } from '../../lib/structures/Listener'; import { Events } from '../../lib/types/Events'; @@ -40,6 +40,7 @@ export class CoreListener extends Listener { } private async canRunInChannel(message: Message): Promise { + if (message.channel.type === ChannelType.GroupDM) return false; if (isDMChannel(message.channel)) return true; const me = await message.guild?.members.fetchMe(); diff --git a/src/preconditions/ClientPermissions.ts b/src/preconditions/ClientPermissions.ts index 42547bd89..aa15c7f0a 100644 --- a/src/preconditions/ClientPermissions.ts +++ b/src/preconditions/ClientPermissions.ts @@ -154,6 +154,7 @@ export class CorePrecondition extends AllFlowsPrecondition { Stream: 'Stream', UseApplicationCommands: 'Use Application Commands', UseEmbeddedActivities: 'Start Activities', + UseExternalApps: 'Use External Apps', UseExternalEmojis: 'Use External Emojis', UseExternalSounds: 'Use External Sounds', UseExternalStickers: 'Use External Stickers', diff --git a/yarn.lock b/yarn.lock index 663a69d3a..7215fad78 100644 --- a/yarn.lock +++ b/yarn.lock @@ -297,18 +297,18 @@ __metadata: languageName: node linkType: hard -"@discordjs/builders@npm:^1.8.2": - version: 1.8.2 - resolution: "@discordjs/builders@npm:1.8.2" - dependencies: - "@discordjs/formatters": "npm:^0.4.0" - "@discordjs/util": "npm:^1.1.0" - "@sapphire/shapeshift": "npm:^3.9.7" - discord-api-types: "npm:0.37.83" +"@discordjs/builders@npm:^1.9.0": + version: 1.9.0 + resolution: "@discordjs/builders@npm:1.9.0" + dependencies: + "@discordjs/formatters": "npm:^0.5.0" + "@discordjs/util": "npm:^1.1.1" + "@sapphire/shapeshift": "npm:^4.0.0" + discord-api-types: "npm:0.37.97" fast-deep-equal: "npm:^3.1.3" ts-mixer: "npm:^6.0.4" - tslib: "npm:^2.6.2" - checksum: 10/64de3c72fdde202cc168ae5e42c05df44d3a4323cc1706fa667077b5bef1d60cf10d8e871bd4c758140432252f3c9c2747370f56fa0ff08c55669cb0a1e516d7 + tslib: "npm:^2.6.3" + checksum: 10/8d45f4919355237d8e442df7a98cec49fcd9dcdcb193cdbb88dbc8775d5cb25f6451317a40542921ab54649a9e9fc801e781617f290634db78ae3cd91454ccd3 languageName: node linkType: hard @@ -326,12 +326,19 @@ __metadata: languageName: node linkType: hard -"@discordjs/formatters@npm:^0.4.0": - version: 0.4.0 - resolution: "@discordjs/formatters@npm:0.4.0" +"@discordjs/collection@npm:^2.1.1": + version: 2.1.1 + resolution: "@discordjs/collection@npm:2.1.1" + checksum: 10/2bf815120929e20bdcc94a7d0a9c0e567ef859b8cc502f5ecddaeae31ba3457711df708ab200ac6e86ffccab31f796192860f8ad609a9ddc2cdd7ffe5825a266 + languageName: node + linkType: hard + +"@discordjs/formatters@npm:^0.5.0": + version: 0.5.0 + resolution: "@discordjs/formatters@npm:0.5.0" dependencies: - discord-api-types: "npm:0.37.83" - checksum: 10/dbc75cf1048c928ddefb3d3f6268f8c153fce3030ef08afad06b7e2b1cd407451069eef1bcd903fc654d5e02fd1bf26372e12da41496182eb8fbee3dab87a83c + discord-api-types: "npm:0.37.97" + checksum: 10/71643849aef40cdbee997739cad95fcd2e803800fd8db9c8decffd9bbfc37467b0ca1dd8dd827d4bd34651c2b0944e93aea0879f9db6b7f03bdc24fbc07928bf languageName: node linkType: hard @@ -352,6 +359,23 @@ __metadata: languageName: node linkType: hard +"@discordjs/rest@npm:^2.4.0": + version: 2.4.0 + resolution: "@discordjs/rest@npm:2.4.0" + dependencies: + "@discordjs/collection": "npm:^2.1.1" + "@discordjs/util": "npm:^1.1.1" + "@sapphire/async-queue": "npm:^1.5.3" + "@sapphire/snowflake": "npm:^3.5.3" + "@vladfrangu/async_event_emitter": "npm:^2.4.6" + discord-api-types: "npm:0.37.97" + magic-bytes.js: "npm:^1.10.0" + tslib: "npm:^2.6.3" + undici: "npm:6.19.8" + checksum: 10/aca81c02f24b953400425d0ba96b96bf1a7b9a42aa9ccff021ea795cd9bed3fa36586a921720569a88cceb659507a76084b72c28f08b931121ea0e4b292a1431 + languageName: node + linkType: hard + "@discordjs/util@npm:^1.1.0": version: 1.1.0 resolution: "@discordjs/util@npm:1.1.0" @@ -359,7 +383,14 @@ __metadata: languageName: node linkType: hard -"@discordjs/ws@npm:^1.1.1": +"@discordjs/util@npm:^1.1.1": + version: 1.1.1 + resolution: "@discordjs/util@npm:1.1.1" + checksum: 10/3c8ae0c47fcf124e13bfef6232cf4564c35da9ac6b95b63888458c6662742e387324cdafa6207d625415553a5d05fc854f106c726a00c8e81c3414fd5e7eaf2c + languageName: node + linkType: hard + +"@discordjs/ws@npm:1.1.1": version: 1.1.1 resolution: "@discordjs/ws@npm:1.1.1" dependencies: @@ -1175,14 +1206,14 @@ __metadata: languageName: node linkType: hard -"@sapphire/async-queue@npm:^1.5.2": +"@sapphire/async-queue@npm:^1.5.2, @sapphire/async-queue@npm:^1.5.3": version: 1.5.3 resolution: "@sapphire/async-queue@npm:1.5.3" checksum: 10/6a9fdeeaa3e4591c057cb67b5aae86d9c94326dcb0ea9e8e3b8eba8cbcfee2a0f672d837a51e3da2c838f9861a6117fced2b0ac8e1b719bc5caf1bbbee781fb3 languageName: node linkType: hard -"@sapphire/discord-utilities@npm:^3.3.0, @sapphire/discord-utilities@npm:^3.4.0": +"@sapphire/discord-utilities@npm:^3.3.0": version: 3.4.0 resolution: "@sapphire/discord-utilities@npm:3.4.0" dependencies: @@ -1191,6 +1222,15 @@ __metadata: languageName: node linkType: hard +"@sapphire/discord-utilities@npm:^3.4.1": + version: 3.4.1 + resolution: "@sapphire/discord-utilities@npm:3.4.1" + dependencies: + discord-api-types: "npm:^0.37.98" + checksum: 10/daf008e75ad27adf1f89c213d80b086ff29a417b06b5dbd8dd42b0bb29a9dc94d22715772afb2c02b89ca0586aa9b25bc4d2e8f4368f37aa725108d96c2af881 + languageName: node + linkType: hard + "@sapphire/discord.js-utilities@npm:^7.3.0": version: 7.3.0 resolution: "@sapphire/discord.js-utilities@npm:7.3.0" @@ -1240,11 +1280,11 @@ __metadata: dependencies: "@commitlint/cli": "npm:^19.4.1" "@commitlint/config-conventional": "npm:^19.4.1" - "@discordjs/builders": "npm:^1.8.2" + "@discordjs/builders": "npm:^1.9.0" "@favware/cliff-jumper": "npm:^4.1.0" "@favware/npm-deprecate": "npm:^1.0.7" "@favware/rollup-type-bundler": "npm:^3.3.0" - "@sapphire/discord-utilities": "npm:^3.4.0" + "@sapphire/discord-utilities": "npm:^3.4.1" "@sapphire/discord.js-utilities": "npm:^7.3.0" "@sapphire/eslint-config": "npm:^5.0.5" "@sapphire/lexure": "npm:^1.1.7" @@ -1263,7 +1303,7 @@ __metadata: "@vitest/coverage-v8": "npm:^2.0.5" concurrently: "npm:^8.2.2" cz-conventional-changelog: "npm:^3.3.0" - discord.js: "npm:^14.15.3" + discord.js: "npm:^14.16.1" esbuild-plugin-file-path-extensions: "npm:^2.1.2" esbuild-plugin-version-injector: "npm:^1.2.1" eslint: "npm:^8.57.0" @@ -1332,13 +1372,13 @@ __metadata: languageName: node linkType: hard -"@sapphire/shapeshift@npm:^3.9.7": - version: 3.9.7 - resolution: "@sapphire/shapeshift@npm:3.9.7" +"@sapphire/shapeshift@npm:^4.0.0": + version: 4.0.0 + resolution: "@sapphire/shapeshift@npm:4.0.0" dependencies: fast-deep-equal: "npm:^3.1.3" lodash: "npm:^4.17.21" - checksum: 10/f90f8e25920fe953a5231aa65f24829e1f2ecb26dcac7a09ff1a1f3cb988f174e27b3ac82fc4f6368891edff8ad6f90ee78cf5c0cab3038fd2714d02eba4eb0c + checksum: 10/71437388066ca19a521f94f3066633010a5b3e24d9da1c07664389b9b02635af502b81236af92f24bb4c0f312a93b0f4ac544391afd464c2e98e6f93e2a4ded0 languageName: node linkType: hard @@ -1679,6 +1719,13 @@ __metadata: languageName: node linkType: hard +"@vladfrangu/async_event_emitter@npm:^2.4.6": + version: 2.4.6 + resolution: "@vladfrangu/async_event_emitter@npm:2.4.6" + checksum: 10/6a329441bbd36bb8bdc8c49f18328abf724834597c8cab56b5741f18fa167a010bb841bc9ec3638b6b73c6692b85d0de724612b0a416b523650574576fd1a197 + languageName: node + linkType: hard + "JSONStream@npm:^1.3.5": version: 1.3.5 resolution: "JSONStream@npm:1.3.5" @@ -2600,6 +2647,13 @@ __metadata: languageName: node linkType: hard +"discord-api-types@npm:0.37.97": + version: 0.37.97 + resolution: "discord-api-types@npm:0.37.97" + checksum: 10/94eea4b95ebb7ab89cce325c5c5654ce7fd3f1e17efa997fd375b7fe81cd5e872c097cf98cfc9d4d7ff233c924f501d812516a048913023bde02f3bbba21849b + languageName: node + linkType: hard + "discord-api-types@npm:^0.37.97": version: 0.37.98 resolution: "discord-api-types@npm:0.37.98" @@ -2607,23 +2661,30 @@ __metadata: languageName: node linkType: hard -"discord.js@npm:^14.15.3": - version: 14.15.3 - resolution: "discord.js@npm:14.15.3" +"discord-api-types@npm:^0.37.98": + version: 0.37.100 + resolution: "discord-api-types@npm:0.37.100" + checksum: 10/44b7366784b11e32d9015709658d2429d040a643748c0b8733752a1d2b0db328dc1ab9fa3210f93423d6b3762561e60ada6ba781ac1edd7fddf6174e3c645311 + languageName: node + linkType: hard + +"discord.js@npm:^14.16.1": + version: 14.16.1 + resolution: "discord.js@npm:14.16.1" dependencies: - "@discordjs/builders": "npm:^1.8.2" + "@discordjs/builders": "npm:^1.9.0" "@discordjs/collection": "npm:1.5.3" - "@discordjs/formatters": "npm:^0.4.0" - "@discordjs/rest": "npm:^2.3.0" - "@discordjs/util": "npm:^1.1.0" - "@discordjs/ws": "npm:^1.1.1" + "@discordjs/formatters": "npm:^0.5.0" + "@discordjs/rest": "npm:^2.4.0" + "@discordjs/util": "npm:^1.1.1" + "@discordjs/ws": "npm:1.1.1" "@sapphire/snowflake": "npm:3.5.3" - discord-api-types: "npm:0.37.83" + discord-api-types: "npm:0.37.97" fast-deep-equal: "npm:3.1.3" lodash.snakecase: "npm:4.1.1" - tslib: "npm:2.6.2" - undici: "npm:6.13.0" - checksum: 10/b18decbe8a0f1a3f569eb144be2a7039a08068131be2760190ac70fefdeb255cfed10ee0368e488f6c38d53d190c2988a6cc50c7db57a802cf54bb20cc47dc2e + tslib: "npm:^2.6.3" + undici: "npm:6.19.8" + checksum: 10/e75d0f8dd1a8e9aae313e016ba88d0c4b75dfe502663b08edae94cc99936f634e5647022bae71f517b6233d44af2a8bd4cabbe53db398e954116178b196030c4 languageName: node linkType: hard @@ -6174,13 +6235,6 @@ __metadata: languageName: node linkType: hard -"tslib@npm:2.6.2": - version: 2.6.2 - resolution: "tslib@npm:2.6.2" - checksum: 10/bd26c22d36736513980091a1e356378e8b662ded04204453d353a7f34a4c21ed0afc59b5f90719d4ba756e581a162ecbf93118dc9c6be5acf70aa309188166ca - languageName: node - linkType: hard - "tslib@npm:^2.1.0, tslib@npm:^2.3.1, tslib@npm:^2.6.2, tslib@npm:^2.6.3": version: 2.6.3 resolution: "tslib@npm:2.6.3" @@ -6348,6 +6402,13 @@ __metadata: languageName: node linkType: hard +"undici@npm:6.19.8": + version: 6.19.8 + resolution: "undici@npm:6.19.8" + checksum: 10/19ae4ba38b029a664d99fd330935ef59136cf99edb04ed821042f27b5a9e84777265fb744c8a7abc83f2059afb019446c69a4ebef07bbc0ed6b2de8d67ef4090 + languageName: node + linkType: hard + "unicorn-magic@npm:^0.1.0": version: 0.1.0 resolution: "unicorn-magic@npm:0.1.0"