Skip to content

Commit

Permalink
Merge branch 'main' into feat/max-stage
Browse files Browse the repository at this point in the history
  • Loading branch information
Jiralite authored Sep 18, 2022
2 parents 1fca7b1 + 8a8d519 commit a9c997d
Show file tree
Hide file tree
Showing 43 changed files with 999 additions and 316 deletions.
26 changes: 24 additions & 2 deletions packages/api-extractor-utils/src/ApiNodeJSONEncoder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,12 +82,14 @@ export interface ApiMethodSignatureJSON
ApiTypeParameterListJSON,
ApiParameterListJSON,
ApiInheritableJSON {
mergedSiblings: ApiMethodSignatureJSON[];
optional: boolean;
overloadIndex: number;
returnTypeTokens: TokenDocumentation[];
}

export interface ApiMethodJSON extends ApiMethodSignatureJSON {
mergedSiblings: ApiMethodJSON[];
protected: boolean;
static: boolean;
}
Expand Down Expand Up @@ -133,6 +135,7 @@ export interface ApiVariableJSON extends ApiItemJSON {
}

export interface ApiFunctionJSON extends ApiItemJSON, ApiTypeParameterListJSON, ApiParameterListJSON {
mergedSiblings: ApiFunctionJSON[];
overloadIndex: number;
returnTypeTokens: TokenDocumentation[];
}
Expand Down Expand Up @@ -255,7 +258,7 @@ export class ApiNodeJSONEncoder {
};
}

