fix: regression in allowedMentions when replying (#10866)

* fix: regression in allowedMentions

* fix: lint

* fix: jsdoc

* tests: added a manual regression test

* fix: lint

* fix: tests

* fix: tests

* fix: typo

* fix: typings test

* chore: bumo zlib-sync to not crash on mac
This commit is contained in:
Qjuh
2025-05-02 12:48:57 +02:00
committed by GitHub
parent 096cd92b87
commit 2ebb5cbd53
8 changed files with 163 additions and 13 deletions

View File

@@ -1,5 +1,5 @@
{
"$schema": "https://json.schemastore.org/lintstagedrc.schema.json",
"*": "prettier --ignore-unknown --write",
"{src/**,test/**,typings/**,scripts/**}.{mjs,js,ts}": "cross-env ESLINT_USE_FLAT_CONFIG=false eslint --ext mjs,js,ts --fix"
"{src/**,typings/**,scripts/**}.{mjs,js,ts}": "cross-env ESLINT_USE_FLAT_CONFIG=false eslint --ext mjs,js,ts --fix"
}

View File

@@ -249,7 +249,9 @@ class MessagePayload {
username,
avatar_url: avatarURL,
allowed_mentions:
this.isMessage && this.target.author.id !== this.target.client.user.id ? undefined : allowedMentions,
this.isMessage && message_reference === undefined && this.target.author.id !== this.target.client.user.id
? undefined
: allowedMentions,
flags,
message_reference,
attachments: this.options.attachments,

View File

@@ -152,7 +152,7 @@
/**
* @external APIMediaGalleryItem
* @se {@link https://discord-api-types.dev/api/discord-api-types-v10/interface/APIMediaGalleryItem}
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10/interface/APIMediaGalleryItem}
*/
/**

View File

@@ -0,0 +1,148 @@
'use strict';
const { readFile } = require('node:fs/promises');
const { createReadStream } = require('node:fs');
const path = require('node:path');
const { setTimeout: sleep } = require('node:timers/promises');
const util = require('node:util');
const { fetch } = require('undici');
const { Client, GatewayIntentBits, AttachmentBuilder, EmbedBuilder, MessageFlags, ComponentType } = require('../src');
const client = new Client({
intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages, GatewayIntentBits.MessageContent],
});
const buffer = l =>
fetch(l)
.then(res => res.arrayBuffer())
.then(Buffer.from);
const linkA = 'https://discord.js.org/static/logo.svg';
const fileA = path.join(__dirname, 'blobReach.png');
const embed = () => new EmbedBuilder();
const attach = (attachment, name) => new AttachmentBuilder(attachment, { name });
const tests = [
m => m.channel.send('x'),
m => m.channel.send({ content: 'x', embeds: [{ description: 'a' }] }),
m => m.channel.send({ embeds: [{ description: 'a' }] }),
m => m.channel.send({ files: [{ attachment: fileA }] }),
m =>
m.channel.send({
embeds: [{ description: 'a' }],
files: [{ attachment: fileA, name: 'xyz.png' }],
}),
m => m.channel.send({ content: 'x', embeds: [embed().setDescription('a')] }),
m => m.channel.send({ embeds: [embed().setDescription('a')] }),
m => m.channel.send({ embeds: [embed().setDescription('a'), embed().setDescription('b')] }),
m => m.channel.send({ content: 'x', files: [attach(fileA)] }),
m => m.channel.send({ files: [fileA] }),
m => m.channel.send({ files: [attach(fileA)] }),
async m => m.channel.send({ files: [await buffer(linkA)] }),
async m => m.channel.send({ files: [{ attachment: await buffer(linkA) }] }),
m => m.channel.send({ files: [attach(fileA), attach(fileA)] }),
m => m.channel.send({ embeds: [{ description: 'a' }] }).then(m2 => m2.edit('x')),
m => m.channel.send({ embeds: [embed().setDescription('a')] }).then(m2 => m2.edit('x')),
m => m.channel.send('x').then(m2 => m2.edit({ embeds: [{ description: 'a' }] })),
m => m.channel.send('x').then(m2 => m2.edit({ embeds: [embed().setDescription('a')] })),
m => m.channel.send({ embeds: [{ description: 'a' }] }).then(m2 => m2.edit({ content: 'x', embeds: [] })),
m => m.channel.send({ embeds: [embed().setDescription('a')] }).then(m2 => m2.edit({ content: 'x', embeds: [] })),
m => m.channel.send({ content: 'x', embeds: [embed().setDescription('a')], files: [attach(fileA)] }),
m => m.channel.send({ content: 'x', files: [attach(fileA), attach(fileA)] }),
m => m.channel.send({ embeds: [embed().setDescription('a')], files: [attach(fileA)] }),
m =>
m.channel.send({
embeds: [embed().setImage('attachment://two.png')],
files: [attach(fileA, 'two.png')],
}),
m => m.channel.send({ content: 'x', files: [attach(fileA)] }),
m => m.channel.send({ files: [fileA] }),
m => m.channel.send({ files: [attach(fileA)] }),
async m => m.channel.send({ files: [await readFile(fileA)] }),
m => m.channel.send({ content: 'x', files: [attach(createReadStream(fileA))] }),
m => m.channel.send({ files: [createReadStream(fileA)] }),
m => m.channel.send({ files: [{ attachment: createReadStream(fileA) }] }),
m => m.reply({ content: 'x', allowedMentions: { repliedUser: false } }),
m => m.reply({ content: 'x', allowedMentions: { repliedUser: true } }),
m => m.reply({ content: 'x' }),
m => m.reply({ content: `${m.author}`, allowedMentions: { repliedUser: false } }),
m => m.reply({ content: `${m.author}`, allowedMentions: { parse: ['users'], repliedUser: false } }),
m => m.reply({ content: `${m.author}`, allowedMentions: { parse: ['users'], repliedUser: true } }),
m => m.reply({ content: `${m.author}` }),
m => m.edit({ flags: MessageFlags.SuppressEmbeds }),
m => m.edit({ flags: MessageFlags.SuppressEmbeds, allowedMentions: { repliedUser: false } }),
m =>
m
.reply({ content: 'x', allowedMentions: { repliedUser: false } })
.then(msg => msg.edit({ content: 'a', allowedMentions: { repliedUser: true } })),
m =>
m.channel.send({
components: [{ type: ComponentType.TextDisplay, content: `${m.author}` }],
flags: MessageFlags.IsComponentsV2,
}),
m =>
m.channel.send({
components: [{ type: ComponentType.TextDisplay, content: `${m.author}` }],
flags: MessageFlags.IsComponentsV2,
allowedMentions: { parse: ['users'] },
}),
m =>
m.channel.send({
components: [{ type: ComponentType.TextDisplay, content: `${m.author}` }],
flags: MessageFlags.IsComponentsV2,
allowedMentions: { parse: [] },
}),
m =>
m.reply({
components: [{ type: ComponentType.TextDisplay, content: `${m.author}` }],
flags: MessageFlags.IsComponentsV2,
allowedMentions: { parse: [], repliedUser: true },
}),
m =>
m.reply({
components: [{ type: ComponentType.TextDisplay, content: `${m.author}` }],
flags: MessageFlags.IsComponentsV2,
allowedMentions: { parse: [], repliedUser: false },
}),
m => m.channel.send('Done!'),
];
client.on('messageCreate', async message => {
if (message.author.id !== process.env.OWNER) return;
const match = message.content.match(/^do (.+)$/);
if (match?.[1] === 'it') {
/* eslint-disable no-await-in-loop */
for (const [i, test] of tests.entries()) {
await message.channel.send(`**#${i}**\n\`\`\`js\n${test.toString()}\`\`\``);
await test(message).catch(e => message.channel.send(`Error!\n\`\`\`\n${e}\`\`\``));
await sleep(1_000);
}
/* eslint-enable no-await-in-loop */
} else if (match) {
const n = parseInt(match[1]) || 0;
const test = tests.slice(n)[0];
const i = tests.indexOf(test);
await message.channel.send(`**#${i}**\n\`\`\`js\n${test.toString()}\`\`\``);
await test(message).catch(e => message.channel.send(`Error!\n\`\`\`\n${e}\`\`\``));
}
});
client.login();
// eslint-disable-next-line no-console
process.on('unhandledRejection', console.error);

