diff --git a/index.d.ts b/index.d.ts index efd4c9c2c..3b09c24e4 100644 --- a/index.d.ts +++ b/index.d.ts @@ -45,6 +45,13 @@ declare namespace Eris { type ApplicationCommandPermissionTypes = Constants["ApplicationCommandPermissionTypes"][keyof Constants["ApplicationCommandPermissionTypes"]]; type ApplicationCommandTypes = Constants["ApplicationCommandTypes"][keyof Constants["ApplicationCommandTypes"]]; + // Auto Moderation + type AutoModerationActionType = Constants["AutoModerationActionTypes"][keyof Constants["AutoModerationActionTypes"]]; + type AutoModerationEventType = Constants["AutoModerationEventTypes"][keyof Constants["AutoModerationEventTypes"]]; + type AutoModerationKeywordPresetType = Constants["AutoModerationKeywordPresetTypes"][keyof Constants["AutoModerationKeywordPresetTypes"]]; + type AutoModerationTriggerType = Constants["AutoModerationTriggerTypes"][keyof Constants["AutoModerationTriggerTypes"]]; + type EditAutoModerationRuleOptions = Partial; + // Cache interface Uncached { id: string } @@ -255,6 +262,61 @@ declare namespace Eris { permissions?: ApplicationCommandPermissions[]; } + // Auto Moderation + interface AutoModerationAction { + metadata?: AutoModerationActionMetadata; + type: AutoModerationActionType; + } + interface AutoModerationActionExecution { + action: AutoModerationAction; + alertSystemMessageID?: string; + channelID?: string; + content?: string; + guildID: string; + matchedContent?: string | null; + matchedKeyword: string | null; + messageID?: string; + ruleID: string; + ruleTriggerType: AutoModerationTriggerType; + userID: string; + } + interface AutoModerationActionMetadata { + /** valid for SEND_ALERT_MESSAGE */ + channelID?: string; + /** valid for TIMEOUT */ + durationSeconds?: number; + } + interface AutoModerationRule { + actions: AutoModerationAction[]; + creatorID: string; + enabled: boolean; + eventType: AutoModerationEventType; + exemptRoles: string[]; + exemptUsers: string[]; + guildID: string; + id: string; + name: string; + triggerMetadata: AutoModerationTriggerMetadata; + triggerType: AutoModerationTriggerType; + } + interface CreateAutoModerationRuleOptions { + actions: AutoModerationAction[]; + enabled?: boolean; + eventType: AutoModerationActionType; + exemptChannels?: string[]; + exemptRoles?: string[]; + name: string; + reason?: string; + triggerMetadata?: AutoModerationTriggerMetadata; + triggerType: AutoModerationTriggerType; + } + + interface AutoModerationTriggerMetadata { + /** valid for KEYWORD */ + keywordFilter: string[]; + /** valid for KEYWORD_PRESET */ + presets: AutoModerationKeywordPresetType[]; + } // Channel interface ChannelFollow { channel_id: string; @@ -694,6 +756,10 @@ declare namespace Eris { selfVideo: boolean; } interface EventListeners { + autoModerationActionExecution: [guild: Guild, action: AutoModerationActionExecution]; + autoModerationRuleCreate: [guild: Guild, rule: AutoModerationRule]; + autoModerationRuleDelete: [guild: Guild, rule: AutoModerationRule]; + autoModerationRuleUpdate: [guild: Guild, rule: AutoModerationRule | null, newRule: AutoModerationRule]; callCreate: [call: Call]; callDelete: [call: Call]; callRing: [call: Call]; @@ -1565,6 +1631,30 @@ declare namespace Eris { THREAD_DELETE: 112; APPLICATION_COMMAND_PERMISSION_UPDATE: 121; + + AUTO_MODERATION_RULE_CREATE: 140; + AUTO_MODERATION_RULE_UPDATE: 141; + AUTO_MODERATION_RULE_DELETE: 142; + AUTO_MODERATION_BLOCK_MESSAGE: 143; + }; + AutoModerationActionTypes: { + BLOCK_MESSAGE: 1; + SEND_ALERT_MESSAGE: 2; + TIMEOUT: 3; + }; + AutoModerationEventTypes: { + MESSAGE_SEND: 1; + }; + AutoModerationKeywordPresetTypes: { + PROFANITY: 1; + SEXUAL_CONTENT: 2; + SLURS: 3; + }; + AutoModerationTriggerTypes: { + KEYWORD: 1; + HARMFUL_LINK: 2; + SPAM: 3; + KEYWORD_PRESET: 4; }; ButtonStyles: { PRIMARY: 1; @@ -1630,6 +1720,7 @@ declare namespace Eris { SYNC_CALL: 13; }; GuildFeatures: [ + "AUTO_MODERATION", "ANIMATED_ICON", "BANNER", "COMMERCE", @@ -1681,26 +1772,28 @@ declare namespace Eris { MINIMUM: 16; }; Intents: { - guilds: 1; - guildMembers: 2; - guildBans: 4; - guildEmojisAndStickers: 8; + guilds: 1; + guildMembers: 2; + guildBans: 4; + guildEmojisAndStickers: 8; /** @deprecated */ - guildEmojis: 8; - guildIntegrations: 16; - guildWebhooks: 32; - guildInvites: 64; - guildVoiceStates: 128; - guildPresences: 256; - guildMessages: 512; - guildMessageReactions: 1024; - guildMessageTyping: 2048; - directMessages: 4096; - directMessageReactions: 8192; - directMessageTyping: 16384; - allNonPrivileged: 32509; - allPrivileged: 258; - all: 32767; + guildEmojis: 8; + guildIntegrations: 16; + guildWebhooks: 32; + guildInvites: 64; + guildVoiceStates: 128; + guildPresences: 256; + guildMessages: 512; + guildMessageReactions: 1024; + guildMessageTyping: 2048; + directMessages: 4096; + directMessageReactions: 8192; + directMessageTyping: 16384; + autoModerationConfiguration: 1048576; + autoModerationExecution: 2097152; + allNonPrivileged: 3178237; + allPrivileged: 258; + all: 317849; }; InteractionResponseTypes: { PONG: 1; @@ -1776,6 +1869,7 @@ declare namespace Eris { THREAD_STARTER_MESSAGE: 21; GUILD_INVITE_REMINDER: 22; CONTEXT_MENU_COMMAND: 23; + AUTO_MODERATION_ACTION: 24; }; PermissionOverwriteTypes: { ROLE: 0; @@ -2146,6 +2240,7 @@ declare namespace Eris { bulkEditGuildCommands(guildID: string, commands: ApplicationCommandStructure[]): Promise; closeVoiceConnection(guildID: string): void; connect(): Promise; + createAutoModerationRule(guildID: string, rule: CreateAutoModerationRuleOptions): Promise; createChannel(guildID: string, name: string): Promise; createChannel( guildID: string, @@ -2271,6 +2366,7 @@ declare namespace Eris { createThreadWithMessage(channelID: string, messageID: string, options: CreateThreadOptions): Promise; createThreadWithoutMessage(channelID: string, options: CreateThreadWithoutMessageOptions): Promise; crosspostMessage(channelID: string, messageID: string): Promise; + deleteAutoModerationRule(guildID: string, ruleID: string, reason?: string): Promise; deleteChannel(channelID: string, reason?: string): Promise; deleteChannelPermission(channelID: string, overwriteID: string, reason?: string): Promise; deleteCommand(commandID: string): Promise; @@ -2294,6 +2390,7 @@ declare namespace Eris { disableSelfMFATOTP(code: string): Promise<{ token: string }>; disconnect(options: { reconnect?: boolean | "auto" }): void; editAFK(afk: boolean): void; + editAutoModerationRule(guildID: string, ruleID: string, options: EditAutoModerationRuleOptions): Promise; editChannel( channelID: string, options: EditChannelOptions, @@ -2372,6 +2469,8 @@ declare namespace Eris { getActiveThreads(channelID: string): Promise; getArchivedThreads(channelID: string, type: "private", options?: GetArchivedThreadsOptions): Promise>; getArchivedThreads(channelID: string, type: "public", options?: GetArchivedThreadsOptions): Promise>; + getAutoModerationRule(guildID: string, ruleID: string): Promise; + getAutoModerationRules(guildID: string): Promise; getBotGateway(): Promise<{ session_start_limit: { max_concurrency: number; remaining: number; reset_after: number; total: number }; shards: number; url: string }>; getChannel(channelID: string): AnyChannel; getChannelInvites(channelID: string): Promise; @@ -2702,13 +2801,14 @@ declare namespace Eris { addMemberRole(memberID: string, roleID: string, reason?: string): Promise; banMember(userID: string, deleteMessageDays?: number, reason?: string): Promise; bulkEditCommands(commands: ApplicationCommandStructure[]): Promise; + createAutoModerationRule(rule: CreateAutoModerationRuleOptions): Promise; createChannel(name: string): Promise; createChannel(name: string, type: Constants["ChannelTypes"]["GUILD_TEXT"], options?: CreateChannelOptions): Promise; createChannel(name: string, type: Constants["ChannelTypes"]["GUILD_VOICE"], options?: CreateChannelOptions): Promise; createChannel(name: string, type: Constants["ChannelTypes"]["GUILD_CATEGORY"], options?: CreateChannelOptions): Promise; createChannel(name: string, type: Constants["ChannelTypes"]["GUILD_NEWS"], options?: CreateChannelOptions | string): Promise; createChannel(name: string, type: Constants["ChannelTypes"]["GUILD_STORE"], options?: CreateChannelOptions | string): Promise; - createChannel(name: string, type: Constants["ChannelTypes"]["GUILD_STAGE"], options?: CreateChannelOptions | string): Promise; + createChannel(name: string, type: Constants["ChannelTypes"]["GUILD_STAGE_VOICE"], options?: CreateChannelOptions | string): Promise; createChannel(name: string, type?: number, options?: CreateChannelOptions): Promise; /** @deprecated */ createChannel(name: string, type: Constants["ChannelTypes"]["GUILD_TEXT"], reason?: string, options?: CreateChannelOptions | string): Promise; @@ -2731,6 +2831,7 @@ declare namespace Eris { createSticker(options: CreateStickerOptions, reason?: string): Promise; createTemplate(name: string, description?: string | null): Promise; delete(): Promise; + deleteAutoModerationRule(ruleID: string, reason?: string): Promise; deleteCommand(commandID: string): Promise; deleteDiscoverySubcategory(categoryID: string, reason?: string): Promise; deleteEmoji(emojiID: string, reason?: string): Promise; @@ -2743,6 +2844,7 @@ declare namespace Eris { dynamicIconURL(format?: ImageFormat, size?: number): string | null; dynamicSplashURL(format?: ImageFormat, size?: number): string | null; edit(options: GuildOptions, reason?: string): Promise; + editAutoModerationRule(ruleID: string, options: EditAutoModerationRuleOptions): Promise; editChannelPositions(channelPositions: ChannelPosition[]): Promise; editCommand(commandID: string, command: ApplicationCommandStructure): Promise; editCommandPermissions(permissions: ApplicationCommandPermissions[]): Promise; @@ -2765,6 +2867,8 @@ declare namespace Eris { getAuditLog(options?: GetGuildAuditLogOptions): Promise; /** @deprecated */ getAuditLogs(limit?: number, before?: string, actionType?: number, userID?: string): Promise; + getAutoModerationRule(guildID: string, ruleID: string): Promise; + getAutoModerationRules(guildID: string): Promise; getBan(userID: string): Promise; getBans(options?: GetGuildBansOptions): Promise; getCommand(commandID: string): Promise; diff --git a/lib/Client.js b/lib/Client.js index 7c609bd23..f8cc448b9 100644 --- a/lib/Client.js +++ b/lib/Client.js @@ -475,6 +475,34 @@ class Client extends EventEmitter { } } + /** + * Create an auto moderation rule + * @arg {String} guildID the ID of the guild to create the rule in + * @arg {Object} options The rule to create + * @arg {Object[]} options.actions The [actions](https://discord.com/developers/docs/resources/auto-moderation#auto-moderation-action-object) done when the rule is violated + * @arg {Boolean} [options.enabled=false] If the rule is enabled, false by default + * @arg {Number} options.eventType The [event type](https://discord.com/developers/docs/resources/auto-moderation#auto-moderation-rule-object-event-types) for the rule + * @arg {String[]} [options.exemptChannels] Any channels where this rule does not apply + * @arg {String[]} [options.exemptRoles] Any roles to which this rule does not apply + * @arg {String} options.name The name of the rule + * @arg {Object} [options.triggerMetadata] The [trigger metadata](https://discord.com/developers/docs/resources/auto-moderation#auto-moderation-rule-object-trigger-metadata) for the rule + * @arg {Number} options.triggerType The [trigger type](https://discord.com/developers/docs/resources/auto-moderation#auto-moderation-rule-object-trigger-types) of the rule + * @arg {String} [options.reason] The reason to be displayed in audit logs + * @returns {Promise} + */ + createAutoModerationRule(guildID, options) { + return this.requestHandler.request("POST", Endpoints.AUTO_MODERATION_RULES(guildID), true, { + actions: options.actions, + enabled: options.enabled, + event_type: options.eventType, + exempt_channels: options.exemptChannels, + exempt_roles: options.exemptRoles, + name: options.name, + trigger_metadata: options.triggerMetadata, + trigger_type: options.triggerType + }); + } + /** * Create a channel in a guild * @arg {String} guildID The ID of the guild to create the channel in @@ -953,6 +981,19 @@ class Client extends EventEmitter { return this.requestHandler.request("POST", Endpoints.CHANNEL_CROSSPOST(channelID, messageID), true).then((message) => new Message(message, this)); } + /** + * Delete an auto moderation rule + * @arg {String} guildID The guildID to delete the rule from + * @arg {String} ruleID The ID of the rule to delete + * @arg {String} [reason] The reason to be displayed in audit logs + * @returns {Promise} + */ + deleteAutoModerationRule(guildID, ruleID, reason) { + return this.requestHandler.request("DELETE", Endpoints.AUTO_MODERATION_RULE(guildID, ruleID), true, { + reason + }); + } + /** * Delete a guild channel, or leave a private or group channel * @arg {String} channelID The ID of the channel @@ -1242,6 +1283,35 @@ class Client extends EventEmitter { }); } + /** + * edit an existing auto moderation rule + * @arg {String} guildID the ID of the guild to edit the rule in + * @arg {String} ruleID The ID of the rule to edit + * @arg {Object} options The rule to create + * @arg {Object[]} [options.actions] The [actions](https://discord.com/developers/docs/resources/auto-moderation#auto-moderation-action-object) done when the rule is violated + * @arg {Boolean} [options.enabled=false] If the rule is enabled, false by default + * @arg {Number} [options.eventType] The [event type](https://discord.com/developers/docs/resources/auto-moderation#auto-moderation-rule-object-event-types) for the rule + * @arg {String[]} [options.exemptChannels] Any channels where this rule does not apply + * @arg {String[]} [options.exemptRoles] Any roles to which this rule does not apply + * @arg {String} [options.name] The name of the rule + * @arg {Object} [options.triggerMetadata] The [trigger metadata](https://discord.com/developers/docs/resources/auto-moderation#auto-moderation-rule-object-trigger-metadata) for the rule + * @arg {Number} [options.triggerType] The [trigger type](https://discord.com/developers/docs/resources/auto-moderation#auto-moderation-rule-object-trigger-types) of the rule + * @arg {String} [options.reason] The reason to be displayed in audit logs + * @returns {Promise} + */ + editAutoModerationRule(guildID, ruleID, options) { + return this.requestHandler.request("PATCH", Endpoints.AUTO_MODERATION_RULE(guildID, ruleID), true, { + actions: options.actions, + enabled: options.enabled, + event_type: options.eventType, + exempt_channels: options.exemptChannels, + exempt_roles: options.exemptRoles, + name: options.name, + trigger_metadata: options.triggerMetadata, + trigger_type: options.triggerType + }); + } + /** * Edit a channel's properties * @arg {String} channelID The ID of the channel @@ -2172,6 +2242,25 @@ class Client extends EventEmitter { }); } + /** + * Get an existing auto moderation rule + * @arg {String} guildID The ID of the guild to get the rule from + * @arg {String} ruleID The ID of the rule to get + * @returns {Promise} + */ + getAutoModerationRule(guildID, ruleID) { + return this.requestHandler.request("GET", Endpoints.AUTO_MODERATION_RULE(guildID, ruleID), true); + } + + /** + * Get a guild's auto moderation rules + * @arg {String} guildID The ID of the guild to get the rules of + * @returns {Promise} + */ + getAutoModerationRules(guildID) { + return this.requestHandler.request("GET", Endpoints.AUTO_MODERATION_RULES(guildID), true); + } + /** * Get general and bot-specific info on connecting to the Discord gateway (e.g. connection ratelimit) * @returns {Promise} Resolves with an object containing gateway connection info diff --git a/lib/Constants.js b/lib/Constants.js index bcabd634b..3879e7384 100644 --- a/lib/Constants.js +++ b/lib/Constants.js @@ -97,7 +97,35 @@ module.exports.AuditLogActions = { THREAD_UPDATE: 111, THREAD_DELETE: 112, - APPLICATION_COMMAND_PERMISSION_UPDATE: 121 + APPLICATION_COMMAND_PERMISSION_UPDATE: 121, + + AUTO_MODERATION_RULE_CREATE: 140, + AUTO_MODERATION_RULE_UPDATE: 141, + AUTO_MODERATION_RULE_DELETE: 142, + AUTO_MODERATION_BLOCK_MESSAGE: 143 +}; + +module.exports.AutoModerationActionTypes = { + BLOCK_MESSAGE: 1, + SEND_ALERT_MESSAGE: 2, + TIMEOUT: 3 +}; + +module.exports.AutoModerationEventTypes = { + MESSAGE_SEND: 1 +}; + +module.exports.AutoModerationKeywordPresetTypes = { + PROFANITY: 1, + SEXUAL_CONTENT: 2, + SLURS: 3 +}; + +module.exports.AutoModerationTriggerTypes = { + KEYWORD: 1, + HARMFUL_LINK: 2, + SPAM: 3, + KEYWORD_PRESET: 4 }; module.exports.ButtonStyles = { @@ -163,6 +191,7 @@ module.exports.GatewayOPCodes = { }; module.exports.GuildFeatures = [ + "AUTO_MODERATION", "ANIMATED_ICON", "BANNER", "COMMERCE", @@ -219,21 +248,24 @@ module.exports.ImageSizeBoundaries = { }; const Intents = { - guilds: 1 << 0, - guildMembers: 1 << 1, - guildBans: 1 << 2, - guildEmojisAndStickers: 1 << 3, guildEmojis: 1 << 3, // [DEPRECATED] - guildIntegrations: 1 << 4, - guildWebhooks: 1 << 5, - guildInvites: 1 << 6, - guildVoiceStates: 1 << 7, - guildPresences: 1 << 8, - guildMessages: 1 << 9, - guildMessageReactions: 1 << 10, - guildMessageTyping: 1 << 11, - directMessages: 1 << 12, - directMessageReactions: 1 << 13, - directMessageTyping: 1 << 14 + guilds: 1 << 0, + guildMembers: 1 << 1, + guildBans: 1 << 2, + guildEmojisAndStickers: 1 << 3, guildEmojis: 1 << 3, // [DEPRECATED] + guildIntegrations: 1 << 4, + guildWebhooks: 1 << 5, + guildInvites: 1 << 6, + guildVoiceStates: 1 << 7, + guildPresences: 1 << 8, + guildMessages: 1 << 9, + guildMessageReactions: 1 << 10, + guildMessageTyping: 1 << 11, + directMessages: 1 << 12, + directMessageReactions: 1 << 13, + directMessageTyping: 1 << 14, + + autoModerationConfiguration: 1 << 20, + autoModerationExecution: 1 << 21 }; Intents.allNonPrivileged = Intents.guilds | Intents.guildBans @@ -247,7 +279,9 @@ Intents.allNonPrivileged = Intents.guilds | Intents.guildMessageTyping | Intents.directMessages | Intents.directMessageReactions - | Intents.directMessageTyping; + | Intents.directMessageTyping + | Intents.autoModerationConfiguration + | Intents.autoModerationExecution; Intents.allPrivileged = Intents.guildMembers | Intents.guildPresences; Intents.all = Intents.allNonPrivileged | Intents.allPrivileged; @@ -333,7 +367,8 @@ module.exports.MessageTypes = { CHAT_INPUT_COMMAND: 20, THREAD_STARTER_MESSAGE: 21, GUILD_INVITE_REMINDER: 22, - CONTEXT_MENU_COMMAND: 23 + CONTEXT_MENU_COMMAND: 23, + AUTO_MODERATION_ACTION: 24 }; module.exports.PermissionOverwriteTypes = { diff --git a/lib/gateway/Shard.js b/lib/gateway/Shard.js index 86a31af7d..2f1b89c6a 100644 --- a/lib/gateway/Shard.js +++ b/lib/gateway/Shard.js @@ -606,6 +606,138 @@ class Shard extends EventEmitter { wsEvent(packet) { switch(packet.t) { /* eslint-disable no-redeclare */ // (╯°□°)╯︵ ┻━┻ + case "AUTO_MODERATION_ACTION_EXECUTION": { + const guild = this.client.guilds.get(packet.d.guild_id); + if(!guild) { + this.emit("debug", `Missing guild ${packet.d.guild_id} in AUTO_MODERATION_ACTION_EXECUTION`); + break; + } + + /** + * Fired when an auto moderation action is executed. + * @event Client#autoModerationActionExecution + * @prop {Guild} guild The guild associated with the action + * @prop {Object} action The exection action + */ + this.emit("autoModerationActionExecution", guild, { + action: packet.d.action, + alertSystemMessageID: packet.d.alert_system_message_id, + channelID: packet.d.channel_id, + content: packet.d.content, + guildID: packet.d.guild_id, + matchedContent: packet.d.matched_content, + matchedKeyword: packet.d.matched_keyword, + messageID: packet.d.message_id, + ruleID: packet.d.rule_id, + ruleTriggerType: packet.d.rule_trigger_type, + userID: packet.d.user_id + }); + break; + } + + case "AUTO_MODERATION_RULE_CREATE": { + const guild = this.client.guilds.get(packet.d.guild_id); + if(!guild) { + this.emit("debug", `Missing guild ${packet.d.guild_id} in AUTO_MODERATION_RULE_CREATE`); + break; + } + + /** + * Fired when an auto moderation rule is created + * @event Client#autoModerationRuleCreate + * @prop {Guild} guild The guild associated with the rule + * @prop {Object} rule The created rule + */ + this.emit("autoModerationRuleCreate", guild, { + actions: packet.d.actions.map((action) => ({ + channelID: action.channel_id, + durationSeconds: action.duration_seconds + })), + creatorID: packet.d.creator_id, + enabled: packet.d.enabled, + eventType: packet.d.event_type, + exemptRoles: packet.d.exempt_roles, + exemptUsers: packet.d.exempt_users, + guildID: packet.d.guild_id, + id: packet.d.id, + name: packet.d.name, + triggerMetadata: packet.d.trigger_metadata ? { + keywordFilter: packet.d.trigger_metadata.keyword_filter, + presets: packet.d.trigger_metadata.presets + } : undefined, + triggerType: packet.d.trigger_type + }); + break; + } + case "AUTO_MODERATION_RULE_DELETE": { + const guild = this.client.guilds.get(packet.d.guild_id); + if(!guild) { + this.emit("debug", `Missing guild ${packet.d.guild_id} in AUTO_MODERATION_RULE_DELETE`); + break; + } + + /** + * Fired when an auto moderation rule is deleted + * @event Client#autoModerationRuleDelete + * @prop {Guild} guild The guild associated with the rule + * @prop {Object} rule The deleted rule + */ + this.emit("autoModerationRuleDelete", guild, { + actions: packet.d.actions.map((action) => ({ + channelID: action.channel_id, + durationSeconds: action.duration_seconds + })), + creatorID: packet.d.creator_id, + enabled: packet.d.enabled, + eventType: packet.d.event_type, + exemptRoles: packet.d.exempt_roles, + exemptUsers: packet.d.exempt_users, + guildID: packet.d.guild_id, + id: packet.d.id, + name: packet.d.name, + triggerMetadata: packet.d.trigger_metadata ? { + keywordFilter: packet.d.trigger_metadata.keyword_filter, + presets: packet.d.trigger_metadata.presets + } : undefined, + triggerType: packet.d.trigger_type + }); + break; + } + case "AUTO_MODERATION_RULE_UPDATE": { + const guild = this.client.guilds.get(packet.d.guild_id); + if(!guild) { + this.emit("debug", `Missing guild ${packet.d.guild_id} in AUTO_MODERATION_RULE_DELETE`); + break; + } + + /** + * Fired when an auto moderation rule is updated + * @event Client#autoModerationRuleUpdate + * @prop {Guild} guild The guild associated with the rule + * @prop {Object?} rule The old rule, null if uncached + * @prop {Object} newRule The new rule + */ + this.emit("autoModerationRuleUpdate", guild, null, { + actions: packet.d.actions.map((action) => ({ + channelID: action.channel_id, + durationSeconds: action.duration_seconds + })), + creatorID: packet.d.creator_id, + enabled: packet.d.enabled, + eventType: packet.d.event_type, + exemptRoles: packet.d.exempt_roles, + exemptUsers: packet.d.exempt_users, + guildID: packet.d.guild_id, + id: packet.d.id, + name: packet.d.name, + triggerMetadata: packet.d.trigger_metadata ? { + keywordFilter: packet.d.trigger_metadata.keyword_filter, + presets: packet.d.trigger_metadata.presets + } : undefined, + triggerType: packet.d.trigger_type + }); + break; + } case "PRESENCE_UPDATE": { if(packet.d.user.username !== undefined) { let user = this.client.users.get(packet.d.user.id); diff --git a/lib/rest/Endpoints.js b/lib/rest/Endpoints.js index a61140bc7..34c727262 100644 --- a/lib/rest/Endpoints.js +++ b/lib/rest/Endpoints.js @@ -6,6 +6,8 @@ module.exports.BASE_URL = "/api/v" + REST_VERSION; module.exports.CDN_URL = "https://cdn.discordapp.com"; module.exports.CLIENT_URL = "https://discord.com"; +module.exports.AUTO_MODERATION_RULES = (guildID) => `/guilds/${guildID}/auto-moderation/rules`; +module.exports.AUTO_MODERATION_RULE = (guildID, ruleID) => `/guilds/${guildID}/auto-moderation/rules/${ruleID}`; module.exports.ORIGINAL_INTERACTION_RESPONSE = (appID, interactToken) => `/webhooks/${appID}/${interactToken}`; module.exports.COMMAND = (applicationID, commandID) => `/applications/${applicationID}/commands/${commandID}`; module.exports.COMMANDS = (applicationID) => `/applications/${applicationID}/commands`; diff --git a/lib/structures/Guild.js b/lib/structures/Guild.js index ed3d5bd62..ee4f0aa5c 100644 --- a/lib/structures/Guild.js +++ b/lib/structures/Guild.js @@ -384,6 +384,24 @@ class Guild extends Base { return this._client.bulkEditGuildCommands.call(this._client, this.id, commands); } + /** + * Create an auto moderation rule + * @arg {Object} options The rule to create + * @arg {Object[]} options.actions The [actions](https://discord.com/developers/docs/resources/auto-moderation#auto-moderation-action-object) done when the rule is violated + * @arg {Boolean} [options.enabled=false] If the rule is enabled, false by default + * @arg {Number} options.eventType The [event type](https://discord.com/developers/docs/resources/auto-moderation#auto-moderation-rule-object-event-types) for the rule + * @arg {String[]} [options.exemptChannels] Any channels where this rule does not apply + * @arg {String[]} [options.exemptRoles] Any roles to which this rule does not apply + * @arg {String} options.name The name of the rule + * @arg {Object} [options.triggerMetadata] The [trigger metadata](https://discord.com/developers/docs/resources/auto-moderation#auto-moderation-rule-object-trigger-metadata) for the rule + * @arg {Number} options.triggerType The [trigger type](https://discord.com/developers/docs/resources/auto-moderation#auto-moderation-rule-object-trigger-types) of the rule + * @arg {String} [options.reason] The reason to be displayed in audit logs + * @returns {Promise} + */ + createAutoModerationRule(options) { + return this._client.createAutoModerationRule.call(this._client, this.id, options); + } + /** * Create a channel in the guild * @arg {String} name The name of the channel @@ -482,6 +500,16 @@ class Guild extends Base { return this._client.deleteGuild.call(this._client, this.id); } + /** + * Delete an auto moderation rule + * @arg {String} ruleID The ID of the rule to delete + * @arg {String} [reason] The reason to be displayed in audit logs + * @returns {Promise} + */ + deleteAutoModerationRule(ruleID, reason) { + return this._client.deleteAutoModerationRule.call(this._client, this.id, ruleID, reason); + } + /** * Delete a guild application command * @arg {String} commandID The command id @@ -617,6 +645,25 @@ class Guild extends Base { return this._client.editGuild.call(this._client, this.id, options, reason); } + /** + * edit an existing auto moderation rule + * @arg {String} ruleID The ID of the rule to edit + * @arg {Object} options The rule to create + * @arg {Object[]} [options.actions] The [actions](https://discord.com/developers/docs/resources/auto-moderation#auto-moderation-action-object) done when the rule is violated + * @arg {Boolean} [options.enabled=false] If the rule is enabled, false by default + * @arg {Number} [options.eventType] The [event type](https://discord.com/developers/docs/resources/auto-moderation#auto-moderation-rule-object-event-types) for the rule + * @arg {String[]} [options.exemptChannels] Any channels where this rule does not apply + * @arg {String[]} [options.exemptRoles] Any roles to which this rule does not apply + * @arg {String} [options.name] The name of the rule + * @arg {Object} [options.triggerMetadata] The [trigger metadata](https://discord.com/developers/docs/resources/auto-moderation#auto-moderation-rule-object-trigger-metadata) for the rule + * @arg {Number} [options.triggerType] The [trigger type](https://discord.com/developers/docs/resources/auto-moderation#auto-moderation-rule-object-trigger-types) of the rule + * @arg {String} [options.reason] The reason to be displayed in audit logs + * @returns {Promise} + */ + editAutoModerationRule(ruleID, options) { + return this._client.editAutoModerationRule.call(this._client, this.id, ruleID, options); + } + /** * Edit multiple channels' positions. Note that channel position numbers are grouped by type (category, text, voice), then sorted in ascending order (lowest number is on top). * @arg {Array} channelPositions An array of [ChannelPosition](https://discord.com/developers/docs/resources/guild#modify-guild-channel-positions) @@ -869,6 +916,25 @@ class Guild extends Base { return this._client.getGuildAuditLogs.call(this._client, this.id, limit, before, actionType, userID); } + /** + * Get an existing auto moderation rule + * @arg {String} guildID The ID of the guild to get the rule from + * @arg {String} ruleID The ID of the rule to get + * @returns {Promise} + */ + getAutoModerationRule(ruleID) { + return this._client.getAutoModerationRule.call(this._client, this.id, ruleID); + } + + /** + * Get a guild's auto moderation rules + * @arg {String} guildID The ID of the guild to get the rules of + * @returns {Promise} + */ + getAutoModerationRules() { + return this._client.getAutoModerationRules.call(this._client, this.id); + } + /** * Get a ban from the ban list of a guild * @arg {String} userID The ID of the banned user diff --git a/lib/structures/Message.js b/lib/structures/Message.js index 76a400344..d6760f036 100644 --- a/lib/structures/Message.js +++ b/lib/structures/Message.js @@ -241,6 +241,9 @@ class Message extends Base { data.content = "Wondering who to invite?\nStart by inviting anyone who can help you build the server!"; break; } + case MessageTypes.AUTO_MODERATION_ACTION: { + break; + } default: { this._client.emit("warn", `Unhandled MESSAGE_CREATE type: ${JSON.stringify(data, null, 2)}`); break;