public static encodeFunction(model: ApiModel, item: FunctionLike, version: string): ApiFunctionJSON {
public static encodeFunctionLike(model: ApiModel, item: FunctionLike, version: string) {
return {
...this.encodeItem(model, item, version),
...this.encodeParameterList(model, item, version),
Expand All @@ -265,16 +268,31 @@ export class ApiNodeJSONEncoder {
};
}

public static encodeFunction(model: ApiModel, item: FunctionLike, version: string, nested = false): ApiFunctionJSON {
return {
...this.encodeFunctionLike(model, item, version),
mergedSiblings: nested
? []
: item.getMergedSiblings().map((item) => this.encodeFunction(model, item as ApiFunction, version, true)),
};
}

public static encodeMethodSignature(
model: ApiModel,
item: ApiMethodSignature,
parent: ApiItemContainerMixin,
version: string,
nested = false,
): ApiMethodSignatureJSON {
return {
...this.encodeFunction(model, item, version),
...this.encodeFunctionLike(model, item, version),
...this.encodeInheritanceData(item, parent, version),
optional: item.isOptional,
mergedSiblings: nested
? []
: item
.getMergedSiblings()
.map((item) => this.encodeMethodSignature(model, item as ApiMethodSignature, parent, version, true)),
};
}

Expand All @@ -283,11 +301,15 @@ export class ApiNodeJSONEncoder {
item: ApiMethod,
parent: ApiItemContainerMixin,
version: string,
nested = false,
): ApiMethodJSON {
return {
...this.encodeMethodSignature(model, item, parent, version),
static: item.isStatic,
protected: item.isProtected,
mergedSiblings: nested
? []
: item.getMergedSiblings().map((item) => this.encodeMethod(model, item as ApiMethod, parent, version, true)),
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ describe('Slash Commands', () => {

expect(() => {
getBuilder().addChannelOption(
getChannelOption().addChannelTypes(ChannelType.GuildNews, ChannelType.GuildText),
getChannelOption().addChannelTypes(ChannelType.GuildAnnouncement, ChannelType.GuildText),
);
}).not.toThrowError();
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ const allowedChannelTypes = [
ChannelType.GuildText,
ChannelType.GuildVoice,
ChannelType.GuildCategory,
ChannelType.GuildNews,
ChannelType.GuildNewsThread,
ChannelType.GuildPublicThread,
ChannelType.GuildPrivateThread,
ChannelType.GuildAnnouncement,
ChannelType.AnnouncementThread,
ChannelType.PublicThread,
ChannelType.PrivateThread,
ChannelType.GuildStageVoice,
] as const;

Expand Down
4 changes: 4 additions & 0 deletions packages/discord.js/src/errors/ErrorCodes.js
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,8 @@
* @property {'NotImplemented'} NotImplemented
* @property {'GuildForumMessageRequired'} GuildForumMessageRequired
* @property {'SweepFilterReturn'} SweepFilterReturn
*/

Expand Down Expand Up @@ -288,6 +290,8 @@ const keys = [
'NotImplemented',

'SweepFilterReturn',

'GuildForumMessageRequired',
];

// JSDoc for IntelliSense purposes
Expand Down
2 changes: 2 additions & 0 deletions packages/discord.js/src/errors/Messages.js
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,8 @@ const Messages = {
[DjsErrorCodes.NotImplemented]: (what, name) => `Method ${what} not implemented on ${name}.`,

[DjsErrorCodes.SweepFilterReturn]: 'The return value of the sweepFilter function was not false or a Function',

[DjsErrorCodes.GuildForumMessageRequired]: 'You must provide a message to create a guild forum thread',
};

module.exports = Messages;
4 changes: 4 additions & 0 deletions packages/discord.js/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ exports.ActivityFlagsBitField = require('./util/ActivityFlagsBitField');
exports.ApplicationFlagsBitField = require('./util/ApplicationFlagsBitField');
exports.BaseManager = require('./managers/BaseManager');
exports.BitField = require('./util/BitField');
exports.ChannelFlagsBitField = require('./util/ChannelFlagsBitField');
exports.Collection = require('@discordjs/collection').Collection;
exports.Constants = require('./util/Constants');
exports.Colors = require('./util/Colors');
Expand Down Expand Up @@ -58,12 +59,14 @@ exports.GuildBanManager = require('./managers/GuildBanManager');
exports.GuildChannelManager = require('./managers/GuildChannelManager');
exports.GuildEmojiManager = require('./managers/GuildEmojiManager');
exports.GuildEmojiRoleManager = require('./managers/GuildEmojiRoleManager');
exports.GuildForumThreadManager = require('./managers/GuildForumThreadManager');
exports.GuildInviteManager = require('./managers/GuildInviteManager');
exports.GuildManager = require('./managers/GuildManager');
exports.GuildMemberManager = require('./managers/GuildMemberManager');
exports.GuildMemberRoleManager = require('./managers/GuildMemberRoleManager');
exports.GuildScheduledEventManager = require('./managers/GuildScheduledEventManager');
exports.GuildStickerManager = require('./managers/GuildStickerManager');
exports.GuildTextThreadManager = require('./managers/GuildTextThreadManager');
exports.MessageManager = require('./managers/MessageManager');
exports.PermissionOverwriteManager = require('./managers/PermissionOverwriteManager');
exports.PresenceManager = require('./managers/PresenceManager');
Expand Down Expand Up @@ -109,6 +112,7 @@ exports.DMChannel = require('./structures/DMChannel');
exports.Embed = require('./structures/Embed');
exports.EmbedBuilder = require('./structures/EmbedBuilder');
exports.Emoji = require('./structures/Emoji').Emoji;
exports.ForumChannel = require('./structures/ForumChannel');
exports.Guild = require('./structures/Guild').Guild;
exports.GuildAuditLogs = require('./structures/GuildAuditLogs');
exports.GuildAuditLogsEntry = require('./structures/GuildAuditLogsEntry');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ class CategoryChannelChildManager extends DataManager {
* @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 {VideoQualityMode} [videoQualityMode] The camera video quality mode of the voice channel
* @property {GuildForumTagData[]} [availableTags] The tags that can be used in this channel (forum only).
* @property {DefaultReactionEmoji} [defaultReactionEmoji]
* The emoji to show in the add reaction button on a thread in a guild forum channel.
* @property {string} [reason] Reason for creating the new channel
*/

Expand Down
15 changes: 13 additions & 2 deletions packages/discord.js/src/managers/GuildChannelManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@ const process = require('node:process');
const { Collection } = require('@discordjs/collection');
const { ChannelType, Routes } = require('discord-api-types/v10');
const CachedManager = require('./CachedManager');
const ThreadManager = require('./ThreadManager');
const GuildTextThreadManager = require('./GuildTextThreadManager');
const { Error, TypeError, ErrorCodes } = require('../errors');
const GuildChannel = require('../structures/GuildChannel');
const PermissionOverwrites = require('../structures/PermissionOverwrites');
const ThreadChannel = require('../structures/ThreadChannel');
const Webhook = require('../structures/Webhook');
const { transformGuildForumTag, transformGuildDefaultReaction } = require('../util/Channels');
const { ThreadChannelTypes } = require('../util/Constants');
const DataResolver = require('../util/DataResolver');
const { setPosition } = require('../util/Util');
Expand Down Expand Up @@ -137,6 +138,8 @@ class GuildChannelManager extends CachedManager {
rateLimitPerUser,
rtcRegion,
videoQualityMode,
availableTags,
defaultReactionEmoji,
reason,
}) {
parent &&= this.client.channels.resolveId(parent);
Expand All @@ -156,6 +159,8 @@ class GuildChannelManager extends CachedManager {
rate_limit_per_user: rateLimitPerUser,
rtc_region: rtcRegion,
video_quality_mode: videoQualityMode,
available_tags: availableTags?.map(availableTag => transformGuildForumTag(availableTag)),
default_reaction_emoji: defaultReactionEmoji && transformGuildDefaultReaction(defaultReactionEmoji),
},
reason,
});
Expand Down Expand Up @@ -218,6 +223,9 @@ class GuildChannelManager extends CachedManager {
* The default auto archive duration for all new threads in this channel
* @property {?string} [rtcRegion] The RTC region of the channel
* @property {?VideoQualityMode} [videoQualityMode] The camera video quality mode of 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 {string} [reason] Reason for editing this channel
*/

Expand Down Expand Up @@ -274,6 +282,9 @@ class GuildChannelManager extends CachedManager {
rate_limit_per_user: data.rateLimitPerUser,
default_auto_archive_duration: data.defaultAutoArchiveDuration,
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,
},
reason: data.reason,
});
Expand Down Expand Up @@ -418,7 +429,7 @@ class GuildChannelManager extends CachedManager {
*/
async fetchActiveThreads(cache = true) {
const raw = await this.client.rest.get(Routes.guildActiveThreads(this.guild.id));
return ThreadManager._mapThreads(raw, this.client, { guild: this.guild, cache });
return GuildTextThreadManager._mapThreads(raw, this.client, { guild: this.guild, cache });
}

/**
Expand Down
76 changes: 76 additions & 0 deletions packages/discord.js/src/managers/GuildForumThreadManager.js
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 packages/discord.js/src/managers/GuildTextThreadManager.js
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;
Loading

0 comments on commit a9c997d

Please sign in to comment.