mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-09 16:13:31 +01:00
fix(ThreadMembersUpdate): Only emit added & removed thread members (#7539)
This commit is contained in:
1
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
1
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -96,6 +96,7 @@ body:
|
||||
- Message
|
||||
- Reaction
|
||||
- GuildScheduledEvent
|
||||
- ThreadMember
|
||||
multiple: true
|
||||
validations:
|
||||
required: true
|
||||
|
||||
@@ -110,6 +110,10 @@ class GenericAction {
|
||||
Partials.GuildScheduledEvent,
|
||||
);
|
||||
}
|
||||
|
||||
getThreadMember(id, manager) {
|
||||
return this.getPayload({ user_id: id }, manager, id, Partials.ThreadMember, false);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = GenericAction;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
const { Collection } = require('@discordjs/collection');
|
||||
const Action = require('./Action');
|
||||
const Events = require('../../util/Events');
|
||||
|
||||
@@ -8,24 +9,35 @@ class ThreadMembersUpdateAction extends Action {
|
||||
const client = this.client;
|
||||
const thread = client.channels.cache.get(data.id);
|
||||
if (thread) {
|
||||
const old = thread.members.cache.clone();
|
||||
thread.memberCount = data.member_count;
|
||||
const addedMembers = new Collection();
|
||||
const removedMembers = new Collection();
|
||||
|
||||
data.added_members?.forEach(rawMember => {
|
||||
thread.members._add(rawMember);
|
||||
});
|
||||
data.added_members?.reduce(
|
||||
(_addedMembers, addedMember) => _addedMembers.set(addedMember.user_id, thread.members._add(addedMember)),
|
||||
addedMembers,
|
||||
);
|
||||
|
||||
data.removed_member_ids?.forEach(memberId => {
|
||||
thread.members.cache.delete(memberId);
|
||||
});
|
||||
data.removed_member_ids?.reduce((removedMembersIds, removedMembersId) => {
|
||||
const threadMember = this.getThreadMember(removedMembersId, thread.members);
|
||||
if (threadMember) removedMembersIds.set(threadMember.id, threadMember);
|
||||
thread.members.cache.delete(removedMembersId);
|
||||
return removedMembersIds;
|
||||
}, removedMembers);
|
||||
|
||||
if (addedMembers.size === 0 && removedMembers.size === 0) {
|
||||
// Uncached thread member(s) left.
|
||||
return {};
|
||||
}
|
||||
|
||||
/**
|
||||
* Emitted whenever members are added or removed from a thread. Requires `GUILD_MEMBERS` privileged intent
|
||||
* @event Client#threadMembersUpdate
|
||||
* @param {Collection<Snowflake, ThreadMember>} oldMembers The members before the update
|
||||
* @param {Collection<Snowflake, ThreadMember>} newMembers The members after the update
|
||||
* @param {ThreadChannel} thread The thread where members got updated
|
||||
* @param {Collection<Snowflake, ThreadMember>} addedMembers The members that were added
|
||||
* @param {Collection<Snowflake, ThreadMember>} removedMembers The members that were removed
|
||||
*/
|
||||
client.emit(Events.ThreadMembersUpdate, old, thread.members.cache);
|
||||
client.emit(Events.ThreadMembersUpdate, thread, addedMembers, removedMembers);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -23,6 +23,12 @@ class ThreadMember extends Base {
|
||||
*/
|
||||
this.joinedTimestamp = null;
|
||||
|
||||
/**
|
||||
* The flags for this thread member. This will be `null` if partial.
|
||||
* @type {?ThreadMemberFlagsBitField}
|
||||
*/
|
||||
this.flags = null;
|
||||
|
||||
/**
|
||||
* The id of the thread member
|
||||
* @type {Snowflake}
|
||||
@@ -34,14 +40,16 @@ class ThreadMember extends Base {
|
||||
|
||||
_patch(data) {
|
||||
if ('join_timestamp' in data) this.joinedTimestamp = Date.parse(data.join_timestamp);
|
||||
if ('flags' in data) this.flags = new ThreadMemberFlagsBitField(data.flags).freeze();
|
||||
}
|
||||
|
||||
if ('flags' in data) {
|
||||
/**
|
||||
* The flags for this thread member
|
||||
* @type {ThreadMemberFlagsBitField}
|
||||
*/
|
||||
this.flags = new ThreadMemberFlagsBitField(data.flags).freeze();
|
||||
}
|
||||
/**
|
||||
* Whether this thread member is a partial
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
*/
|
||||
get partial() {
|
||||
return this.flags === null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,4 +2,12 @@
|
||||
|
||||
const { createEnum } = require('./Enums');
|
||||
|
||||
module.exports = createEnum(['User', 'Channel', 'GuildMember', 'Message', 'Reaction', 'GuildScheduledEvent']);
|
||||
module.exports = createEnum([
|
||||
'User',
|
||||
'Channel',
|
||||
'GuildMember',
|
||||
'Message',
|
||||
'Reaction',
|
||||
'GuildScheduledEvent',
|
||||
'ThreadMember',
|
||||
]);
|
||||
|
||||
11
packages/discord.js/typings/index.d.ts
vendored
11
packages/discord.js/typings/index.d.ts
vendored
@@ -2338,6 +2338,7 @@ export class ThreadMember extends Base {
|
||||
public get manageable(): boolean;
|
||||
public thread: ThreadChannel;
|
||||
public get user(): User | null;
|
||||
public get partial(): false;
|
||||
public remove(reason?: string): Promise<ThreadMember>;
|
||||
}
|
||||
|
||||
@@ -3289,7 +3290,7 @@ export interface AddGuildMemberOptions {
|
||||
fetchWhenExisting?: boolean;
|
||||
}
|
||||
|
||||
export type AllowedPartial = User | Channel | GuildMember | Message | MessageReaction;
|
||||
export type AllowedPartial = User | Channel | GuildMember | Message | MessageReaction | ThreadMember;
|
||||
|
||||
export type AllowedThreadTypeForNewsChannel = ChannelType.GuildNewsThread;
|
||||
|
||||
@@ -3671,8 +3672,9 @@ export interface ClientEvents {
|
||||
threadListSync: [threads: Collection<Snowflake, ThreadChannel>];
|
||||
threadMemberUpdate: [oldMember: ThreadMember, newMember: ThreadMember];
|
||||
threadMembersUpdate: [
|
||||
oldMembers: Collection<Snowflake, ThreadMember>,
|
||||
newMembers: Collection<Snowflake, ThreadMember>,
|
||||
thread: ThreadChannel,
|
||||
addedMembers: Collection<Snowflake, ThreadMember>,
|
||||
removedMembers: Collection<Snowflake, ThreadMember | PartialThreadMember>,
|
||||
];
|
||||
threadUpdate: [oldThread: ThreadChannel, newThread: ThreadChannel];
|
||||
typingStart: [typing: Typing];
|
||||
@@ -4877,6 +4879,8 @@ export interface PartialMessage
|
||||
|
||||
export interface PartialMessageReaction extends Partialize<MessageReaction, 'count'> {}
|
||||
|
||||
export interface PartialThreadMember extends Partialize<ThreadMember, 'flags' | 'joinedAt' | 'joinedTimestamp'> {}
|
||||
|
||||
export interface PartialOverwriteData {
|
||||
id: Snowflake | number;
|
||||
type?: OverwriteType;
|
||||
@@ -4895,6 +4899,7 @@ export enum Partials {
|
||||
Message,
|
||||
Reaction,
|
||||
GuildScheduledEvent,
|
||||
ThreadMember,
|
||||
}
|
||||
|
||||
export interface PartialUser extends Partialize<User, 'username' | 'tag' | 'discriminator'> {}
|
||||
|
||||
@@ -107,6 +107,8 @@ import {
|
||||
CategoryChannelChildManager,
|
||||
ActionRowData,
|
||||
MessageActionRowComponentData,
|
||||
PartialThreadMember,
|
||||
ThreadMemberFlagsBitField,
|
||||
Embed,
|
||||
} from '.';
|
||||
import { expectAssignable, expectDeprecated, expectNotAssignable, expectNotType, expectType } from 'tsd';
|
||||
@@ -719,6 +721,22 @@ client.on('messageCreate', async message => {
|
||||
});
|
||||
});
|
||||
|
||||
client.on('threadMembersUpdate', (thread, addedMembers, removedMembers) => {
|
||||
expectType<ThreadChannel>(thread);
|
||||
expectType<Collection<Snowflake, ThreadMember>>(addedMembers);
|
||||
expectType<Collection<Snowflake, ThreadMember | PartialThreadMember>>(removedMembers);
|
||||
const left = removedMembers.first();
|
||||
if (!left) return;
|
||||
|
||||
if (left.partial) {
|
||||
expectType<PartialThreadMember>(left);
|
||||
expectType<null>(left.flags);
|
||||
} else {
|
||||
expectType<ThreadMember>(left);
|
||||
expectType<ThreadMemberFlagsBitField>(left.flags);
|
||||
}
|
||||
});
|
||||
|
||||
client.on('interactionCreate', async interaction => {
|
||||
expectType<Snowflake | null>(interaction.guildId);
|
||||
expectType<Snowflake | null>(interaction.channelId);
|
||||
|
||||
Reference in New Issue
Block a user