View File

@@ -3219,7 +3219,7 @@ export type SelectMenuType = APISelectMenuComponent['type'];
export interface SeparatorComponentData extends BaseComponentData {
spacing?: SeparatorSpacingSize;
dividier?: boolean;
divider?: boolean;
}
export class SeparatorComponent extends Component<APISeparatorComponent> {
private constructor(data: APISeparatorComponent);

View File

@@ -687,7 +687,7 @@ client.on('messageCreate', async message => {
const rawSeparator: SeparatorComponentData = {
type: ComponentType.Separator,
spacing: 1,
dividier: false,
divider: false,
};
const rawFile: FileComponentData = {

View File

@@ -102,7 +102,7 @@
"typescript": "~5.5.4",
"undici": "6.21.1",
"vitest": "^2.0.5",
"zlib-sync": "^0.1.9"
"zlib-sync": "^0.1.10"
},
"engines": {
"node": ">=20"

14
pnpm-lock.yaml generated
View File

@@ -1780,8 +1780,8 @@ importers:
specifier: ^2.0.5
version: 2.0.5(@edge-runtime/vm@3.2.0)(@types/node@18.19.45)(happy-dom@14.12.3)(terser@5.39.0)
zlib-sync:
specifier: ^0.1.9
version: 0.1.9
specifier: ^0.1.10
version: 0.1.10
packages:
@@ -14625,8 +14625,8 @@ packages:
engines: {node: '>=8.0.0'}
hasBin: true
zlib-sync@0.1.9:
resolution: {integrity: sha512-DinB43xCjVwIBDpaIvQqHbmDsnYnSt6HJ/yiB2MZQGTqgPcwBSZqLkimXwK8BvdjQ/MaZysb5uEenImncqvCqQ==}
zlib-sync@0.1.10:
resolution: {integrity: sha512-t7/pYg5tLBznL1RuhmbAt8rNp5tbhr+TSrJFnMkRtrGIaPJZ6Dc0uR4u3OoQI2d6cGlVI62E3Gy6gwkxyIqr/w==}
zod-validation-error@2.1.0:
resolution: {integrity: sha512-VJh93e2wb4c3tWtGgTa0OF/dTt/zoPCPzXq4V11ZjxmEAFaPi/Zss1xIZdEB5RD8GD00U0/iVXgqkF77RV7pdQ==}
@@ -24515,7 +24515,7 @@ snapshots:
espree: 10.1.0
esquery: 1.6.0
parse-imports: 2.1.1
semver: 7.6.3
semver: 7.7.1
spdx-expression-parse: 4.0.0
synckit: 0.9.1
transitivePeerDependencies:
@@ -24729,7 +24729,7 @@ snapshots:
natural-compare: 1.4.0
nth-check: 2.1.1
postcss-selector-parser: 6.1.2
semver: 7.6.3
semver: 7.7.1
vue-eslint-parser: 9.4.3(eslint@8.57.0)
xml-name-validator: 4.0.0
transitivePeerDependencies:
@@ -32503,7 +32503,7 @@ snapshots:
optionalDependencies:
commander: 9.5.0
zlib-sync@0.1.9:
zlib-sync@0.1.10:
dependencies:
nan: 2.20.0