-
-
Notifications
You must be signed in to change notification settings - Fork 4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add support for guild forums (#7791)
* feat: add support for guild forums * feat(webhook): add support for creating forum channel posts * fix: duplicated docs * feat: add support for message counts * feat: add support for latest upstream changes * fix: serialize forum channels * types: fix channel unions * types: fix tests * types: fix tests (again) * types: fix tests (again (again)) * chore: make requested changes * chore: fix bugs and make requested changes * types: use correct type for guild forum start messages * chore: remove console.log * chore: make requested changes * chore: make requested changes * chore: fix docs * Update packages/discord.js/src/managers/GuildForumThreadManager.js Co-authored-by: Jiralite <[email protected]> * chore: update types * chore: make requested changes * chore: Apply suggestions Co-authored-by: Jaworek <[email protected]> Co-authored-by: Jonathan Rubenstein <[email protected]> * fix: import `ErrorCodes` * fix: remove defunct code * refactor: be consistent with channel class names * feat(GuildChannel): add flags * fix: rename file * refactor: channel flags are everywhere! * fix: import flags correctly * chore(ThreadChannel): update message count string * docs(Channels): correct `@param` type * docs(Channels): ignore transformGuildDefaultReaction * refactor: emoji object in tags * chore: renaming consistency * fix: document default reaction emojis in patching * fix(GuildChannelManager): document `defaultThreadRateLimitPerUser` * chore: semicolon * docs(ErrorCodes): document `GuildForumMessageRequired` * refactor: transform default reactions * docs(APITypes): Add `ChannelFlags` * fix: convert tags properly * fix: pass an array of snowflakes * refactor: handle flags better * fix(ThreadChannel): receive tags * fix(PartialGroupDMChannel): nullify `flags` Apparently did not do this earlier. * chore: misc sorting * refactor: nullify emoji on tags if not present * refactor(ForumChannel): modify returns * types: protect the thread manager! Co-authored-by: SpaceEEC <[email protected]> * chore: update `ChannelType` usage * Update index.d.ts * docs: Update default reaction emoji property names Co-authored-by: Almeida <[email protected]> * fix: only `name` is required when editing tags - discord/discord-api-docs#5458 * types: add tests for `channel.flags` * fix: allow unsetting the default reaction emoji * refactor: remove v13 remnants * docs: add missing closing tag * feat: add `rateLimitPerUser` * feat: add missing properties for create guild channel - discord/discord-api-docs#5474 * refactor(GuildForumThreadManager): refactor message payload * fix: handle magical `null` case Co-authored-by: A. Román <[email protected]> Co-authored-by: Jiralite <[email protected]> Co-authored-by: Jaworek <[email protected]> Co-authored-by: Jonathan Rubenstein <[email protected]> Co-authored-by: SpaceEEC <[email protected]> Co-authored-by: Almeida <[email protected]> Co-authored-by: A. Román <[email protected]>
- Loading branch information
1 parent
669c3cd
commit 8a8d519
Showing
22 changed files
with
645 additions
and
95 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
76 changes: 76 additions & 0 deletions
76
packages/discord.js/src/managers/GuildForumThreadManager.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
'use strict'; | ||
|
||
const { Routes } = require('discord-api-types/v10'); | ||
const ThreadManager = require('./ThreadManager'); | ||
const { TypeError, ErrorCodes } = require('../errors'); | ||
const MessagePayload = require('../structures/MessagePayload'); | ||
|
||
/** | ||
* Manages API methods for threads in forum channels and stores their cache. | ||
* @extends {ThreadManager} | ||
*/ | ||
class GuildForumThreadManager extends ThreadManager { | ||
/** | ||
* @typedef {BaseMessageOptions} GuildForumThreadCreateOptions | ||
* @property {stickers} [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 {GuildForumThreadCreateOptions|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: ThreadAutoArchiveDuration.OneHour, | ||
* 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(ErrorCodes.GuildForumMessageRequired); | ||
} | ||
|
||
const { body, files } = await (message instanceof MessagePayload ? message : MessagePayload.create(this, message)) | ||
.resolveBody() | ||
.resolveFiles(); | ||
|
||
const data = await this.client.rest.post(Routes.threads(this.channel.id), { | ||
body: { | ||
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; |
85 changes: 85 additions & 0 deletions
85
packages/discord.js/src/managers/GuildTextThreadManager.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
'use strict'; | ||
|
||
const { ChannelType, Routes } = require('discord-api-types/v10'); | ||
const ThreadManager = require('./ThreadManager'); | ||
const { ErrorCodes, TypeError } = require('../errors'); | ||
|
||
/** | ||
* Manages API methods for {@link ThreadChannel} objects and stores their cache. | ||
* @extends {CachedManager} | ||
*/ | ||
class GuildTextThreadManager extends ThreadManager { | ||
/** | ||
* 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 the `type` of thread gets inferred automatically and cannot be changed.</warn> | ||
* @property {ThreadChannelTypes} [type] The type of thread to create. | ||
* Defaults to {@link ChannelType.PublicThread} if created in a {@link TextChannel} | ||
* <warn>When creating threads in a {@link NewsChannel}, this is ignored and is always | ||
* {@link ChannelType.AnnouncementThread}</warn> | ||
* @property {boolean} [invitable] Whether non-moderators can add other non-moderators to the thread | ||
* <info>Can only be set when type will be {@link ChannelType.PrivateThread}</info> | ||
*/ | ||
|
||
/** | ||
* 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: ThreadAutoArchiveDuration.OneHour, | ||
* 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: ThreadAutoArchiveDuration.OneHour, | ||
* type: ChannelType.PrivateThread, | ||
* 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 resolvedType = | ||
this.channel.type === ChannelType.GuildAnnouncement ? ChannelType.AnnouncementThread : ChannelType.PublicThread; | ||
let startMessageId; | ||
if (startMessage) { | ||
startMessageId = this.channel.messages.resolveId(startMessage); | ||
if (!startMessageId) throw new TypeError(ErrorCodes.InvalidType, 'startMessage', 'MessageResolvable'); | ||
} else if (this.channel.type !== ChannelType.GuildAnnouncement) { | ||
resolvedType = type ?? resolvedType; | ||
} | ||
|
||
const data = await this.client.rest.post(Routes.threads(this.channel.id, startMessageId), { | ||
body: { | ||
name, | ||
auto_archive_duration: autoArchiveDuration, | ||
type: resolvedType, | ||
invitable: resolvedType === ChannelType.PrivateThread ? invitable : undefined, | ||
rate_limit_per_user: rateLimitPerUser, | ||
}, | ||
reason, | ||
}); | ||
|
||
return this.client.actions.ThreadCreate.handle(data).thread; | ||
} | ||
} | ||
|
||
module.exports = GuildTextThreadManager; |
Oops, something went wrong.