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