mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-19 13:03:31 +01:00
feat: backport guild forum support to v13 (#8651)
Co-authored-by: Jaworek <jaworekwiadomosci@gmail.com> Co-authored-by: Sugden <28943913+NotSugden@users.noreply.github.com>
This commit is contained in:
@@ -10,7 +10,7 @@ class WebhooksUpdate extends Action {
|
|||||||
/**
|
/**
|
||||||
* Emitted whenever a channel has its webhooks changed.
|
* Emitted whenever a channel has its webhooks changed.
|
||||||
* @event Client#webhookUpdate
|
* @event Client#webhookUpdate
|
||||||
* @param {TextChannel|NewsChannel|VoiceChannel} channel The channel that had a webhook update
|
* @param {TextChannel|NewsChannel|VoiceChannel|ForumChannel} channel The channel that had a webhook update
|
||||||
*/
|
*/
|
||||||
if (channel) client.emit(Events.WEBHOOKS_UPDATE, channel);
|
if (channel) client.emit(Events.WEBHOOKS_UPDATE, channel);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -166,6 +166,8 @@ const Messages = {
|
|||||||
NOT_IMPLEMENTED: (what, name) => `Method ${what} not implemented on ${name}.`,
|
NOT_IMPLEMENTED: (what, name) => `Method ${what} not implemented on ${name}.`,
|
||||||
|
|
||||||
SWEEP_FILTER_RETURN: 'The return value of the sweepFilter function was not false or a Function',
|
SWEEP_FILTER_RETURN: 'The return value of the sweepFilter function was not false or a Function',
|
||||||
|
|
||||||
|
GUILD_FORUM_MESSAGE_REQUIRED: 'You must provide a message to create a guild forum thread',
|
||||||
};
|
};
|
||||||
|
|
||||||
for (const [name, message] of Object.entries(Messages)) register(name, message);
|
for (const [name, message] of Object.entries(Messages)) register(name, message);
|
||||||
|
|||||||
@@ -9,10 +9,17 @@ const GuildChannel = require('../structures/GuildChannel');
|
|||||||
const PermissionOverwrites = require('../structures/PermissionOverwrites');
|
const PermissionOverwrites = require('../structures/PermissionOverwrites');
|
||||||
const ThreadChannel = require('../structures/ThreadChannel');
|
const ThreadChannel = require('../structures/ThreadChannel');
|
||||||
const Webhook = require('../structures/Webhook');
|
const Webhook = require('../structures/Webhook');
|
||||||
const { ThreadChannelTypes, ChannelTypes, VideoQualityModes } = require('../util/Constants');
|
const ChannelFlags = require('../util/ChannelFlags');
|
||||||
|
const {
|
||||||
|
ThreadChannelTypes,
|
||||||
|
ChannelTypes,
|
||||||
|
VideoQualityModes,
|
||||||
|
SortOrderTypes,
|
||||||
|
ForumLayoutTypes,
|
||||||
|
} = require('../util/Constants');
|
||||||
const DataResolver = require('../util/DataResolver');
|
const DataResolver = require('../util/DataResolver');
|
||||||
const Util = require('../util/Util');
|
const Util = require('../util/Util');
|
||||||
const { resolveAutoArchiveMaxLimit } = require('../util/Util');
|
const { resolveAutoArchiveMaxLimit, transformGuildForumTag, transformGuildDefaultReaction } = require('../util/Util');
|
||||||
|
|
||||||
let cacheWarningEmitted = false;
|
let cacheWarningEmitted = false;
|
||||||
let storeChannelDeprecationEmitted = false;
|
let storeChannelDeprecationEmitted = false;
|
||||||
@@ -73,8 +80,9 @@ class GuildChannelManager extends CachedManager {
|
|||||||
* Data that can be resolved to give a Guild Channel object. This can be:
|
* Data that can be resolved to give a Guild Channel object. This can be:
|
||||||
* * A GuildChannel object
|
* * A GuildChannel object
|
||||||
* * A ThreadChannel object
|
* * A ThreadChannel object
|
||||||
|
* * A ForumChannel object
|
||||||
* * A Snowflake
|
* * A Snowflake
|
||||||
* @typedef {GuildChannel|ThreadChannel|Snowflake} GuildChannelResolvable
|
* @typedef {GuildChannel|ThreadChannel|ForumChannel|Snowflake} GuildChannelResolvable
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -138,6 +146,11 @@ class GuildChannelManager extends CachedManager {
|
|||||||
position,
|
position,
|
||||||
rateLimitPerUser,
|
rateLimitPerUser,
|
||||||
rtcRegion,
|
rtcRegion,
|
||||||
|
videoQualityMode,
|
||||||
|
availableTags,
|
||||||
|
defaultReactionEmoji,
|
||||||
|
defaultSortOrder,
|
||||||
|
defaultForumLayout,
|
||||||
reason,
|
reason,
|
||||||
} = {},
|
} = {},
|
||||||
) {
|
) {
|
||||||
@@ -145,6 +158,13 @@ class GuildChannelManager extends CachedManager {
|
|||||||
permissionOverwrites &&= permissionOverwrites.map(o => PermissionOverwrites.resolve(o, this.guild));
|
permissionOverwrites &&= permissionOverwrites.map(o => PermissionOverwrites.resolve(o, this.guild));
|
||||||
const intType = typeof type === 'number' ? type : ChannelTypes[type] ?? ChannelTypes.GUILD_TEXT;
|
const intType = typeof type === 'number' ? type : ChannelTypes[type] ?? ChannelTypes.GUILD_TEXT;
|
||||||
|
|
||||||
|
const videoMode = typeof videoQualityMode === 'number' ? videoQualityMode : VideoQualityModes[videoQualityMode];
|
||||||
|
|
||||||
|
const sortMode = typeof defaultSortOrder === 'number' ? defaultSortOrder : SortOrderTypes[defaultSortOrder];
|
||||||
|
|
||||||
|
const layoutMode =
|
||||||
|
typeof defaultForumLayout === 'number' ? defaultForumLayout : ForumLayoutTypes[defaultForumLayout];
|
||||||
|
|
||||||
if (intType === ChannelTypes.GUILD_STORE && !storeChannelDeprecationEmitted) {
|
if (intType === ChannelTypes.GUILD_STORE && !storeChannelDeprecationEmitted) {
|
||||||
storeChannelDeprecationEmitted = true;
|
storeChannelDeprecationEmitted = true;
|
||||||
process.emitWarning(
|
process.emitWarning(
|
||||||
@@ -167,6 +187,11 @@ class GuildChannelManager extends CachedManager {
|
|||||||
permission_overwrites: permissionOverwrites,
|
permission_overwrites: permissionOverwrites,
|
||||||
rate_limit_per_user: rateLimitPerUser,
|
rate_limit_per_user: rateLimitPerUser,
|
||||||
rtc_region: rtcRegion,
|
rtc_region: rtcRegion,
|
||||||
|
video_quality_mode: videoMode,
|
||||||
|
available_tags: availableTags?.map(availableTag => transformGuildForumTag(availableTag)),
|
||||||
|
default_reaction_emoji: defaultReactionEmoji && transformGuildDefaultReaction(defaultReactionEmoji),
|
||||||
|
default_sort_order: sortMode,
|
||||||
|
default_forum_layout: layoutMode,
|
||||||
},
|
},
|
||||||
reason,
|
reason,
|
||||||
});
|
});
|
||||||
@@ -175,7 +200,7 @@ class GuildChannelManager extends CachedManager {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a webhook for the channel.
|
* Creates a webhook for the channel.
|
||||||
* @param {TextChannel|NewsChannel|VoiceChannel|Snowflake} channel The channel to create the webhook for
|
* @param {GuildChannelResolvable} channel The channel to create the webhook for
|
||||||
* @param {string} name The name of the webhook
|
* @param {string} name The name of the webhook
|
||||||
* @param {ChannelWebhookCreateOptions} [options] Options for creating the webhook
|
* @param {ChannelWebhookCreateOptions} [options] Options for creating the webhook
|
||||||
* @returns {Promise<Webhook>} Returns the created Webhook
|
* @returns {Promise<Webhook>} Returns the created Webhook
|
||||||
@@ -224,6 +249,11 @@ class GuildChannelManager extends CachedManager {
|
|||||||
* The default auto archive duration for all new threads in this channel
|
* The default auto archive duration for all new threads in this channel
|
||||||
* @property {?string} [rtcRegion] The RTC region of the channel
|
* @property {?string} [rtcRegion] The RTC region of the channel
|
||||||
* @property {?VideoQualityMode|number} [videoQualityMode] The camera video quality mode of the channel
|
* @property {?VideoQualityMode|number} [videoQualityMode] The camera video quality mode of the channel
|
||||||
|
* @property {ChannelFlagsResolvable} [flags] The flags to set on the channel
|
||||||
|
* @property {GuildForumTagData[]} [availableTags] The tags to set as available in a forum channel
|
||||||
|
* @property {?DefaultReactionEmoji} [defaultReactionEmoji] The emoji to set as the default reaction emoji
|
||||||
|
* @property {number} [defaultThreadRateLimitPerUser] The rate limit per user (slowmode) to set on forum posts
|
||||||
|
* @property {?SortOrderType} [defaultSortOrder] The default sort order mode to set on the channel
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -282,6 +312,12 @@ class GuildChannelManager extends CachedManager {
|
|||||||
rate_limit_per_user: data.rateLimitPerUser,
|
rate_limit_per_user: data.rateLimitPerUser,
|
||||||
default_auto_archive_duration: defaultAutoArchiveDuration,
|
default_auto_archive_duration: defaultAutoArchiveDuration,
|
||||||
permission_overwrites,
|
permission_overwrites,
|
||||||
|
available_tags: data.availableTags?.map(availableTag => transformGuildForumTag(availableTag)),
|
||||||
|
default_reaction_emoji: data.defaultReactionEmoji && transformGuildDefaultReaction(data.defaultReactionEmoji),
|
||||||
|
default_thread_rate_limit_per_user: data.defaultThreadRateLimitPerUser,
|
||||||
|
flags: 'flags' in data ? ChannelFlags.resolve(data.flags) : undefined,
|
||||||
|
default_sort_order:
|
||||||
|
typeof data.defaultSortOrder === 'string' ? SortOrderTypes[data.defaultSortOrder] : data.defaultSortOrder,
|
||||||
},
|
},
|
||||||
reason,
|
reason,
|
||||||
});
|
});
|
||||||
|
|||||||
90
src/managers/GuildForumThreadManager.js
Normal file
90
src/managers/GuildForumThreadManager.js
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const ThreadManager = require('./ThreadManager');
|
||||||
|
const { TypeError } = require('../errors');
|
||||||
|
const MessagePayload = require('../structures/MessagePayload');
|
||||||
|
const { resolveAutoArchiveMaxLimit } = require('../util/Util');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manages API methods for threads in forum channels and stores their cache.
|
||||||
|
* @extends {ThreadManager}
|
||||||
|
*/
|
||||||
|
class GuildForumThreadManager extends ThreadManager {
|
||||||
|
/**
|
||||||
|
* The channel this Manager belongs to
|
||||||
|
* @name GuildForumThreadManager#channel
|
||||||
|
* @type {ForumChannel}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {BaseMessageOptions} GuildForumThreadMessageCreateOptions
|
||||||
|
* @property {StickerResolvable} [stickers] The stickers to send with the message
|
||||||
|
* @property {BitFieldResolvable} [flags] The flags to send with the message
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Options for creating a thread.
|
||||||
|
* @typedef {StartThreadOptions} GuildForumThreadCreateOptions
|
||||||
|
* @property {GuildForumThreadMessageCreateOptions|MessagePayload} message The message associated with the thread post
|
||||||
|
* @property {Snowflake[]} [appliedTags] The tags to apply to the thread
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new thread in the channel.
|
||||||
|
* @param {GuildForumThreadCreateOptions} [options] Options to create a new thread
|
||||||
|
* @returns {Promise<ThreadChannel>}
|
||||||
|
* @example
|
||||||
|
* // Create a new forum post
|
||||||
|
* forum.threads
|
||||||
|
* .create({
|
||||||
|
* name: 'Food Talk',
|
||||||
|
* autoArchiveDuration: 60,
|
||||||
|
* message: {
|
||||||
|
* content: 'Discuss your favorite food!',
|
||||||
|
* },
|
||||||
|
* reason: 'Needed a separate thread for food',
|
||||||
|
* })
|
||||||
|
* .then(threadChannel => console.log(threadChannel))
|
||||||
|
* .catch(console.error);
|
||||||
|
*/
|
||||||
|
async create({
|
||||||
|
name,
|
||||||
|
autoArchiveDuration = this.channel.defaultAutoArchiveDuration,
|
||||||
|
message,
|
||||||
|
reason,
|
||||||
|
rateLimitPerUser,
|
||||||
|
appliedTags,
|
||||||
|
} = {}) {
|
||||||
|
if (!message) {
|
||||||
|
throw new TypeError('GUILD_FORUM_MESSAGE_REQUIRED');
|
||||||
|
}
|
||||||
|
|
||||||
|
let messagePayload;
|
||||||
|
|
||||||
|
if (message instanceof MessagePayload) {
|
||||||
|
messagePayload = message.resolveData();
|
||||||
|
} else {
|
||||||
|
messagePayload = MessagePayload.create(this, message).resolveData();
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data: body, files } = await messagePayload.resolveFiles();
|
||||||
|
|
||||||
|
if (autoArchiveDuration === 'MAX') autoArchiveDuration = resolveAutoArchiveMaxLimit(this.channel.guild);
|
||||||
|
|
||||||
|
const data = await this.client.api.channels(this.channel.id).threads.post({
|
||||||
|
data: {
|
||||||
|
name,
|
||||||
|
auto_archive_duration: autoArchiveDuration,
|
||||||
|
rate_limit_per_user: rateLimitPerUser,
|
||||||
|
applied_tags: appliedTags,
|
||||||
|
message: body,
|
||||||
|
},
|
||||||
|
files,
|
||||||
|
reason,
|
||||||
|
});
|
||||||
|
|
||||||
|
return this.client.actions.ThreadCreate.handle(data).thread;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = GuildForumThreadManager;
|
||||||
98
src/managers/GuildTextThreadManager.js
Normal file
98
src/managers/GuildTextThreadManager.js
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const ThreadManager = require('./ThreadManager');
|
||||||
|
const { TypeError } = require('../errors');
|
||||||
|
const { ChannelTypes } = require('../util/Constants');
|
||||||
|
const { resolveAutoArchiveMaxLimit } = require('../util/Util');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manages API methods for {@link ThreadChannel} objects and stores their cache.
|
||||||
|
* @extends {ThreadManager}
|
||||||
|
*/
|
||||||
|
class GuildTextThreadManager extends ThreadManager {
|
||||||
|
/**
|
||||||
|
* The channel this Manager belongs to
|
||||||
|
* @name GuildTextThreadManager#channel
|
||||||
|
* @type {TextChannel|NewsChannel}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Options for creating a thread. <warn>Only one of `startMessage` or `type` can be defined.</warn>
|
||||||
|
* @typedef {StartThreadOptions} GuildTextThreadCreateOptions
|
||||||
|
* @property {MessageResolvable} [startMessage] The message to start a thread from. <warn>If this is defined then type
|
||||||
|
* of thread gets automatically defined and cannot be changed. The provided `type` field will be ignored</warn>
|
||||||
|
* @property {ThreadChannelTypes|number} [type] The type of thread to create. Defaults to `GUILD_PUBLIC_THREAD` if
|
||||||
|
* created in a {@link TextChannel} <warn>When creating threads in a {@link NewsChannel} this is ignored and is always
|
||||||
|
* `GUILD_NEWS_THREAD`</warn>
|
||||||
|
* @property {boolean} [invitable] Whether non-moderators can add other non-moderators to the thread
|
||||||
|
* <info>Can only be set when type will be `GUILD_PRIVATE_THREAD`</info>
|
||||||
|
* @property {number} [rateLimitPerUser] The rate limit per user (slowmode) for the new channel in seconds
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new thread in the channel.
|
||||||
|
* @param {GuildTextThreadCreateOptions} [options] Options to create a new thread
|
||||||
|
* @returns {Promise<ThreadChannel>}
|
||||||
|
* @example
|
||||||
|
* // Create a new public thread
|
||||||
|
* channel.threads
|
||||||
|
* .create({
|
||||||
|
* name: 'food-talk',
|
||||||
|
* autoArchiveDuration: 60,
|
||||||
|
* reason: 'Needed a separate thread for food',
|
||||||
|
* })
|
||||||
|
* .then(threadChannel => console.log(threadChannel))
|
||||||
|
* .catch(console.error);
|
||||||
|
* @example
|
||||||
|
* // Create a new private thread
|
||||||
|
* channel.threads
|
||||||
|
* .create({
|
||||||
|
* name: 'mod-talk',
|
||||||
|
* autoArchiveDuration: 60,
|
||||||
|
* type: 'GUILD_PRIVATE_THREAD',
|
||||||
|
* reason: 'Needed a separate thread for moderation',
|
||||||
|
* })
|
||||||
|
* .then(threadChannel => console.log(threadChannel))
|
||||||
|
* .catch(console.error);
|
||||||
|
*/
|
||||||
|
async create({
|
||||||
|
name,
|
||||||
|
autoArchiveDuration = this.channel.defaultAutoArchiveDuration,
|
||||||
|
startMessage,
|
||||||
|
type,
|
||||||
|
invitable,
|
||||||
|
reason,
|
||||||
|
rateLimitPerUser,
|
||||||
|
} = {}) {
|
||||||
|
let path = this.client.api.channels(this.channel.id);
|
||||||
|
if (type && typeof type !== 'string' && typeof type !== 'number') {
|
||||||
|
throw new TypeError('INVALID_TYPE', 'type', 'ThreadChannelType or Number');
|
||||||
|
}
|
||||||
|
let resolvedType =
|
||||||
|
this.channel.type === 'GUILD_NEWS' ? ChannelTypes.GUILD_NEWS_THREAD : ChannelTypes.GUILD_PUBLIC_THREAD;
|
||||||
|
if (startMessage) {
|
||||||
|
const startMessageId = this.channel.messages.resolveId(startMessage);
|
||||||
|
if (!startMessageId) throw new TypeError('INVALID_TYPE', 'startMessage', 'MessageResolvable');
|
||||||
|
path = path.messages(startMessageId);
|
||||||
|
} else if (this.channel.type !== 'GUILD_NEWS') {
|
||||||
|
resolvedType = typeof type === 'string' ? ChannelTypes[type] : type ?? resolvedType;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (autoArchiveDuration === 'MAX') autoArchiveDuration = resolveAutoArchiveMaxLimit(this.channel.guild);
|
||||||
|
|
||||||
|
const data = await path.threads.post({
|
||||||
|
data: {
|
||||||
|
name,
|
||||||
|
auto_archive_duration: autoArchiveDuration,
|
||||||
|
type: resolvedType,
|
||||||
|
invitable: resolvedType === ChannelTypes.GUILD_PRIVATE_THREAD ? invitable : undefined,
|
||||||
|
rate_limit_per_user: rateLimitPerUser,
|
||||||
|
},
|
||||||
|
reason,
|
||||||
|
});
|
||||||
|
|
||||||
|
return this.client.actions.ThreadCreate.handle(data).thread;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = GuildTextThreadManager;
|
||||||
@@ -4,8 +4,6 @@ const { Collection } = require('@discordjs/collection');
|
|||||||
const CachedManager = require('./CachedManager');
|
const CachedManager = require('./CachedManager');
|
||||||
const { TypeError } = require('../errors');
|
const { TypeError } = require('../errors');
|
||||||
const ThreadChannel = require('../structures/ThreadChannel');
|
const ThreadChannel = require('../structures/ThreadChannel');
|
||||||
const { ChannelTypes } = require('../util/Constants');
|
|
||||||
const { resolveAutoArchiveMaxLimit } = require('../util/Util');
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manages API methods for {@link ThreadChannel} objects and stores their cache.
|
* Manages API methods for {@link ThreadChannel} objects and stores their cache.
|
||||||
@@ -60,84 +58,6 @@ class ThreadManager extends CachedManager {
|
|||||||
* @returns {?Snowflake}
|
* @returns {?Snowflake}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
|
||||||
* Options for creating a thread. <warn>Only one of `startMessage` or `type` can be defined.</warn>
|
|
||||||
* @typedef {StartThreadOptions} ThreadCreateOptions
|
|
||||||
* @property {MessageResolvable} [startMessage] The message to start a thread from. <warn>If this is defined then type
|
|
||||||
* of thread gets automatically defined and cannot be changed. The provided `type` field will be ignored</warn>
|
|
||||||
* @property {ThreadChannelTypes|number} [type] The type of thread to create. Defaults to `GUILD_PUBLIC_THREAD` if
|
|
||||||
* created in a {@link TextChannel} <warn>When creating threads in a {@link NewsChannel} this is ignored and is always
|
|
||||||
* `GUILD_NEWS_THREAD`</warn>
|
|
||||||
* @property {boolean} [invitable] Whether non-moderators can add other non-moderators to the thread
|
|
||||||
* <info>Can only be set when type will be `GUILD_PRIVATE_THREAD`</info>
|
|
||||||
* @property {number} [rateLimitPerUser] The rate limit per user (slowmode) for the new channel in seconds
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new thread in the channel.
|
|
||||||
* @param {ThreadCreateOptions} [options] Options to create a new thread
|
|
||||||
* @returns {Promise<ThreadChannel>}
|
|
||||||
* @example
|
|
||||||
* // Create a new public thread
|
|
||||||
* channel.threads
|
|
||||||
* .create({
|
|
||||||
* name: 'food-talk',
|
|
||||||
* autoArchiveDuration: 60,
|
|
||||||
* reason: 'Needed a separate thread for food',
|
|
||||||
* })
|
|
||||||
* .then(threadChannel => console.log(threadChannel))
|
|
||||||
* .catch(console.error);
|
|
||||||
* @example
|
|
||||||
* // Create a new private thread
|
|
||||||
* channel.threads
|
|
||||||
* .create({
|
|
||||||
* name: 'mod-talk',
|
|
||||||
* autoArchiveDuration: 60,
|
|
||||||
* type: 'GUILD_PRIVATE_THREAD',
|
|
||||||
* reason: 'Needed a separate thread for moderation',
|
|
||||||
* })
|
|
||||||
* .then(threadChannel => console.log(threadChannel))
|
|
||||||
* .catch(console.error);
|
|
||||||
*/
|
|
||||||
async create({
|
|
||||||
name,
|
|
||||||
autoArchiveDuration = this.channel.defaultAutoArchiveDuration,
|
|
||||||
startMessage,
|
|
||||||
type,
|
|
||||||
invitable,
|
|
||||||
reason,
|
|
||||||
rateLimitPerUser,
|
|
||||||
} = {}) {
|
|
||||||
let path = this.client.api.channels(this.channel.id);
|
|
||||||
if (type && typeof type !== 'string' && typeof type !== 'number') {
|
|
||||||
throw new TypeError('INVALID_TYPE', 'type', 'ThreadChannelType or Number');
|
|
||||||
}
|
|
||||||
let resolvedType =
|
|
||||||
this.channel.type === 'GUILD_NEWS' ? ChannelTypes.GUILD_NEWS_THREAD : ChannelTypes.GUILD_PUBLIC_THREAD;
|
|
||||||
if (startMessage) {
|
|
||||||
const startMessageId = this.channel.messages.resolveId(startMessage);
|
|
||||||
if (!startMessageId) throw new TypeError('INVALID_TYPE', 'startMessage', 'MessageResolvable');
|
|
||||||
path = path.messages(startMessageId);
|
|
||||||
} else if (this.channel.type !== 'GUILD_NEWS') {
|
|
||||||
resolvedType = typeof type === 'string' ? ChannelTypes[type] : type ?? resolvedType;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (autoArchiveDuration === 'MAX') autoArchiveDuration = resolveAutoArchiveMaxLimit(this.channel.guild);
|
|
||||||
|
|
||||||
const data = await path.threads.post({
|
|
||||||
data: {
|
|
||||||
name,
|
|
||||||
auto_archive_duration: autoArchiveDuration,
|
|
||||||
type: resolvedType,
|
|
||||||
invitable: resolvedType === ChannelTypes.GUILD_PRIVATE_THREAD ? invitable : undefined,
|
|
||||||
rate_limit_per_user: rateLimitPerUser,
|
|
||||||
},
|
|
||||||
reason,
|
|
||||||
});
|
|
||||||
|
|
||||||
return this.client.actions.ThreadCreate.handle(data).thread;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The options for fetching multiple threads, the properties are mutually exclusive
|
* The options for fetching multiple threads, the properties are mutually exclusive
|
||||||
* @typedef {Object} FetchThreadsOptions
|
* @typedef {Object} FetchThreadsOptions
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
const GuildChannel = require('./GuildChannel');
|
const GuildChannel = require('./GuildChannel');
|
||||||
const TextBasedChannel = require('./interfaces/TextBasedChannel');
|
const TextBasedChannel = require('./interfaces/TextBasedChannel');
|
||||||
|
const GuildTextThreadManager = require('../managers/GuildTextThreadManager');
|
||||||
const MessageManager = require('../managers/MessageManager');
|
const MessageManager = require('../managers/MessageManager');
|
||||||
const ThreadManager = require('../managers/ThreadManager');
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a text-based guild channel on Discord.
|
* Represents a text-based guild channel on Discord.
|
||||||
@@ -22,9 +22,9 @@ class BaseGuildTextChannel extends GuildChannel {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* A manager of the threads belonging to this channel
|
* A manager of the threads belonging to this channel
|
||||||
* @type {ThreadManager}
|
* @type {GuildTextThreadManager}
|
||||||
*/
|
*/
|
||||||
this.threads = new ThreadManager(this);
|
this.threads = new GuildTextThreadManager(this);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the guild considers this channel NSFW
|
* If the guild considers this channel NSFW
|
||||||
|
|||||||
@@ -30,16 +30,25 @@ class CategoryChannel extends GuildChannel {
|
|||||||
/**
|
/**
|
||||||
* Options for creating a channel using {@link CategoryChannel#createChannel}.
|
* Options for creating a channel using {@link CategoryChannel#createChannel}.
|
||||||
* @typedef {Object} CategoryCreateChannelOptions
|
* @typedef {Object} CategoryCreateChannelOptions
|
||||||
|
* @property {string} [name] The name of the new channel
|
||||||
* @property {ChannelType|number} [type='GUILD_TEXT'] The type of the new channel.
|
* @property {ChannelType|number} [type='GUILD_TEXT'] The type of the new channel.
|
||||||
|
* @property {number} [position] Position of the new channel
|
||||||
* @property {string} [topic] The topic for the new channel
|
* @property {string} [topic] The topic for the new channel
|
||||||
* @property {boolean} [nsfw] Whether the new channel is NSFW
|
* @property {boolean} [nsfw] Whether the new channel is NSFW
|
||||||
* @property {number} [bitrate] Bitrate of the new channel in bits (only voice)
|
* @property {number} [bitrate] Bitrate of the new channel in bits (only voice)
|
||||||
* @property {number} [userLimit] Maximum amount of users allowed in the new channel (only voice)
|
* @property {number} [userLimit] Maximum amount of users allowed in the new channel (only voice)
|
||||||
* @property {OverwriteResolvable[]|Collection<Snowflake, OverwriteResolvable>} [permissionOverwrites]
|
* @property {OverwriteResolvable[]|Collection<Snowflake, OverwriteResolvable>} [permissionOverwrites]
|
||||||
* Permission overwrites of the new channel
|
* Permission overwrites of the new channel
|
||||||
* @property {number} [position] Position of the new channel
|
|
||||||
* @property {number} [rateLimitPerUser] The rate limit per user (slowmode) for the new channel in seconds
|
* @property {number} [rateLimitPerUser] The rate limit per user (slowmode) for the new channel in seconds
|
||||||
* @property {string} [rtcRegion] The specific region of the new channel.
|
* @property {ThreadAutoArchiveDuration} [defaultAutoArchiveDuration]
|
||||||
|
* The default auto archive duration for all new threads in this channel
|
||||||
|
* @property {?string} [rtcRegion] The specific region of the new channel
|
||||||
|
* @property {?VideoQualityMode|number} [videoQualityMode] The camera video quality mode of the new channel
|
||||||
|
* @property {ChannelFlagsResolvable} [flags] The flags to set on the new channel
|
||||||
|
* @property {GuildForumTagData[]} [availableTags] The tags to set as available in a forum channel
|
||||||
|
* @property {?DefaultReactionEmoji} [defaultReactionEmoji] The emoji to set as the default reaction emoji
|
||||||
|
* @property {number} [defaultThreadRateLimitPerUser] The rate limit per user (slowmode) to set on forum posts
|
||||||
|
* @property {?SortOrderType} [defaultSortOrder] The default sort order mode to set on the new channel
|
||||||
* @property {string} [reason] Reason for creating the new channel
|
* @property {string} [reason] Reason for creating the new channel
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ let TextChannel;
|
|||||||
let ThreadChannel;
|
let ThreadChannel;
|
||||||
let VoiceChannel;
|
let VoiceChannel;
|
||||||
let DirectoryChannel;
|
let DirectoryChannel;
|
||||||
|
let ForumChannel;
|
||||||
|
const ChannelFlags = require('../util/ChannelFlags');
|
||||||
const { ChannelTypes, ThreadChannelTypes, VoiceBasedChannelTypes } = require('../util/Constants');
|
const { ChannelTypes, ThreadChannelTypes, VoiceBasedChannelTypes } = require('../util/Constants');
|
||||||
const SnowflakeUtil = require('../util/SnowflakeUtil');
|
const SnowflakeUtil = require('../util/SnowflakeUtil');
|
||||||
|
|
||||||
@@ -47,6 +49,17 @@ class Channel extends Base {
|
|||||||
* @type {Snowflake}
|
* @type {Snowflake}
|
||||||
*/
|
*/
|
||||||
this.id = data.id;
|
this.id = data.id;
|
||||||
|
|
||||||
|
if ('flags' in data) {
|
||||||
|
/**
|
||||||
|
* The flags that are applied to the channel.
|
||||||
|
* <info>This is only `null` in a {@link PartialGroupDMChannel}. In all other cases, it is not `null`.</info>
|
||||||
|
* @type {?Readonly<ChannelFlags>}
|
||||||
|
*/
|
||||||
|
this.flags = new ChannelFlags(data.flags).freeze();
|
||||||
|
} else {
|
||||||
|
this.flags ??= new ChannelFlags().freeze();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -183,6 +196,7 @@ class Channel extends Base {
|
|||||||
ThreadChannel ??= require('./ThreadChannel');
|
ThreadChannel ??= require('./ThreadChannel');
|
||||||
VoiceChannel ??= require('./VoiceChannel');
|
VoiceChannel ??= require('./VoiceChannel');
|
||||||
DirectoryChannel ??= require('./DirectoryChannel');
|
DirectoryChannel ??= require('./DirectoryChannel');
|
||||||
|
ForumChannel ??= require('./ForumChannel');
|
||||||
|
|
||||||
let channel;
|
let channel;
|
||||||
if (!data.guild_id && !guild) {
|
if (!data.guild_id && !guild) {
|
||||||
@@ -232,6 +246,10 @@ class Channel extends Base {
|
|||||||
case ChannelTypes.GUILD_DIRECTORY:
|
case ChannelTypes.GUILD_DIRECTORY:
|
||||||
channel = new DirectoryChannel(client, data);
|
channel = new DirectoryChannel(client, data);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ChannelTypes.GUILD_FORUM:
|
||||||
|
channel = new ForumChannel(guild, data, client);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (channel && !allowUnknownGuild) guild.channels?.cache.set(channel.id, channel);
|
if (channel && !allowUnknownGuild) guild.channels?.cache.set(channel.id, channel);
|
||||||
}
|
}
|
||||||
|
|||||||
264
src/structures/ForumChannel.js
Normal file
264
src/structures/ForumChannel.js
Normal file
@@ -0,0 +1,264 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const GuildChannel = require('./GuildChannel');
|
||||||
|
const TextBasedChannel = require('./interfaces/TextBasedChannel');
|
||||||
|
const GuildForumThreadManager = require('../managers/GuildForumThreadManager');
|
||||||
|
const { SortOrderTypes, ForumLayoutTypes } = require('../util/Constants');
|
||||||
|
const { transformAPIGuildForumTag, transformAPIGuildDefaultReaction } = require('../util/Util');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} GuildForumTagEmoji
|
||||||
|
* @property {?Snowflake} id The id of a guild's custom emoji
|
||||||
|
* @property {?string} name The unicode character of the emoji
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} GuildForumTag
|
||||||
|
* @property {Snowflake} id The id of the tag
|
||||||
|
* @property {string} name The name of the tag
|
||||||
|
* @property {boolean} moderated Whether this tag can only be added to or removed from threads
|
||||||
|
* by a member with the `ManageThreads` permission
|
||||||
|
* @property {?GuildForumTagEmoji} emoji The emoji of this tag
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} GuildForumTagData
|
||||||
|
* @property {Snowflake} [id] The id of the tag
|
||||||
|
* @property {string} name The name of the tag
|
||||||
|
* @property {boolean} [moderated] Whether this tag can only be added to or removed from threads
|
||||||
|
* by a member with the `ManageThreads` permission
|
||||||
|
* @property {?GuildForumTagEmoji} [emoji] The emoji of this tag
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} DefaultReactionEmoji
|
||||||
|
* @property {?Snowflake} id The id of a guild's custom emoji
|
||||||
|
* @property {?string} name The unicode character of the emoji
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a channel that only contains threads
|
||||||
|
* @extends {GuildChannel}
|
||||||
|
* @implements {TextBasedChannel}
|
||||||
|
*/
|
||||||
|
class ForumChannel extends GuildChannel {
|
||||||
|
constructor(guild, data, client) {
|
||||||
|
super(guild, data, client, false);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A manager of the threads belonging to this channel
|
||||||
|
* @type {GuildForumThreadManager}
|
||||||
|
*/
|
||||||
|
this.threads = new GuildForumThreadManager(this);
|
||||||
|
|
||||||
|
this._patch(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
_patch(data) {
|
||||||
|
super._patch(data);
|
||||||
|
if ('available_tags' in data) {
|
||||||
|
/**
|
||||||
|
* The set of tags that can be used in this channel.
|
||||||
|
* @type {GuildForumTag[]}
|
||||||
|
*/
|
||||||
|
this.availableTags = data.available_tags.map(tag => transformAPIGuildForumTag(tag));
|
||||||
|
} else {
|
||||||
|
this.availableTags ??= [];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('default_reaction_emoji' in data) {
|
||||||
|
/**
|
||||||
|
* The emoji to show in the add reaction button on a thread in a guild forum channel
|
||||||
|
* @type {?DefaultReactionEmoji}
|
||||||
|
*/
|
||||||
|
this.defaultReactionEmoji =
|
||||||
|
data.default_reaction_emoji && transformAPIGuildDefaultReaction(data.default_reaction_emoji);
|
||||||
|
} else {
|
||||||
|
this.defaultReactionEmoji ??= null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('default_thread_rate_limit_per_user' in data) {
|
||||||
|
/**
|
||||||
|
* The initial rate limit per user (slowmode) to set on newly created threads in a channel.
|
||||||
|
* @type {?number}
|
||||||
|
*/
|
||||||
|
this.defaultThreadRateLimitPerUser = data.default_thread_rate_limit_per_user;
|
||||||
|
} else {
|
||||||
|
this.defaultThreadRateLimitPerUser ??= null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('rate_limit_per_user' in data) {
|
||||||
|
/**
|
||||||
|
* The rate limit per user (slowmode) for this channel.
|
||||||
|
* @type {?number}
|
||||||
|
*/
|
||||||
|
this.rateLimitPerUser = data.rate_limit_per_user;
|
||||||
|
} else {
|
||||||
|
this.rateLimitPerUser ??= null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('default_auto_archive_duration' in data) {
|
||||||
|
/**
|
||||||
|
* The default auto archive duration for newly created threads in this channel.
|
||||||
|
* @type {?ThreadAutoArchiveDuration}
|
||||||
|
*/
|
||||||
|
this.defaultAutoArchiveDuration = data.default_auto_archive_duration;
|
||||||
|
} else {
|
||||||
|
this.defaultAutoArchiveDuration ??= null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('nsfw' in data) {
|
||||||
|
/**
|
||||||
|
* If this channel is considered NSFW.
|
||||||
|
* @type {boolean}
|
||||||
|
*/
|
||||||
|
this.nsfw = data.nsfw;
|
||||||
|
} else {
|
||||||
|
this.nsfw ??= false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('topic' in data) {
|
||||||
|
/**
|
||||||
|
* The topic of this channel.
|
||||||
|
* @type {?string}
|
||||||
|
*/
|
||||||
|
this.topic = data.topic;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('default_sort_order' in data) {
|
||||||
|
/**
|
||||||
|
* The default sort order mode used to order posts
|
||||||
|
* @type {?SortOrderType}
|
||||||
|
*/
|
||||||
|
this.defaultSortOrder = SortOrderTypes[data.default_sort_order];
|
||||||
|
} else {
|
||||||
|
this.defaultSortOrder ??= null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default layout type used to display posts
|
||||||
|
* @type {ForumLayoutType}
|
||||||
|
*/
|
||||||
|
this.defaultForumLayout = ForumLayoutTypes[data.default_forum_layout];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the available tags for this forum channel
|
||||||
|
* @param {GuildForumTagData[]} availableTags The tags to set as available in this channel
|
||||||
|
* @param {string} [reason] Reason for changing the available tags
|
||||||
|
* @returns {Promise<ForumChannel>}
|
||||||
|
*/
|
||||||
|
setAvailableTags(availableTags, reason) {
|
||||||
|
return this.edit({ availableTags }, reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the default reaction emoji for this channel
|
||||||
|
* @param {?DefaultReactionEmoji} defaultReactionEmoji The emoji to set as the default reaction emoji
|
||||||
|
* @param {string} [reason] Reason for changing the default reaction emoji
|
||||||
|
* @returns {Promise<ForumChannel>}
|
||||||
|
*/
|
||||||
|
setDefaultReactionEmoji(defaultReactionEmoji, reason) {
|
||||||
|
return this.edit({ defaultReactionEmoji }, reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the default rate limit per user (slowmode) for new threads in this channel
|
||||||
|
* @param {number} defaultThreadRateLimitPerUser The rate limit to set on newly created threads in this channel
|
||||||
|
* @param {string} [reason] Reason for changing the default rate limit
|
||||||
|
* @returns {Promise<ForumChannel>}
|
||||||
|
*/
|
||||||
|
setDefaultThreadRateLimitPerUser(defaultThreadRateLimitPerUser, reason) {
|
||||||
|
return this.edit({ defaultThreadRateLimitPerUser }, reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the default sort order mode used to order posts
|
||||||
|
* @param {?SortOrderType} defaultSortOrder The default sort order mode to set on this channel
|
||||||
|
* @param {string} [reason] Reason for changing the default sort order
|
||||||
|
* @returns {Promise<ForumChannel>}
|
||||||
|
*/
|
||||||
|
setDefaultSortOrder(defaultSortOrder, reason) {
|
||||||
|
return this.edit({ defaultSortOrder }, reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the default forum layout type used to display posts
|
||||||
|
* @param {ForumLayoutType} defaultForumLayout The default forum layout type to set on this channel
|
||||||
|
* @param {string} [reason] Reason for changing the default forum layout
|
||||||
|
* @returns {Promise<ForumChannel>}
|
||||||
|
*/
|
||||||
|
setDefaultForumLayout(defaultForumLayout, reason) {
|
||||||
|
return this.edit({ defaultForumLayout }, reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an invite to this guild channel.
|
||||||
|
* @param {CreateInviteOptions} [options={}] The options for creating the invite
|
||||||
|
* @returns {Promise<Invite>}
|
||||||
|
* @example
|
||||||
|
* // Create an invite to a channel
|
||||||
|
* channel.createInvite()
|
||||||
|
* .then(invite => console.log(`Created an invite with a code of ${invite.code}`))
|
||||||
|
* .catch(console.error);
|
||||||
|
*/
|
||||||
|
createInvite(options) {
|
||||||
|
return this.guild.invites.create(this.id, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches a collection of invites to this guild channel.
|
||||||
|
* Resolves with a collection mapping invites by their codes.
|
||||||
|
* @param {boolean} [cache=true] Whether or not to cache the fetched invites
|
||||||
|
* @returns {Promise<Collection<string, Invite>>}
|
||||||
|
*/
|
||||||
|
fetchInvites(cache = true) {
|
||||||
|
return this.guild.invites.fetch({ channelId: this.id, cache });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the default auto archive duration for all newly created threads in this channel.
|
||||||
|
* @param {ThreadAutoArchiveDuration} defaultAutoArchiveDuration The new default auto archive duration
|
||||||
|
* @param {string} [reason] Reason for changing the channel's default auto archive duration
|
||||||
|
* @returns {Promise<ForumChannel>}
|
||||||
|
*/
|
||||||
|
setDefaultAutoArchiveDuration(defaultAutoArchiveDuration, reason) {
|
||||||
|
return this.edit({ defaultAutoArchiveDuration }, reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a new topic for the guild channel.
|
||||||
|
* @param {?string} topic The new topic for the guild channel
|
||||||
|
* @param {string} [reason] Reason for changing the guild channel's topic
|
||||||
|
* @returns {Promise<ForumChannel>}
|
||||||
|
* @example
|
||||||
|
* // Set a new channel topic
|
||||||
|
* channel.setTopic('needs more rate limiting')
|
||||||
|
* .then(newChannel => console.log(`Channel's new topic is ${newChannel.topic}`))
|
||||||
|
* .catch(console.error);
|
||||||
|
*/
|
||||||
|
setTopic(topic, reason) {
|
||||||
|
return this.edit({ topic }, reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
// These are here only for documentation purposes - they are implemented by TextBasedChannel
|
||||||
|
/* eslint-disable no-empty-function */
|
||||||
|
createWebhook() {}
|
||||||
|
fetchWebhooks() {}
|
||||||
|
setNSFW() {}
|
||||||
|
setRateLimitPerUser() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
TextBasedChannel.applyToClass(ForumChannel, true, [
|
||||||
|
'send',
|
||||||
|
'lastMessage',
|
||||||
|
'lastPinAt',
|
||||||
|
'bulkDelete',
|
||||||
|
'sendTyping',
|
||||||
|
'createMessageCollector',
|
||||||
|
'awaitMessages',
|
||||||
|
'createMessageComponentCollector',
|
||||||
|
'awaitMessageComponent',
|
||||||
|
]);
|
||||||
|
|
||||||
|
module.exports = ForumChannel;
|
||||||
@@ -562,7 +562,7 @@ class Guild extends AnonymousGuild {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Widget channel for this guild
|
* Widget channel for this guild
|
||||||
* @type {?TextChannel}
|
* @type {?(TextChannel|NewsChannel|VoiceChannel|StageChannel|ForumChannel)}
|
||||||
* @readonly
|
* @readonly
|
||||||
*/
|
*/
|
||||||
get widgetChannel() {
|
get widgetChannel() {
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ const Permissions = require('../util/Permissions');
|
|||||||
* - {@link NewsChannel}
|
* - {@link NewsChannel}
|
||||||
* - {@link StoreChannel}
|
* - {@link StoreChannel}
|
||||||
* - {@link StageChannel}
|
* - {@link StageChannel}
|
||||||
|
* - {@link ForumChannel}
|
||||||
* @extends {Channel}
|
* @extends {Channel}
|
||||||
* @abstract
|
* @abstract
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -58,6 +58,17 @@ class Message extends Base {
|
|||||||
*/
|
*/
|
||||||
this.id = data.id;
|
this.id = data.id;
|
||||||
|
|
||||||
|
if ('position' in data) {
|
||||||
|
/**
|
||||||
|
* A generally increasing integer (there may be gaps or duplicates) that represents
|
||||||
|
* the approximate position of the message in a thread.
|
||||||
|
* @type {?number}
|
||||||
|
*/
|
||||||
|
this.position = data.position;
|
||||||
|
} else {
|
||||||
|
this.position ??= null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The timestamp the message was sent at
|
* The timestamp the message was sent at
|
||||||
* @type {number}
|
* @type {number}
|
||||||
@@ -855,9 +866,10 @@ class Message extends Base {
|
|||||||
* archived. This can be:
|
* archived. This can be:
|
||||||
* * `60` (1 hour)
|
* * `60` (1 hour)
|
||||||
* * `1440` (1 day)
|
* * `1440` (1 day)
|
||||||
* * `4320` (3 days) <warn>This is only available when the guild has the `THREE_DAY_THREAD_ARCHIVE` feature.</warn>
|
* * `4320` (3 days)
|
||||||
* * `10080` (7 days) <warn>This is only available when the guild has the `SEVEN_DAY_THREAD_ARCHIVE` feature.</warn>
|
* * `10080` (7 days)
|
||||||
* * `'MAX'` Based on the guild's features
|
* * `'MAX'` (7 days)
|
||||||
|
* <warn>This option is deprecated and will be removed in the next major version.</warn>
|
||||||
* @typedef {number|string} ThreadAutoArchiveDuration
|
* @typedef {number|string} ThreadAutoArchiveDuration
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -873,7 +885,7 @@ class Message extends Base {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new public thread from this message
|
* Create a new public thread from this message
|
||||||
* @see ThreadManager#create
|
* @see GuildTextThreadManager#create
|
||||||
* @param {StartThreadOptions} [options] Options for starting a thread on this message
|
* @param {StartThreadOptions} [options] Options for starting a thread on this message
|
||||||
* @returns {Promise<ThreadChannel>}
|
* @returns {Promise<ThreadChannel>}
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -142,9 +142,11 @@ class MessagePayload {
|
|||||||
|
|
||||||
let username;
|
let username;
|
||||||
let avatarURL;
|
let avatarURL;
|
||||||
|
let threadName;
|
||||||
if (isWebhook) {
|
if (isWebhook) {
|
||||||
username = this.options.username ?? this.target.name;
|
username = this.options.username ?? this.target.name;
|
||||||
if (this.options.avatarURL) avatarURL = this.options.avatarURL;
|
if (this.options.avatarURL) avatarURL = this.options.avatarURL;
|
||||||
|
if (this.options.threadName) threadName = this.options.threadName;
|
||||||
}
|
}
|
||||||
|
|
||||||
let flags;
|
let flags;
|
||||||
@@ -208,6 +210,7 @@ class MessagePayload {
|
|||||||
message_reference,
|
message_reference,
|
||||||
attachments: this.options.attachments,
|
attachments: this.options.attachments,
|
||||||
sticker_ids: this.options.stickers?.map(sticker => sticker.id ?? sticker),
|
sticker_ids: this.options.stickers?.map(sticker => sticker.id ?? sticker),
|
||||||
|
thread_name: threadName,
|
||||||
};
|
};
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,9 @@ class PartialGroupDMChannel extends Channel {
|
|||||||
constructor(client, data) {
|
constructor(client, data) {
|
||||||
super(client, data);
|
super(client, data);
|
||||||
|
|
||||||
|
// No flags are present when fetching partial group DM channels.
|
||||||
|
this.flags = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The name of this Group DM Channel
|
* The name of this Group DM Channel
|
||||||
* @type {?string}
|
* @type {?string}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ const TextBasedChannel = require('./interfaces/TextBasedChannel');
|
|||||||
const { RangeError } = require('../errors');
|
const { RangeError } = require('../errors');
|
||||||
const MessageManager = require('../managers/MessageManager');
|
const MessageManager = require('../managers/MessageManager');
|
||||||
const ThreadMemberManager = require('../managers/ThreadMemberManager');
|
const ThreadMemberManager = require('../managers/ThreadMemberManager');
|
||||||
|
const ChannelFlags = require('../util/ChannelFlags');
|
||||||
const Permissions = require('../util/Permissions');
|
const Permissions = require('../util/Permissions');
|
||||||
const { resolveAutoArchiveMaxLimit } = require('../util/Util');
|
const { resolveAutoArchiveMaxLimit } = require('../util/Util');
|
||||||
|
|
||||||
@@ -158,9 +159,8 @@ class ThreadChannel extends Channel {
|
|||||||
|
|
||||||
if ('message_count' in data) {
|
if ('message_count' in data) {
|
||||||
/**
|
/**
|
||||||
* The approximate count of messages in this thread
|
* <info>Threads created before July 1, 2022 may have an inaccurate count.
|
||||||
* <info>This stops counting at 50. If you need an approximate value higher than that, use
|
* If you need an approximate value higher than that, use `ThreadChannel#messages.cache.size`</info>
|
||||||
* `ThreadChannel#messages.cache.size`</info>
|
|
||||||
* @type {?number}
|
* @type {?number}
|
||||||
*/
|
*/
|
||||||
this.messageCount = data.message_count;
|
this.messageCount = data.message_count;
|
||||||
@@ -180,6 +180,27 @@ class ThreadChannel extends Channel {
|
|||||||
this.memberCount ??= null;
|
this.memberCount ??= null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ('total_message_sent' in data) {
|
||||||
|
/**
|
||||||
|
* The number of messages ever sent in a thread, similar to {@link ThreadChannel#messageCount} except it
|
||||||
|
* will not decrement whenever a message is deleted
|
||||||
|
* @type {?number}
|
||||||
|
*/
|
||||||
|
this.totalMessageSent = data.total_message_sent;
|
||||||
|
} else {
|
||||||
|
this.totalMessageSent ??= null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('applied_tags' in data) {
|
||||||
|
/**
|
||||||
|
* The tags applied to this thread
|
||||||
|
* @type {Snowflake[]}
|
||||||
|
*/
|
||||||
|
this.appliedTags = data.applied_tags;
|
||||||
|
} else {
|
||||||
|
this.appliedTags ??= [];
|
||||||
|
}
|
||||||
|
|
||||||
if (data.member && this.client.user) this.members._add({ user_id: this.client.user.id, ...data.member });
|
if (data.member && this.client.user) this.members._add({ user_id: this.client.user.id, ...data.member });
|
||||||
if (data.messages) for (const message of data.messages) this.messages._add(message);
|
if (data.messages) for (const message of data.messages) this.messages._add(message);
|
||||||
}
|
}
|
||||||
@@ -225,7 +246,7 @@ class ThreadChannel extends Channel {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The parent channel of this thread
|
* The parent channel of this thread
|
||||||
* @type {?(NewsChannel|TextChannel)}
|
* @type {?(NewsChannel|TextChannel|ForumChannel)}
|
||||||
* @readonly
|
* @readonly
|
||||||
*/
|
*/
|
||||||
get parent() {
|
get parent() {
|
||||||
@@ -280,14 +301,16 @@ class ThreadChannel extends Channel {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetches the message that started this thread, if any.
|
* Fetches the message that started this thread, if any.
|
||||||
* <info>This only works when the thread started from a message in the parent channel, otherwise the promise will
|
* <info>The `Promise` will reject if the original message in a forum post is deleted
|
||||||
* reject. If you just need the id of that message, use {@link ThreadChannel#id} instead.</info>
|
* or when the original message in the parent channel is deleted.
|
||||||
|
* If you just need the id of that message, use {@link ThreadChannel#id} instead.</info>
|
||||||
* @param {BaseFetchOptions} [options] Additional options for this fetch
|
* @param {BaseFetchOptions} [options] Additional options for this fetch
|
||||||
* @returns {Promise<Message|null>}
|
* @returns {Promise<Message|null>}
|
||||||
*/
|
*/
|
||||||
// eslint-disable-next-line require-await
|
// eslint-disable-next-line require-await
|
||||||
async fetchStarterMessage(options) {
|
async fetchStarterMessage(options) {
|
||||||
return this.parent?.messages.fetch(this.id, options) ?? null;
|
const channel = this.parent?.type === 'GUILD_FORUM' ? this : this.parent;
|
||||||
|
return channel?.messages.fetch({ message: this.id, ...options }) ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -300,6 +323,7 @@ class ThreadChannel extends Channel {
|
|||||||
* @property {number} [rateLimitPerUser] The rate limit per user (slowmode) for the thread in seconds
|
* @property {number} [rateLimitPerUser] The rate limit per user (slowmode) for the thread in seconds
|
||||||
* @property {boolean} [locked] Whether the thread is locked
|
* @property {boolean} [locked] Whether the thread is locked
|
||||||
* @property {boolean} [invitable] Whether non-moderators can add other non-moderators to a thread
|
* @property {boolean} [invitable] Whether non-moderators can add other non-moderators to a thread
|
||||||
|
* @property {ChannelFlagsResolvable} [flags] The flags to set on the channel
|
||||||
* <info>Can only be edited on `GUILD_PRIVATE_THREAD`</info>
|
* <info>Can only be edited on `GUILD_PRIVATE_THREAD`</info>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -326,6 +350,8 @@ class ThreadChannel extends Channel {
|
|||||||
rate_limit_per_user: data.rateLimitPerUser,
|
rate_limit_per_user: data.rateLimitPerUser,
|
||||||
locked: data.locked,
|
locked: data.locked,
|
||||||
invitable: this.type === 'GUILD_PRIVATE_THREAD' ? data.invitable : undefined,
|
invitable: this.type === 'GUILD_PRIVATE_THREAD' ? data.invitable : undefined,
|
||||||
|
applied_tags: data.appliedTags,
|
||||||
|
flags: 'flags' in data ? ChannelFlags.resolve(data.flags) : undefined,
|
||||||
},
|
},
|
||||||
reason,
|
reason,
|
||||||
});
|
});
|
||||||
@@ -419,6 +445,34 @@ class ThreadChannel extends Channel {
|
|||||||
return this.edit({ rateLimitPerUser }, reason);
|
return this.edit({ rateLimitPerUser }, reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pins this thread from the forum channel.
|
||||||
|
* @param {string} [reason] Reason for pinning
|
||||||
|
* @returns {Promise<ThreadChannel>}
|
||||||
|
*/
|
||||||
|
pin(reason) {
|
||||||
|
return this.edit({ flags: this.flags.add(ChannelFlags.FLAGS.PINNED), reason });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unpins this thread from the forum channel.
|
||||||
|
* @param {string} [reason] Reason for unpinning
|
||||||
|
* @returns {Promise<ThreadChannel>}
|
||||||
|
*/
|
||||||
|
unpin(reason) {
|
||||||
|
return this.edit({ flags: this.flags.remove(ChannelFlags.FLAGS.PINNED), reason });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the applied tags for this channel (only applicable to forum threads)
|
||||||
|
* @param {Snowflake[]} appliedTags The tags to set for this channel
|
||||||
|
* @param {string} [reason] Reason for changing the thread's applied tags
|
||||||
|
* @returns {Promise<GuildForumThreadChannel>}
|
||||||
|
*/
|
||||||
|
setAppliedTags(appliedTags, reason) {
|
||||||
|
return this.edit({ appliedTags, reason });
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether the client user is a member of the thread.
|
* Whether the client user is a member of the thread.
|
||||||
* @type {boolean}
|
* @type {boolean}
|
||||||
|
|||||||
@@ -131,6 +131,7 @@ class Webhook {
|
|||||||
* Action rows containing interactive components for the message (buttons, select menus)
|
* Action rows containing interactive components for the message (buttons, select menus)
|
||||||
* @property {Snowflake} [threadId] The id of the thread this message belongs to
|
* @property {Snowflake} [threadId] The id of the thread this message belongs to
|
||||||
* <info>For interaction webhooks, this property is ignored</info>
|
* <info>For interaction webhooks, this property is ignored</info>
|
||||||
|
* @property {string} [threadName] Name of the thread to create (only available if webhook is in a forum channel)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ class WelcomeChannel extends Base {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The channel of this welcome channel
|
* The channel of this welcome channel
|
||||||
* @type {?(TextChannel|NewsChannel|StoreChannel)}
|
* @type {?(TextChannel|NewsChannel|StoreChannel|ForumChannel)}
|
||||||
*/
|
*/
|
||||||
get channel() {
|
get channel() {
|
||||||
return this.client.channels.resolve(this.channelId);
|
return this.client.channels.resolve(this.channelId);
|
||||||
|
|||||||
45
src/util/ChannelFlags.js
Normal file
45
src/util/ChannelFlags.js
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const BitField = require('./BitField');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data structure that makes it easy to interact with a {@link BaseChannel#flags} bitfield.
|
||||||
|
* @extends {BitField}
|
||||||
|
*/
|
||||||
|
class ChannelFlags extends BitField {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Numeric guild channel flags. All available properties:
|
||||||
|
* * `PINNED`
|
||||||
|
* * `REQUIRE_TAG`
|
||||||
|
* @type {Object}
|
||||||
|
* @see {@link https://discord.com/developers/docs/resources/channel#channel-object-channel-flags}
|
||||||
|
*/
|
||||||
|
ChannelFlags.FLAGS = {
|
||||||
|
PINNED: 1 << 1,
|
||||||
|
REQUIRE_TAG: 1 << 4,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name ChannelFlags
|
||||||
|
* @kind constructor
|
||||||
|
* @memberof ChannelFlags
|
||||||
|
* @param {BitFieldResolvable} [bits=0] Bit(s) to read from
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bitfield of the packed bits
|
||||||
|
* @type {number}
|
||||||
|
* @name ChannelFlags#bitfield
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data that can be resolved to give a channel flag bitfield. This can be:
|
||||||
|
* * A string (see {@link ChannelFlags.FLAGS})
|
||||||
|
* * A channel flag
|
||||||
|
* * An instance of ChannelFlags
|
||||||
|
* * An Array of ChannelFlags
|
||||||
|
* @typedef {string|number|ChannelFlags|ChannelFlagsResolvable[]} ChannelFlagsResolvable
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports = ChannelFlags;
|
||||||
@@ -648,6 +648,7 @@ exports.ActivityTypes = createEnum(['PLAYING', 'STREAMING', 'LISTENING', 'WATCHI
|
|||||||
* * `GUILD_PRIVATE_THREAD` - a guild text channel's private thread channel
|
* * `GUILD_PRIVATE_THREAD` - a guild text channel's private thread channel
|
||||||
* * `GUILD_STAGE_VOICE` - a guild stage voice channel
|
* * `GUILD_STAGE_VOICE` - a guild stage voice channel
|
||||||
* * `GUILD_DIRECTORY` - the channel in a hub containing guilds
|
* * `GUILD_DIRECTORY` - the channel in a hub containing guilds
|
||||||
|
* * `GUILD_FORUM` - a channel that can only contain threads
|
||||||
* * `UNKNOWN` - a generic channel of unknown type, could be Channel or GuildChannel
|
* * `UNKNOWN` - a generic channel of unknown type, could be Channel or GuildChannel
|
||||||
* @typedef {string} ChannelType
|
* @typedef {string} ChannelType
|
||||||
* @see {@link https://discord.com/developers/docs/resources/channel#channel-object-channel-types}
|
* @see {@link https://discord.com/developers/docs/resources/channel#channel-object-channel-types}
|
||||||
@@ -667,6 +668,7 @@ exports.ChannelTypes = createEnum([
|
|||||||
'GUILD_PRIVATE_THREAD',
|
'GUILD_PRIVATE_THREAD',
|
||||||
'GUILD_STAGE_VOICE',
|
'GUILD_STAGE_VOICE',
|
||||||
'GUILD_DIRECTORY',
|
'GUILD_DIRECTORY',
|
||||||
|
'GUILD_FORUM',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1383,6 +1385,25 @@ exports.GuildScheduledEventEntityTypes = createEnum([null, 'STAGE_INSTANCE', 'VO
|
|||||||
*/
|
*/
|
||||||
exports.VideoQualityModes = createEnum([null, 'AUTO', 'FULL']);
|
exports.VideoQualityModes = createEnum([null, 'AUTO', 'FULL']);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sort {@link ForumChannel} posts by creation time or activity
|
||||||
|
* * LATEST_ACTIVITY
|
||||||
|
* * CREATION_DATE
|
||||||
|
* @typedef {string} SortOrderType
|
||||||
|
* @see {@link https://discord.com/developers/docs/resources/channel/#channel-object-sort-order-types}
|
||||||
|
*/
|
||||||
|
exports.SortOrderTypes = createEnum([null, 'LATEST_ACTIVITY', 'CREATION_DATE']);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default forum layout to set on the {@link ForumChannel}
|
||||||
|
* * NOT_SET
|
||||||
|
* * LIST_VIEW
|
||||||
|
* * GALLERY_VIEW
|
||||||
|
* @typedef {string} ForumLayoutType
|
||||||
|
* @see {@link https://discord.com/developers/docs/resources/channel/#channel-object-forum-layout-types}
|
||||||
|
*/
|
||||||
|
exports.ForumLayoutTypes = createEnum(['NOT_SET', 'LIST_VIEW', 'GALLERY_VIEW']);
|
||||||
|
|
||||||
exports._cleanupSymbol = Symbol('djsCleanup');
|
exports._cleanupSymbol = Symbol('djsCleanup');
|
||||||
|
|
||||||
function keyMirror(arr) {
|
function keyMirror(arr) {
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ const isObject = d => typeof d === 'object' && d !== null;
|
|||||||
|
|
||||||
let deprecationEmittedForSplitMessage = false;
|
let deprecationEmittedForSplitMessage = false;
|
||||||
let deprecationEmittedForRemoveMentions = false;
|
let deprecationEmittedForRemoveMentions = false;
|
||||||
|
let deprecationEmittedForResolveAutoArchiveMaxLimit = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contains various general-purpose utility methods.
|
* Contains various general-purpose utility methods.
|
||||||
@@ -661,12 +662,84 @@ class Util extends null {
|
|||||||
/**
|
/**
|
||||||
* Resolves the maximum time a guild's thread channels should automatcally archive in case of no recent activity.
|
* Resolves the maximum time a guild's thread channels should automatcally archive in case of no recent activity.
|
||||||
* @param {Guild} guild The guild to resolve this limit from.
|
* @param {Guild} guild The guild to resolve this limit from.
|
||||||
|
* @deprecated This will be removed in the next major version.
|
||||||
* @returns {number}
|
* @returns {number}
|
||||||
*/
|
*/
|
||||||
static resolveAutoArchiveMaxLimit({ features }) {
|
static resolveAutoArchiveMaxLimit() {
|
||||||
if (features.includes('SEVEN_DAY_THREAD_ARCHIVE')) return 10080;
|
if (!deprecationEmittedForResolveAutoArchiveMaxLimit) {
|
||||||
if (features.includes('THREE_DAY_THREAD_ARCHIVE')) return 4320;
|
process.emitWarning(
|
||||||
return 1440;
|
// eslint-disable-next-line max-len
|
||||||
|
"The Util.resolveAutoArchiveMaxLimit method and the 'MAX' option are deprecated and will be removed in the next major version.",
|
||||||
|
'DeprecationWarning',
|
||||||
|
);
|
||||||
|
deprecationEmittedForResolveAutoArchiveMaxLimit = true;
|
||||||
|
}
|
||||||
|
return 10080;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transforms an API guild forum tag to camel-cased guild forum tag.
|
||||||
|
* @param {APIGuildForumTag} tag The tag to transform
|
||||||
|
* @returns {GuildForumTag}
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
|
static transformAPIGuildForumTag(tag) {
|
||||||
|
return {
|
||||||
|
id: tag.id,
|
||||||
|
name: tag.name,
|
||||||
|
moderated: tag.moderated,
|
||||||
|
emoji:
|
||||||
|
tag.emoji_id ?? tag.emoji_name
|
||||||
|
? {
|
||||||
|
id: tag.emoji_id,
|
||||||
|
name: tag.emoji_name,
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transforms a camel-cased guild forum tag to an API guild forum tag.
|
||||||
|
* @param {GuildForumTag} tag The tag to transform
|
||||||
|
* @returns {APIGuildForumTag}
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
|
static transformGuildForumTag(tag) {
|
||||||
|
return {
|
||||||
|
id: tag.id,
|
||||||
|
name: tag.name,
|
||||||
|
moderated: tag.moderated,
|
||||||
|
emoji_id: tag.emoji?.id ?? null,
|
||||||
|
emoji_name: tag.emoji?.name ?? null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transforms an API guild forum default reaction object to a
|
||||||
|
* camel-cased guild forum default reaction object.
|
||||||
|
* @param {APIGuildForumDefaultReactionEmoji} defaultReaction The default reaction to transform
|
||||||
|
* @returns {DefaultReactionEmoji}
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
|
static transformAPIGuildDefaultReaction(defaultReaction) {
|
||||||
|
return {
|
||||||
|
id: defaultReaction.emoji_id,
|
||||||
|
name: defaultReaction.emoji_name,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transforms a camel-cased guild forum default reaction object to an
|
||||||
|
* API guild forum default reaction object.
|
||||||
|
* @param {DefaultReactionEmoji} defaultReaction The default reaction to transform
|
||||||
|
* @returns {APIGuildForumDefaultReactionEmoji}
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
|
static transformGuildDefaultReaction(defaultReaction) {
|
||||||
|
return {
|
||||||
|
emoji_id: defaultReaction.id,
|
||||||
|
emoji_name: defaultReaction.name,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
12
typings/enums.d.ts
vendored
12
typings/enums.d.ts
vendored
@@ -49,6 +49,18 @@ export const enum ChannelTypes {
|
|||||||
GUILD_PRIVATE_THREAD = 12,
|
GUILD_PRIVATE_THREAD = 12,
|
||||||
GUILD_STAGE_VOICE = 13,
|
GUILD_STAGE_VOICE = 13,
|
||||||
GUILD_DIRECTORY = 14,
|
GUILD_DIRECTORY = 14,
|
||||||
|
GUILD_FORUM = 15,
|
||||||
|
}
|
||||||
|
|
||||||
|
export const enum SortOrderType {
|
||||||
|
LATEST_ACTIVITY = 1,
|
||||||
|
CREATION_DATE = 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
export const enum ForumLayoutType {
|
||||||
|
NOT_SET = 0,
|
||||||
|
LIST_VIEW = 1,
|
||||||
|
GALLERY_VIEW = 2,
|
||||||
}
|
}
|
||||||
|
|
||||||
export const enum MessageTypes {
|
export const enum MessageTypes {
|
||||||
|
|||||||
147
typings/index.d.ts
vendored
147
typings/index.d.ts
vendored
@@ -90,6 +90,8 @@ import {
|
|||||||
GuildScheduledEventStatuses,
|
GuildScheduledEventStatuses,
|
||||||
GuildScheduledEventPrivacyLevels,
|
GuildScheduledEventPrivacyLevels,
|
||||||
VideoQualityModes,
|
VideoQualityModes,
|
||||||
|
SortOrderType,
|
||||||
|
ForumLayoutType,
|
||||||
} from './enums';
|
} from './enums';
|
||||||
import {
|
import {
|
||||||
RawActivityData,
|
RawActivityData,
|
||||||
@@ -442,7 +444,7 @@ export class BaseGuildTextChannel extends TextBasedChannelMixin(GuildChannel) {
|
|||||||
public defaultAutoArchiveDuration?: ThreadAutoArchiveDuration;
|
public defaultAutoArchiveDuration?: ThreadAutoArchiveDuration;
|
||||||
public rateLimitPerUser: number | null;
|
public rateLimitPerUser: number | null;
|
||||||
public nsfw: boolean;
|
public nsfw: boolean;
|
||||||
public threads: ThreadManager<AllowedThreadTypeForTextChannel | AllowedThreadTypeForNewsChannel>;
|
public threads: GuildTextThreadManager<AllowedThreadTypeForTextChannel | AllowedThreadTypeForNewsChannel>;
|
||||||
public topic: string | null;
|
public topic: string | null;
|
||||||
public createInvite(options?: CreateInviteOptions): Promise<Invite>;
|
public createInvite(options?: CreateInviteOptions): Promise<Invite>;
|
||||||
public fetchInvites(cache?: boolean): Promise<Collection<string, Invite>>;
|
public fetchInvites(cache?: boolean): Promise<Collection<string, Invite>>;
|
||||||
@@ -525,6 +527,7 @@ export type MappedChannelCategoryTypes = EnumValueMapped<
|
|||||||
GUILD_TEXT: TextChannel;
|
GUILD_TEXT: TextChannel;
|
||||||
GUILD_STORE: StoreChannel;
|
GUILD_STORE: StoreChannel;
|
||||||
GUILD_STAGE_VOICE: StageChannel;
|
GUILD_STAGE_VOICE: StageChannel;
|
||||||
|
GUILD_FORUM: ForumChannel;
|
||||||
}
|
}
|
||||||
>;
|
>;
|
||||||
|
|
||||||
@@ -567,6 +570,7 @@ export abstract class Channel extends Base {
|
|||||||
public id: Snowflake;
|
public id: Snowflake;
|
||||||
public readonly partial: false;
|
public readonly partial: false;
|
||||||
public type: keyof typeof ChannelTypes;
|
public type: keyof typeof ChannelTypes;
|
||||||
|
public flags: Readonly<ChannelFlags> | null;
|
||||||
public delete(): Promise<this>;
|
public delete(): Promise<this>;
|
||||||
public fetch(force?: boolean): Promise<this>;
|
public fetch(force?: boolean): Promise<this>;
|
||||||
public isText(): this is TextBasedChannel;
|
public isText(): this is TextBasedChannel;
|
||||||
@@ -701,6 +705,14 @@ export interface CollectorEventTypes<K, V, F extends unknown[] = []> {
|
|||||||
end: [collected: Collection<K, V>, reason: string];
|
end: [collected: Collection<K, V>, reason: string];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type ChannelFlagsString =
|
||||||
|
| 'PINNED'
|
||||||
|
| 'REQUIRE_TAG';
|
||||||
|
export class ChannelFlags extends BitField<ChannelFlagsString> {
|
||||||
|
public static FLAGS: Record<ChannelFlagsString, number>;
|
||||||
|
public static resolve(bit?: BitFieldResolvable<ChannelFlagsString, number>): number;
|
||||||
|
}
|
||||||
|
|
||||||
export abstract class Collector<K, V, F extends unknown[] = []> extends EventEmitter {
|
export abstract class Collector<K, V, F extends unknown[] = []> extends EventEmitter {
|
||||||
protected constructor(client: Client, options?: CollectorOptions<[V, ...F]>);
|
protected constructor(client: Client, options?: CollectorOptions<[V, ...F]>);
|
||||||
private _timeout: NodeJS.Timeout | null;
|
private _timeout: NodeJS.Timeout | null;
|
||||||
@@ -907,6 +919,7 @@ export class DMChannel extends TextBasedChannelMixin(Channel, [
|
|||||||
private constructor(client: Client, data?: RawDMChannelData);
|
private constructor(client: Client, data?: RawDMChannelData);
|
||||||
public recipient: User;
|
public recipient: User;
|
||||||
public type: 'DM';
|
public type: 'DM';
|
||||||
|
public flags: Readonly<ChannelFlags>;
|
||||||
public fetch(force?: boolean): Promise<this>;
|
public fetch(force?: boolean): Promise<this>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -978,7 +991,7 @@ export class Guild extends AnonymousGuild {
|
|||||||
public vanityURLUses: number | null;
|
public vanityURLUses: number | null;
|
||||||
public readonly voiceAdapterCreator: InternalDiscordGatewayAdapterCreator;
|
public readonly voiceAdapterCreator: InternalDiscordGatewayAdapterCreator;
|
||||||
public readonly voiceStates: VoiceStateManager;
|
public readonly voiceStates: VoiceStateManager;
|
||||||
public readonly widgetChannel: TextChannel | null;
|
public readonly widgetChannel: TextChannel | NewsChannel | VoiceBasedChannel | ForumChannel | null;
|
||||||
public widgetChannelId: Snowflake | null;
|
public widgetChannelId: Snowflake | null;
|
||||||
public widgetEnabled: boolean | null;
|
public widgetEnabled: boolean | null;
|
||||||
public readonly maximumBitrate: number;
|
public readonly maximumBitrate: number;
|
||||||
@@ -1111,6 +1124,7 @@ export abstract class GuildChannel extends Channel {
|
|||||||
public readonly position: number;
|
public readonly position: number;
|
||||||
public rawPosition: number;
|
public rawPosition: number;
|
||||||
public type: Exclude<keyof typeof ChannelTypes, 'DM' | 'GROUP_DM' | 'UNKNOWN'>;
|
public type: Exclude<keyof typeof ChannelTypes, 'DM' | 'GROUP_DM' | 'UNKNOWN'>;
|
||||||
|
public flags: Readonly<ChannelFlags>;
|
||||||
public readonly viewable: boolean;
|
public readonly viewable: boolean;
|
||||||
public clone(options?: GuildChannelCloneOptions): Promise<this>;
|
public clone(options?: GuildChannelCloneOptions): Promise<this>;
|
||||||
public delete(reason?: string): Promise<this>;
|
public delete(reason?: string): Promise<this>;
|
||||||
@@ -1593,6 +1607,7 @@ export class Message<Cached extends boolean = boolean> extends Base {
|
|||||||
public webhookId: Snowflake | null;
|
public webhookId: Snowflake | null;
|
||||||
public flags: Readonly<MessageFlags>;
|
public flags: Readonly<MessageFlags>;
|
||||||
public reference: MessageReference | null;
|
public reference: MessageReference | null;
|
||||||
|
public position: number | null;
|
||||||
public awaitMessageComponent<T extends MessageComponentTypeResolvable = 'ACTION_ROW'>(
|
public awaitMessageComponent<T extends MessageComponentTypeResolvable = 'ACTION_ROW'>(
|
||||||
options?: AwaitMessageCollectorOptionsParams<T, Cached>,
|
options?: AwaitMessageCollectorOptionsParams<T, Cached>,
|
||||||
): Promise<MappedInteractionTypes<Cached>[T]>;
|
): Promise<MappedInteractionTypes<Cached>[T]>;
|
||||||
@@ -1972,7 +1987,7 @@ export class ModalSubmitInteraction<Cached extends CacheType = CacheType> extend
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class NewsChannel extends BaseGuildTextChannel {
|
export class NewsChannel extends BaseGuildTextChannel {
|
||||||
public threads: ThreadManager<AllowedThreadTypeForNewsChannel>;
|
public threads: GuildTextThreadManager<AllowedThreadTypeForNewsChannel>;
|
||||||
public type: 'GUILD_NEWS';
|
public type: 'GUILD_NEWS';
|
||||||
public addFollower(channel: TextChannelResolvable, reason?: string): Promise<NewsChannel>;
|
public addFollower(channel: TextChannelResolvable, reason?: string): Promise<NewsChannel>;
|
||||||
}
|
}
|
||||||
@@ -1987,6 +2002,7 @@ export class PartialGroupDMChannel extends Channel {
|
|||||||
private constructor(client: Client, data: RawPartialGroupDMChannelData);
|
private constructor(client: Client, data: RawPartialGroupDMChannelData);
|
||||||
public name: string | null;
|
public name: string | null;
|
||||||
public icon: string | null;
|
public icon: string | null;
|
||||||
|
public flags: null;
|
||||||
public recipients: PartialRecipient[];
|
public recipients: PartialRecipient[];
|
||||||
public iconURL(options?: StaticImageURLOptions): string | null;
|
public iconURL(options?: StaticImageURLOptions): string | null;
|
||||||
}
|
}
|
||||||
@@ -2273,7 +2289,9 @@ export class StageChannel extends BaseGuildVoiceChannel {
|
|||||||
public setTopic(topic: string): Promise<StageChannel>;
|
public setTopic(topic: string): Promise<StageChannel>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DirectoryChannel extends Channel {}
|
export class DirectoryChannel extends Channel {
|
||||||
|
public flags: Readonly<ChannelFlags>;
|
||||||
|
}
|
||||||
|
|
||||||
export class StageInstance extends Base {
|
export class StageInstance extends Base {
|
||||||
private constructor(client: Client, data: RawStageInstanceData, channel: StageChannel);
|
private constructor(client: Client, data: RawStageInstanceData, channel: StageChannel);
|
||||||
@@ -2447,10 +2465,65 @@ export class TeamMember extends Base {
|
|||||||
|
|
||||||
export class TextChannel extends BaseGuildTextChannel {
|
export class TextChannel extends BaseGuildTextChannel {
|
||||||
public rateLimitPerUser: number;
|
public rateLimitPerUser: number;
|
||||||
public threads: ThreadManager<AllowedThreadTypeForTextChannel>;
|
public threads: GuildTextThreadManager<AllowedThreadTypeForTextChannel>;
|
||||||
public type: 'GUILD_TEXT';
|
public type: 'GUILD_TEXT';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface GuildForumTagEmoji {
|
||||||
|
id: Snowflake | null;
|
||||||
|
name: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GuildForumTag {
|
||||||
|
id: Snowflake;
|
||||||
|
name: string;
|
||||||
|
moderated: boolean;
|
||||||
|
emoji: GuildForumTagEmoji | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type GuildForumTagData = Partial<GuildForumTag> & { name: string };
|
||||||
|
|
||||||
|
export interface DefaultReactionEmoji {
|
||||||
|
id: Snowflake | null;
|
||||||
|
name: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ForumChannel extends TextBasedChannelMixin(GuildChannel, [
|
||||||
|
'send',
|
||||||
|
'lastMessage',
|
||||||
|
'lastPinAt',
|
||||||
|
'bulkDelete',
|
||||||
|
'sendTyping',
|
||||||
|
'createMessageCollector',
|
||||||
|
'awaitMessages',
|
||||||
|
'createMessageComponentCollector',
|
||||||
|
'awaitMessageComponent',
|
||||||
|
]) {
|
||||||
|
public type: 'GUILD_FORUM';
|
||||||
|
public threads: GuildForumThreadManager;
|
||||||
|
public availableTags: GuildForumTag[];
|
||||||
|
public defaultReactionEmoji: DefaultReactionEmoji | null;
|
||||||
|
public defaultThreadRateLimitPerUser: number | null;
|
||||||
|
public rateLimitPerUser: number | null;
|
||||||
|
public defaultAutoArchiveDuration: ThreadAutoArchiveDuration | null;
|
||||||
|
public nsfw: boolean;
|
||||||
|
public topic: string | null;
|
||||||
|
public defaultSortOrder: SortOrderType | null;
|
||||||
|
public defaultForumLayout: ForumLayoutType;
|
||||||
|
public setAvailableTags(tags: GuildForumTagData[], reason?: string): Promise<this>;
|
||||||
|
public setDefaultReactionEmoji(emojiId: DefaultReactionEmoji | null, reason?: string): Promise<this>;
|
||||||
|
public setDefaultThreadRateLimitPerUser(rateLimit: number, reason?: string): Promise<this>;
|
||||||
|
public createInvite(options?: CreateInviteOptions): Promise<Invite>;
|
||||||
|
public fetchInvites(cache?: boolean): Promise<Collection<string, Invite>>;
|
||||||
|
public setDefaultAutoArchiveDuration(
|
||||||
|
defaultAutoArchiveDuration: ThreadAutoArchiveDuration,
|
||||||
|
reason?: string,
|
||||||
|
): Promise<this>;
|
||||||
|
public setTopic(topic: string | null, reason?: string): Promise<this>;
|
||||||
|
public setDefaultSortOrder(defaultSortOrder: SortOrderType | null, reason?: string): Promise<this>;
|
||||||
|
public setDefaultForumLayout(defaultForumLayout: ForumLayoutType, reason?: string): Promise<this>;
|
||||||
|
}
|
||||||
|
|
||||||
export class TextInputComponent extends BaseMessageComponent {
|
export class TextInputComponent extends BaseMessageComponent {
|
||||||
public constructor(data?: TextInputComponent | TextInputComponentOptions);
|
public constructor(data?: TextInputComponent | TextInputComponentOptions);
|
||||||
public customId: string | null;
|
public customId: string | null;
|
||||||
@@ -2498,10 +2571,13 @@ export class ThreadChannel extends TextBasedChannelMixin(Channel, ['fetchWebhook
|
|||||||
public members: ThreadMemberManager;
|
public members: ThreadMemberManager;
|
||||||
public name: string;
|
public name: string;
|
||||||
public ownerId: Snowflake | null;
|
public ownerId: Snowflake | null;
|
||||||
public readonly parent: TextChannel | NewsChannel | null;
|
public readonly parent: TextChannel | NewsChannel | ForumChannel | null;
|
||||||
public parentId: Snowflake | null;
|
public parentId: Snowflake | null;
|
||||||
public rateLimitPerUser: number | null;
|
public rateLimitPerUser: number | null;
|
||||||
public type: ThreadChannelTypes;
|
public type: ThreadChannelTypes;
|
||||||
|
public flags: Readonly<ChannelFlags>;
|
||||||
|
public appliedTags: Snowflake[];
|
||||||
|
public totalMessageSent: number | null;
|
||||||
public readonly unarchivable: boolean;
|
public readonly unarchivable: boolean;
|
||||||
public isPrivate(): this is this & {
|
public isPrivate(): this is this & {
|
||||||
readonly createdTimestamp: number;
|
readonly createdTimestamp: number;
|
||||||
@@ -2527,6 +2603,9 @@ export class ThreadChannel extends TextBasedChannelMixin(Channel, ['fetchWebhook
|
|||||||
public setInvitable(invitable?: boolean, reason?: string): Promise<ThreadChannel>;
|
public setInvitable(invitable?: boolean, reason?: string): Promise<ThreadChannel>;
|
||||||
public setLocked(locked?: boolean, reason?: string): Promise<ThreadChannel>;
|
public setLocked(locked?: boolean, reason?: string): Promise<ThreadChannel>;
|
||||||
public setName(name: string, reason?: string): Promise<ThreadChannel>;
|
public setName(name: string, reason?: string): Promise<ThreadChannel>;
|
||||||
|
public setAppliedTags(appliedTags: Snowflake[], reason?: string): Promise<ThreadChannel>;
|
||||||
|
public pin(reason?: string): Promise<ThreadChannel>;
|
||||||
|
public unpin(reason?: string): Promise<ThreadChannel>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ThreadMember extends Base {
|
export class ThreadMember extends Base {
|
||||||
@@ -2652,6 +2731,7 @@ export class Util extends null {
|
|||||||
): Promise<{ id: Snowflake; position: number }[]>;
|
): Promise<{ id: Snowflake; position: number }[]>;
|
||||||
/** @deprecated This will be removed in the next major version. */
|
/** @deprecated This will be removed in the next major version. */
|
||||||
public static splitMessage(text: string, options?: SplitOptions): string[];
|
public static splitMessage(text: string, options?: SplitOptions): string[];
|
||||||
|
/** @deprecated This will be removed in the next major version. */
|
||||||
public static resolveAutoArchiveMaxLimit(guild: Guild): Exclude<ThreadAutoArchiveDuration, 60>;
|
public static resolveAutoArchiveMaxLimit(guild: Guild): Exclude<ThreadAutoArchiveDuration, 60>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2893,7 +2973,7 @@ export class WelcomeChannel extends Base {
|
|||||||
public channelId: Snowflake;
|
public channelId: Snowflake;
|
||||||
public guild: Guild | InviteGuild;
|
public guild: Guild | InviteGuild;
|
||||||
public description: string;
|
public description: string;
|
||||||
public readonly channel: TextChannel | NewsChannel | StoreChannel | null;
|
public readonly channel: TextChannel | NewsChannel | StoreChannel | ForumChannel | null;
|
||||||
public readonly emoji: GuildEmoji | Emoji;
|
public readonly emoji: GuildEmoji | Emoji;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3479,16 +3559,23 @@ export class StageInstanceManager extends CachedManager<Snowflake, StageInstance
|
|||||||
public delete(channel: StageChannelResolvable): Promise<void>;
|
public delete(channel: StageChannelResolvable): Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ThreadManager<AllowedThreadType> extends CachedManager<Snowflake, ThreadChannel, ThreadChannelResolvable> {
|
export class ThreadManager extends CachedManager<Snowflake, ThreadChannel, ThreadChannelResolvable> {
|
||||||
private constructor(channel: TextChannel | NewsChannel, iterable?: Iterable<RawThreadChannelData>);
|
protected constructor(channel: TextChannel | NewsChannel, iterable?: Iterable<RawThreadChannelData>);
|
||||||
public channel: TextChannel | NewsChannel;
|
public channel: TextChannel | NewsChannel;
|
||||||
public create(options: ThreadCreateOptions<AllowedThreadType>): Promise<ThreadChannel>;
|
|
||||||
public fetch(options: ThreadChannelResolvable, cacheOptions?: BaseFetchOptions): Promise<ThreadChannel | null>;
|
public fetch(options: ThreadChannelResolvable, cacheOptions?: BaseFetchOptions): Promise<ThreadChannel | null>;
|
||||||
public fetch(options?: FetchThreadsOptions, cacheOptions?: { cache?: boolean }): Promise<FetchedThreads>;
|
public fetch(options?: FetchThreadsOptions, cacheOptions?: { cache?: boolean }): Promise<FetchedThreads>;
|
||||||
public fetchArchived(options?: FetchArchivedThreadOptions, cache?: boolean): Promise<FetchedThreads>;
|
public fetchArchived(options?: FetchArchivedThreadOptions, cache?: boolean): Promise<FetchedThreads>;
|
||||||
public fetchActive(cache?: boolean): Promise<FetchedThreads>;
|
public fetchActive(cache?: boolean): Promise<FetchedThreads>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class GuildTextThreadManager<AllowedThreadType> extends ThreadManager {
|
||||||
|
public create(options: GuildTextThreadCreateOptions<AllowedThreadType>): Promise<ThreadChannel>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class GuildForumThreadManager extends ThreadManager {
|
||||||
|
public create(options: GuildForumThreadCreateOptions): Promise<ThreadChannel>;
|
||||||
|
}
|
||||||
|
|
||||||
export class ThreadMemberManager extends CachedManager<Snowflake, ThreadMember, ThreadMemberResolvable> {
|
export class ThreadMemberManager extends CachedManager<Snowflake, ThreadMember, ThreadMemberResolvable> {
|
||||||
private constructor(thread: ThreadChannel, iterable?: Iterable<RawThreadMemberData>);
|
private constructor(thread: ThreadChannel, iterable?: Iterable<RawThreadMemberData>);
|
||||||
public thread: ThreadChannel;
|
public thread: ThreadChannel;
|
||||||
@@ -4111,7 +4198,6 @@ export type CacheWithLimitsOptions = {
|
|||||||
? LimitedCollectionOptions<K, V> | number
|
? LimitedCollectionOptions<K, V> | number
|
||||||
: never;
|
: never;
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface CategoryCreateChannelOptions {
|
export interface CategoryCreateChannelOptions {
|
||||||
permissionOverwrites?: OverwriteResolvable[] | Collection<Snowflake, OverwriteResolvable>;
|
permissionOverwrites?: OverwriteResolvable[] | Collection<Snowflake, OverwriteResolvable>;
|
||||||
topic?: string;
|
topic?: string;
|
||||||
@@ -4131,6 +4217,11 @@ export interface CategoryCreateChannelOptions {
|
|||||||
rateLimitPerUser?: number;
|
rateLimitPerUser?: number;
|
||||||
position?: number;
|
position?: number;
|
||||||
rtcRegion?: string;
|
rtcRegion?: string;
|
||||||
|
videoQualityMode?: VideoQualityMode;
|
||||||
|
availableTags?: GuildForumTagData[];
|
||||||
|
defaultReactionEmoji?: DefaultReactionEmoji;
|
||||||
|
defaultSortOrder?: SortOrderType;
|
||||||
|
defaultForumLayout?: ForumLayoutType;
|
||||||
reason?: string;
|
reason?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4155,6 +4246,12 @@ export interface ChannelData {
|
|||||||
defaultAutoArchiveDuration?: ThreadAutoArchiveDuration | 'MAX';
|
defaultAutoArchiveDuration?: ThreadAutoArchiveDuration | 'MAX';
|
||||||
rtcRegion?: string | null;
|
rtcRegion?: string | null;
|
||||||
videoQualityMode?: VideoQualityMode | null;
|
videoQualityMode?: VideoQualityMode | null;
|
||||||
|
availableTags?: GuildForumTagData[];
|
||||||
|
defaultReactionEmoji?: DefaultReactionEmoji;
|
||||||
|
defaultThreadRateLimitPerUser?: number;
|
||||||
|
defaultSortOrder?: SortOrderType | null;
|
||||||
|
defaultForumLayout?: ForumLayoutType;
|
||||||
|
flags?: ChannelFlagsResolvable;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ChannelLogsQueryOptions {
|
export interface ChannelLogsQueryOptions {
|
||||||
@@ -4258,7 +4355,7 @@ export interface ClientEvents extends BaseClientEvents {
|
|||||||
typingStart: [typing: Typing];
|
typingStart: [typing: Typing];
|
||||||
userUpdate: [oldUser: User | PartialUser, newUser: User];
|
userUpdate: [oldUser: User | PartialUser, newUser: User];
|
||||||
voiceStateUpdate: [oldState: VoiceState, newState: VoiceState];
|
voiceStateUpdate: [oldState: VoiceState, newState: VoiceState];
|
||||||
webhookUpdate: [channel: TextChannel | NewsChannel | VoiceChannel];
|
webhookUpdate: [channel: TextChannel | NewsChannel | VoiceChannel | ForumChannel];
|
||||||
/** @deprecated Use interactionCreate instead */
|
/** @deprecated Use interactionCreate instead */
|
||||||
interaction: [interaction: Interaction];
|
interaction: [interaction: Interaction];
|
||||||
interactionCreate: [interaction: Interaction];
|
interactionCreate: [interaction: Interaction];
|
||||||
@@ -5378,6 +5475,9 @@ export type MessageComponentType = keyof typeof MessageComponentTypes;
|
|||||||
|
|
||||||
export type MessageComponentTypeResolvable = MessageComponentType | MessageComponentTypes;
|
export type MessageComponentTypeResolvable = MessageComponentType | MessageComponentTypes;
|
||||||
|
|
||||||
|
export type GuildForumThreadMessageCreateOptions = MessageOptions &
|
||||||
|
Pick<MessageOptions, 'flags' | 'stickers'>;
|
||||||
|
|
||||||
export interface MessageEditOptions {
|
export interface MessageEditOptions {
|
||||||
attachments?: MessageAttachment[];
|
attachments?: MessageAttachment[];
|
||||||
content?: string | null;
|
content?: string | null;
|
||||||
@@ -5690,6 +5790,9 @@ export interface PartialChannelData {
|
|||||||
videoQualityMode?: VideoQualityMode;
|
videoQualityMode?: VideoQualityMode;
|
||||||
permissionOverwrites?: PartialOverwriteData[];
|
permissionOverwrites?: PartialOverwriteData[];
|
||||||
rateLimitPerUser?: number;
|
rateLimitPerUser?: number;
|
||||||
|
availableTags?: GuildForumTagData[];
|
||||||
|
defaultReactionEmoji?: DefaultReactionEmoji;
|
||||||
|
defaultThreadRateLimitPerUser?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Partialize<
|
export type Partialize<
|
||||||
@@ -5863,6 +5966,8 @@ export type SystemChannelFlagsString =
|
|||||||
|
|
||||||
export type SystemChannelFlagsResolvable = BitFieldResolvable<SystemChannelFlagsString, number>;
|
export type SystemChannelFlagsResolvable = BitFieldResolvable<SystemChannelFlagsString, number>;
|
||||||
|
|
||||||
|
export type ChannelFlagsResolvable = BitFieldResolvable<ChannelFlagsString, number>;
|
||||||
|
|
||||||
export type SystemMessageType = Exclude<
|
export type SystemMessageType = Exclude<
|
||||||
MessageType,
|
MessageType,
|
||||||
'DEFAULT' | 'REPLY' | 'APPLICATION_COMMAND' | 'CONTEXT_MENU_COMMAND'
|
'DEFAULT' | 'REPLY' | 'APPLICATION_COMMAND' | 'CONTEXT_MENU_COMMAND'
|
||||||
@@ -5935,9 +6040,10 @@ export type AnyChannel =
|
|||||||
| StoreChannel
|
| StoreChannel
|
||||||
| TextChannel
|
| TextChannel
|
||||||
| ThreadChannel
|
| ThreadChannel
|
||||||
| VoiceChannel;
|
| VoiceChannel
|
||||||
|
| ForumChannel;
|
||||||
|
|
||||||
export type TextBasedChannel = Extract<AnyChannel, { messages: MessageManager }>;
|
export type TextBasedChannel = Exclude<Extract<AnyChannel, { messages: MessageManager }>, ForumChannel>;
|
||||||
|
|
||||||
export type TextBasedChannelTypes = TextBasedChannel['type'];
|
export type TextBasedChannelTypes = TextBasedChannel['type'];
|
||||||
|
|
||||||
@@ -5966,7 +6072,7 @@ export type GuildBasedChannel = Extract<AnyChannel, { guild: Guild }>;
|
|||||||
|
|
||||||
export type NonThreadGuildBasedChannel = Exclude<GuildBasedChannel, ThreadChannel>;
|
export type NonThreadGuildBasedChannel = Exclude<GuildBasedChannel, ThreadChannel>;
|
||||||
|
|
||||||
export type GuildTextBasedChannel = Extract<GuildBasedChannel, TextBasedChannel>;
|
export type GuildTextBasedChannel = Exclude<Extract<GuildBasedChannel, TextBasedChannel>, ForumChannel>;
|
||||||
|
|
||||||
export type TextChannelResolvable = Snowflake | TextChannel;
|
export type TextChannelResolvable = Snowflake | TextChannel;
|
||||||
|
|
||||||
@@ -5978,13 +6084,18 @@ export type ThreadChannelResolvable = ThreadChannel | Snowflake;
|
|||||||
|
|
||||||
export type ThreadChannelTypes = 'GUILD_NEWS_THREAD' | 'GUILD_PUBLIC_THREAD' | 'GUILD_PRIVATE_THREAD';
|
export type ThreadChannelTypes = 'GUILD_NEWS_THREAD' | 'GUILD_PUBLIC_THREAD' | 'GUILD_PRIVATE_THREAD';
|
||||||
|
|
||||||
export interface ThreadCreateOptions<AllowedThreadType> extends StartThreadOptions {
|
export interface GuildTextThreadCreateOptions<AllowedThreadType> extends StartThreadOptions {
|
||||||
startMessage?: MessageResolvable;
|
startMessage?: MessageResolvable;
|
||||||
type?: AllowedThreadType;
|
type?: AllowedThreadType;
|
||||||
invitable?: AllowedThreadType extends 'GUILD_PRIVATE_THREAD' | 12 ? boolean : never;
|
invitable?: AllowedThreadType extends 'GUILD_PRIVATE_THREAD' | 12 ? boolean : never;
|
||||||
rateLimitPerUser?: number;
|
rateLimitPerUser?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface GuildForumThreadCreateOptions extends StartThreadOptions {
|
||||||
|
message: GuildForumThreadMessageCreateOptions | MessagePayload;
|
||||||
|
appliedTags?: Snowflake[];
|
||||||
|
}
|
||||||
|
|
||||||
export interface ThreadEditData {
|
export interface ThreadEditData {
|
||||||
name?: string;
|
name?: string;
|
||||||
archived?: boolean;
|
archived?: boolean;
|
||||||
@@ -5992,6 +6103,8 @@ export interface ThreadEditData {
|
|||||||
rateLimitPerUser?: number;
|
rateLimitPerUser?: number;
|
||||||
locked?: boolean;
|
locked?: boolean;
|
||||||
invitable?: boolean;
|
invitable?: boolean;
|
||||||
|
threadName?: string;
|
||||||
|
flags?: ChannelFlagsResolvable;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ThreadMemberFlagsString = '';
|
export type ThreadMemberFlagsString = '';
|
||||||
@@ -6104,7 +6217,7 @@ export interface WidgetChannel {
|
|||||||
|
|
||||||
export interface WelcomeChannelData {
|
export interface WelcomeChannelData {
|
||||||
description: string;
|
description: string;
|
||||||
channel: TextChannel | NewsChannel | StoreChannel | Snowflake;
|
channel: TextChannel | NewsChannel | StoreChannel | ForumChannel | Snowflake;
|
||||||
emoji?: EmojiIdentifierResolvable;
|
emoji?: EmojiIdentifierResolvable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -97,6 +97,7 @@ import {
|
|||||||
InteractionResponseFields,
|
InteractionResponseFields,
|
||||||
GuildBan,
|
GuildBan,
|
||||||
GuildBanManager,
|
GuildBanManager,
|
||||||
|
ForumChannel,
|
||||||
} from '.';
|
} from '.';
|
||||||
import type { ApplicationCommandOptionTypes } from './enums';
|
import type { ApplicationCommandOptionTypes } from './enums';
|
||||||
import { expectAssignable, expectDeprecated, expectNotAssignable, expectNotType, expectType } from 'tsd';
|
import { expectAssignable, expectDeprecated, expectNotAssignable, expectNotType, expectType } from 'tsd';
|
||||||
@@ -897,7 +898,7 @@ declare const categoryChannel: CategoryChannel;
|
|||||||
|
|
||||||
declare const guildChannelManager: GuildChannelManager;
|
declare const guildChannelManager: GuildChannelManager;
|
||||||
{
|
{
|
||||||
type AnyChannel = TextChannel | VoiceChannel | CategoryChannel | NewsChannel | StoreChannel | StageChannel;
|
type AnyChannel = TextChannel | VoiceChannel | CategoryChannel | NewsChannel | StoreChannel | StageChannel | ForumChannel;
|
||||||
|
|
||||||
expectType<Promise<TextChannel>>(guildChannelManager.create('name'));
|
expectType<Promise<TextChannel>>(guildChannelManager.create('name'));
|
||||||
expectType<Promise<TextChannel>>(guildChannelManager.create('name', {}));
|
expectType<Promise<TextChannel>>(guildChannelManager.create('name', {}));
|
||||||
@@ -1333,10 +1334,10 @@ expectType<
|
|||||||
| 'GUILD_VOICE'
|
| 'GUILD_VOICE'
|
||||||
>(TextBasedChannelTypes);
|
>(TextBasedChannelTypes);
|
||||||
expectType<StageChannel | VoiceChannel>(VoiceBasedChannel);
|
expectType<StageChannel | VoiceChannel>(VoiceBasedChannel);
|
||||||
expectType<CategoryChannel | NewsChannel | StageChannel | StoreChannel | TextChannel | ThreadChannel | VoiceChannel>(
|
expectType<CategoryChannel | NewsChannel | StageChannel | StoreChannel | TextChannel | ThreadChannel | VoiceChannel | ForumChannel>(
|
||||||
GuildBasedChannel,
|
GuildBasedChannel,
|
||||||
);
|
);
|
||||||
expectType<CategoryChannel | NewsChannel | StageChannel | StoreChannel | TextChannel | VoiceChannel>(
|
expectType<CategoryChannel | NewsChannel | StageChannel | StoreChannel | TextChannel | VoiceChannel | ForumChannel>(
|
||||||
NonThreadGuildBasedChannel,
|
NonThreadGuildBasedChannel,
|
||||||
);
|
);
|
||||||
expectType<NewsChannel | TextChannel | ThreadChannel | VoiceChannel>(GuildTextBasedChannel);
|
expectType<NewsChannel | TextChannel | ThreadChannel | VoiceChannel>(GuildTextBasedChannel);
|
||||||
|
|||||||
Reference in New Issue
Block a user