Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(ThreadChannel): better property handling #6172

Merged
merged 3 commits into from Jul 28, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 4 additions & 4 deletions src/managers/ChannelManager.js
Expand Up @@ -19,18 +19,18 @@ class ChannelManager extends CachedManager {
* @name ChannelManager#cache
*/

_add(data, guild, cache = true, allowUnknownGuild = false) {
_add(data, guild, { cache = true, allowUnknownGuild = false, fromInteraction = false } = {}) {
const existing = this.cache.get(data.id);
if (existing) {
if (cache) existing._patch(data);
if (cache) existing._patch(data, fromInteraction);
guild?.channels?._add(existing);
if (ThreadChannelTypes.includes(existing.type)) {
existing.parent?.threads?._add(existing);
}
return existing;
}

const channel = Channel.create(this.client, data, guild, allowUnknownGuild);
const channel = Channel.create(this.client, data, guild, { allowUnknownGuild, fromInteraction });

if (!channel) {
this.client.emit(Events.DEBUG, `Failed to find guild, or unknown type for channel ${data.id} ${data.type}`);
Expand Down Expand Up @@ -99,7 +99,7 @@ class ChannelManager extends CachedManager {
}

const data = await this.client.api.channels(id).get();
return this._add(data, null, cache, allowUnknownGuild);
return this._add(data, null, { cache, allowUnknownGuild });
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/managers/GuildChannelManager.js
Expand Up @@ -169,12 +169,12 @@ class GuildChannelManager extends CachedManager {
const data = await this.client.api.channels(id).get();
// Since this is the guild manager, throw if on a different guild
if (this.guild.id !== data.guild_id) throw new Error('GUILD_CHANNEL_UNOWNED');
return this.client.channels._add(data, this.guild, cache);
return this.client.channels._add(data, this.guild, { cache });
}

const data = await this.client.api.guilds(this.guild.id).channels.get();
const channels = new Collection();
for (const channel of data) channels.set(channel.id, this.client.channels._add(channel, this.guild, cache));
for (const channel of data) channels.set(channel.id, this.client.channels._add(channel, this.guild, { cache }));
return channels;
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/managers/ThreadManager.js
Expand Up @@ -235,7 +235,7 @@ class ThreadManager extends CachedManager {

_mapThreads(rawThreads, cache) {
const threads = rawThreads.threads.reduce((coll, raw) => {
const thread = this.client.channels._add(raw, null, cache);
const thread = this.client.channels._add(raw, null, { cache });
return coll.set(thread.id, thread);
}, new Collection());
// Discord sends the thread id as id in this object
Expand Down
4 changes: 2 additions & 2 deletions src/structures/Channel.js
Expand Up @@ -126,7 +126,7 @@ class Channel extends Base {
return ThreadChannelTypes.includes(this.type);
}

static create(client, data, guild, allowUnknownGuild) {
static create(client, data, guild, { allowUnknownGuild, fromInteraction }) {
if (!CategoryChannel) CategoryChannel = require('./CategoryChannel');
if (!DMChannel) DMChannel = require('./DMChannel');
if (!NewsChannel) NewsChannel = require('./NewsChannel');
Expand Down Expand Up @@ -176,7 +176,7 @@ class Channel extends Base {
case ChannelTypes.GUILD_NEWS_THREAD:
case ChannelTypes.GUILD_PUBLIC_THREAD:
case ChannelTypes.GUILD_PRIVATE_THREAD: {
channel = new ThreadChannel(guild, data, client);
channel = new ThreadChannel(guild, data, client, fromInteraction);
if (!allowUnknownGuild) channel.parent?.threads.cache.set(channel.id, channel);
break;
}
Expand Down
4 changes: 3 additions & 1 deletion src/structures/CommandInteraction.js
Expand Up @@ -121,7 +121,9 @@ class CommandInteraction extends Interaction {
if (member) result.member = this.guild?.members._add({ user, ...member }) ?? member;

const channel = resolved.channels?.[option.value];
if (channel) result.channel = this.client.channels._add(channel, this.guild) ?? channel;
if (channel) {
result.channel = this.client.channels._add(channel, this.guild, { fromInteraction: true }) ?? channel;
}

const role = resolved.roles?.[option.value];
if (role) result.role = this.guild?.roles._add(role) ?? role;
Expand Down
2 changes: 1 addition & 1 deletion src/structures/Invite.js
Expand Up @@ -109,7 +109,7 @@ class Invite extends Base {
* The channel the invite is for
* @type {Channel}
*/
this.channel = this.client.channels._add(data.channel, this.guild, false);
this.channel = this.client.channels._add(data.channel, this.guild, { cache: false });

/**
* The timestamp the invite was created at
Expand Down
55 changes: 42 additions & 13 deletions src/structures/ThreadChannel.js
Expand Up @@ -16,8 +16,9 @@ class ThreadChannel extends Channel {
* @param {Guild} guild The guild the thread channel is part of
* @param {APIChannel} data The data for the thread channel
* @param {Client} [client] A safety parameter for the client that instantiated this
* @param {boolean} [fromInteraction=false] Whether the data was from an interaction (partial)
*/
constructor(guild, data, client) {
constructor(guild, data, client, fromInteraction = false) {
super(guild?.client ?? client, data, false);

/**
Expand All @@ -43,10 +44,10 @@ class ThreadChannel extends Channel {
* @type {ThreadMemberManager}
*/
this.members = new ThreadMemberManager(this);
if (data) this._patch(data);
if (data) this._patch(data, fromInteraction);
}

_patch(data) {
_patch(data, partial = false) {
super._patch(data);

/**
Expand All @@ -62,37 +63,52 @@ class ThreadChannel extends Channel {
if ('parent_id' in data) {
/**
* The id of the parent channel of this thread
* @type {Snowflake}
* @type {?Snowflake}
*/
this.parentId = data.parent_id;
} else if (!this.parentId) {
this.parentId = null;
}

if ('thread_metadata' in data) {
/**
* Whether the thread is locked
* @type {boolean}
* @type {?boolean}
ckohen marked this conversation as resolved.
Show resolved Hide resolved
*/
this.locked = data.thread_metadata.locked ?? false;

/**
* Whether the thread is archived
* @type {boolean}
* @type {?boolean}
*/
this.archived = data.thread_metadata.archived;

/**
* The amount of time (in minutes) after which the thread will automatically archive in case of no recent activity
* @type {number}
* @type {?number}
*/
this.autoArchiveDuration = data.thread_metadata.auto_archive_duration;

/**
* The timestamp when the thread's archive status was last changed
* <info>If the thread was never archived or unarchived, this is the timestamp at which the thread was
* created</info>
* @type {number}
* @type {?number}
*/
this.archiveTimestamp = new Date(data.thread_metadata.archive_timestamp).getTime();
} else {
if (!this.locked) {
this.locked = null;
}
if (!this.archived) {
this.archived = null;
}
if (!this.autoArchiveDuration) {
this.autoArchiveDuration = null;
}
if (!this.archiveTimestamp) {
this.archiveTimestamp = null;
}
}

if ('owner_id' in data) {
Expand All @@ -101,6 +117,8 @@ class ThreadChannel extends Channel {
* @type {?Snowflake}
*/
this.ownerId = data.owner_id;
} else if (!this.ownerId) {
this.ownerId = null;
}

if ('last_message_id' in data) {
Expand All @@ -109,6 +127,8 @@ class ThreadChannel extends Channel {
* @type {?Snowflake}
*/
this.lastMessageId = data.last_message_id;
} else if (!this.lastMessageId) {
this.lastMessageId = null;
}

if ('last_pin_timestamp' in data) {
Expand All @@ -117,34 +137,42 @@ class ThreadChannel extends Channel {
* @type {?number}
*/
this.lastPinTimestamp = data.last_pin_timestamp ? new Date(data.last_pin_timestamp).getTime() : null;
} else if (!this.lastPinTimestamp) {
this.lastPinTimestamp = null;
}

if ('rate_limit_per_user' in data) {
if ('rate_limit_per_user' in data || !partial) {
/**
* The ratelimit per user for this thread (in seconds)
* @type {number}
* @type {?number}
*/
this.rateLimitPerUser = data.rate_limit_per_user ?? 0;
} else if (!this.rateLimitPerUser) {
this.rateLimitPerUser = null;
}

if ('message_count' in data) {
/**
* The approximate count of messages in this thread
* <info>This stops counting at 50. If you need an approximate value higher than that, use
* `ThreadChannel#messages.cache.size`</info>
* @type {number}
* @type {?number}
*/
this.messageCount = data.message_count;
} else if (!this.messageCount) {
this.messageCount = null;
}

if ('member_count' in data) {
/**
* The approximate count of users in this thread
* <info>This stops counting at 50. If you need an approximate value higher than that, use
* `ThreadChannel#members.cache.size`</info>
* @type {number}
* @type {?number}
*/
this.memberCount = data.member_count;
} else if (!this.memberCount) {
this.memberCount = null;
}

if (data.member && this.client.user) this.members._add({ user_id: this.client.user.id, ...data.member });
Expand All @@ -163,10 +191,11 @@ class ThreadChannel extends Channel {
/**
* The time at which this thread's archive status was last changed
* <info>If the thread was never archived or unarchived, this is the time at which the thread was created</info>
* @type {Date}
* @type {?Date}
* @readonly
*/
get archivedAt() {
if (!this.archiveTimestamp) return null;
return new Date(this.archiveTimestamp);
}

Expand Down
18 changes: 9 additions & 9 deletions typings/index.d.ts
Expand Up @@ -1660,29 +1660,29 @@ export class TextChannel extends TextBasedChannel(GuildChannel) {
}

export class ThreadChannel extends TextBasedChannel(Channel) {
public constructor(guild: Guild, data?: object, client?: Client);
public archived: boolean;
public readonly archivedAt: Date;
public archiveTimestamp: number;
public autoArchiveDuration: ThreadAutoArchiveDuration;
public constructor(guild: Guild, data?: object, client?: Client, fromInteraction?: boolean);
public archived: boolean | null;
public readonly archivedAt: Date | null;
public archiveTimestamp: number | null;
public autoArchiveDuration: ThreadAutoArchiveDuration | null;
public readonly editable: boolean;
public guild: Guild;
public guildId: Snowflake;
public readonly guildMembers: Collection<Snowflake, GuildMember>;
public readonly joinable: boolean;
public readonly joined: boolean;
public locked: boolean;
public locked: boolean | null;
public readonly manageable: boolean;
public readonly sendable: boolean;
public memberCount: number | null;
public messageCount: number | null;
public messages: MessageManager;
public members: ThreadMemberManager;
public name: string;
public ownerId: Snowflake;
public ownerId: Snowflake | null;
public readonly parent: TextChannel | NewsChannel | null;
public parentId: Snowflake;
public rateLimitPerUser: number;
public parentId: Snowflake | null;
public rateLimitPerUser: number | null;
public type: ThreadChannelTypes;
public readonly unarchivable: boolean;
public delete(reason?: string): Promise<ThreadChannel>;
Expand Down