From 466e53b1fd05827c29e3d0ab2e5f1d9bbe7f4af1 Mon Sep 17 00:00:00 2001 From: Jaw0r3k Date: Tue, 29 Nov 2022 19:38:21 +0100 Subject: [PATCH 01/11] feat(v13): backboard automod --- src/client/actions/ActionsManager.js | 4 + .../actions/AutoModerationActionExecution.js | 26 ++ .../actions/AutoModerationRuleCreate.js | 27 ++ .../actions/AutoModerationRuleDelete.js | 31 ++ .../actions/AutoModerationRuleUpdate.js | 29 ++ .../AUTO_MODERATION_ACTION_EXECUTION.js | 5 + .../handlers/AUTO_MODERATION_RULE_CREATE.js | 5 + .../handlers/AUTO_MODERATION_RULE_DELETE.js | 5 + .../handlers/AUTO_MODERATION_RULE_UPDATE.js | 5 + src/client/websocket/handlers/index.js | 4 + src/index.js | 3 + src/managers/AutoModerationRuleManager.js | 288 ++++++++++++++++++ .../AutoModerationActionExecution.js | 87 ++++++ src/structures/AutoModerationRule.js | 279 +++++++++++++++++ src/structures/Guild.js | 7 + src/structures/GuildAuditLogs.js | 58 +++- src/util/Constants.js | 57 +++- src/util/Intents.js | 4 + src/util/Sweepers.js | 10 + 19 files changed, 925 insertions(+), 9 deletions(-) create mode 100644 src/client/actions/AutoModerationActionExecution.js create mode 100644 src/client/actions/AutoModerationRuleCreate.js create mode 100644 src/client/actions/AutoModerationRuleDelete.js create mode 100644 src/client/actions/AutoModerationRuleUpdate.js create mode 100644 src/client/websocket/handlers/AUTO_MODERATION_ACTION_EXECUTION.js create mode 100644 src/client/websocket/handlers/AUTO_MODERATION_RULE_CREATE.js create mode 100644 src/client/websocket/handlers/AUTO_MODERATION_RULE_DELETE.js create mode 100644 src/client/websocket/handlers/AUTO_MODERATION_RULE_UPDATE.js create mode 100644 src/managers/AutoModerationRuleManager.js create mode 100644 src/structures/AutoModerationActionExecution.js create mode 100644 src/structures/AutoModerationRule.js diff --git a/src/client/actions/ActionsManager.js b/src/client/actions/ActionsManager.js index 584177719339..0f3f53169f7a 100644 --- a/src/client/actions/ActionsManager.js +++ b/src/client/actions/ActionsManager.js @@ -4,6 +4,10 @@ class ActionsManager { constructor(client) { this.client = client; + this.register(require('./AutoModerationActionExecution')); + this.register(require('./AutoModerationRuleCreate')); + this.register(require('./AutoModerationRuleDelete')); + this.register(require('./AutoModerationRuleUpdate')); this.register(require('./ChannelCreate')); this.register(require('./ChannelDelete')); this.register(require('./ChannelUpdate')); diff --git a/src/client/actions/AutoModerationActionExecution.js b/src/client/actions/AutoModerationActionExecution.js new file mode 100644 index 000000000000..0c4380104e71 --- /dev/null +++ b/src/client/actions/AutoModerationActionExecution.js @@ -0,0 +1,26 @@ +'use strict'; + +const Action = require('./Action'); +const AutoModerationActionExecution = require('../../structures/AutoModerationActionExecution'); +const { Events } = require('../../util/Constants'); + +class AutoModerationActionExecutionAction extends Action { + handle(data) { + const { client } = this; + const guild = client.guilds.cache.get(data.guild_id); + + if (guild) { + /** + * Emitted whenever an auto moderation rule is triggered. + * This event requires the {@link Permissions.FLAGS.MANAGE_GUILD} permission. + * @event Client#autoModerationActionExecution + * @param {AutoModerationActionExecution} autoModerationActionExecution The data of the execution + */ + client.emit(Events.AUTO_MODERATION_ACTION_EXECUTION, new AutoModerationActionExecution(data, guild)); + } + + return {}; + } +} + +module.exports = AutoModerationActionExecutionAction; diff --git a/src/client/actions/AutoModerationRuleCreate.js b/src/client/actions/AutoModerationRuleCreate.js new file mode 100644 index 000000000000..a20bd3022d0b --- /dev/null +++ b/src/client/actions/AutoModerationRuleCreate.js @@ -0,0 +1,27 @@ +'use strict'; + +const Action = require('./Action'); +const { Events } = require('../../util/Constants'); + +class AutoModerationRuleCreateAction extends Action { + handle(data) { + const { client } = this; + const guild = client.guilds.cache.get(data.guild_id); + + if (guild) { + const autoModerationRule = guild.autoModerationRules._add(data); + + /** + * Emitted whenever an auto moderation rule is created. + * This event requires the {@link Permissions.FLAGS.MANAGE_GUILD} permission. + * @event Client#autoModerationRuleCreate + * @param {AutoModerationRule} autoModerationRule The created auto moderation rule + */ + client.emit(Events.AUTO_MODERATION_RULE_CREATE, autoModerationRule); + } + + return {}; + } +} + +module.exports = AutoModerationRuleCreateAction; diff --git a/src/client/actions/AutoModerationRuleDelete.js b/src/client/actions/AutoModerationRuleDelete.js new file mode 100644 index 000000000000..a08b458284df --- /dev/null +++ b/src/client/actions/AutoModerationRuleDelete.js @@ -0,0 +1,31 @@ +'use strict'; + +const Action = require('./Action'); +const { Events } = require('../../util/Constants'); + +class AutoModerationRuleDeleteAction extends Action { + handle(data) { + const { client } = this; + const guild = client.guilds.cache.get(data.guild_id); + + if (guild) { + const autoModerationRule = guild.autoModerationRules.cache.get(data.id); + + if (autoModerationRule) { + guild.autoModerationRules.cache.delete(autoModerationRule.id); + + /** + * Emitted whenever an auto moderation rule is deleted. + * This event requires the {@link Permissions.FLAGS.MANAGE_GUILD} permission. + * @event Client#autoModerationRuleDelete + * @param {AutoModerationRule} autoModerationRule The deleted auto moderation rule + */ + client.emit(Events.AUTO_MODERATION_RULE_DELETE, autoModerationRule); + } + } + + return {}; + } +} + +module.exports = AutoModerationRuleDeleteAction; diff --git a/src/client/actions/AutoModerationRuleUpdate.js b/src/client/actions/AutoModerationRuleUpdate.js new file mode 100644 index 000000000000..0a608fa7834a --- /dev/null +++ b/src/client/actions/AutoModerationRuleUpdate.js @@ -0,0 +1,29 @@ +'use strict'; + +const Action = require('./Action'); +const { Events } = require('../../util/Constants'); + +class AutoModerationRuleUpdateAction extends Action { + handle(data) { + const { client } = this; + const guild = client.guilds.cache.get(data.guild_id); + + if (guild) { + const oldAutoModerationRule = guild.autoModerationRules.cache.get(data.id)?._clone() ?? null; + const newAutoModerationRule = guild.autoModerationRules._add(data); + + /** + * Emitted whenever an auto moderation rule gets updated. + * This event requires the {@link Permissions.FLAGS.MANAGE_GUILD} permission. + * @event Client#autoModerationRuleUpdate + * @param {?AutoModerationRule} oldAutoModerationRule The auto moderation rule before the update + * @param {AutoModerationRule} newAutoModerationRule The auto moderation rule after the update + */ + client.emit(Events.AUTO_MODERATION_RULE_UPDATE, oldAutoModerationRule, newAutoModerationRule); + } + + return {}; + } +} + +module.exports = AutoModerationRuleUpdateAction; diff --git a/src/client/websocket/handlers/AUTO_MODERATION_ACTION_EXECUTION.js b/src/client/websocket/handlers/AUTO_MODERATION_ACTION_EXECUTION.js new file mode 100644 index 000000000000..22463b6e1eee --- /dev/null +++ b/src/client/websocket/handlers/AUTO_MODERATION_ACTION_EXECUTION.js @@ -0,0 +1,5 @@ +'use strict'; + +module.exports = (client, packet) => { + client.actions.AutoModerationActionExecution.handle(packet.d); +}; diff --git a/src/client/websocket/handlers/AUTO_MODERATION_RULE_CREATE.js b/src/client/websocket/handlers/AUTO_MODERATION_RULE_CREATE.js new file mode 100644 index 000000000000..af64b9cbcc98 --- /dev/null +++ b/src/client/websocket/handlers/AUTO_MODERATION_RULE_CREATE.js @@ -0,0 +1,5 @@ +'use strict'; + +module.exports = (client, packet) => { + client.actions.AutoModerationRuleCreate.handle(packet.d); +}; diff --git a/src/client/websocket/handlers/AUTO_MODERATION_RULE_DELETE.js b/src/client/websocket/handlers/AUTO_MODERATION_RULE_DELETE.js new file mode 100644 index 000000000000..56ec504a9460 --- /dev/null +++ b/src/client/websocket/handlers/AUTO_MODERATION_RULE_DELETE.js @@ -0,0 +1,5 @@ +'use strict'; + +module.exports = (client, packet) => { + client.actions.AutoModerationRuleDelete.handle(packet.d); +}; diff --git a/src/client/websocket/handlers/AUTO_MODERATION_RULE_UPDATE.js b/src/client/websocket/handlers/AUTO_MODERATION_RULE_UPDATE.js new file mode 100644 index 000000000000..3caf6ba55028 --- /dev/null +++ b/src/client/websocket/handlers/AUTO_MODERATION_RULE_UPDATE.js @@ -0,0 +1,5 @@ +'use strict'; + +module.exports = (client, packet) => { + client.actions.AutoModerationRuleUpdate.handle(packet.d); +}; diff --git a/src/client/websocket/handlers/index.js b/src/client/websocket/handlers/index.js index 65880ad9ddbf..7a0926499b69 100644 --- a/src/client/websocket/handlers/index.js +++ b/src/client/websocket/handlers/index.js @@ -6,6 +6,10 @@ const handlers = Object.fromEntries([ ['APPLICATION_COMMAND_CREATE', require('./APPLICATION_COMMAND_CREATE')], ['APPLICATION_COMMAND_DELETE', require('./APPLICATION_COMMAND_DELETE')], ['APPLICATION_COMMAND_UPDATE', require('./APPLICATION_COMMAND_UPDATE')], + ['AUTO_MODERATION_ACTION_EXECUTION', require('./AUTO_MODERATION_ACTION_EXECUTION')], + ['AUTO_MODERATION_RULE_CREATE', require('./AUTO_MODERATION_RULE_CREATE')], + ['AUTO_MODERATION_RULE_DELETE', require('./AUTO_MODERATION_RULE_DELETE')], + ['AUTO_MODERATION_RULE_UPDATE', require('./AUTO_MODERATION_RULE_UPDATE')], ['GUILD_CREATE', require('./GUILD_CREATE')], ['GUILD_DELETE', require('./GUILD_DELETE')], ['GUILD_UPDATE', require('./GUILD_UPDATE')], diff --git a/src/index.js b/src/index.js index 9e7906928feb..1842a8421dc4 100644 --- a/src/index.js +++ b/src/index.js @@ -36,6 +36,7 @@ exports.version = require('../package.json').version; // Managers exports.ApplicationCommandManager = require('./managers/ApplicationCommandManager'); exports.ApplicationCommandPermissionsManager = require('./managers/ApplicationCommandPermissionsManager'); +exports.AutoModerationRuleManager = require('./managers/AutoModerationRuleManager'); exports.BaseGuildEmojiManager = require('./managers/BaseGuildEmojiManager'); exports.CachedManager = require('./managers/CachedManager'); exports.ChannelManager = require('./managers/ChannelManager'); @@ -72,6 +73,8 @@ exports.AnonymousGuild = require('./structures/AnonymousGuild'); exports.Application = require('./structures/interfaces/Application'); exports.ApplicationCommand = require('./structures/ApplicationCommand'); exports.AutocompleteInteraction = require('./structures/AutocompleteInteraction'); +exports.AutoModerationActionExecution = require('./structures/AutoModerationActionExecution'); +exports.AutoModerationRule = require('./structures/AutoModerationRule'); exports.Base = require('./structures/Base'); exports.BaseCommandInteraction = require('./structures/BaseCommandInteraction'); exports.BaseGuild = require('./structures/BaseGuild'); diff --git a/src/managers/AutoModerationRuleManager.js b/src/managers/AutoModerationRuleManager.js new file mode 100644 index 000000000000..124789038486 --- /dev/null +++ b/src/managers/AutoModerationRuleManager.js @@ -0,0 +1,288 @@ +'use strict'; + +const { Collection } = require('@discordjs/collection'); +const CachedManager = require('./CachedManager'); +const AutoModerationRule = require('../structures/AutoModerationRule'); +const { + AutoModerationRuleEventTypes, + AutoModerationRuleTriggerTypes, + AutoModerationActionTypes, + AutoModerationRuleKeywordPresetTypes, +} = require('../util/Constants'); + +/** + * Manages API methods for auto moderation rules and stores their cache. + * @extends {CachedManager} + */ +class AutoModerationRuleManager extends CachedManager { + constructor(guild, iterable) { + super(guild.client, AutoModerationRule, iterable); + + /** + * The guild this manager belongs to. + * @type {Guild} + */ + this.guild = guild; + } + + _add(data, cache) { + return super._add(data, cache, { extras: [this.guild] }); + } + + /** + * Options used to set the trigger metadata of an auto moderation rule. + * @typedef {Object} AutoModerationTriggerMetadataOptions + * @property {string[]} [keywordFilter] The substrings that will be searched for in the content + * @property {string[]} [regexPatterns] The regular expression patterns which will be matched against the content + * Only Rust-flavored regular expressions are supported. + * @property {AutoModerationRuleKeywordPresetType[]} [presets] + * The internally pre-defined wordsets which will be searched for in the content + * @property {string[]} [allowList] The substrings that will be exempt from triggering + * {@link AutoModerationRuleTriggerType.KEYWORD} and {@link AutoModerationRuleTriggerType.KEYWORD_PRESET} + * @property {?number} [mentionTotalLimit] The total number of role & user mentions allowed per message + */ + + /** + * Options used to set the actions of an auto moderation rule. + * @typedef {Object} AutoModerationActionOptions + * @property {AutoModerationActionType} type The type of this auto moderation rule action + * @property {AutoModerationActionMetadataOptions} [metadata] Additional metadata needed during execution + * This property is required if using a `type` of + * {@link AutoModerationActionType.SEND_ALERT_MESSAGE} or {@link AutoModerationActionType.TIMEOUT}. + */ + + /** + * Options used to set the metadata of an auto moderation rule action. + * @typedef {Object} AutoModerationActionMetadataOptions + * @property {GuildTextChannelResolvable|ThreadChannel} [channel] The channel to which content will be logged + * @property {number} [durationSeconds] The timeout duration in seconds + */ + + /** + * Options used to create an auto moderation rule. + * @typedef {Object} AutoModerationRuleCreateOptions + * @property {string} name The name of the auto moderation rule + * @property {AutoModerationRuleEventType} eventType The event type of the auto moderation rule + * @property {AutoModerationRuleTriggerType} triggerType The trigger type of the auto moderation rule + * @property {AutoModerationTriggerMetadataOptions} [triggerMetadata] The trigger metadata of the auto moderation rule + * This property is required if using a `triggerType` of + * {@link AutoModerationRuleTriggerType.KEYWORD}, {@link AutoModerationRuleTriggerType.KEYWORD_PRESET}, + * or {@link AutoModerationRuleTriggerType.MENTION_SPAM}. + * @property {AutoModerationActionOptions[]} actions + * The actions that will execute when the auto moderation rule is triggered + * @property {boolean} [enabled] Whether the auto moderation rule should be enabled + * @property {Collection|RoleResolvable[]} [exemptRoles] + * The roles that should not be affected by the auto moderation rule + * @property {Collection|GuildChannelResolvable[]} [exemptChannels] + * The channels that should not be affected by the auto moderation rule + * @property {string} [reason] The reason for creating the auto moderation rule + */ + + /** + * Creates a new auto moderation rule. + * @param {AutoModerationRuleCreateOptions} options Options for creating the auto moderation rule + * @returns {Promise} + */ + async create({ + name, + eventType, + triggerType, + triggerMetadata, + actions, + enabled, + exemptRoles, + exemptChannels, + reason, + }) { + const data = await this.client.api.guilds(this.guild.id)['auto-moderation'].rules.post({ + data: { + name, + event_type: typeof eventType === 'number' ? eventType : AutoModerationRuleEventTypes[eventType], + trigger_type: typeof triggerType === 'number' ? triggerType : AutoModerationRuleTriggerTypes[triggerType], + trigger_metadata: triggerMetadata && { + keyword_filter: triggerMetadata.keywordFilter, + regex_patterns: triggerMetadata.regexPatterns, + presets: triggerMetadata.presets?.map(preset => + typeof preset === 'number' ? preset : AutoModerationRuleKeywordPresetTypes[preset], + ), + allow_list: triggerMetadata.allowList, + mention_total_limit: triggerMetadata.mentionTotalLimit, + }, + actions: actions.map(action => ({ + type: typeof action.type === 'number' ? action.type : AutoModerationActionTypes[action.type], + metadata: { + duration_seconds: action.metadata?.durationSeconds, + channel_id: action.metadata?.channel && this.guild.channels.resolveId(action.metadata.channel), + }, + })), + enabled, + exempt_roles: exemptRoles?.map(exemptRole => this.guild.roles.resolveId(exemptRole)), + exempt_channels: exemptChannels?.map(exemptChannel => this.guild.channels.resolveId(exemptChannel)), + }, + reason, + }); + + return this._add(data); + } + + /** + * Options used to edit an auto moderation rule. + * @typedef {Object} AutoModerationRuleEditOptions + * @property {string} [name] The name of the auto moderation rule + * @property {AutoModerationRuleEventType} [eventType] The event type of the auto moderation rule + * @property {AutoModerationTriggerMetadataOptions} [triggerMetadata] The trigger metadata of the auto moderation rule + * @property {AutoModerationActionOptions[]} [actions] + * The actions that will execute when the auto moderation rule is triggered + * @property {boolean} [enabled] Whether the auto moderation rule should be enabled + * @property {Collection|RoleResolvable[]} [exemptRoles] + * The roles that should not be affected by the auto moderation rule + * @property {Collection|GuildChannelResolvable[]} [exemptChannels] + * The channels that should not be affected by the auto moderation rule + * @property {string} [reason] The reason for creating the auto moderation rule + */ + + /** + * Edits an auto moderation rule. + * @param {AutoModerationRuleResolvable} autoModerationRule The auto moderation rule to edit + * @param {AutoModerationRuleEditOptions} options Options for editing the auto moderation rule + * @returns {Promise} + */ + async edit( + autoModerationRule, + { name, eventType, triggerMetadata, actions, enabled, exemptRoles, exemptChannels, reason }, + ) { + const autoModerationRuleId = this.resolveId(autoModerationRule); + + const data = await this.client.api + .guilds(this.guild.id)('auto-moderation') + .rules(autoModerationRuleId) + .patch({ + data: { + name, + event_type: typeof eventType === 'number' ? eventType : AutoModerationRuleEventTypes[eventType], + trigger_metadata: triggerMetadata && { + keyword_filter: triggerMetadata.keywordFilter, + regex_patterns: triggerMetadata.regexPatterns, + presets: triggerMetadata.presets?.map(preset => + typeof preset === 'number' ? preset : AutoModerationRuleKeywordPresetTypes[preset], + ), + allow_list: triggerMetadata.allowList, + mention_total_limit: triggerMetadata.mentionTotalLimit, + }, + actions: actions?.map(action => ({ + type: typeof action.type === 'number' ? action.type : AutoModerationActionTypes[action.type], + metadata: { + duration_seconds: action.metadata?.durationSeconds, + channel_id: action.metadata?.channel && this.guild.channels.resolveId(action.metadata.channel), + }, + })), + enabled, + exempt_roles: exemptRoles?.map(exemptRole => this.guild.roles.resolveId(exemptRole)), + exempt_channels: exemptChannels?.map(exemptChannel => this.guild.channels.resolveId(exemptChannel)), + }, + reason, + }); + + return this._add(data); + } + + /** + * Data that can be resolved to give an AutoModerationRule object. This can be: + * * An AutoModerationRule + * * A Snowflake + * @typedef {AutoModerationRule|Snowflake} AutoModerationRuleResolvable + */ + + /** + * Options used to fetch a single auto moderation rule from a guild. + * @typedef {BaseFetchOptions} FetchAutoModerationRuleOptions + * @property {AutoModerationRuleResolvable} autoModerationRule The auto moderation rule to fetch + */ + + /** + * Options used to fetch all auto moderation rules from a guild. + * @typedef {Object} FetchAutoModerationRulesOptions + * @property {boolean} [cache] Whether to cache the fetched auto moderation rules + */ + + /** + * Fetches auto moderation rules from Discord. + * @param {AutoModerationRuleResolvable|FetchAutoModerationRuleOptions|FetchAutoModerationRulesOptions} [options] + * Options for fetching auto moderation rule(s) + * @returns {Promise>} + * @example + * // Fetch all auto moderation rules from a guild without caching + * guild.autoModerationRules.fetch({ cache: false }) + * .then(console.log) + * .catch(console.error); + * @example + * // Fetch a single auto moderation rule + * guild.autoModerationRules.fetch('979083472868098119') + * .then(console.log) + * .catch(console.error); + * @example + * // Fetch a single auto moderation rule without checking cache and without caching + * guild.autoModerationRules.fetch({ autoModerationRule: '979083472868098119', cache: false, force: true }) + * .then(console.log) + * .catch(console.error) + */ + fetch(options) { + if (!options) return this._fetchMany(); + const { autoModerationRule, cache, force } = options; + const resolvedAutoModerationRule = this.resolveId(autoModerationRule ?? options); + if (resolvedAutoModerationRule) { + return this._fetchSingle({ autoModerationRule: resolvedAutoModerationRule, cache, force }); + } + return this._fetchMany(options); + } + + async _fetchSingle({ autoModerationRule, cache, force = false }) { + if (!force) { + const existing = this.cache.get(autoModerationRule); + if (existing) return existing; + } + + const data = await this.client.api.guilds(this.guild.id)('auto-moderation').rules(autoModerationRule).get(); + return this._add(data, cache); + } + + async _fetchMany(options = {}) { + const data = await this.client.api.guilds(this.guild.id)('auto-moderation').rules.get(); + + return data.reduce( + (col, autoModerationRule) => col.set(autoModerationRule.id, this._add(autoModerationRule, options.cache)), + new Collection(), + ); + } + + /** + * Deletes an auto moderation rule. + * @param {AutoModerationRuleResolvable} autoModerationRule The auto moderation rule to delete + * @param {string} [reason] The reason for deleting the auto moderation rule + * @returns {Promise} + */ + async delete(autoModerationRule, reason) { + const autoModerationRuleId = this.resolveId(autoModerationRule); + await this.client.api.guilds(this.guild.id)('auto-moderation').rules(autoModerationRuleId).delete({ reason }); + } + + /** + * Resolves an {@link AutoModerationRuleResolvable} to an {@link AutoModerationRule} object. + * @method resolve + * @memberof AutoModerationRuleManager + * @instance + * @param {AutoModerationRuleResolvable} autoModerationRule The AutoModerationRule resolvable to resolve + * @returns {?AutoModerationRule} + */ + + /** + * Resolves an {@link AutoModerationRuleResolvable} to a {@link AutoModerationRule} id. + * @method resolveId + * @memberof AutoModerationRuleManager + * @instance + * @param {AutoModerationRuleResolvable} autoModerationRule The AutoModerationRule resolvable to resolve + * @returns {?Snowflake} + */ +} + +module.exports = AutoModerationRuleManager; diff --git a/src/structures/AutoModerationActionExecution.js b/src/structures/AutoModerationActionExecution.js new file mode 100644 index 000000000000..45c2949ab1a6 --- /dev/null +++ b/src/structures/AutoModerationActionExecution.js @@ -0,0 +1,87 @@ +'use strict'; + +/** + * Represents the structure of an executed action when an {@link AutoModerationRule} is triggered. + */ +class AutoModerationActionExecution { + constructor(data, guild) { + /** + * The guild where this action was executed from. + * @type {Guild} + */ + this.guild = guild; + + /** + * The action that was executed. + * @type {AutoModerationAction} + */ + this.action = data.action; + + /** + * The id of the auto moderation rule this action belongs to. + * @type {Snowflake} + */ + this.ruleId = data.rule_id; + + /** + * The trigger type of the auto moderation rule which was triggered. + * @type {AutoModerationRuleTriggerType} + */ + this.ruleTriggerType = data.rule_trigger_type; + + /** + * The id of the user that triggered this action. + * @type {Snowflake} + */ + this.userId = data.user_id; + + /** + * The id of the channel where this action was triggered from. + * @type {?Snowflake} + */ + this.channelId = data.channel_id ?? null; + + /** + * The id of the message that triggered this action. + * @type {?Snowflake} + * This will not be present if the message was blocked or the content was not part of any message. + */ + this.messageId = data.message_id ?? null; + + /** + * The id of any system auto moderation messages posted as a result of this action. + * @type {?Snowflake} + */ + this.alertSystemMessageId = data.alert_system_message_id ?? null; + + /** + * The content that triggered this action. + * This property requires the {@link GatewayIntentBits.MessageContent} privileged gateway intent. + * @type {string} + */ + this.content = data.content; + + /** + * The word or phrase configured in the rule that triggered this action. + * @type {?string} + */ + this.matchedKeyword = data.matched_keyword ?? null; + + /** + * The substring in content that triggered this action. + * @type {?string} + */ + this.matchedContent = data.matched_content ?? null; + } + + /** + * The auto moderation rule this action belongs to. + * @type {?AutoModerationRule} + * @readonly + */ + get autoModerationRule() { + return this.guild.autoModerationRules.cache.get(this.ruleId) ?? null; + } +} + +module.exports = AutoModerationActionExecution; diff --git a/src/structures/AutoModerationRule.js b/src/structures/AutoModerationRule.js new file mode 100644 index 000000000000..8816d2393760 --- /dev/null +++ b/src/structures/AutoModerationRule.js @@ -0,0 +1,279 @@ +'use strict'; + +const { Collection } = require('@discordjs/collection'); +const Base = require('./Base'); +const { + AutoModerationRuleKeywordPresetTypes, + AutoModerationRuleTriggerTypes, + AutoModerationRuleEventTypes, + AutoModerationActionTypes, +} = require('../util/Constants'); + +/** + * Represents an auto moderation rule. + * @extends {Base} + */ +class AutoModerationRule extends Base { + constructor(client, data, guild) { + super(client); + + /** + * The id of this auto moderation rule. + * @type {Snowflake} + */ + this.id = data.id; + + /** + * The guild this auto moderation rule is for. + * @type {Guild} + */ + this.guild = guild; + + /** + * The user that created this auto moderation rule. + * @type {Snowflake} + */ + this.creatorId = data.creator_id; + + /** + * The trigger type of this auto moderation rule. + * @type {AutoModerationRuleTriggerType} + */ + this.triggerType = AutoModerationRuleTriggerTypes[data.trigger_type]; + + this._patch(data); + } + + _patch(data) { + if ('name' in data) { + /** + * The name of this auto moderation rule. + * @type {string} + */ + this.name = data.name; + } + + if ('event_type' in data) { + /** + * The event type of this auto moderation rule. + * @type {AutoModerationRuleEventType} + */ + this.eventType = AutoModerationRuleEventTypes[data.event_type]; + } + + if ('trigger_metadata' in data) { + /** + * Additional data used to determine whether an auto moderation rule should be triggered. + * @typedef {Object} AutoModerationTriggerMetadata + * @property {string[]} keywordFilter The substrings that will be searched for in the content + * @property {string[]} regexPatterns The regular expression patterns which will be matched against the content + * Only Rust-flavored regular expressions are supported. + * @property {AutoModerationRuleKeywordPresetType[]} presets + * The internally pre-defined wordsets which will be searched for in the content + * @property {string[]} allowList The substrings that will be exempt from triggering + * {@link AutoModerationRuleTriggerTypes.Keyword} and {@link AutoModerationRuleTriggerTypes.KeywordPreset} + * @property {?number} mentionTotalLimit The total number of role & user mentions allowed per message + */ + + /** + * The trigger metadata of the rule. + * @type {AutoModerationTriggerMetadata} + */ + this.triggerMetadata = { + keywordFilter: data.trigger_metadata.keyword_filter ?? [], + regexPatterns: data.trigger_metadata.regex_patterns ?? [], + presets: data.trigger_metadata.presets?.map(preset => AutoModerationRuleKeywordPresetTypes[preset]) ?? [], + allowList: data.trigger_metadata.allow_list ?? [], + mentionTotalLimit: data.trigger_metadata.mention_total_limit ?? null, + }; + } + + if ('actions' in data) { + /** + * An object containing information about an auto moderation rule action. + * @typedef {Object} AutoModerationAction + * @property {AutoModerationActionType} type The type of this auto moderation rule action + * @property {AutoModerationActionMetadata} metadata Additional metadata needed during execution + */ + + /** + * Additional data used when an auto moderation rule is executed. + * @typedef {Object} AutoModerationActionMetadata + * @property {?Snowflake} channelId The id of the channel to which content will be logged + * @property {?number} durationSeconds The timeout duration in seconds + */ + + /** + * The actions of this auto moderation rule. + * @type {AutoModerationAction[]} + */ + this.actions = data.actions.map(action => ({ + type: AutoModerationActionTypes[action.type], + metadata: { + durationSeconds: action.metadata.duration_seconds ?? null, + channelId: action.metadata.channel_id ?? null, + }, + })); + } + + if ('enabled' in data) { + /** + * Whether this auto moderation rule is enabled. + * @type {boolean} + */ + this.enabled = data.enabled; + } + + if ('exempt_roles' in data) { + /** + * The roles exempt by this auto moderation rule. + * @type {Collection} + */ + this.exemptRoles = new Collection( + data.exempt_roles.map(exemptRole => [exemptRole, this.guild.roles.cache.get(exemptRole)]), + ); + } + + if ('exempt_channels' in data) { + /** + * The channels exempt by this auto moderation rule. + * @type {Collection} + */ + this.exemptChannels = new Collection( + data.exempt_channels.map(exemptChannel => [exemptChannel, this.guild.channels.cache.get(exemptChannel)]), + ); + } + } + + /** + * Edits this auto moderation rule. + * @param {AutoModerationRuleEditOptions} options Options for editing this auto moderation rule + * @returns {Promise} + */ + edit(options) { + return this.guild.autoModerationRules.edit(this.id, options); + } + + /** + * Deletes this auto moderation rule. + * @param {string} [reason] The reason for deleting this auto moderation rule + * @returns {Promise} + */ + delete(reason) { + return this.guild.autoModerationRules.delete(this.id, reason); + } + + /** + * Sets the name for this auto moderation rule. + * @param {string} name The name of this auto moderation rule + * @param {string} [reason] The reason for changing the name of this auto moderation rule + * @returns {Promise} + */ + setName(name, reason) { + return this.edit({ name, reason }); + } + + /** + * Sets the event type for this auto moderation rule. + * @param {AutoModerationRuleEventType} eventType The event type of this auto moderation rule + * @param {string} [reason] The reason for changing the event type of this auto moderation rule + * @returns {Promise} + */ + setEventType(eventType, reason) { + return this.edit({ eventType, reason }); + } + + /** + * Sets the keyword filter for this auto moderation rule. + * @param {string[]} keywordFilter The keyword filter of this auto moderation rule + * @param {string} [reason] The reason for changing the keyword filter of this auto moderation rule + * @returns {Promise} + */ + setKeywordFilter(keywordFilter, reason) { + return this.edit({ triggerMetadata: { keywordFilter }, reason }); + } + + /** + * Sets the regular expression patterns for this auto moderation rule. + * @param {string[]} regexPatterns The regular expression patterns of this auto moderation rule + * Only Rust-flavored regular expressions are supported. + * @param {string} [reason] The reason for changing the regular expression patterns of this auto moderation rule + * @returns {Promise} + */ + setRegexPatterns(regexPatterns, reason) { + return this.edit({ triggerMetadata: { regexPatterns }, reason }); + } + + /** + * Sets the presets for this auto moderation rule. + * @param {AutoModerationRuleKeywordPresetType[]} presets The presets of this auto moderation rule + * @param {string} [reason] The reason for changing the presets of this auto moderation rule + * @returns {Promise} + */ + setPresets(presets, reason) { + return this.edit({ triggerMetadata: { presets }, reason }); + } + + /** + * Sets the allow list for this auto moderation rule. + * @param {string[]} allowList The allow list of this auto moderation rule + * @param {string} [reason] The reason for changing the allow list of this auto moderation rule + * @returns {Promise} + */ + setAllowList(allowList, reason) { + return this.edit({ triggerMetadata: { allowList }, reason }); + } + + /** + * Sets the mention total limit for this auto moderation rule. + * @param {number} mentionTotalLimit The mention total limit of this auto moderation rule + * @param {string} [reason] The reason for changing the mention total limit of this auto moderation rule + * @returns {Promise} + */ + setMentionTotalLimit(mentionTotalLimit, reason) { + return this.edit({ triggerMetadata: { mentionTotalLimit }, reason }); + } + + /** + * Sets the actions for this auto moderation rule. + * @param {AutoModerationActionOptions} actions The actions of this auto moderation rule + * @param {string} [reason] The reason for changing the actions of this auto moderation rule + * @returns {Promise} + */ + setActions(actions, reason) { + return this.edit({ actions, reason }); + } + + /** + * Sets whether this auto moderation rule should be enabled. + * @param {boolean} [enabled=true] Whether to enable this auto moderation rule + * @param {string} [reason] The reason for enabling or disabling this auto moderation rule + * @returns {Promise} + */ + setEnabled(enabled = true, reason) { + return this.edit({ enabled, reason }); + } + + /** + * Sets the exempt roles for this auto moderation rule. + * @param {Collection|RoleResolvable[]} [exemptRoles] The exempt roles of this auto moderation rule + * @param {string} [reason] The reason for changing the exempt roles of this auto moderation rule + * @returns {Promise} + */ + setExemptRoles(exemptRoles, reason) { + return this.edit({ exemptRoles, reason }); + } + + /** + * Sets the exempt channels for this auto moderation rule. + * @param {Collection|GuildChannelResolvable[]} [exemptChannels] + * The exempt channels of this auto moderation rule + * @param {string} [reason] The reason for changing the exempt channels of this auto moderation rule + * @returns {Promise} + */ + setExemptChannels(exemptChannels, reason) { + return this.edit({ exemptChannels, reason }); + } +} + +module.exports = AutoModerationRule; diff --git a/src/structures/Guild.js b/src/structures/Guild.js index ff06ea5ed18c..060d2a63ee96 100644 --- a/src/structures/Guild.js +++ b/src/structures/Guild.js @@ -10,6 +10,7 @@ const Integration = require('./Integration'); const Webhook = require('./Webhook'); const WelcomeScreen = require('./WelcomeScreen'); const { Error } = require('../errors'); +const AutoModerationRuleManager = require('../managers/AutoModerationRuleManager'); const GuildApplicationCommandManager = require('../managers/GuildApplicationCommandManager'); const GuildBanManager = require('../managers/GuildBanManager'); const GuildChannelManager = require('../managers/GuildChannelManager'); @@ -117,6 +118,12 @@ class Guild extends AnonymousGuild { */ this.scheduledEvents = new GuildScheduledEventManager(this); + /** + * A manager of the auto moderation rules of this guild. + * @type {AutoModerationRuleManager} + */ + this.autoModerationRules = new AutoModerationRuleManager(this); + if (!data) return; if (data.unavailable) { /** diff --git a/src/structures/GuildAuditLogs.js b/src/structures/GuildAuditLogs.js index 48086c37d130..f0a737a6bf30 100644 --- a/src/structures/GuildAuditLogs.js +++ b/src/structures/GuildAuditLogs.js @@ -1,6 +1,7 @@ 'use strict'; const { Collection } = require('@discordjs/collection'); +const AutoModerationRule = require('./AutoModerationRule'); const { GuildScheduledEvent } = require('./GuildScheduledEvent'); const Integration = require('./Integration'); const Invite = require('./Invite'); @@ -26,6 +27,7 @@ const Util = require('../util/Util'); * * STICKER * * THREAD * * GUILD_SCHEDULED_EVENT + * * AUTO_MODERATION * @typedef {string} AuditLogTargetType */ @@ -49,6 +51,7 @@ const Targets = { STAGE_INSTANCE: 'STAGE_INSTANCE', STICKER: 'STICKER', THREAD: 'THREAD', + AUTO_MODERATION: 'AUTO_MODERATION', UNKNOWN: 'UNKNOWN', }; @@ -102,6 +105,12 @@ const Targets = { * * THREAD_CREATE: 110 * * THREAD_UPDATE: 111 * * THREAD_DELETE: 112 + * * AUTO_MODERATION_RULE_CREATE: 140 + * * AUTO_MODERATION_RULE_UPDATE: 141 + * * AUTO_MODERATION_RULE_DELETE: 142 + * * AUTO_MODERATION_BLOCK_MESSAGE: 143 + * * AUTO_MODERATION_FLAG_TO_CHANNEL: 144 + * * AUTO_MODERATION_USER_COMMUNICATION_DISABLED: 145 * @typedef {?(number|string)} AuditLogAction * @see {@link https://discord.com/developers/docs/resources/audit-log#audit-log-entry-object-audit-log-events} */ @@ -160,6 +169,12 @@ const Actions = { THREAD_CREATE: 110, THREAD_UPDATE: 111, THREAD_DELETE: 112, + AUTO_MODERATION_RULE_CREATE: 140, + AUTO_MODERATION_RULE_UPDATE: 141, + AUTO_MODERATION_RULE_DELETE: 142, + AUTO_MODERATION_BLOCK_MESSAGE: 143, + AUTO_MODERATION_FLAG_TO_CHANNEL: 144, + AUTO_MODERATION_USER_COMMUNICATION_DISABLED: 145, }; /** @@ -193,6 +208,17 @@ class GuildAuditLogs { } } + /** + * Cached auto moderation rules. + * @type {Collection} + * @private + */ + this.autoModerationRules = data.auto_moderation_rules.reduce( + (autoModerationRules, autoModerationRule) => + autoModerationRules.set(autoModerationRule.id, guild.autoModerationRules._add(autoModerationRule)), + new Collection(), + ); + /** * The entries for this guild's audit logs * @type {Collection} @@ -229,10 +255,11 @@ class GuildAuditLogs { * * A sticker * * A guild scheduled event * * A thread + * * An auto moderation rule * * An object with an id key if target was deleted * * An object where the keys represent either the new value or the old value * @typedef {?(Object|Guild|Channel|User|Role|Invite|Webhook|GuildEmoji|Message|Integration|StageInstance|Sticker| - * GuildScheduledEvent)} AuditLogEntryTarget + * GuildScheduledEvent|AutoModerationRule)} AuditLogEntryTarget */ /** @@ -254,6 +281,7 @@ class GuildAuditLogs { if (target < 100) return Targets.STICKER; if (target < 110) return Targets.GUILD_SCHEDULED_EVENT; if (target < 120) return Targets.THREAD; + if (target >= 140 && target < 150) return Targets.AUTO_MODERATION; return Targets.UNKNOWN; } @@ -288,6 +316,8 @@ class GuildAuditLogs { Actions.STICKER_CREATE, Actions.GUILD_SCHEDULED_EVENT_CREATE, Actions.THREAD_CREATE, + Actions.AUTO_MODERATION_RULE_CREATE, + Actions.AUTO_MODERATION_BLOCK_MESSAGE, ].includes(action) ) { return 'CREATE'; @@ -313,6 +343,7 @@ class GuildAuditLogs { Actions.STICKER_DELETE, Actions.GUILD_SCHEDULED_EVENT_DELETE, Actions.THREAD_DELETE, + Actions.AUTO_MODERATION_RULE_DELETE, ].includes(action) ) { return 'DELETE'; @@ -335,6 +366,7 @@ class GuildAuditLogs { Actions.STICKER_UPDATE, Actions.GUILD_SCHEDULED_EVENT_UPDATE, Actions.THREAD_UPDATE, + Actions.AUTO_MODERATION_RULE_UPDATE, ].includes(action) ) { return 'UPDATE'; @@ -429,7 +461,6 @@ class GuildAuditLogsEntry { count: Number(data.options.count), }; break; - case Actions.MESSAGE_PIN: case Actions.MESSAGE_UNPIN: this.extra = { @@ -475,7 +506,14 @@ class GuildAuditLogsEntry { channel: guild.client.channels.cache.get(data.options?.channel_id) ?? { id: data.options?.channel_id }, }; break; - + case Actions.AUTO_MODERATION_BLOCK_MESSAGE: + case Actions.AUTO_MODERATION_FLAG_TO_CHANNEL: + case Actions.AUTO_MODERATION_USER_COMMUNICATION_DISABLED: + this.extra = { + autoModerationRuleName: data.options.auto_moderation_rule_name, + autoModerationRuleTriggerType: data.options.auto_moderation_rule_trigger_type, + }; + break; default: break; } @@ -603,6 +641,20 @@ class GuildAuditLogsEntry { { id: data.target_id, guild_id: guild.id }, ), ); + } else if (targetType === Targets.AUTO_MODERATION) { + this.target = + guild.autoModerationRules.cache.get(data.target_id) ?? + new AutoModerationRule( + guild.client, + this.changes.reduce( + (o, c) => { + o[c.key] = c.new ?? c.old; + return o; + }, + { id: data.target_id, guild_id: guild.id }, + ), + guild, + ); } else if (data.target_id) { this.target = guild[`${targetType.toLowerCase()}s`]?.cache.get(data.target_id) ?? { id: data.target_id }; } diff --git a/src/util/Constants.js b/src/util/Constants.js index 7db258bab82d..78c417cbdf8d 100644 --- a/src/util/Constants.js +++ b/src/util/Constants.js @@ -174,6 +174,10 @@ exports.Opcodes = { * * APPLICATION_COMMAND_CREATE: applicationCommandCreate (deprecated) * * APPLICATION_COMMAND_DELETE: applicationCommandDelete (deprecated) * * APPLICATION_COMMAND_UPDATE: applicationCommandUpdate (deprecated) + * * AUTO_MODERATION_ACTION_EXECUTION: autoModerationActionExecution + * * AUTO_MODERATION_RULE_CREATE: autoModerationRuleCreate + * * AUTO_MODERATION_RULE_DELETE: autoModerationRuleDelete + * * AUTO_MODERATION_RULE_UPDATE: autoModerationRuleUpdate * * GUILD_CREATE: guildCreate * * GUILD_DELETE: guildDelete * * GUILD_UPDATE: guildUpdate @@ -252,6 +256,10 @@ exports.Events = { APPLICATION_COMMAND_CREATE: 'applicationCommandCreate', APPLICATION_COMMAND_DELETE: 'applicationCommandDelete', APPLICATION_COMMAND_UPDATE: 'applicationCommandUpdate', + AUTO_MODERATION_ACTION_EXECUTION: 'autoModerationActionExecution', + AUTO_MODERATION_RULE_CREATE: 'autoModerationRuleCreate', + AUTO_MODERATION_RULE_DELETE: 'autoModerationRuleDelete', + AUTO_MODERATION_RULE_UPDATE: 'autoModerationRuleUpdate', GUILD_CREATE: 'guildCreate', GUILD_DELETE: 'guildDelete', GUILD_UPDATE: 'guildUpdate', @@ -573,6 +581,7 @@ exports.MessageTypes = [ /** * The name of an item to be swept in Sweepers * * `applicationCommands` - both global and guild commands + * * `autoModerationRules` * * `bans` * * `emojis` * * `invites` - accepts the `lifetime` property, using it will sweep based on expires timestamp @@ -590,6 +599,7 @@ exports.MessageTypes = [ */ exports.SweeperKeys = [ 'applicationCommands', + 'autoModerationRules', 'bans', 'emojis', 'invites', @@ -1219,14 +1229,44 @@ exports.ApplicationCommandOptionTypes = createEnum([ ]); /** - * The type of an {@link ApplicationCommandPermissions} object: - * * ROLE - * * USER - * @typedef {string} ApplicationCommandPermissionType - * @see {@link https://discord.com/developers/docs/interactions/application-commands#application-command-permissions-object-application-command-permission-type} + * The type of an {@link AutoModerationRuleTriggerTypes} object: + * * KEYWORD + * * SPAM + * * KEYWORD_PRESET + * * MENTION_SPAM + * @typedef {string} AutoModerationRuleTriggerType + * @see {@link https://discord.com/developers/docs/resources/auto-moderation#auto-moderation-rule-object-trigger-types} + */ +exports.AutoModerationRuleTriggerTypes = createEnum([null, 'KEYWORD', null, 'SPAM', 'KEYWORD_PRESET', 'MENTION_SPAM']); + +/** + * The type of an {@link AutoModerationRuleKeywordPresetTypes} object: + * * KEYWORD + * * SPAM + * * KEYWORD_PRESET + * * MENTION_SPAM + * @typedef {string} AutoModerationRuleKeywordPresetType + * @see {@link https://discord.com/developers/docs/resources/auto-moderation#auto-moderation-rule-object-keyword-preset-types} + */ +exports.AutoModerationRuleKeywordPresetTypes = createEnum([null, 'PROFANITY', 'SEXUAL_CONTENT', 'SLURS']); +/** + * The type of an {@link AutoModerationActionTypes} object: + * * BLOCK_MESSAGE + * * SEND_ALERT_MESSAGE + * * TIMEOUT + * @typedef {string} AutoModerationActionType + * @see {@link https://discord.com/developers/docs/resources/auto-moderation#auto-moderation-action-object-action-types} + */ +exports.AutoModerationActionTypes = createEnum([null, 'BLOCK_MESSAGE', 'SEND_ALERT_MESSAGE', 'TIMEOUT']); + +/** + * The type of an {@link AutoModerationRuleEventTypes} object: + * * MESSAGE_SEND + * @typedef {string} AutoModerationRuleEventType + * @see {@link https://discord.com/developers/docs/resources/auto-moderation#auto-moderation-rule-object-event-types} */ -exports.ApplicationCommandPermissionTypes = createEnum([null, 'ROLE', 'USER']); +exports.AutoModerationRuleEventTypes = createEnum([null, 'MESSAGE_SEND']); /** * The type of an {@link Interaction} object: * * PING @@ -1411,6 +1451,11 @@ function createEnum(keys) { * The type of an {@link ApplicationCommandPermissions} object. * @property {Object} ApplicationCommandTypes * The type of an {@link ApplicationCommand} object. + * @property {Object} AutoModerationRuleTriggerTypes Characterizes the type + * of contentwhich can trigger the rule. + * @property {Object} AutoModerationActionTypes + * @property {Object} AutoModerationRuleKeywordPresetTypes + * @property {Object} AutoModerationRuleEventTypes * @property {Object} ChannelTypes All available channel types. * @property {ClientApplicationAssetTypes} ClientApplicationAssetTypes The types of an {@link ApplicationAsset} object. * @property {Object} Colors An object with regularly used colors. diff --git a/src/util/Intents.js b/src/util/Intents.js index 6600f596b548..77f856e5aa15 100644 --- a/src/util/Intents.js +++ b/src/util/Intents.js @@ -42,6 +42,8 @@ class Intents extends BitField {} * * `DIRECT_MESSAGE_TYPING` * * `MESSAGE_CONTENT` * * `GUILD_SCHEDULED_EVENTS` + * * `AUTO_MODERATION_CONFIGURATION` + * * `AUTO_MODERATION_EXECUTION` * @type {Object} * @see {@link https://discord.com/developers/docs/topics/gateway#list-of-intents} */ @@ -63,6 +65,8 @@ Intents.FLAGS = { DIRECT_MESSAGE_TYPING: 1 << 14, MESSAGE_CONTENT: 1 << 15, GUILD_SCHEDULED_EVENTS: 1 << 16, + AUTO_MODERATION_CONFIGURATION: 1 << 20, + AUTO_MODERATION_EXECUTION: 1 << 21, }; module.exports = Intents; diff --git a/src/util/Sweepers.js b/src/util/Sweepers.js index a826115a3900..a104d3f4c0ed 100644 --- a/src/util/Sweepers.js +++ b/src/util/Sweepers.js @@ -77,6 +77,16 @@ class Sweepers { return guildCommands + globalCommands; } + /** + * Sweeps all auto moderation rules and removes the ones which are indicated by the filter. + * @param {Function} filter The function used to determine + * which auto moderation rules will be removed from the caches + * @returns {number} Amount of auto moderation rules that were removed from the caches + */ + sweepAutoModerationRules(filter) { + return this._sweepGuildDirectProp('autoModerationRules', filter).items; + } + /** * Sweeps all guild bans and removes the ones which are indicated by the filter. * @param {Function} filter The function used to determine which bans will be removed from the caches. From e5fe1e1f26d7991f93edd48ece570eb96dc3f45a Mon Sep 17 00:00:00 2001 From: Jaw0r3k Date: Wed, 30 Nov 2022 15:01:22 +0100 Subject: [PATCH 02/11] feat: backboard automod ( typings ) --- src/managers/AutoModerationRuleManager.js | 17 +- .../AutoModerationActionExecution.js | 4 +- src/structures/AutoModerationRule.js | 12 +- src/structures/GuildAuditLogs.js | 4 +- typings/enums.d.ts | 23 +++ typings/index.d.ts | 183 +++++++++++++++++- typings/rawDataTypes.d.ts | 54 +++++- 7 files changed, 278 insertions(+), 19 deletions(-) diff --git a/src/managers/AutoModerationRuleManager.js b/src/managers/AutoModerationRuleManager.js index 124789038486..191c26ff4871 100644 --- a/src/managers/AutoModerationRuleManager.js +++ b/src/managers/AutoModerationRuleManager.js @@ -33,7 +33,8 @@ class AutoModerationRuleManager extends CachedManager { * Options used to set the trigger metadata of an auto moderation rule. * @typedef {Object} AutoModerationTriggerMetadataOptions * @property {string[]} [keywordFilter] The substrings that will be searched for in the content - * @property {string[]} [regexPatterns] The regular expression patterns which will be matched against the content + * @property {(string|RegExp)[]} [regexPatterns] The regular expression patterns + * which will be matched against the content * Only Rust-flavored regular expressions are supported. * @property {AutoModerationRuleKeywordPresetType[]} [presets] * The internally pre-defined wordsets which will be searched for in the content @@ -66,8 +67,8 @@ class AutoModerationRuleManager extends CachedManager { * @property {AutoModerationRuleTriggerType} triggerType The trigger type of the auto moderation rule * @property {AutoModerationTriggerMetadataOptions} [triggerMetadata] The trigger metadata of the auto moderation rule * This property is required if using a `triggerType` of - * {@link AutoModerationRuleTriggerType.KEYWORD}, {@link AutoModerationRuleTriggerType.KEYWORD_PRESET}, - * or {@link AutoModerationRuleTriggerType.MENTION_SPAM}. + * {@link AutoModerationRuleTriggerTypes.KEYWORD}, {@link AutoModerationRuleTriggerTypes.KEYWORD_PRESET}, + * or {@link AutoModerationRuleTriggerTypes.MENTION_SPAM}. * @property {AutoModerationActionOptions[]} actions * The actions that will execute when the auto moderation rule is triggered * @property {boolean} [enabled] Whether the auto moderation rule should be enabled @@ -101,14 +102,16 @@ class AutoModerationRuleManager extends CachedManager { trigger_type: typeof triggerType === 'number' ? triggerType : AutoModerationRuleTriggerTypes[triggerType], trigger_metadata: triggerMetadata && { keyword_filter: triggerMetadata.keywordFilter, - regex_patterns: triggerMetadata.regexPatterns, + regex_patterns: triggerMetadata.regexPatterns?.map(regex => + regex instanceof RegExp ? regex.source : regex.toString(), + ), presets: triggerMetadata.presets?.map(preset => typeof preset === 'number' ? preset : AutoModerationRuleKeywordPresetTypes[preset], ), allow_list: triggerMetadata.allowList, mention_total_limit: triggerMetadata.mentionTotalLimit, }, - actions: actions.map(action => ({ + actions: actions?.map(action => ({ type: typeof action.type === 'number' ? action.type : AutoModerationActionTypes[action.type], metadata: { duration_seconds: action.metadata?.durationSeconds, @@ -162,7 +165,9 @@ class AutoModerationRuleManager extends CachedManager { event_type: typeof eventType === 'number' ? eventType : AutoModerationRuleEventTypes[eventType], trigger_metadata: triggerMetadata && { keyword_filter: triggerMetadata.keywordFilter, - regex_patterns: triggerMetadata.regexPatterns, + regex_patterns: triggerMetadata.regexPatterns?.map(regex => + regex instanceof RegExp ? regex.source : regex.toString(), + ), presets: triggerMetadata.presets?.map(preset => typeof preset === 'number' ? preset : AutoModerationRuleKeywordPresetTypes[preset], ), diff --git a/src/structures/AutoModerationActionExecution.js b/src/structures/AutoModerationActionExecution.js index 45c2949ab1a6..7de7e5498e87 100644 --- a/src/structures/AutoModerationActionExecution.js +++ b/src/structures/AutoModerationActionExecution.js @@ -1,5 +1,7 @@ 'use strict'; +const { AutoModerationRuleTriggerTypes } = require('../util/Constants'); + /** * Represents the structure of an executed action when an {@link AutoModerationRule} is triggered. */ @@ -27,7 +29,7 @@ class AutoModerationActionExecution { * The trigger type of the auto moderation rule which was triggered. * @type {AutoModerationRuleTriggerType} */ - this.ruleTriggerType = data.rule_trigger_type; + this.ruleTriggerType = AutoModerationRuleTriggerTypes[data.rule_trigger_type]; /** * The id of the user that triggered this action. diff --git a/src/structures/AutoModerationRule.js b/src/structures/AutoModerationRule.js index 8816d2393760..691389cdc3a4 100644 --- a/src/structures/AutoModerationRule.js +++ b/src/structures/AutoModerationRule.js @@ -190,18 +190,18 @@ class AutoModerationRule extends Base { * @returns {Promise} */ setKeywordFilter(keywordFilter, reason) { - return this.edit({ triggerMetadata: { keywordFilter }, reason }); + return this.edit({ triggerMetadata: { ...this.triggerMetadata, keywordFilter }, reason }); } /** * Sets the regular expression patterns for this auto moderation rule. - * @param {string[]} regexPatterns The regular expression patterns of this auto moderation rule + * @param {(string|RegExp)[]} regexPatterns The regular expression patterns of this auto moderation rule * Only Rust-flavored regular expressions are supported. * @param {string} [reason] The reason for changing the regular expression patterns of this auto moderation rule * @returns {Promise} */ setRegexPatterns(regexPatterns, reason) { - return this.edit({ triggerMetadata: { regexPatterns }, reason }); + return this.edit({ triggerMetadata: { ...this.triggerMetadata, regexPatterns }, reason }); } /** @@ -211,7 +211,7 @@ class AutoModerationRule extends Base { * @returns {Promise} */ setPresets(presets, reason) { - return this.edit({ triggerMetadata: { presets }, reason }); + return this.edit({ triggerMetadata: { ...this.triggerMetadata, presets }, reason }); } /** @@ -221,7 +221,7 @@ class AutoModerationRule extends Base { * @returns {Promise} */ setAllowList(allowList, reason) { - return this.edit({ triggerMetadata: { allowList }, reason }); + return this.edit({ triggerMetadata: { ...this.triggerMetadata, allowList }, reason }); } /** @@ -231,7 +231,7 @@ class AutoModerationRule extends Base { * @returns {Promise} */ setMentionTotalLimit(mentionTotalLimit, reason) { - return this.edit({ triggerMetadata: { mentionTotalLimit }, reason }); + return this.edit({ triggerMetadata: { ...this.triggerMetadata, mentionTotalLimit }, reason }); } /** diff --git a/src/structures/GuildAuditLogs.js b/src/structures/GuildAuditLogs.js index f0a737a6bf30..2a736f51795c 100644 --- a/src/structures/GuildAuditLogs.js +++ b/src/structures/GuildAuditLogs.js @@ -8,7 +8,7 @@ const Invite = require('./Invite'); const { StageInstance } = require('./StageInstance'); const { Sticker } = require('./Sticker'); const Webhook = require('./Webhook'); -const { OverwriteTypes, PartialTypes } = require('../util/Constants'); +const { OverwriteTypes, PartialTypes, AutoModerationRuleTriggerTypes } = require('../util/Constants'); const SnowflakeUtil = require('../util/SnowflakeUtil'); const Util = require('../util/Util'); @@ -511,7 +511,7 @@ class GuildAuditLogsEntry { case Actions.AUTO_MODERATION_USER_COMMUNICATION_DISABLED: this.extra = { autoModerationRuleName: data.options.auto_moderation_rule_name, - autoModerationRuleTriggerType: data.options.auto_moderation_rule_trigger_type, + autoModerationRuleTriggerType: AutoModerationRuleTriggerTypes[data.options.auto_moderation_rule_trigger_type], }; break; default: diff --git a/typings/enums.d.ts b/typings/enums.d.ts index 67e0fa84f30b..df580f45d876 100644 --- a/typings/enums.d.ts +++ b/typings/enums.d.ts @@ -35,6 +35,29 @@ export const enum ApplicationCommandPermissionTypes { USER = 2, } +export const enum AutoModerationRuleTriggerTypes { + KEYWORD = 1, + SPAM = 2, + KEYWORD_PRESET = 3, + MENTION_SPAM = 4, +} + +export const enum AutoModerationRuleKeywordPresetTypes { + PROFANITY = 1, + SEXUAL_CONTENT = 2, + SLURS = 3, +} + +export const enum AutoModerationActionTypes { + BLOCK_MESSAGE = 1, + SEND_ALERT_MESSAGE = 2, + TIMEOUT = 3, +} + +export const enum AutoModerationRuleEventTypes { + MESSAGE_SEND = 1, +} + export const enum ChannelTypes { GUILD_TEXT = 0, DM = 1, diff --git a/typings/index.d.ts b/typings/index.d.ts index caf37f40a04b..acd1a14cbe75 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -65,6 +65,10 @@ import { ApplicationCommandOptionTypes, ApplicationCommandPermissionTypes, ApplicationCommandTypes, + AutoModerationActionTypes, + AutoModerationRuleEventTypes, + AutoModerationRuleKeywordPresetTypes, + AutoModerationRuleTriggerTypes, ChannelTypes, DefaultMessageNotificationLevels, ExplicitContentFilterLevels, @@ -92,6 +96,8 @@ import { VideoQualityModes, } from './enums'; import { + APIAutoModerationRule, + GatewayAutoModerationActionExecutionDispatchData, RawActivityData, RawAnonymousGuildData, RawApplicationCommandData, @@ -282,6 +288,8 @@ export class ApplicationCommand extends Base { export type ApplicationResolvable = Application | Activity | Snowflake; +export type AutoModerationRuleResolvable = AutoModerationRule | Snowflake; + export class ApplicationFlags extends BitField { public static FLAGS: Record; public static resolve(bit?: BitFieldResolvable): number; @@ -937,6 +945,7 @@ export class Guild extends AnonymousGuild { public maxVideoChannelUsers: number | null; public approximateMemberCount: number | null; public approximatePresenceCount: number | null; + public autoModerationRules: AutoModerationRuleManager; public available: boolean; public bans: GuildBanManager; public channels: GuildChannelManager; @@ -1039,7 +1048,7 @@ export class GuildAuditLogs { private constructor(guild: Guild, data: RawGuildAuditLogData); private webhooks: Collection; private integrations: Collection; - + private autoModerationRules: Collection; public entries: Collection>; public static Actions: GuildAuditLogsActions; @@ -3989,6 +3998,84 @@ export type ApplicationCommandType = keyof typeof ApplicationCommandTypes; export type ApplicationCommandOptionType = keyof typeof ApplicationCommandOptionTypes; +export type AutoModerationRuleTriggerType = keyof typeof AutoModerationRuleTriggerTypes; + +export type AutoModerationRuleKeywordPresetType = keyof typeof AutoModerationRuleKeywordPresetTypes; + +export type AutoModerationActionType = keyof typeof AutoModerationActionTypes; + +export type AutoModerationRuleEventType = keyof typeof AutoModerationRuleEventTypes; + +export class AutoModerationActionExecution { + private constructor(data: GatewayAutoModerationActionExecutionDispatchData, guild: Guild); + public guild: Guild; + public action: AutoModerationAction; + public ruleId: Snowflake; + public ruleTriggerType: AutoModerationRuleTriggerType; + public userId: Snowflake; + public channelId: Snowflake | null; + public messageId: Snowflake | null; + public alertSystemMessageId: Snowflake | null; + public content: string; + public matchedKeyword: string | null; + public matchedContent: string | null; + public get autoModerationRule(): AutoModerationRule | null; +} + +export class AutoModerationRule extends Base { + private constructor(client: Client, data: APIAutoModerationRule, guild: Guild); + public id: Snowflake; + public guild: Guild; + public name: string; + public creatorId: Snowflake; + public eventType: AutoModerationRuleEventType; + public triggerType: AutoModerationRuleTriggerType; + public triggerMetadata: AutoModerationTriggerMetadata; + public actions: AutoModerationAction[]; + public enabled: boolean; + public exemptRoles: Collection; + public exemptChannels: Collection; + public edit(options: AutoModerationRuleEditOptions): Promise; + public delete(reason?: string): Promise; + public setName(name: string, reason?: string): Promise; + public setEventType( + eventType: AutoModerationRuleEventType | AutoModerationRuleEventTypes, + reason?: string, + ): Promise; + public setKeywordFilter(keywordFilter: string[], reason?: string): Promise; + public setRegexPatterns(regexPatterns: (string | RegExp)[], reason?: string): Promise; + public setPresets(presets: AutoModerationRuleKeywordPresetType[], reason?: string): Promise; + public setAllowList(allowList: string[], reason?: string): Promise; + public setMentionTotalLimit(mentionTotalLimit: number, reason?: string): Promise; + public setActions(actions: AutoModerationActionOptions, reason?: string): Promise; + public setEnabled(enabled?: boolean, reason?: string): Promise; + public setExemptRoles( + roles: Collection | RoleResolvable[], + reason?: string, + ): Promise; + public setExemptChannels( + channels: Collection | GuildChannelResolvable[], + reason?: string, + ): Promise; +} + +export class AutoModerationRuleManager extends CachedManager< + Snowflake, + AutoModerationRule, + AutoModerationRuleResolvable +> { + private constructor(guild: Guild, iterable: unknown); + public guild: Guild; + public create(options: AutoModerationRuleCreateOptions): Promise; + public edit( + autoModerationRule: AutoModerationRuleResolvable, + options: AutoModerationRuleEditOptions, + ): Promise; + public fetch(options: AutoModerationRuleResolvable | FetchAutoModerationRuleOptions): Promise; + public fetch(options?: FetchAutoModerationRulesOptions): Promise>; + public delete(autoModerationRule: AutoModerationRuleResolvable, reason?: string): Promise; +} + export interface ApplicationCommandPermissionData { id: Snowflake; type: ApplicationCommandPermissionType | ApplicationCommandPermissionTypes; @@ -4013,6 +4100,57 @@ export type ApplicationFlagsString = | 'GATEWAY_MESSAGE_CONTENT' | 'GATEWAY_MESSAGE_CONTENT_LIMITED'; +export interface AutoModerationAction { + type: AutoModerationActionType | AutoModerationActionTypes; + metadata: AutoModerationActionMetadata; +} + +export interface AutoModerationActionMetadata { + channelId: Snowflake | null; + durationSeconds: number | null; +} + +export interface AutoModerationTriggerMetadata { + keywordFilter: string[]; + regexPatterns: (string | RegExp)[]; + presets: (AutoModerationRuleKeywordPresetType | AutoModerationRuleKeywordPresetTypes)[]; + allowList: string[]; + mentionTotalLimit: number | null; +} + +export interface FetchAutoModerationRuleOptions extends BaseFetchOptions { + autoModerationRule: AutoModerationRuleResolvable; +} + +export interface FetchAutoModerationRulesOptions { + cache?: boolean; +} + +export interface AutoModerationRuleCreateOptions { + name: string; + eventType: AutoModerationRuleEventType | AutoModerationRuleEventTypes; + triggerType: AutoModerationRuleTriggerType | AutoModerationRuleTriggerTypes; + triggerMetadata?: AutoModerationTriggerMetadataOptions; + actions: AutoModerationActionOptions; + enabled?: boolean; + exemptRoles?: Collection | RoleResolvable[]; + exemptChannels?: Collection | GuildChannelResolvable[]; + reason?: string; +} + +export interface AutoModerationRuleEditOptions extends Partial> {} + +export interface AutoModerationTriggerMetadataOptions extends Partial {} + +export interface AutoModerationActionOptions { + type: AutoModerationActionType | AutoModerationActionTypes; + metadata?: AutoModerationActionMetadataOptions; +} + +export interface AutoModerationActionMetadataOptions extends Partial> { + channel: GuildTextChannelResolvable | ThreadChannel; +} + export interface AuditLogChange { key: APIAuditLogChange['key']; old?: APIAuditLogChange['old_value']; @@ -4072,6 +4210,7 @@ export type BufferResolvable = Buffer | string; export interface Caches { ApplicationCommandManager: [manager: typeof ApplicationCommandManager, holds: typeof ApplicationCommand]; + AutoModerationRuleManager: [manager: typeof AutoModerationRuleManager, holds: typeof AutoModerationRule]; BaseGuildEmojiManager: [manager: typeof BaseGuildEmojiManager, holds: typeof GuildEmoji]; GuildEmojiManager: [manager: typeof GuildEmojiManager, holds: typeof GuildEmoji]; // TODO: ChannelManager: [manager: typeof ChannelManager, holds: typeof Channel]; @@ -4195,7 +4334,13 @@ export interface ClientEvents extends BaseClientEvents { /** @deprecated See [this issue](https://github.com/discord/discord-api-docs/issues/3690) for more information. */ applicationCommandDelete: [command: ApplicationCommand]; /** @deprecated See [this issue](https://github.com/discord/discord-api-docs/issues/3690) for more information. */ - applicationCommandUpdate: [oldCommand: ApplicationCommand | null, newCommand: ApplicationCommand]; + autoModerationActionExecution: [autoModerationActionExecution: AutoModerationActionExecution]; + autoModerationRuleCreate: [autoModerationRule: AutoModerationRule]; + autoModerationRuleDelete: [autoModerationRule: AutoModerationRule]; + autoModerationRuleUpdate: [ + oldAutoModerationRule: AutoModerationRule | null, + newAutoModerationRule: AutoModerationRule, + ]; cacheSweep: [message: string]; channelCreate: [channel: NonThreadGuildBasedChannel]; channelDelete: [channel: DMChannel | NonThreadGuildBasedChannel]; @@ -4469,6 +4614,10 @@ export interface ConstantsEvents { APPLICATION_COMMAND_DELETE: 'applicationCommandDelete'; /** @deprecated See [this issue](https://github.com/discord/discord-api-docs/issues/3690) for more information. */ APPLICATION_COMMAND_UPDATE: 'applicationCommandUpdate'; + AUTO_MODERATION_ACTION_EXECUTION: 'autoModerationActionExecution'; + AUTO_MODERATION_RULE_CREATE: 'autoModerationRuleCreate'; + AUTO_MODERATION_RULE_DELETE: 'autoModerationRuleDelete'; + AUTO_MODERATION_RULE_UPDATE: 'autoModerationRuleUpdate'; GUILD_CREATE: 'guildCreate'; GUILD_DELETE: 'guildDelete'; GUILD_UPDATE: 'guildUpdate'; @@ -4821,6 +4970,12 @@ interface GuildAuditLogsTypes { THREAD_CREATE: ['THREAD', 'CREATE']; THREAD_UPDATE: ['THREAD', 'UPDATE']; THREAD_DELETE: ['THREAD', 'DELETE']; + AUTO_MODERATION_RULE_CREATE: ['AUTO_MODERATION', 'CREATE']; + AUTO_MODERATION_RULE_UPDATE: ['AUTO_MODERATION', 'UPDATE']; + AUTO_MODERATION_RULE_DELETE: ['AUTO_MODERATION', 'DELETE']; + AUTO_MODERATION_BLOCK_MESSAGE: ['AUTO_MODERATION', 'CREATE']; + AUTO_MODERATION_FLAG_TO_CHANNEL: ['AUTO_MODERATION', 'CREATE']; + AUTO_MODERATION_USER_COMMUNICATION_DISABLED: ['AUTO_MODERATION', 'CREATE']; } export interface GuildAuditLogsIds { @@ -4871,6 +5026,12 @@ export interface GuildAuditLogsIds { 110: 'THREAD_CREATE'; 111: 'THREAD_UPDATE'; 112: 'THREAD_DELETE'; + 140: 'AUTO_MODERATION_RULE_CREATE'; + 141: 'AUTO_MODERATION_RULE_UPDATE'; + 142: 'AUTO_MODERATION_RULE_DELETE'; + 143: 'AUTO_MODERATION_BLOCK_MESSAGE'; + 144: 'AUTO_MODERATION_FLAG_TO_CHANNEL'; + 145: 'AUTO_MODERATION_USER_COMMUNICATION_DISABLED'; } export type GuildAuditLogsActions = { [Key in keyof GuildAuditLogsIds as GuildAuditLogsIds[Key]]: Key } & { ALL: null }; @@ -4905,6 +5066,18 @@ export interface GuildAuditLogsEntryExtraField { STAGE_INSTANCE_CREATE: StageChannel | { id: Snowflake }; STAGE_INSTANCE_DELETE: StageChannel | { id: Snowflake }; STAGE_INSTANCE_UPDATE: StageChannel | { id: Snowflake }; + AUTO_MODERATION_BLOCK_MESSAGE: { + autoModerationRuleName: string; + autoModerationRuleTriggerType: AutoModerationRuleTriggerType; + }; + AUTO_MODERATION_FLAG_TO_CHANNEL: { + autoModerationRuleName: string; + autoModerationRuleTriggerType: AutoModerationRuleTriggerType; + }; + AUTO_MODERATION_USER_COMMUNICATIONDISABLED: { + autoModerationRuleName: string; + autoModerationRuleTriggerType: AutoModerationRuleTriggerType; + }; } export interface GuildAuditLogsEntryTargetField { @@ -4919,6 +5092,7 @@ export interface GuildAuditLogsEntryTargetField { @@ -5232,7 +5406,9 @@ export type IntentsString = | 'DIRECT_MESSAGE_REACTIONS' | 'DIRECT_MESSAGE_TYPING' | 'MESSAGE_CONTENT' - | 'GUILD_SCHEDULED_EVENTS'; + | 'GUILD_SCHEDULED_EVENTS' + | 'AUTO_MODERATION_CONFIGURATION' + | 'AUTO_MODERATION_EXECUTION'; export interface InviteGenerationOptions { permissions?: PermissionResolvable; @@ -5898,6 +6074,7 @@ export interface LifetimeSweepOptions { export interface SweeperDefinitions { applicationCommands: [Snowflake, ApplicationCommand]; + autoModerationRules: [Snowflake, AutoModerationRule]; bans: [Snowflake, GuildBan]; emojis: [Snowflake, GuildEmoji]; invites: [string, Invite, true]; diff --git a/typings/rawDataTypes.d.ts b/typings/rawDataTypes.d.ts index 7c69081965e3..456d5c6c8a16 100644 --- a/typings/rawDataTypes.d.ts +++ b/typings/rawDataTypes.d.ts @@ -82,7 +82,14 @@ import { APIModalSubmitInteraction, } from 'discord-api-types/v9'; import { GuildChannel, Guild, PermissionOverwrites, InteractionType } from '.'; -import type { InteractionTypes, MessageComponentTypes } from './enums'; +import type { + AutoModerationActionTypes, + AutoModerationRuleEventTypes, + AutoModerationRuleKeywordPresetTypes, + AutoModerationRuleTriggerTypes, + InteractionTypes, + MessageComponentTypes, +} from './enums'; export type RawActivityData = GatewayActivity; @@ -216,3 +223,48 @@ export type RawWelcomeScreenData = APIGuildWelcomeScreen; export type RawWidgetData = APIGuildWidget; export type RawWidgetMemberData = APIGuildWidgetMember; + +export interface GatewayAutoModerationActionExecutionDispatchData { + guild_id: Snowflake; + action: APIAutoModerationAction; + rule_id: Snowflake; + rule_trigger_type: AutoModerationRuleTriggerTypes; + user_id: Snowflake; + channel_id?: Snowflake; + message_id?: Snowflake; + alert_system_message_id?: Snowflake; + content: string; + matched_keyword: string | null; + matched_content: string | null; +} + +export interface APIAutoModerationAction { + type: AutoModerationActionTypes; + metadata?: APIAutoModerationActionMetadata; +} +export interface APIAutoModerationActionMetadata { + channel_id?: Snowflake; + duration_seconds?: number; +} + +export interface APIAutoModerationRule { + id: Snowflake; + guild_id: Snowflake; + name: string; + creator_id: Snowflake; + event_type: AutoModerationRuleEventTypes; + trigger_type: AutoModerationRuleTriggerTypes; + trigger_metadata: APIAutoModerationRuleTriggerMetadata; + actions: APIAutoModerationAction[]; + enabled: boolean; + exempt_roles: Snowflake[]; + exempt_channels: Snowflake[]; +} + +export interface APIAutoModerationRuleTriggerMetadata { + keyword_filter?: string[]; + presets?: AutoModerationRuleKeywordPresetTypes[]; + allow_list?: string[]; + regex_patterns?: string[]; + mention_total_limit?: number; +} From 582183529a5cd9eddc29659389c79e1385aad6a0 Mon Sep 17 00:00:00 2001 From: Jaw0r3k Date: Wed, 30 Nov 2022 15:24:29 +0100 Subject: [PATCH 03/11] fix: remove regexp --- src/managers/AutoModerationRuleManager.js | 10 +++------- src/structures/AutoModerationRule.js | 2 +- src/util/Constants.js | 9 +++++++++ typings/index.d.ts | 12 +++++++++--- 4 files changed, 22 insertions(+), 11 deletions(-) diff --git a/src/managers/AutoModerationRuleManager.js b/src/managers/AutoModerationRuleManager.js index 191c26ff4871..2b3732690f23 100644 --- a/src/managers/AutoModerationRuleManager.js +++ b/src/managers/AutoModerationRuleManager.js @@ -33,7 +33,7 @@ class AutoModerationRuleManager extends CachedManager { * Options used to set the trigger metadata of an auto moderation rule. * @typedef {Object} AutoModerationTriggerMetadataOptions * @property {string[]} [keywordFilter] The substrings that will be searched for in the content - * @property {(string|RegExp)[]} [regexPatterns] The regular expression patterns + * @property {string[]} [regexPatterns] The regular expression patterns * which will be matched against the content * Only Rust-flavored regular expressions are supported. * @property {AutoModerationRuleKeywordPresetType[]} [presets] @@ -102,9 +102,7 @@ class AutoModerationRuleManager extends CachedManager { trigger_type: typeof triggerType === 'number' ? triggerType : AutoModerationRuleTriggerTypes[triggerType], trigger_metadata: triggerMetadata && { keyword_filter: triggerMetadata.keywordFilter, - regex_patterns: triggerMetadata.regexPatterns?.map(regex => - regex instanceof RegExp ? regex.source : regex.toString(), - ), + regex_patterns: triggerMetadata.regexPatterns, presets: triggerMetadata.presets?.map(preset => typeof preset === 'number' ? preset : AutoModerationRuleKeywordPresetTypes[preset], ), @@ -165,9 +163,7 @@ class AutoModerationRuleManager extends CachedManager { event_type: typeof eventType === 'number' ? eventType : AutoModerationRuleEventTypes[eventType], trigger_metadata: triggerMetadata && { keyword_filter: triggerMetadata.keywordFilter, - regex_patterns: triggerMetadata.regexPatterns?.map(regex => - regex instanceof RegExp ? regex.source : regex.toString(), - ), + regex_patterns: triggerMetadata.regexPatterns, presets: triggerMetadata.presets?.map(preset => typeof preset === 'number' ? preset : AutoModerationRuleKeywordPresetTypes[preset], ), diff --git a/src/structures/AutoModerationRule.js b/src/structures/AutoModerationRule.js index 691389cdc3a4..1d88259b6fa6 100644 --- a/src/structures/AutoModerationRule.js +++ b/src/structures/AutoModerationRule.js @@ -195,7 +195,7 @@ class AutoModerationRule extends Base { /** * Sets the regular expression patterns for this auto moderation rule. - * @param {(string|RegExp)[]} regexPatterns The regular expression patterns of this auto moderation rule + * @param {string[]} regexPatterns The regular expression patterns of this auto moderation rule * Only Rust-flavored regular expressions are supported. * @param {string} [reason] The reason for changing the regular expression patterns of this auto moderation rule * @returns {Promise} diff --git a/src/util/Constants.js b/src/util/Constants.js index 78c417cbdf8d..2aa6173b2e06 100644 --- a/src/util/Constants.js +++ b/src/util/Constants.js @@ -1228,6 +1228,15 @@ exports.ApplicationCommandOptionTypes = createEnum([ 'ATTACHMENT', ]); +/** + * The type of an {@link ApplicationCommandPermissions} object: + * * ROLE + * * USER + * @typedef {string} ApplicationCommandPermissionType + * @see {@link https://discord.com/developers/docs/interactions/application-commands#application-command-permissions-object-application-command-permission-type} + */ +exports.ApplicationCommandPermissionTypes = createEnum([null, 'ROLE', 'USER']); + /** * The type of an {@link AutoModerationRuleTriggerTypes} object: * * KEYWORD diff --git a/typings/index.d.ts b/typings/index.d.ts index acd1a14cbe75..ef576256097e 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -1049,6 +1049,7 @@ export class GuildAuditLogs { private webhooks: Collection; private integrations: Collection; private autoModerationRules: Collection; + public entries: Collection>; public static Actions: GuildAuditLogsActions; @@ -3040,7 +3041,11 @@ export const Constants: { DefaultMessageNotificationLevels: EnumHolder; VerificationLevels: EnumHolder; MembershipStates: EnumHolder; - ApplicationCommandOptionTypes: EnumHolder; + AutoModerationRuleTriggerTypes: EnumHolder; + AutoModerationRuleKeywordPresetTypes: EnumHolder; + AutoModerationActionTypes: EnumHolder; + AutoModerationRuleEventTypes: EnumHolder; + ApplicationCommandPermissionTypes: EnumHolder; InteractionTypes: EnumHolder; InteractionResponseTypes: EnumHolder; @@ -4043,7 +4048,7 @@ export class AutoModerationRule extends Base { reason?: string, ): Promise; public setKeywordFilter(keywordFilter: string[], reason?: string): Promise; - public setRegexPatterns(regexPatterns: (string | RegExp)[], reason?: string): Promise; + public setRegexPatterns(regexPatterns: string[], reason?: string): Promise; public setPresets(presets: AutoModerationRuleKeywordPresetType[], reason?: string): Promise; public setAllowList(allowList: string[], reason?: string): Promise; public setMentionTotalLimit(mentionTotalLimit: number, reason?: string): Promise; @@ -4112,7 +4117,7 @@ export interface AutoModerationActionMetadata { export interface AutoModerationTriggerMetadata { keywordFilter: string[]; - regexPatterns: (string | RegExp)[]; + regexPatterns: string[]; presets: (AutoModerationRuleKeywordPresetType | AutoModerationRuleKeywordPresetTypes)[]; allowList: string[]; mentionTotalLimit: number | null; @@ -4334,6 +4339,7 @@ export interface ClientEvents extends BaseClientEvents { /** @deprecated See [this issue](https://github.com/discord/discord-api-docs/issues/3690) for more information. */ applicationCommandDelete: [command: ApplicationCommand]; /** @deprecated See [this issue](https://github.com/discord/discord-api-docs/issues/3690) for more information. */ + applicationCommandUpdate: [oldCommand: ApplicationCommand | null, newCommand: ApplicationCommand]; autoModerationActionExecution: [autoModerationActionExecution: AutoModerationActionExecution]; autoModerationRuleCreate: [autoModerationRule: AutoModerationRule]; autoModerationRuleDelete: [autoModerationRule: AutoModerationRule]; From 034afba44f5390d94ccf619af03240052adece8c Mon Sep 17 00:00:00 2001 From: Jaworek Date: Mon, 26 Dec 2022 12:37:44 +0100 Subject: [PATCH 04/11] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Aura Román --- src/managers/AutoModerationRuleManager.js | 5 ++--- src/structures/AutoModerationActionExecution.js | 2 +- src/structures/AutoModerationRule.js | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/managers/AutoModerationRuleManager.js b/src/managers/AutoModerationRuleManager.js index 2b3732690f23..2090c9eeece3 100644 --- a/src/managers/AutoModerationRuleManager.js +++ b/src/managers/AutoModerationRuleManager.js @@ -33,8 +33,7 @@ class AutoModerationRuleManager extends CachedManager { * Options used to set the trigger metadata of an auto moderation rule. * @typedef {Object} AutoModerationTriggerMetadataOptions * @property {string[]} [keywordFilter] The substrings that will be searched for in the content - * @property {string[]} [regexPatterns] The regular expression patterns - * which will be matched against the content + * @property {string[]} [regexPatterns] The regular expression patterns which will be matched against the content * Only Rust-flavored regular expressions are supported. * @property {AutoModerationRuleKeywordPresetType[]} [presets] * The internally pre-defined wordsets which will be searched for in the content @@ -109,7 +108,7 @@ class AutoModerationRuleManager extends CachedManager { allow_list: triggerMetadata.allowList, mention_total_limit: triggerMetadata.mentionTotalLimit, }, - actions: actions?.map(action => ({ + actions: actions.map(action => ({ type: typeof action.type === 'number' ? action.type : AutoModerationActionTypes[action.type], metadata: { duration_seconds: action.metadata?.durationSeconds, diff --git a/src/structures/AutoModerationActionExecution.js b/src/structures/AutoModerationActionExecution.js index 7de7e5498e87..75fa632e235e 100644 --- a/src/structures/AutoModerationActionExecution.js +++ b/src/structures/AutoModerationActionExecution.js @@ -58,7 +58,7 @@ class AutoModerationActionExecution { /** * The content that triggered this action. - * This property requires the {@link GatewayIntentBits.MessageContent} privileged gateway intent. + * This property requires the {@link Intents.FLAGS.MESSAGE_CONTENT} privileged gateway intent. * @type {string} */ this.content = data.content; diff --git a/src/structures/AutoModerationRule.js b/src/structures/AutoModerationRule.js index 1d88259b6fa6..291d4b71679d 100644 --- a/src/structures/AutoModerationRule.js +++ b/src/structures/AutoModerationRule.js @@ -71,7 +71,7 @@ class AutoModerationRule extends Base { * @property {AutoModerationRuleKeywordPresetType[]} presets * The internally pre-defined wordsets which will be searched for in the content * @property {string[]} allowList The substrings that will be exempt from triggering - * {@link AutoModerationRuleTriggerTypes.Keyword} and {@link AutoModerationRuleTriggerTypes.KeywordPreset} + * {@link AutoModerationRuleTriggerTypes.KEYWORD} and {@link AutoModerationRuleTriggerTypes.KEYWORD_PRESET} * @property {?number} mentionTotalLimit The total number of role & user mentions allowed per message */ From e525c86d6d0fb72d428e87906cce242bbf9ba3ee Mon Sep 17 00:00:00 2001 From: Jaworek Date: Mon, 26 Dec 2022 13:58:19 +0100 Subject: [PATCH 05/11] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Aura Román --- src/structures/AutoModerationRule.js | 2 +- typings/index.d.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/structures/AutoModerationRule.js b/src/structures/AutoModerationRule.js index 291d4b71679d..3968a83253a3 100644 --- a/src/structures/AutoModerationRule.js +++ b/src/structures/AutoModerationRule.js @@ -236,7 +236,7 @@ class AutoModerationRule extends Base { /** * Sets the actions for this auto moderation rule. - * @param {AutoModerationActionOptions} actions The actions of this auto moderation rule + * @param {AutoModerationActionOptions[]} actions The actions of this auto moderation rule * @param {string} [reason] The reason for changing the actions of this auto moderation rule * @returns {Promise} */ diff --git a/typings/index.d.ts b/typings/index.d.ts index ef576256097e..22cad8361d19 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -4052,7 +4052,7 @@ export class AutoModerationRule extends Base { public setPresets(presets: AutoModerationRuleKeywordPresetType[], reason?: string): Promise; public setAllowList(allowList: string[], reason?: string): Promise; public setMentionTotalLimit(mentionTotalLimit: number, reason?: string): Promise; - public setActions(actions: AutoModerationActionOptions, reason?: string): Promise; + public setActions(actions: AutoModerationActionOptions[], reason?: string): Promise; public setEnabled(enabled?: boolean, reason?: string): Promise; public setExemptRoles( roles: Collection | RoleResolvable[], @@ -4136,7 +4136,7 @@ export interface AutoModerationRuleCreateOptions { eventType: AutoModerationRuleEventType | AutoModerationRuleEventTypes; triggerType: AutoModerationRuleTriggerType | AutoModerationRuleTriggerTypes; triggerMetadata?: AutoModerationTriggerMetadataOptions; - actions: AutoModerationActionOptions; + actions: AutoModerationActionOptions[]; enabled?: boolean; exemptRoles?: Collection | RoleResolvable[]; exemptChannels?: Collection | GuildChannelResolvable[]; From 36437fcc3ff0bedcd5d7545e7f1bc2752787bcd2 Mon Sep 17 00:00:00 2001 From: Jaworek Date: Mon, 26 Dec 2022 14:38:04 +0100 Subject: [PATCH 06/11] Update Constants.js --- src/util/Constants.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/util/Constants.js b/src/util/Constants.js index 2aa6173b2e06..09c0a3c8d4dc 100644 --- a/src/util/Constants.js +++ b/src/util/Constants.js @@ -1461,10 +1461,13 @@ function createEnum(keys) { * @property {Object} ApplicationCommandTypes * The type of an {@link ApplicationCommand} object. * @property {Object} AutoModerationRuleTriggerTypes Characterizes the type - * of contentwhich can trigger the rule. + * of content which can trigger the rule. * @property {Object} AutoModerationActionTypes + * A type of an action which executes whenever a rule is triggered. * @property {Object} AutoModerationRuleKeywordPresetTypes - * @property {Object} AutoModerationRuleEventTypes + * The internally pre-defined wordsetswhich will be searched for in content + * @property {Object} AutoModerationRuleEventTypes Indicates in what event context + * a rule should be checked. * @property {Object} ChannelTypes All available channel types. * @property {ClientApplicationAssetTypes} ClientApplicationAssetTypes The types of an {@link ApplicationAsset} object. * @property {Object} Colors An object with regularly used colors. From 4ec2c4b5e0789d9b0f4c5bd727773bcd7dde9ee6 Mon Sep 17 00:00:00 2001 From: Jaworek Date: Mon, 26 Dec 2022 14:40:34 +0100 Subject: [PATCH 07/11] Update AutoModerationRuleManager.js --- src/managers/AutoModerationRuleManager.js | 44 +++++++++++------------ 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/managers/AutoModerationRuleManager.js b/src/managers/AutoModerationRuleManager.js index 2090c9eeece3..88860906a668 100644 --- a/src/managers/AutoModerationRuleManager.js +++ b/src/managers/AutoModerationRuleManager.js @@ -17,13 +17,34 @@ const { class AutoModerationRuleManager extends CachedManager { constructor(guild, iterable) { super(guild.client, AutoModerationRule, iterable); - + /** * The guild this manager belongs to. * @type {Guild} */ this.guild = guild; } + + /** + * Deletes an auto moderation rule. + * @param {AutoModerationRuleResolvable} autoModerationRule The auto moderation rule to delete + /** + * Resolves an {@link AutoModerationRuleResolvable} to an {@link AutoModerationRule} object. + * @method resolve + * @memberof AutoModerationRuleManager + * @instance + * @param {AutoModerationRuleResolvable} autoModerationRule The AutoModerationRule resolvable to resolve + * @returns {?AutoModerationRule} + */ + + /** + * Resolves an {@link AutoModerationRuleResolvable} to a {@link AutoModerationRule} id. + * @method resolveId + * @memberof AutoModerationRuleManager + * @instance + * @param {AutoModerationRuleResolvable} autoModerationRule The AutoModerationRule resolvable to resolve + * @returns {?Snowflake} + */ _add(data, cache) { return super._add(data, cache, { extras: [this.guild] }); @@ -255,9 +276,6 @@ class AutoModerationRuleManager extends CachedManager { ); } - /** - * Deletes an auto moderation rule. - * @param {AutoModerationRuleResolvable} autoModerationRule The auto moderation rule to delete * @param {string} [reason] The reason for deleting the auto moderation rule * @returns {Promise} */ @@ -265,24 +283,6 @@ class AutoModerationRuleManager extends CachedManager { const autoModerationRuleId = this.resolveId(autoModerationRule); await this.client.api.guilds(this.guild.id)('auto-moderation').rules(autoModerationRuleId).delete({ reason }); } - - /** - * Resolves an {@link AutoModerationRuleResolvable} to an {@link AutoModerationRule} object. - * @method resolve - * @memberof AutoModerationRuleManager - * @instance - * @param {AutoModerationRuleResolvable} autoModerationRule The AutoModerationRule resolvable to resolve - * @returns {?AutoModerationRule} - */ - - /** - * Resolves an {@link AutoModerationRuleResolvable} to a {@link AutoModerationRule} id. - * @method resolveId - * @memberof AutoModerationRuleManager - * @instance - * @param {AutoModerationRuleResolvable} autoModerationRule The AutoModerationRule resolvable to resolve - * @returns {?Snowflake} - */ } module.exports = AutoModerationRuleManager; From 027d242ed6d1deb08cb6a301a9034acf29d0f46a Mon Sep 17 00:00:00 2001 From: Jaworek Date: Mon, 26 Dec 2022 14:42:20 +0100 Subject: [PATCH 08/11] nvm --- src/managers/AutoModerationRuleManager.js | 41 +++++++++++------------ 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/src/managers/AutoModerationRuleManager.js b/src/managers/AutoModerationRuleManager.js index 88860906a668..4076baaedbcf 100644 --- a/src/managers/AutoModerationRuleManager.js +++ b/src/managers/AutoModerationRuleManager.js @@ -17,34 +17,30 @@ const { class AutoModerationRuleManager extends CachedManager { constructor(guild, iterable) { super(guild.client, AutoModerationRule, iterable); - + /** * The guild this manager belongs to. * @type {Guild} */ this.guild = guild; } - /** - * Deletes an auto moderation rule. - * @param {AutoModerationRuleResolvable} autoModerationRule The auto moderation rule to delete - /** - * Resolves an {@link AutoModerationRuleResolvable} to an {@link AutoModerationRule} object. - * @method resolve - * @memberof AutoModerationRuleManager - * @instance - * @param {AutoModerationRuleResolvable} autoModerationRule The AutoModerationRule resolvable to resolve - * @returns {?AutoModerationRule} - */ - - /** - * Resolves an {@link AutoModerationRuleResolvable} to a {@link AutoModerationRule} id. - * @method resolveId - * @memberof AutoModerationRuleManager - * @instance - * @param {AutoModerationRuleResolvable} autoModerationRule The AutoModerationRule resolvable to resolve - * @returns {?Snowflake} - */ + * Resolves an {@link AutoModerationRuleResolvable} to an {@link AutoModerationRule} object. + * @method resolve + * @memberof AutoModerationRuleManager + * @instance + * @param {AutoModerationRuleResolvable} autoModerationRule The AutoModerationRule resolvable to resolve + * @returns {?AutoModerationRule} + */ + + /** + * Resolves an {@link AutoModerationRuleResolvable} to a {@link AutoModerationRule} id. + * @method resolveId + * @memberof AutoModerationRuleManager + * @instance + * @param {AutoModerationRuleResolvable} autoModerationRule The AutoModerationRule resolvable to resolve + * @returns {?Snowflake} + */ _add(data, cache) { return super._add(data, cache, { extras: [this.guild] }); @@ -276,6 +272,9 @@ class AutoModerationRuleManager extends CachedManager { ); } + /** + * Deletes an auto moderation rule. + * @param {AutoModerationRuleResolvable} autoModerationRule The auto moderation rule to delete * @param {string} [reason] The reason for deleting the auto moderation rule * @returns {Promise} */ From 1b71aca42b25f91a1ce62e05d7c3c0fef216203a Mon Sep 17 00:00:00 2001 From: Jaworek Date: Mon, 26 Dec 2022 15:01:46 +0100 Subject: [PATCH 09/11] Update src/managers/AutoModerationRuleManager.js MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Aura Román --- src/managers/AutoModerationRuleManager.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/managers/AutoModerationRuleManager.js b/src/managers/AutoModerationRuleManager.js index 4076baaedbcf..ff886c7c3a96 100644 --- a/src/managers/AutoModerationRuleManager.js +++ b/src/managers/AutoModerationRuleManager.js @@ -24,6 +24,7 @@ class AutoModerationRuleManager extends CachedManager { */ this.guild = guild; } + /** * Resolves an {@link AutoModerationRuleResolvable} to an {@link AutoModerationRule} object. * @method resolve From bd197d2b3f7c53589d2d675afd860e005316f30d Mon Sep 17 00:00:00 2001 From: Jaw0r3k Date: Wed, 11 Jan 2023 16:17:02 +0100 Subject: [PATCH 10/11] feat: add AUTO_MODERATION_ACTION message type --- src/util/Constants.js | 2 ++ typings/enums.d.ts | 1 + 2 files changed, 3 insertions(+) diff --git a/src/util/Constants.js b/src/util/Constants.js index 367927c22aa1..cf70715960db 100644 --- a/src/util/Constants.js +++ b/src/util/Constants.js @@ -548,6 +548,7 @@ exports.IntegrationExpireBehaviors = createEnum(['REMOVE_ROLE', 'KICK']); * * THREAD_STARTER_MESSAGE * * GUILD_INVITE_REMINDER * * CONTEXT_MENU_COMMAND + * * AUTO_MODERATION_ACTION * @typedef {string} MessageType * @see {@link https://discord.com/developers/docs/resources/channel#message-object-message-types} */ @@ -576,6 +577,7 @@ exports.MessageTypes = [ 'THREAD_STARTER_MESSAGE', 'GUILD_INVITE_REMINDER', 'CONTEXT_MENU_COMMAND', + 'AUTO_MODERATION_ACTION', ]; /** diff --git a/typings/enums.d.ts b/typings/enums.d.ts index 8c6eb3220c5f..fd8d06c897c3 100644 --- a/typings/enums.d.ts +++ b/typings/enums.d.ts @@ -110,6 +110,7 @@ export const enum MessageTypes { THREAD_STARTER_MESSAGE, GUILD_INVITE_REMINDER, CONTEXT_MENU_COMMAND, + AUTO_MODERATION_ACTION, } export const enum DefaultMessageNotificationLevels { From 63115243c01675e425f15e9f922e2c28dd44ef99 Mon Sep 17 00:00:00 2001 From: Jaw0r3k Date: Wed, 11 Jan 2023 16:54:28 +0100 Subject: [PATCH 11/11] feat: add feature --- src/structures/Guild.js | 1 + typings/index.d.ts | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/structures/Guild.js b/src/structures/Guild.js index f97c0b32701e..7fcbd61fca9e 100644 --- a/src/structures/Guild.js +++ b/src/structures/Guild.js @@ -249,6 +249,7 @@ class Guild extends AnonymousGuild { * * SEVEN_DAY_THREAD_ARCHIVE * * PRIVATE_THREADS * * ROLE_ICONS + * * AUTO_MODERATION * @typedef {string} Features * @see {@link https://discord.com/developers/docs/resources/guild#guild-object-guild-features} */ diff --git a/typings/index.d.ts b/typings/index.d.ts index 30b2c2c3e9bf..cd5e8b9e0037 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -5326,7 +5326,8 @@ export type GuildFeatures = | 'THREE_DAY_THREAD_ARCHIVE' | 'SEVEN_DAY_THREAD_ARCHIVE' | 'PRIVATE_THREADS' - | 'ROLE_ICONS'; + | 'ROLE_ICONS' + | 'AUTO_MODERATION'; export interface GuildMemberEditData { nick?: string | null;