feat: Add media channels

#9662 backport
This commit is contained in:
Elysia
2024-09-17 17:50:34 +07:00
parent 293a8b8fd8
commit 35ca0c89bf
13 changed files with 301 additions and 257 deletions

View File

@@ -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|StageChannel|ForumChannel} channel * @param {TextChannel|NewsChannel|VoiceChannel|StageChannel|ForumChannel|MediaChannel} channel
* The channel that had a webhook update * The channel that had a webhook update
*/ */
if (channel) client.emit(Events.WEBHOOKS_UPDATE, channel); if (channel) client.emit(Events.WEBHOOKS_UPDATE, channel);

View File

@@ -13,7 +13,7 @@ class GuildForumThreadManager extends ThreadManager {
/** /**
* The channel this Manager belongs to * The channel this Manager belongs to
* @name GuildForumThreadManager#channel * @name GuildForumThreadManager#channel
* @type {ForumChannel} * @type {ForumChannel|MediaChannel}
*/ */
/** /**

View File

@@ -1,140 +1,15 @@
'use strict'; 'use strict';
const GuildChannel = require('./GuildChannel'); const ThreadOnlyChannel = require('./ThreadOnlyChannel');
const TextBasedChannel = require('./interfaces/TextBasedChannel'); const { ForumLayoutTypes } = require('../util/Constants');
const GuildForumThreadManager = require('../managers/GuildForumThreadManager');
const { SortOrderTypes, ForumLayoutTypes } = require('../util/Constants');
const { transformAPIGuildForumTag, transformAPIGuildDefaultReaction } = require('../util/Util');
/** /**
* @typedef {Object} GuildForumTagEmoji * Represents a forum channel.
* @property {?Snowflake} id The id of a guild's custom emoji * @extends {ThreadOnlyChannel}
* @property {?string} name The unicode character of the emoji
*/ */
class ForumChannel extends ThreadOnlyChannel {
/**
* @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) { _patch(data) {
super._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 * The default layout type used to display posts
* @type {ForumLayoutType} * @type {ForumLayoutType}
@@ -142,46 +17,6 @@ class ForumChannel extends GuildChannel {
this.defaultForumLayout = ForumLayoutTypes[data.default_forum_layout]; 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 * Sets the default forum layout type used to display posts
* @param {ForumLayoutType} defaultForumLayout The default forum layout type to set on this channel * @param {ForumLayoutType} defaultForumLayout The default forum layout type to set on this channel
@@ -191,71 +26,6 @@ class ForumChannel extends GuildChannel {
setDefaultForumLayout(defaultForumLayout, reason) { setDefaultForumLayout(defaultForumLayout, reason) {
return this.edit({ 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',
'sendTyping',
'createMessageCollector',
'awaitMessages',
]);
module.exports = ForumChannel; module.exports = ForumChannel;

View File

@@ -607,7 +607,7 @@ class Guild extends AnonymousGuild {
/** /**
* Widget channel for this guild * Widget channel for this guild
* @type {?(TextChannel|NewsChannel|VoiceChannel|StageChannel|ForumChannel)} * @type {?(TextChannel|NewsChannel|VoiceChannel|StageChannel|ForumChannel|MediaChannel)}
* @readonly * @readonly
*/ */
get widgetChannel() { get widgetChannel() {

View File

@@ -16,6 +16,7 @@ const Util = require('../util/Util');
* - {@link StoreChannel} * - {@link StoreChannel}
* - {@link StageChannel} * - {@link StageChannel}
* - {@link ForumChannel} * - {@link ForumChannel}
* - {@link MediaChannel}
* @extends {Channel} * @extends {Channel}
* @abstract * @abstract
*/ */

View File

@@ -0,0 +1,11 @@
'use strict';
const ThreadOnlyChannel = require('./ThreadOnlyChannel');
/**
* Represents a media channel.
* @extends {ThreadOnlyChannel}
*/
class MediaChannel extends ThreadOnlyChannel {}
module.exports = MediaChannel;

View File

@@ -246,7 +246,7 @@ class ThreadChannel extends Channel {
/** /**
* The parent channel of this thread * The parent channel of this thread
* @type {?(NewsChannel|TextChannel|ForumChannel)} * @type {?(NewsChannel|TextChannel|ForumChannel|MediaChannel)}
* @readonly * @readonly
*/ */
get parent() { get parent() {

View File

@@ -0,0 +1,249 @@
'use strict';
const GuildChannel = require('./GuildChannel');
const TextBasedChannel = require('./interfaces/TextBasedChannel');
const GuildForumThreadManager = require('../managers/GuildForumThreadManager');
const { SortOrderTypes } = 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}
* @abstract
*/
class ThreadOnlyChannel 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;
}
}
/**
* 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<this>}
*/
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<this>}
*/
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<this>}
*/
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<this>}
*/
setDefaultSortOrder(defaultSortOrder, reason) {
return this.edit({ defaultSortOrder }, 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<this>}
*/
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<this>}
* @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(ThreadOnlyChannel, true, [
'send',
'lastMessage',
'lastPinAt',
'bulkDelete',
'sendTyping',
'createMessageCollector',
'awaitMessages',
'createMessageComponentCollector',
'awaitMessageComponent',
]);
module.exports = ThreadOnlyChannel;

View File

@@ -239,7 +239,7 @@ class Webhook {
* @typedef {Object} WebhookEditData * @typedef {Object} WebhookEditData
* @property {string} [name=this.name] The new name for the webhook * @property {string} [name=this.name] The new name for the webhook
* @property {?(BufferResolvable)} [avatar] The new avatar for the webhook * @property {?(BufferResolvable)} [avatar] The new avatar for the webhook
* @property {GuildTextChannelResolvable|VoiceChannel|StageChannel|ForumChannel} [channel] * @property {GuildTextChannelResolvable|VoiceChannel|StageChannel|ForumChannel|MediaChannel} [channel]
* The new channel for the webhook * The new channel for the webhook
*/ */
@@ -385,7 +385,7 @@ class Webhook {
/** /**
* The channel the webhook belongs to * The channel the webhook belongs to
* @type {?(TextChannel|VoiceChannel|NewsChannel|ForumChannel)} * @type {?(TextChannel|VoiceChannel|NewsChannel|ForumChannel|MediaChannel)}
* @readonly * @readonly
*/ */
get channel() { get channel() {

View File

@@ -42,7 +42,7 @@ class WelcomeChannel extends Base {
/** /**
* The channel of this welcome channel * The channel of this welcome channel
* @type {?(TextChannel|NewsChannel|StoreChannel|ForumChannel)} * @type {?(TextChannel|NewsChannel|StoreChannel|ForumChannel|MediaChannel)}
*/ */
get channel() { get channel() {
return this.client.channels.resolve(this.channelId); return this.client.channels.resolve(this.channelId);

View File

@@ -824,6 +824,7 @@ exports.ActivityTypes = createEnum(['PLAYING', 'STREAMING', 'LISTENING', 'WATCHI
* * `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 * * `GUILD_FORUM` - a channel that can only contain threads
* * `GUILD_MEDIA` - a channel that can only contain threads, similar to `GUILD_FORUM` channels
* * `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}
@@ -844,6 +845,7 @@ exports.ChannelTypes = createEnum([
'GUILD_STAGE_VOICE', 'GUILD_STAGE_VOICE',
'GUILD_DIRECTORY', 'GUILD_DIRECTORY',
'GUILD_FORUM', 'GUILD_FORUM',
'GUILD_MEDIA',
]); ]);
/** /**
@@ -1676,7 +1678,7 @@ 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 * Sort {@link ThreadOnlyChannel} posts by creation time or activity
* * LATEST_ACTIVITY * * LATEST_ACTIVITY
* * CREATION_DATE * * CREATION_DATE
* @typedef {string} SortOrderType * @typedef {string} SortOrderType

1
typings/enums.d.ts vendored
View File

@@ -74,6 +74,7 @@ export const enum ChannelTypes {
GUILD_STAGE_VOICE = 13, GUILD_STAGE_VOICE = 13,
GUILD_DIRECTORY = 14, GUILD_DIRECTORY = 14,
GUILD_FORUM = 15, GUILD_FORUM = 15,
GUILD_MEDIA = 16,
} }
export const enum SortOrderType { export const enum SortOrderType {

38
typings/index.d.ts vendored
View File

@@ -678,6 +678,7 @@ export type MappedChannelCategoryTypes = EnumValueMapped<
GUILD_STORE: StoreChannel; GUILD_STORE: StoreChannel;
GUILD_STAGE_VOICE: StageChannel; GUILD_STAGE_VOICE: StageChannel;
GUILD_FORUM: ForumChannel; GUILD_FORUM: ForumChannel;
GUILD_MEDIA: MediaChannel;
} }
>; >;
@@ -1408,7 +1409,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 | NewsChannel | VoiceBasedChannel | ForumChannel | null; public readonly widgetChannel: TextChannel | NewsChannel | VoiceBasedChannel | ForumChannel | MediaChannel | 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;
@@ -3194,7 +3195,7 @@ export interface DefaultReactionEmoji {
name: string | null; name: string | null;
} }
export class ForumChannel extends TextBasedChannelMixin(GuildChannel, [ export abstract class ThreadOnlyChannel extends TextBasedChannelMixin(GuildChannel, [
'send', 'send',
'lastMessage', 'lastMessage',
'lastPinAt', 'lastPinAt',
@@ -3202,7 +3203,7 @@ export class ForumChannel extends TextBasedChannelMixin(GuildChannel, [
'createMessageCollector', 'createMessageCollector',
'awaitMessages', 'awaitMessages',
]) { ]) {
public type: 'GUILD_FORUM'; public type: 'GUILD_FORUM' | 'GUILD_MEDIA';
public threads: GuildForumThreadManager; public threads: GuildForumThreadManager;
public availableTags: GuildForumTag[]; public availableTags: GuildForumTag[];
public defaultReactionEmoji: DefaultReactionEmoji | null; public defaultReactionEmoji: DefaultReactionEmoji | null;
@@ -3212,7 +3213,6 @@ export class ForumChannel extends TextBasedChannelMixin(GuildChannel, [
public nsfw: boolean; public nsfw: boolean;
public topic: string | null; public topic: string | null;
public defaultSortOrder: SortOrderType | null; public defaultSortOrder: SortOrderType | null;
public defaultForumLayout: ForumLayoutType;
public setAvailableTags(tags: GuildForumTagData[], reason?: string): Promise<this>; public setAvailableTags(tags: GuildForumTagData[], reason?: string): Promise<this>;
public setDefaultReactionEmoji(emojiId: DefaultReactionEmoji | null, reason?: string): Promise<this>; public setDefaultReactionEmoji(emojiId: DefaultReactionEmoji | null, reason?: string): Promise<this>;
public setDefaultThreadRateLimitPerUser(rateLimit: number, reason?: string): Promise<this>; public setDefaultThreadRateLimitPerUser(rateLimit: number, reason?: string): Promise<this>;
@@ -3224,9 +3224,18 @@ export class ForumChannel extends TextBasedChannelMixin(GuildChannel, [
): Promise<this>; ): Promise<this>;
public setTopic(topic: string | null, reason?: string): Promise<this>; public setTopic(topic: string | null, reason?: string): Promise<this>;
public setDefaultSortOrder(defaultSortOrder: SortOrderType | null, reason?: string): Promise<this>; public setDefaultSortOrder(defaultSortOrder: SortOrderType | null, reason?: string): Promise<this>;
}
export class ForumChannel extends ThreadOnlyChannel {
public type: 'GUILD_FORUM';
public defaultForumLayout: ForumLayoutType;
public setDefaultForumLayout(defaultForumLayout: ForumLayoutType, reason?: string): Promise<this>; public setDefaultForumLayout(defaultForumLayout: ForumLayoutType, reason?: string): Promise<this>;
} }
export class MediaChannel extends ThreadOnlyChannel {
public type: 'GUILD_MEDIA';
}
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;
@@ -3267,7 +3276,7 @@ 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 | ForumChannel | null; public readonly parent: TextChannel | NewsChannel | ForumChannel | MediaChannel | null;
public parentId: Snowflake | null; public parentId: Snowflake | null;
public rateLimitPerUser: number | null; public rateLimitPerUser: number | null;
public type: ThreadChannelTypes; public type: ThreadChannelTypes;
@@ -3547,7 +3556,7 @@ export class Webhook extends WebhookMixin() {
private constructor(client: Client, data?: RawWebhookData); private constructor(client: Client, data?: RawWebhookData);
public avatar: string; public avatar: string;
public avatarURL(options?: StaticImageURLOptions): string | null; public avatarURL(options?: StaticImageURLOptions): string | null;
public readonly channel: TextChannel | VoiceChannel | NewsChannel | ForumChannel | null; public readonly channel: TextChannel | VoiceChannel | NewsChannel | ForumChannel | MediaChannel | null;
public channelId: Snowflake; public channelId: Snowflake;
public client: Client; public client: Client;
public guildId: Snowflake; public guildId: Snowflake;
@@ -3711,7 +3720,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 | ForumChannel | null; public readonly channel: TextChannel | NewsChannel | StoreChannel | ForumChannel | MediaChannel | null;
public readonly emoji: GuildEmoji | Emoji; public readonly emoji: GuildEmoji | Emoji;
} }
@@ -4200,7 +4209,7 @@ export class GuildChannelManager extends CachedManager<Snowflake, GuildBasedChan
public createWebhook( public createWebhook(
channel: GuildChannelResolvable, channel: GuildChannelResolvable,
name: string, name: string,
options?: TextChannel | NewsChannel | VoiceChannel | StageChannel | ForumChannel | Snowflake, options?: TextChannel | NewsChannel | VoiceChannel | StageChannel | ForumChannel | MediaChannel | Snowflake,
): Promise<Webhook>; ): Promise<Webhook>;
public addFollower( public addFollower(
channel: NewsChannel | Snowflake, channel: NewsChannel | Snowflake,
@@ -5481,7 +5490,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 | ForumChannel | StageChannel]; webhookUpdate: [channel: TextChannel | NewsChannel | VoiceChannel | ForumChannel | MediaChannel | StageChannel];
shardDisconnect: [closeEvent: CloseEvent, shardId: number]; shardDisconnect: [closeEvent: CloseEvent, shardId: number];
shardError: [error: Error, shardId: number]; shardError: [error: Error, shardId: number];
shardReady: [shardId: number, unavailableGuilds: Set<Snowflake> | undefined]; shardReady: [shardId: number, unavailableGuilds: Set<Snowflake> | undefined];
@@ -5500,7 +5509,7 @@ export interface ClientEvents extends BaseClientEvents {
]; ];
guildScheduledEventDelete: [guildScheduledEvent: GuildScheduledEvent | PartialGuildScheduledEvent]; guildScheduledEventDelete: [guildScheduledEvent: GuildScheduledEvent | PartialGuildScheduledEvent];
guildScheduledEventUserAdd: [guildScheduledEvent: GuildScheduledEvent | PartialGuildScheduledEvent, user: User]; guildScheduledEventUserAdd: [guildScheduledEvent: GuildScheduledEvent | PartialGuildScheduledEvent, user: User];
guildScheduledEventUserRemove: [guildScheduledEvent: GuildScheduledEvent, | PartialGuildScheduledEvent, user: User]; guildScheduledEventUserRemove: [guildScheduledEvent: GuildScheduledEvent, PartialGuildScheduledEvent, user: User];
guildAuditLogEntryCreate: [auditLogEntry: GuildAuditLogsEntry, guild: Guild]; guildAuditLogEntryCreate: [auditLogEntry: GuildAuditLogsEntry, guild: Guild];
unhandledPacket: [packet: { t?: string; d: any }, shard: number]; unhandledPacket: [packet: { t?: string; d: any }, shard: number];
relationshipAdd: [userId: Snowflake, shouldNotify: boolean]; relationshipAdd: [userId: Snowflake, shouldNotify: boolean];
@@ -7394,9 +7403,10 @@ export type AnyChannel =
| TextChannel | TextChannel
| ThreadChannel | ThreadChannel
| VoiceChannel | VoiceChannel
| ForumChannel; | ForumChannel
| MediaChannel;
export type TextBasedChannel = Exclude<Extract<AnyChannel, { messages: MessageManager }>, ForumChannel>; export type TextBasedChannel = Exclude<Extract<AnyChannel, { messages: MessageManager }>, ForumChannel | MediaChannel>;
export type TextBasedChannelTypes = TextBasedChannel['type']; export type TextBasedChannelTypes = TextBasedChannel['type'];
@@ -7526,7 +7536,7 @@ export type WebhookClientOptions = Pick<
export interface WebhookEditData { export interface WebhookEditData {
name?: string; name?: string;
avatar?: BufferResolvable | null; avatar?: BufferResolvable | null;
channel?: GuildTextChannelResolvable | VoiceChannel | StageChannel | ForumChannel; channel?: GuildTextChannelResolvable | VoiceChannel | StageChannel | ForumChannel | MediaChannel;
} }
export type WebhookEditMessageOptions = Pick< export type WebhookEditMessageOptions = Pick<
@@ -7581,7 +7591,7 @@ export interface WidgetChannel {
export interface WelcomeChannelData { export interface WelcomeChannelData {
description: string; description: string;
channel: TextChannel | NewsChannel | StoreChannel | ForumChannel | Snowflake; channel: TextChannel | NewsChannel | StoreChannel | ForumChannel | MediaChannel | Snowflake;
emoji?: EmojiIdentifierResolvable; emoji?: EmojiIdentifierResolvable;
} }