Compare commits

...

15 Commits

Author SHA1 Message Date
Jiralite
0516dc7862 chore(discord.js): release discord.js@14.26.4 2026-05-01 14:31:45 +01:00
Qjuh
b8d8812a05 fix(MessageCreateAction): receive DMs in uncached DMChannels again (#11495) 2026-05-01 13:29:54 +01:00
Jiralite
f95b629d44 chore(TeamMember): update permissions comment 2026-04-15 11:37:20 +01:00
Jiralite
666fce0516 chore(discord.js): release discord.js@14.26.3 2026-04-14 13:36:49 +01:00
Jiralite
dced1970eb fix(TeamMember): allow a default permissions
Discord stopped sending this field at some point on or before 2026-04-14.
2026-04-14 13:21:04 +01:00
Vlad Frangu
e662290faa chore(discord.js): release discord.js@14.26.2 2026-04-04 00:22:54 +03:00
Qjuh
b86573db3c fix(Action): don't add recipients to guild channels (#11479)
* fix(Action): don't add recipients to guild channels

* pref: no array

---------

Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>
2026-04-03 23:18:30 +02:00
Jiralite
cd1b6a0f63 chore(discord.js): release discord.js@14.26.1 2026-04-03 20:32:44 +01:00
Qjuh
67566d0b0e fix: only return DMChannel that have the user as known recipient (#11478) 2026-04-03 20:19:26 +01:00
Jiralite
6a0cd82566 chore(builders): increase @discordjs/builders version 2026-03-31 18:35:30 +01:00
Jiralite
2eaec32414 chore(builders): release @discordjs/builders@1.14.1 2026-03-31 18:25:46 +01:00
ducktrshessami
6e45ddc067 fix: actually accept rest in RadioGroup/CheckBoxGroupBuilder#setOptions (#11472) 2026-03-31 19:21:57 +02:00
Vlad Frangu
eee6f948ee chore(discord.js): release discord.js@14.26.0 2026-03-31 11:30:58 +03:00
Qjuh
45bd430c0d feat: allow partial DMChannel without client user (#11462)
* feat(DMChannel): allow partial DMChannel without client user

* chore: apply code review comments

* chore: apply code review suggestion
2026-03-27 14:34:33 +01:00
Vlad Frangu
d20e10305b chore(builders): release @discordjs/builders@1.14.0 2026-03-23 02:02:08 +02:00
13 changed files with 112 additions and 18 deletions

View File

@@ -2,6 +2,22 @@
All notable changes to this project will be documented in this file.
# [@discordjs/builders@1.14.1](https://github.com/discordjs/discord.js/compare/@discordjs/builders@1.14.0...@discordjs/builders@1.14.1) - (2026-03-31)
## Bug Fixes
- Actually accept rest in RadioGroup/CheckBoxGroupBuilder#setOptions (#11472) ([6e45ddc](https://github.com/discordjs/discord.js/commit/6e45ddc067816b01d6676f04faea54d34469fefc))
# [@discordjs/builders@1.14.0](https://github.com/discordjs/discord.js/compare/@discordjs/builders@1.13.1...@discordjs/builders@1.14.0) - (2026-03-22)
## Documentation
- **builders:** Edited docs to correctly link to splice (#11430) ([ec5d921](https://github.com/discordjs/discord.js/commit/ec5d921b75255cf28fd572a91e715b37305f4cf8))
## Features
- **builders:** Add checkbox, checkboxgroup, and radiogroup builders (#11410) ([ca7719e](https://github.com/discordjs/discord.js/commit/ca7719e822e02a83e5a7b769de3c5fd615dc24fd))
# [@discordjs/builders@1.13.1](https://github.com/discordjs/discord.js/compare/@discordjs/builders@1.13.0...@discordjs/builders@1.13.1) - (2025-11-30)
## Bug Fixes

View File

@@ -1,7 +1,7 @@
{
"$schema": "https://json.schemastore.org/package.json",
"name": "@discordjs/builders",
"version": "1.13.1",
"version": "1.14.1",
"description": "A set of builders that you can use when creating your bot",
"scripts": {
"test": "vitest run",

View File

@@ -86,7 +86,7 @@ export class CheckboxGroupBuilder extends ComponentBuilder<APICheckboxGroupCompo
*
* @param options - The options to use
*/
public setOptions(options: RestOrArray<APICheckboxGroupOption | CheckboxGroupOptionBuilder>) {
public setOptions(...options: RestOrArray<APICheckboxGroupOption | CheckboxGroupOptionBuilder>) {
return this.spliceOptions(0, this.options.length, ...options);
}

View File

@@ -84,7 +84,7 @@ export class RadioGroupBuilder extends ComponentBuilder<APIRadioGroupComponent>
*
* @param options - The options to use
*/
public setOptions(options: RestOrArray<APIRadioGroupOption | RadioGroupOptionBuilder>) {
public setOptions(...options: RestOrArray<APIRadioGroupOption | RadioGroupOptionBuilder>) {
return this.spliceOptions(0, this.options.length, ...options);
}

View File

@@ -2,6 +2,50 @@
All notable changes to this project will be documented in this file.
# [14.26.4](https://github.com/discordjs/discord.js/compare/14.26.3...14.26.4) - (2026-05-01)
## Bug Fixes
- **MessageCreateAction:** Receive DMs in uncached DMChannels again (#11495) ([b8d8812](https://github.com/discordjs/discord.js/commit/b8d8812a05c14a93cc40b2839e19be38ed928cb7))
# [14.26.3](https://github.com/discordjs/discord.js/compare/14.26.2...14.26.3) - (2026-04-14)
## Bug Fixes
- **TeamMember:** Allow a default `permissions` ([dced197](https://github.com/discordjs/discord.js/commit/dced1970ebb481ae7c5cf46ec5fadee4b05215bb))
# [14.26.2](https://github.com/discordjs/discord.js/compare/14.26.1...14.26.2) - (2026-04-03)
## Bug Fixes
- **Action:** Don't add recipients to guild channels (#11479) ([b86573d](https://github.com/discordjs/discord.js/commit/b86573db3c13fe0292bdf6756bcd4351f84e2950))
# [14.26.1](https://github.com/discordjs/discord.js/compare/14.26.0...14.26.1) - (2026-04-03)
## Bug Fixes
- Only return DMChannel that have the user as known recipient (#11478) ([67566d0](https://github.com/discordjs/discord.js/commit/67566d0b0efd64012088e3357ad9cd6bacc23930))
# [14.26.0](https://github.com/discordjs/discord.js/compare/14.25.1...14.26.0) - (2026-03-31)
## Bug Fixes
- Remove manage messages check for pinnable (#11453) ([1a0da18](https://github.com/discordjs/discord.js/commit/1a0da18b3611a31553fd5250b6f882b755d8d003))
- **DJSError:** Differentiate error type (#11295) ([f5b3f84](https://github.com/discordjs/discord.js/commit/f5b3f842e39ec1f211a0017fadb683ae3b372e02))
## Features
- Allow partial DMChannel without client user (#11462) ([45bd430](https://github.com/discordjs/discord.js/commit/45bd430c0d55ddb98380ea320fab9dc56211e07a))
- Modal radio group and checkbox components for v14 (#11437) ([b42e499](https://github.com/discordjs/discord.js/commit/b42e4994109ee83f3e329e810cc8733cf4176dbe))
## Refactor
- **DJSError:** Prefer `this.constructor.name` (#11294) ([e32f0c1](https://github.com/discordjs/discord.js/commit/e32f0c141a4ef17383f7a868e26c26a2878fb4f2))
## Typings
- BroadcastEval overload order (#11422) ([16d70b9](https://github.com/discordjs/discord.js/commit/16d70b9232559f505f4d6c1a5b1122ebbac5e35d))
# [14.25.1](https://github.com/discordjs/discord.js/compare/14.25.0...14.25.1) - (2025-11-21)
## Bug Fixes

View File

@@ -1,7 +1,7 @@
{
"$schema": "https://json.schemastore.org/package.json",
"name": "discord.js",
"version": "14.25.1",
"version": "14.26.4",
"description": "A powerful library for interacting with the Discord API",
"scripts": {
"test": "pnpm run docs:test && pnpm run test:typescript",

View File

@@ -1,5 +1,6 @@
'use strict';
const { ChannelType } = require('discord-api-types/v10');
const { Poll } = require('../../structures/Poll.js');
const { PollAnswer } = require('../../structures/PollAnswer.js');
const Partials = require('../../util/Partials.js');
@@ -33,10 +34,16 @@ class GenericAction {
const payloadData = {};
const id = data.channel_id ?? data.id;
if (!('recipients' in data)) {
// Try to resolve the recipient, but do not add the client user.
if ('recipients' in data) {
// Try to resolve the recipient, but do not add if already existing in recipients.
const recipient = data.author ?? data.user ?? { id: data.user_id };
if (recipient.id !== this.client.user.id) payloadData.recipients = [recipient];
if (!data.recipients.some(existingRecipient => recipient.id === existingRecipient.id)) {
payloadData.recipients = [...data.recipients, recipient];
}
} else if (data.type === ChannelType.DM || data.type === ChannelType.GroupDM) {
// Try to resolve the recipient.
const recipient = data.author ?? data.user ?? { id: data.user_id };
payloadData.recipients = [recipient];
}
if (id !== undefined) payloadData.id = id;

View File

@@ -21,7 +21,9 @@ class InteractionCreateAction extends Action {
const client = this.client;
// Resolve and cache partial channels for Interaction#channel getter
const channel = data.channel && this.getChannel(data.channel);
const channel =
data.channel &&
this.getChannel({ ...data.channel, ...('recipients' in data.channel ? { user: data.user } : undefined) });
// Do not emit this for interactions that cache messages that are non-text-based.
let InteractionClass;

View File

@@ -10,6 +10,7 @@ class MessageCreateAction extends Action {
id: data.channel_id,
author: data.author,
...('guild_id' in data && { guild_id: data.guild_id }),
...('channel_type' in data && { type: data.channel_type }),
});
if (channel) {
if (!channel.isTextBased()) return {};

View File

@@ -41,9 +41,14 @@ class UserManager extends CachedManager {
* @private
*/
dmChannel(userId) {
const expectedRecipientIds = [userId, this.client.user.id];
return (
this.client.channels.cache.find(channel => channel.type === ChannelType.DM && channel.recipientId === userId) ??
null
this.client.channels.cache.find(
channel =>
channel.type === ChannelType.DM &&
channel.recipientId === userId &&
channel.recipientIds.every(id => expectedRecipientIds.includes(id)),
) ?? null
);
}

View File

@@ -30,16 +30,18 @@ class DMChannel extends BaseChannel {
super._patch(data);
if (data.recipients) {
const recipient = data.recipients[0];
/**
* The recipient's id
* @type {Snowflake}
* The recipients' ids
* @type {Snowflake[]}
*/
this.recipientId = recipient.id;
this.recipientIds = [
...new Set([...(this.recipientIds ?? []), ...data.recipients.map(recipient => recipient.id)]),
];
if ('username' in recipient || this.client.options.partials.includes(Partials.User)) {
this.client.users._add(recipient);
for (const recipient of data.recipients) {
if ('username' in recipient || this.client.options.partials.includes(Partials.User)) {
this.client.users._add(recipient);
}
}
}
@@ -71,6 +73,18 @@ class DMChannel extends BaseChannel {
return this.lastMessageId === undefined;
}
/**
* The recipient's id.
* <info>For DMChannel the client user is not a part of this might return a wrong id.
* This will return `null` in the next major version.</info>
* @type {Snowflake}
* @readonly
*/
get recipientId() {
// To not be a breaking change this returns the arbitrary first id if this is not a DMChannel with the client user
return this.recipientIds.find(recipientId => recipientId !== this.client.user.id) ?? this.recipientIds[0];
}
/**
* The recipient on the other end of the DM
* @type {?User}

View File

@@ -27,6 +27,10 @@ class TeamMember extends Base {
* @deprecated Use {@link TeamMember#role} instead.
*/
this.permissions = data.permissions;
} else {
// Discord stopped sending this field at some point on or before 2026-04-14.
// Later on the same day, Discord started sending it again, which resulted in this code path.
this.permissions ??= [];
}
if ('membership_state' in data) {

View File

@@ -1514,7 +1514,8 @@ export interface DMChannel extends Omit<
export class DMChannel extends BaseChannel {
private constructor(client: Client<true>, data?: RawDMChannelData);
public flags: Readonly<ChannelFlagsBitField>;
public recipientId: Snowflake;
public get recipientId(): Snowflake;
public recipientIds: Snowflake[];
public get recipient(): User | null;
public type: ChannelType.DM;
public fetch(force?: boolean): Promise<this>;