diff --git a/src/main/java/net/dv8tion/jda/api/audit/ActionType.java b/src/main/java/net/dv8tion/jda/api/audit/ActionType.java index c77764b6ca..32efb8933e 100644 --- a/src/main/java/net/dv8tion/jda/api/audit/ActionType.java +++ b/src/main/java/net/dv8tion/jda/api/audit/ActionType.java @@ -586,6 +586,55 @@ public enum ActionType */ APPLICATION_COMMAND_PRIVILEGES_UPDATE(121, TargetType.INTEGRATION), + /** + * A moderator created a new {@link net.dv8tion.jda.api.entities.automod.AutoModRule AutoModRule} + */ + AUTO_MODERATION_RULE_CREATE(140, TargetType.AUTO_MODERATION_RULE), + + /** + * A moderator updated an existing {@link net.dv8tion.jda.api.entities.automod.AutoModRule AutoModRule} + */ + AUTO_MODERATION_RULE_UPDATE(141, TargetType.AUTO_MODERATION_RULE), + + /** + * A moderator deleted an existing {@link net.dv8tion.jda.api.entities.automod.AutoModRule AutoModRule} + */ + AUTO_MODERATION_RULE_DELETE(142, TargetType.AUTO_MODERATION_RULE), + + /** + * An automod rule blocked a message from being sent + * + *
Possible Keys
+ *
Possible Keys
+ *
Possible Keys
+ *
Expected type: String
+ */
+ CHANNEL_ID("channel_id"),
+
// /**
// * The {@link ForumChannel#getDefaultSortOrder()} value.
// *
Only for {@link ChannelType#FORUM}.
@@ -657,7 +666,25 @@ public enum AuditLogKey
*
*
Expected type: int */ - INVITE_MAX_USES("max_uses"); + INVITE_MAX_USES("max_uses"), + + // AUTO MODERATION + /** + * Change of the {@link AutoModRule#getName()} for the target {@link AutoModRule} + * + *
Expected type: String + */ + AUTO_MODERATION_RULE_NAME("auto_moderation_rule_name"), + + /** + * The {@link AutoModRule#getTriggerType()} for an {@link AutoModRule} trigger + * + *
Use with {@link AutoModTriggerType#fromKey(int)} + * + *
Expected type: int
+ */
+ AUTO_MODERATION_RULE_TRIGGER_TYPE("auto_moderation_rule_trigger_type"),
+ ;
private final String key;
diff --git a/src/main/java/net/dv8tion/jda/api/audit/TargetType.java b/src/main/java/net/dv8tion/jda/api/audit/TargetType.java
index 98c5918365..7ef8b38967 100644
--- a/src/main/java/net/dv8tion/jda/api/audit/TargetType.java
+++ b/src/main/java/net/dv8tion/jda/api/audit/TargetType.java
@@ -42,6 +42,7 @@ public enum TargetType
STAGE_INSTANCE,
STICKER,
THREAD,
- SCHEDULED_EVENT,
+ SCHEDULED_EVENT,
+ AUTO_MODERATION_RULE,
UNKNOWN
}
diff --git a/src/main/java/net/dv8tion/jda/api/entities/Guild.java b/src/main/java/net/dv8tion/jda/api/entities/Guild.java
index a08d1984b4..1775542b6e 100644
--- a/src/main/java/net/dv8tion/jda/api/entities/Guild.java
+++ b/src/main/java/net/dv8tion/jda/api/entities/Guild.java
@@ -22,6 +22,10 @@
import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.Permission;
import net.dv8tion.jda.api.Region;
+import net.dv8tion.jda.api.entities.automod.AutoModResponse;
+import net.dv8tion.jda.api.entities.automod.AutoModRule;
+import net.dv8tion.jda.api.entities.automod.AutoModTriggerType;
+import net.dv8tion.jda.api.entities.automod.build.AutoModRuleData;
import net.dv8tion.jda.api.entities.channel.Channel;
import net.dv8tion.jda.api.entities.channel.attribute.ICopyableChannel;
import net.dv8tion.jda.api.entities.channel.attribute.IGuildChannelContainer;
@@ -42,10 +46,7 @@
import net.dv8tion.jda.api.interactions.commands.build.CommandData;
import net.dv8tion.jda.api.interactions.commands.build.Commands;
import net.dv8tion.jda.api.interactions.commands.privileges.IntegrationPrivilege;
-import net.dv8tion.jda.api.managers.AudioManager;
-import net.dv8tion.jda.api.managers.GuildManager;
-import net.dv8tion.jda.api.managers.GuildStickerManager;
-import net.dv8tion.jda.api.managers.GuildWelcomeScreenManager;
+import net.dv8tion.jda.api.managers.*;
import net.dv8tion.jda.api.requests.GatewayIntent;
import net.dv8tion.jda.api.requests.RestAction;
import net.dv8tion.jda.api.requests.restaction.*;
@@ -406,6 +407,142 @@ default RestAction You can only create a certain number of rules for each {@link AutoModTriggerType AutoModTriggerType}.
+ * The maximum is provided by {@link AutoModTriggerType#getMaxPerGuild()}.
+ *
+ * @param data
+ * The data for the new rule
+ *
+ * @throws InsufficientPermissionException
+ * If the currently logged in account does not have the {@link AutoModRuleData#getRequiredPermissions() required permissions}
+ * @throws IllegalStateException
+ * The manager allows modifying multiple fields in a single request.
+ * The manager allows modifying multiple fields in a single request.
+ * For further info, see {@link GuildMessageChannel#sendStickers(Collection)} and {@link MessageCreateAction#setMessageReference(Message)}.
*
+ * Possible {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} include:
+ * For further info, see {@link GuildMessageChannel#sendStickers(Collection)} and {@link MessageCreateAction#setMessageReference(Message)}.
*
+ * Possible {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} include:
+ * Possible {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} include:
+ * Possible {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} include:
+ * Possible {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} include:
+ * Possible {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} include:
+ * Possible {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} include:
+ * Possible {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} include:
+ * Possible {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} include:
+ * Possible {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} include:
+ * Possible {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} include:
+ * Example: Attachment Images
@@ -171,6 +195,12 @@ default WebhookMessageCreateAction Example: Attachment Images
@@ -222,6 +252,12 @@ default WebhookMessageCreateAction Possible {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} include:
+ * Possible {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} include:
+ * This might be {@code null} if the execution occurred by future event types.
+ *
+ * @return The {@link GuildMessageChannelUnion}
+ */
+ @Nullable
+ GuildMessageChannelUnion getChannel();
+
+ /**
+ * The {@link AutoModResponse} that has been triggered by this execution.
+ *
+ * @return The {@link AutoModResponse}
+ */
+ @Nonnull
+ AutoModResponse getResponse();
+
+ /**
+ * The {@link AutoModTriggerType} for the execution.
+ *
+ * @return The {@link AutoModTriggerType}
+ */
+ @Nonnull
+ AutoModTriggerType getTriggerType();
+
+ /**
+ * The id of the user that triggered this execution.
+ *
+ * @return The id of the user
+ */
+ long getUserIdLong();
+
+ /**
+ * The id of the user that triggered this execution.
+ *
+ * @return The id of the user
+ */
+ @Nonnull
+ default String getUserId()
+ {
+ return Long.toUnsignedString(getUserIdLong());
+ }
+
+ /**
+ * The id of the {@link AutoModRule} which has been triggered.
+ *
+ * @return The id of the rule
+ */
+ long getRuleIdLong();
+
+ /**
+ * The id of the {@link AutoModRule} which has been triggered.
+ *
+ * @return The id of the rule
+ */
+ @Nonnull
+ default String getRuleId()
+ {
+ return Long.toUnsignedString(getRuleIdLong());
+ }
+
+ /**
+ * The id of the {@link net.dv8tion.jda.api.entities.Message Message} which triggered the rule.
+ *
+ * @return The id of the message, or 0 if the message has been blocked
+ */
+ long getMessageIdLong();
+
+ /**
+ * The id of the {@link net.dv8tion.jda.api.entities.Message Message} which triggered the rule.
+ *
+ * @return The id of the message, or {@code null} if the message has been blocked
+ */
+ @Nullable
+ default String getMessageId()
+ {
+ long id = getMessageIdLong();
+ return id == 0L ? null : Long.toUnsignedString(getMessageIdLong());
+ }
+
+ /**
+ * The id of the alert {@link net.dv8tion.jda.api.entities.Message Message} sent to the alert channel.
+ *
+ * @return The id of the alert message, or 0 if {@link AutoModResponse#getType()} is not {@link AutoModResponse.Type#SEND_ALERT_MESSAGE}
+ */
+ long getAlertMessageIdLong();
+
+ /**
+ * The id of the alert {@link net.dv8tion.jda.api.entities.Message Message} sent to the alert channel.
+ *
+ * @return The id of the alert message, or {@code null} if {@link AutoModResponse#getType()} is not {@link AutoModResponse.Type#SEND_ALERT_MESSAGE}
+ */
+ @Nullable
+ default String getAlertMessageId()
+ {
+ long id = getAlertMessageIdLong();
+ return id == 0L ? null : Long.toUnsignedString(getAlertMessageIdLong());
+ }
+
+ /**
+ * The user content that triggered this rule.
+ *
+ * This is empty if {@link GatewayIntent#MESSAGE_CONTENT} is not enabled.
+ * However, you can still use {@link #getMatchedKeyword()} regardless.
+ *
+ * @return The user content
+ */
+ @Nonnull
+ String getContent();
+
+ /**
+ * The substring match of the user content that triggered this rule.
+ *
+ * This is empty if {@link GatewayIntent#MESSAGE_CONTENT} is not enabled.
+ * However, you can still use {@link #getMatchedKeyword()} regardless.
+ *
+ * @return The user content substring
+ */
+ @Nullable
+ String getMatchedContent();
+
+ /**
+ * The keyword that was found in the {@link #getContent()}.
+ *
+ * @return The keyword that was found in the content
+ */
+ @Nullable
+ String getMatchedKeyword();
+}
diff --git a/src/main/java/net/dv8tion/jda/api/entities/automod/AutoModResponse.java b/src/main/java/net/dv8tion/jda/api/entities/automod/AutoModResponse.java
new file mode 100644
index 0000000000..b0cfe0a57a
--- /dev/null
+++ b/src/main/java/net/dv8tion/jda/api/entities/automod/AutoModResponse.java
@@ -0,0 +1,260 @@
+/*
+ * Copyright 2015 Austin Keener, Michael Ritter, Florian Spieß, and the JDA contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dv8tion.jda.api.entities.automod;
+
+import net.dv8tion.jda.annotations.Incubating;
+import net.dv8tion.jda.api.entities.channel.middleman.GuildMessageChannel;
+import net.dv8tion.jda.api.utils.data.SerializableData;
+import net.dv8tion.jda.internal.entities.automod.AutoModResponseImpl;
+import net.dv8tion.jda.internal.utils.Checks;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import java.time.Duration;
+import java.util.EnumSet;
+
+/**
+ * An automated response to an {@link AutoModRule}.
+ */
+public interface AutoModResponse extends SerializableData
+{
+ /**
+ * The maximum length of a custom message. ({@value})
+ */
+ int MAX_CUSTOM_MESSAGE_LENGTH = 150;
+
+ /**
+ * The type of response.
+ *
+ * @return The type of response
+ */
+ @Nonnull
+ Type getType();
+
+ /**
+ * The channel to send the alert message to.
+ *
+ * @return The channel to send the alert message to, or null if this is not a {@link Type#SEND_ALERT_MESSAGE} response
+ */
+ @Nullable
+ GuildMessageChannel getChannel();
+
+ /**
+ * The custom message to send to the user.
+ *
+ * @return The custom message to send to the user, or null if this is not a {@link Type#BLOCK_MESSAGE} response
+ */
+ @Nullable
+ String getCustomMessage();
+
+ /**
+ * The duration to timeout the user for.
+ *
+ * @return The duration to timeout the user for, or null if this is not a {@link Type#TIMEOUT} response
+ */
+ @Nullable
+ Duration getTimeoutDuration();
+
+ /**
+ * Create a response that will block the message.
+ * You can optionally pass a custom message to send to the user.
+ *
+ * @return The response instance
+ *
+ * @see #blockMessage(String)
+ */
+ @Nonnull
+ static AutoModResponse blockMessage()
+ {
+ return blockMessage(null);
+ }
+
+ /**
+ * Create a response that will block the message.
+ *
+ * @param customMessage
+ * The custom message to send to the user, or null to send the default message
+ *
+ * @throws IllegalArgumentException
+ * If the provided custom message is longer than {@value #MAX_CUSTOM_MESSAGE_LENGTH} characters
+ *
+ * @return The response instance
+ */
+ @Nonnull
+ static AutoModResponse blockMessage(@Nullable String customMessage)
+ {
+ return new AutoModResponseImpl(Type.BLOCK_MESSAGE, customMessage);
+ }
+
+ /**
+ * Create a response that will send an alert message to the specified channel.
+ *
+ * @param channel
+ * The channel to send the alert message to
+ *
+ * @throws IllegalArgumentException
+ * If the provided channel is {@code null}
+ *
+ * @return The response instance
+ */
+ @Nonnull
+ static AutoModResponse sendAlert(@Nonnull GuildMessageChannel channel)
+ {
+ Checks.notNull(channel, "Channel");
+ return new AutoModResponseImpl(Type.SEND_ALERT_MESSAGE, channel);
+ }
+
+ /**
+ * Create a response that will timeout the user for the specified duration.
+ *
+ * To create a rule with this response, the creator must also have the {@link net.dv8tion.jda.api.Permission#MODERATE_MEMBERS MODERATE_MEMBERS} permission.
+ *
+ * @param duration
+ * The duration to timeout the user for
+ *
+ * @throws IllegalArgumentException
+ * If the provided duration is not positive or longer than {@value net.dv8tion.jda.api.entities.Member#MAX_TIME_OUT_LENGTH} days
+ *
+ * @return The response instance
+ */
+ @Nonnull
+ static AutoModResponse timeoutMember(@Nonnull Duration duration)
+ {
+ Checks.notNull(duration, "Duration");
+ Checks.check(!duration.isNegative() && !duration.isZero(), "Duration must be positive");
+ return new AutoModResponseImpl(Type.TIMEOUT, duration);
+ }
+
+ /**
+ * Create a response that will prevent the member from interacting with anything in the guild until the offending content is removed.
+ *
+ * @return The response instance
+ *
+ * @incubating This has not been officially released yet
+ */
+ @Nonnull
+ @Incubating
+ static AutoModResponse blockMemberInteraction()
+ {
+ return new AutoModResponseImpl(Type.BLOCK_MEMBER_INTERACTION);
+ }
+
+ /**
+ * The type of response.
+ */
+ enum Type
+ {
+ /**
+ * Blocks the message from being sent.
+ */
+ BLOCK_MESSAGE(1, EnumSet.of(AutoModTriggerType.KEYWORD, AutoModTriggerType.KEYWORD_PRESET, AutoModTriggerType.SPAM, AutoModTriggerType.MENTION_SPAM)),
+ /**
+ * Sends an alert message to the specified channel.
+ */
+ SEND_ALERT_MESSAGE(2, EnumSet.of(AutoModTriggerType.KEYWORD, AutoModTriggerType.KEYWORD_PRESET, AutoModTriggerType.SPAM, AutoModTriggerType.MENTION_SPAM)),
+ /**
+ * Times out the user for the specified duration.
+ *
+ * To create a rule with this response, the creator must also have the {@link net.dv8tion.jda.api.Permission#MODERATE_MEMBERS MODERATE_MEMBERS} permission.
+ */
+ TIMEOUT(3, EnumSet.of(AutoModTriggerType.KEYWORD, AutoModTriggerType.MENTION_SPAM)),
+ /**
+ * Blocks the member from interacting with the guild until they update the offending content.
+ *
+ * @incubating This has not been officially released yet
+ */
+ @Incubating
+ BLOCK_MEMBER_INTERACTION(4, EnumSet.of(AutoModTriggerType.MEMBER_PROFILE_KEYWORD)),
+ /**
+ * Placeholder for unknown types.
+ */
+ UNKNOWN(-1, EnumSet.noneOf(AutoModTriggerType.class))
+ ;
+
+ private final int key;
+ private final EnumSet All members of the exempt roles will bypass the rule.
+ *
+ * @return The exempt roles
+ */
+ @Nonnull
+ List All messages in the listed channels will bypass the rule.
+ *
+ * @return The exempt channels
+ */
+ @Nonnull
+ List Only applies to {@link AutoModTriggerType#KEYWORD}.
+ *
+ * @return The blocked keywords
+ */
+ @Nonnull
+ List Only applies to {@link AutoModTriggerType#KEYWORD}.
+ *
+ * @return The blocked regex patterns
+ */
+ @Nonnull
+ List Only applies to {@link AutoModTriggerType#KEYWORD_PRESET}.
+ *
+ * @return The blocked keyword presets
+ */
+ @Nonnull
+ EnumSet Only applies to {@link AutoModTriggerType#KEYWORD} and {@link AutoModTriggerType#KEYWORD_PRESET}.
+ *
+ * @return The whitelisted keywords
+ */
+ @Nonnull
+ List Only applies to {@link AutoModTriggerType#MENTION_SPAM}.
+ *
+ * @return The mention limit, or 0 if this is not using {@link AutoModTriggerType#MENTION_SPAM}
+ */
+ int getMentionLimit();
+
+ /**
+ * Whether this rule is using the raid protection feature.
+ * Only applies to {@link AutoModTriggerType#MENTION_SPAM}.
+ *
+ * @return True, if mention raid protection is enabled
+ */
+ boolean isMentionRaidProtectionEnabled();
+
+ /**
+ * Returns an {@link AutoModRuleManager}, which can be used to modify this rule.
+ * The manager allows modifying multiple fields in a single request.
+ * Keywords added to the allow list will not be considered as a match and won't trigger the rule execution.
+ *
+ * Keywords follow the same rules as {@link CustomKeywordTriggerConfig#addKeywords(String...)}.
+ *
+ * @param keywords
+ * The keywords to allow
+ *
+ * @throws IllegalArgumentException
+ * Keywords added to the allow list will not be considered as a match and won't trigger the rule execution.
+ *
+ * Keywords follow the same rules as {@link CustomKeywordTriggerConfig#addKeywords(String...)}.
+ *
+ * @param keywords
+ * The keywords to allow
+ *
+ * @throws IllegalArgumentException
+ * Keywords added to the allow list will not be considered as a match and won't trigger the rule execution.
+ *
+ * Keywords follow the same rules as {@link CustomKeywordTriggerConfig#addKeywords(String...)}.
+ *
+ * @param keywords
+ * The keywords to allow
+ *
+ * @throws IllegalArgumentException
+ * Every rule must configure at least one {@link #putResponses(AutoModResponse...) response}.
+ *
+ * Example Note that each response type can only be used once.
+ * If multiple responses of the same type are provided, the last one is used.
+ *
+ * @param responses
+ * The responses to configure
+ *
+ * @throws IllegalArgumentException
+ * If null is provided or any of the responses has an {@link AutoModResponse.Type#UNKNOWN unknown type}
+ *
+ * @return The same {@link AutoModRuleData} instance
+ */
+ @Nonnull
+ public AutoModRuleData putResponses(@Nonnull AutoModResponse... responses)
+ {
+ Checks.noneNull(responses, "Responses");
+ for (AutoModResponse response : responses)
+ {
+ AutoModResponse.Type type = response.getType();
+ Checks.check(type != AutoModResponse.Type.UNKNOWN, "Cannot create response with unknown response type");
+ actions.put(type, response);
+ }
+ return this;
+ }
+
+ /**
+ * Configure what the rule should do upon triggering.
+ * Note that each response type can only be used once.
+ * If multiple responses of the same type are provided, the last one is used.
+ *
+ * @param responses
+ * The responses to configure
+ *
+ * @throws IllegalArgumentException
+ * If null is provided or any of the responses has an {@link AutoModResponse.Type#UNKNOWN unknown type}
+ *
+ * @return The same {@link AutoModRuleData} instance
+ */
+ @Nonnull
+ public AutoModRuleData putResponses(@Nonnull Collection extends AutoModResponse> responses)
+ {
+ Checks.noneNull(responses, "Responses");
+ for (AutoModResponse response : responses)
+ {
+ AutoModResponse.Type type = response.getType();
+ Checks.check(type != AutoModResponse.Type.UNKNOWN, "Cannot create response with unknown response type");
+ actions.put(type, response);
+ }
+ return this;
+ }
+
+ /**
+ * Configure what the rule should do upon triggering.
+ * Note that each response type can only be used once.
+ * If multiple responses of the same type are provided, the last one is used.
+ *
+ * @param responses
+ * The responses to configure
+ *
+ * @throws IllegalArgumentException
+ * If null is provided or any of the responses has an {@link AutoModResponse.Type#UNKNOWN unknown type}
+ *
+ * @return The same {@link AutoModRuleData} instance
+ */
+ @Nonnull
+ public AutoModRuleData setResponses(@Nonnull Collection extends AutoModResponse> responses)
+ {
+ Checks.noneNull(responses, "Responses");
+ actions.clear();
+ if (eventType == AutoModEventType.MEMBER_UPDATE)
+ actions.put(AutoModResponse.Type.BLOCK_MEMBER_INTERACTION, AutoModResponse.blockMemberInteraction());
+ for (AutoModResponse response : responses)
+ {
+ AutoModResponse.Type type = response.getType();
+ Checks.check(type != AutoModResponse.Type.UNKNOWN, "Cannot create response with unknown response type");
+ actions.put(type, response);
+ }
+ return this;
+ }
+
+ /**
+ * Add roles which can bypass this rule.
+ *
+ * Roles added to the exemptions will allow all of its members to bypass this rule.
+ *
+ * @param roles
+ * The roles to add (up to {@value AutoModRule#MAX_EXEMPT_ROLES} roles)
+ *
+ * @throws IllegalArgumentException
+ * If null is provided or the number of roles exceeds {@value AutoModRule#MAX_EXEMPT_ROLES}
+ *
+ * @return The same {@link AutoModRuleData} instance
+ */
+ @Nonnull
+ public AutoModRuleData addExemptRoles(@Nonnull Role... roles)
+ {
+ Checks.noneNull(roles, "Roles");
+ Checks.check(roles.length + exemptRoles.size() <= AutoModRule.MAX_EXEMPT_ROLES, "Cannot add more than %d roles", AutoModRule.MAX_EXEMPT_ROLES);
+ for (Role role : roles)
+ exemptRoles.add(role.getId());
+ return this;
+ }
+
+ /**
+ * Add roles which can bypass this rule.
+ *
+ * Roles added to the exemptions will allow all of its members to bypass this rule.
+ *
+ * @param roles
+ * The roles to add (up to {@value AutoModRule#MAX_EXEMPT_ROLES} roles)
+ *
+ * @throws IllegalArgumentException
+ * If null is provided or the number of roles exceeds {@value AutoModRule#MAX_EXEMPT_ROLES}
+ *
+ * @return The same {@link AutoModRuleData} instance
+ */
+ @Nonnull
+ public AutoModRuleData addExemptRoles(@Nonnull Collection extends Role> roles)
+ {
+ Checks.noneNull(roles, "Roles");
+ Checks.check(roles.size() + exemptRoles.size() <= AutoModRule.MAX_EXEMPT_ROLES, "Cannot add more than %d roles", AutoModRule.MAX_EXEMPT_ROLES);
+ for (Role role : roles)
+ exemptRoles.add(role.getId());
+ return this;
+ }
+
+ /**
+ * Set which roles can bypass this rule.
+ *
+ * Roles added to the exemptions will allow all of its members to bypass this rule.
+ *
+ * @param roles
+ * The roles to exempt (up to {@value AutoModRule#MAX_EXEMPT_ROLES} roles)
+ *
+ * @throws IllegalArgumentException
+ * If null is provided or the number of roles exceeds {@value AutoModRule#MAX_EXEMPT_ROLES}
+ *
+ * @return The same {@link AutoModRuleData} instance
+ */
+ @Nonnull
+ public AutoModRuleData setExemptRoles(@Nonnull Collection extends Role> roles)
+ {
+ Checks.noneNull(roles, "Roles");
+ Checks.check(roles.size() <= AutoModRule.MAX_EXEMPT_ROLES, "Cannot add more than %d roles", AutoModRule.MAX_EXEMPT_ROLES);
+ exemptRoles.clear();
+ for (Role role : roles)
+ exemptRoles.add(role.getId());
+ return this;
+ }
+
+ /**
+ * Add channels which can bypass this rule.
+ *
+ * No messages sent in this channel will trigger the rule.
+ *
+ * @param channels
+ * The channels to add (up to {@value AutoModRule#MAX_EXEMPT_CHANNELS} channels)
+ *
+ * @throws IllegalArgumentException
+ * If null is provided or the number of channels exceeds {@value AutoModRule#MAX_EXEMPT_CHANNELS}
+ *
+ * @return The same {@link AutoModRuleData} instance
+ */
+ @Nonnull
+ public AutoModRuleData addExemptChannels(@Nonnull GuildChannel... channels)
+ {
+ Checks.noneNull(channels, "Channels");
+ Checks.check(channels.length + exemptChannels.size() <= AutoModRule.MAX_EXEMPT_CHANNELS, "Cannot add more than %d channels", AutoModRule.MAX_EXEMPT_CHANNELS);
+ for (GuildChannel channel : channels)
+ exemptChannels.add(channel.getId());
+ return this;
+ }
+
+ /**
+ * Add channels which can bypass this rule.
+ *
+ * No messages sent in this channel will trigger the rule.
+ *
+ * @param channels
+ * The channels to add (up to {@value AutoModRule#MAX_EXEMPT_CHANNELS} channels)
+ *
+ * @throws IllegalArgumentException
+ * If null is provided or the number of channels exceeds {@value AutoModRule#MAX_EXEMPT_CHANNELS}
+ *
+ * @return The same {@link AutoModRuleData} instance
+ */
+ @Nonnull
+ public AutoModRuleData addExemptChannels(@Nonnull Collection extends GuildChannel> channels)
+ {
+ Checks.noneNull(channels, "Channels");
+ Checks.check(channels.size() + exemptChannels.size() <= AutoModRule.MAX_EXEMPT_CHANNELS, "Cannot add more than %d channels", AutoModRule.MAX_EXEMPT_CHANNELS);
+ for (GuildChannel channel : channels)
+ exemptChannels.add(channel.getId());
+ return this;
+ }
+
+ /**
+ * Set which channels can bypass this rule.
+ *
+ * No messages sent in this channel will trigger the rule.
+ *
+ * @param channels
+ * The channels to add (up to {@value AutoModRule#MAX_EXEMPT_CHANNELS} channels)
+ *
+ * @throws IllegalArgumentException
+ * If null is provided or the number of channels exceeds {@value AutoModRule#MAX_EXEMPT_CHANNELS}
+ *
+ * @return The same {@link AutoModRuleData} instance
+ */
+ @Nonnull
+ public AutoModRuleData setExemptChannels(@Nonnull Collection extends GuildChannel> channels)
+ {
+ Checks.noneNull(channels, "Channels");
+ Checks.check(channels.size() <= AutoModRule.MAX_EXEMPT_CHANNELS, "Cannot add more than %d channels", AutoModRule.MAX_EXEMPT_CHANNELS);
+ exemptChannels.clear();
+ for (GuildChannel channel : channels)
+ exemptChannels.add(channel.getId());
+ return this;
+ }
+
+ /**
+ * Change the {@link TriggerConfig} for this rule.
+ *
+ * @param config
+ * The new config
+ *
+ * @throws IllegalArgumentException
+ * If null is provided
+ *
+ * @return The same {@link AutoModRuleData} instance
+ */
+ @Nonnull
+ public AutoModRuleData setTriggerConfig(@Nonnull TriggerConfig config)
+ {
+ Checks.notNull(config, "TriggerConfig");
+ Checks.check(config.getType().isEventTypeSupported(eventType), "Cannot use trigger type %s with event type %s", config.getType(), eventType);
+ this.triggerMetadata = config;
+ return this;
+ }
+
+ /**
+ * Returns the {@link Permission Permissions} required to create this rule.
+ * You can use wildcards at the keyword boundaries to extend the matches:
+ * You can also use regex patterns using {@link #patternFilter(String...)}.
+ *
+ * @param keywords
+ * The keywords to match
+ *
+ * @throws IllegalArgumentException
+ * You can use wildcards at the keyword boundaries to extend the matches:
+ * You can also use regex patterns using {@link #patternFilter(Collection)}.
+ *
+ * @param keywords
+ * The keywords to match
+ *
+ * @throws IllegalArgumentException
+ * You can use wildcards at the keyword boundaries to extend the matches:
+ * You can also use regex patterns using {@link #patternFilter(Collection)}.
+ *
+ * @param keywords
+ * The keywords to match
+ *
+ * @throws IllegalArgumentException
+ * Patterns may use anything supported by the rust regex crate.
+ * You can use a validator such as Rustexp to validate your pattern.
+ *
+ * You can also use simple substring keywords using {@link #keywordFilter(String...)}.
+ *
+ * @param patterns
+ * The keyword patterns to match
+ *
+ * @throws IllegalArgumentException
+ * Patterns may use anything supported by the rust regex crate.
+ * You can use a validator such as Rustexp to validate your pattern.
+ *
+ * You can also use simple substring keywords using {@link #keywordFilter(String...)}.
+ *
+ * @param patterns
+ * The keyword patterns to match
+ *
+ * @throws IllegalArgumentException
+ * Patterns may use anything supported by the rust regex crate.
+ * You can use a validator such as Rustexp to validate your pattern.
+ *
+ * You can also use simple substring keywords using {@link #keywordFilter(String...)}.
+ *
+ * @param patterns
+ * The keyword patterns to match
+ *
+ * @throws IllegalArgumentException
+ * Each rule is limited to a single trigger type. You can use the various factory methods on this interface to create a config.
+ *
+ * Supported factories:
+ * Example You can use wildcards at the keyword boundaries to extend the matches:
+ * You can also use regex patterns using {@link #patternFilter(Collection)} or {@link CustomKeywordTriggerConfig#addPatterns(Collection)}.
+ *
+ * @param keywords
+ * The keywords to match (case-insensitive)
+ *
+ * @throws IllegalArgumentException
+ * You can use wildcards at the keyword boundaries to extend the matches:
+ * You can also use regex patterns using {@link #patternFilter(String...)} or {@link CustomKeywordTriggerConfig#addPatterns(String...)}.
+ *
+ * @param keywords
+ * The keywords to match (case-insensitive)
+ *
+ * @throws IllegalArgumentException
+ * Patterns may use anything supported by the rust regex crate.
+ * You can use a validator such as Rustexp to validate your pattern.
+ *
+ * You can also use simple substring keywords using {@link #keywordFilter(String...)} or {@link CustomKeywordTriggerConfig#addKeywords(String...)}.
+ *
+ * @param patterns
+ * The keyword patterns to match
+ *
+ * @throws IllegalArgumentException
+ * Patterns may use anything supported by the rust regex crate.
+ * You can use a validator such as Rustexp to validate your pattern.
+ *
+ * You can also use simple substring keywords using {@link #keywordFilter(String...)} or {@link CustomKeywordTriggerConfig#addKeywords(String...)}.
+ *
+ * @param patterns
+ * The keyword patterns to match
+ *
+ * @throws IllegalArgumentException
+ * Example: Attachment Images
@@ -471,6 +495,12 @@ default MessageCreateAction sendMessageEmbeds(@Nonnull MessageEmbed embed, @Nonn
* Example: Attachment Images
@@ -522,6 +552,12 @@ default MessageCreateAction sendMessageEmbeds(@Nonnull Collection extends Mess
* Example: Attachment Images
@@ -618,6 +660,15 @@ default MessageCreateAction sendMessageComponents(@Nonnull Collection extends
* Example: Attachment Images
@@ -678,6 +729,15 @@ default MessageCreateAction sendFiles(@Nonnull Collection extends FileUpload>
* Example: Attachment Images
diff --git a/src/main/java/net/dv8tion/jda/api/events/automod/AutoModExecutionEvent.java b/src/main/java/net/dv8tion/jda/api/events/automod/AutoModExecutionEvent.java
new file mode 100644
index 0000000000..fbb160d7b3
--- /dev/null
+++ b/src/main/java/net/dv8tion/jda/api/events/automod/AutoModExecutionEvent.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2015 Austin Keener, Michael Ritter, Florian Spieß, and the JDA contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dv8tion.jda.api.events.automod;
+
+import net.dv8tion.jda.api.JDA;
+import net.dv8tion.jda.api.entities.Guild;
+import net.dv8tion.jda.api.entities.automod.AutoModExecution;
+import net.dv8tion.jda.api.entities.automod.AutoModResponse;
+import net.dv8tion.jda.api.entities.automod.AutoModRule;
+import net.dv8tion.jda.api.entities.automod.AutoModTriggerType;
+import net.dv8tion.jda.api.entities.channel.unions.GuildMessageChannelUnion;
+import net.dv8tion.jda.api.events.Event;
+import net.dv8tion.jda.api.requests.GatewayIntent;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+/**
+ * Indicates that an automated {@link AutoModResponse} has been triggered through an {@link AutoModRule}.
+ *
+ * Requirements Requirements These events require the {@link net.dv8tion.jda.api.requests.GatewayIntent#AUTO_MODERATION_CONFIGURATION AUTO_MODERATION_CONFIGURATION} intent to be enabled.
+ */
+public class AutoModRuleCreateEvent extends GenericAutoModRuleEvent
+{
+ public AutoModRuleCreateEvent(@Nonnull JDA api, long responseNumber, @Nonnull AutoModRule rule)
+ {
+ super(api, responseNumber, rule);
+ }
+}
diff --git a/src/main/java/net/dv8tion/jda/api/events/automod/AutoModRuleDeleteEvent.java b/src/main/java/net/dv8tion/jda/api/events/automod/AutoModRuleDeleteEvent.java
new file mode 100644
index 0000000000..67b65ab229
--- /dev/null
+++ b/src/main/java/net/dv8tion/jda/api/events/automod/AutoModRuleDeleteEvent.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2015 Austin Keener, Michael Ritter, Florian Spieß, and the JDA contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dv8tion.jda.api.events.automod;
+
+import net.dv8tion.jda.api.JDA;
+import net.dv8tion.jda.api.entities.automod.AutoModRule;
+
+import javax.annotation.Nonnull;
+
+/**
+ * Indicates that a {@link AutoModRule} was deleted.
+ *
+ * Requirements These events require the {@link net.dv8tion.jda.api.requests.GatewayIntent#AUTO_MODERATION_CONFIGURATION AUTO_MODERATION_CONFIGURATION} intent to be enabled.
+ */
+public class AutoModRuleDeleteEvent extends GenericAutoModRuleEvent
+{
+ public AutoModRuleDeleteEvent(@Nonnull JDA api, long responseNumber, @Nonnull AutoModRule rule)
+ {
+ super(api, responseNumber, rule);
+ }
+}
diff --git a/src/main/java/net/dv8tion/jda/api/events/automod/AutoModRuleUpdateEvent.java b/src/main/java/net/dv8tion/jda/api/events/automod/AutoModRuleUpdateEvent.java
new file mode 100644
index 0000000000..3714dc8f6e
--- /dev/null
+++ b/src/main/java/net/dv8tion/jda/api/events/automod/AutoModRuleUpdateEvent.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2015 Austin Keener, Michael Ritter, Florian Spieß, and the JDA contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dv8tion.jda.api.events.automod;
+
+import net.dv8tion.jda.api.JDA;
+import net.dv8tion.jda.api.entities.automod.AutoModRule;
+
+import javax.annotation.Nonnull;
+
+/**
+ * Indicates that a {@link AutoModRule} was updated.
+ *
+ * Requirements These events require the {@link net.dv8tion.jda.api.requests.GatewayIntent#AUTO_MODERATION_CONFIGURATION AUTO_MODERATION_CONFIGURATION} intent to be enabled.
+ */
+public class AutoModRuleUpdateEvent extends GenericAutoModRuleEvent
+{
+ public AutoModRuleUpdateEvent(@Nonnull JDA api, long responseNumber, @Nonnull AutoModRule rule)
+ {
+ super(api, responseNumber, rule);
+ }
+}
diff --git a/src/main/java/net/dv8tion/jda/api/events/automod/GenericAutoModRuleEvent.java b/src/main/java/net/dv8tion/jda/api/events/automod/GenericAutoModRuleEvent.java
new file mode 100644
index 0000000000..4126257e6f
--- /dev/null
+++ b/src/main/java/net/dv8tion/jda/api/events/automod/GenericAutoModRuleEvent.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2015 Austin Keener, Michael Ritter, Florian Spieß, and the JDA contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dv8tion.jda.api.events.automod;
+
+import net.dv8tion.jda.api.JDA;
+import net.dv8tion.jda.api.entities.automod.AutoModRule;
+import net.dv8tion.jda.api.events.Event;
+
+import javax.annotation.Nonnull;
+
+/**
+ * Indicates that na {@link AutoModRule} was created/removed/updated.
+ *
+ * Requirements These events require the {@link net.dv8tion.jda.api.requests.GatewayIntent#AUTO_MODERATION_CONFIGURATION AUTO_MODERATION_CONFIGURATION} intent to be enabled.
+ */
+public class GenericAutoModRuleEvent extends Event
+{
+ private final AutoModRule rule;
+
+ public GenericAutoModRuleEvent(@Nonnull JDA api, long responseNumber, @Nonnull AutoModRule rule)
+ {
+ super(api, responseNumber);
+ this.rule = rule;
+ }
+
+ /**
+ * The {@link AutoModRule} that was created/removed/updated.
+ *
+ * @return The {@link AutoModRule}
+ */
+ @Nonnull
+ public AutoModRule getRule()
+ {
+ return rule;
+ }
+}
diff --git a/src/main/java/net/dv8tion/jda/api/hooks/ListenerAdapter.java b/src/main/java/net/dv8tion/jda/api/hooks/ListenerAdapter.java
index ff85f8ec7f..2362720ba2 100644
--- a/src/main/java/net/dv8tion/jda/api/hooks/ListenerAdapter.java
+++ b/src/main/java/net/dv8tion/jda/api/hooks/ListenerAdapter.java
@@ -17,6 +17,10 @@
import net.dv8tion.jda.annotations.ForRemoval;
import net.dv8tion.jda.api.events.*;
+import net.dv8tion.jda.api.events.automod.AutoModExecutionEvent;
+import net.dv8tion.jda.api.events.automod.AutoModRuleCreateEvent;
+import net.dv8tion.jda.api.events.automod.AutoModRuleDeleteEvent;
+import net.dv8tion.jda.api.events.automod.AutoModRuleUpdateEvent;
import net.dv8tion.jda.api.events.channel.ChannelCreateEvent;
import net.dv8tion.jda.api.events.channel.ChannelDeleteEvent;
import net.dv8tion.jda.api.events.channel.GenericChannelEvent;
@@ -320,6 +324,12 @@ public void onGuildVoiceStream(@Nonnull GuildVoiceStreamEvent event) {}
public void onGuildVoiceVideo(@Nonnull GuildVoiceVideoEvent event) {}
public void onGuildVoiceRequestToSpeak(@Nonnull GuildVoiceRequestToSpeakEvent event) {}
+ //Guild AutoMod Events
+ public void onAutoModExecution(@Nonnull AutoModExecutionEvent event) {}
+ public void onAutoModRuleCreate(@Nonnull AutoModRuleCreateEvent event) {}
+ public void onAutoModRuleUpdate(@Nonnull AutoModRuleUpdateEvent event) {}
+ public void onAutoModRuleDelete(@Nonnull AutoModRuleDeleteEvent event) {}
+
//Role events
public void onRoleCreate(@Nonnull RoleCreateEvent event) {}
public void onRoleDelete(@Nonnull RoleDeleteEvent event) {}
diff --git a/src/main/java/net/dv8tion/jda/api/interactions/callbacks/IReplyCallback.java b/src/main/java/net/dv8tion/jda/api/interactions/callbacks/IReplyCallback.java
index 8ea5e9ae31..2988de9137 100644
--- a/src/main/java/net/dv8tion/jda/api/interactions/callbacks/IReplyCallback.java
+++ b/src/main/java/net/dv8tion/jda/api/interactions/callbacks/IReplyCallback.java
@@ -16,6 +16,7 @@
package net.dv8tion.jda.api.interactions.callbacks;
+import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.MessageEmbed;
import net.dv8tion.jda.api.interactions.InteractionHook;
@@ -114,6 +115,18 @@ default ReplyCallbackAction deferReply(boolean ephemeral)
* If your handling can take longer than 3 seconds, due to various rate limits or other conditions, you should use {@link #deferReply()} instead.
*
+ * Possible {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} include:
+ * If your handling can take longer than 3 seconds, due to various rate limits or other conditions, you should use {@link #deferReply()} instead.
*
+ * Possible {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} include:
+ * If your handling can take longer than 3 seconds, due to various rate limits or other conditions, you should use {@link #deferReply()} instead.
*
+ * Possible {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} include:
+ * If your handling can take longer than 3 seconds, due to various rate limits or other conditions, you should use {@link #deferReply()} instead.
*
+ * Possible {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} include:
+ * If your handling can take longer than 3 seconds, due to various rate limits or other conditions, you should use {@link #deferReply()} instead.
*
+ * Possible {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} include:
+ * If your handling can take longer than 3 seconds, due to various rate limits or other conditions, you should use {@link #deferReply()} instead.
*
+ * Possible {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} include:
+ * If your handling can take longer than 3 seconds, due to various rate limits or other conditions, you should use {@link #deferReply()} instead.
*
+ * Possible {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} include:
+ * Possible {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} include:
+ * Possible {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} include:
+ * Example
+ * Flag Constants:
+ * Flag Constants:
+ * A rule name must be between 1-{@value AutoModRule#MAX_RULE_NAME_LENGTH} characters long!
+ *
+ * @param name
+ * The new name for the selected {@link AutoModRule}
+ *
+ * @throws IllegalArgumentException
+ * If the provided name is {@code null} or not between 1-{@value AutoModRule#MAX_RULE_NAME_LENGTH} characters long
+ *
+ * @return AutoModRuleManager for chaining convenience
+ */
+ @Nonnull
+ @CheckReturnValue
+ AutoModRuleManager setName(@Nonnull String name);
+
+ /**
+ * Sets the enabled state of the selected {@link AutoModRule}.
+ *
+ * When a rule is disabled, it will not be applied to any messages.
+ *
+ * @param enabled
+ * True, if the selected {@link AutoModRule} should be enabled
+ *
+ * @return AutoModRuleManager for chaining convenience
+ */
+ @Nonnull
+ @CheckReturnValue
+ AutoModRuleManager setEnabled(boolean enabled);
+
+// @Nonnull
+// @CheckReturnValue
+// AutoModRuleManager setEventType(@Nonnull AutoModEventType type);
+
+ /**
+ * Sets what the rule should do upon triggering.
+ *
+ * Note that each response type can only be used once.
+ * If multiple responses of the same type are provided, the last one is used.
+ *
+ * @param responses
+ * The responses to configure
+ *
+ * @throws IllegalArgumentException
+ * Note that each response type can only be used once.
+ * If multiple responses of the same type are provided, the last one is used.
+ *
+ * @param responses
+ * The responses to configure
+ *
+ * @throws IllegalArgumentException
+ * Roles added to the exemptions will allow all of its members to bypass this rule.
+ *
+ * @param roles
+ * The roles to exempt (up to {@value AutoModRule#MAX_EXEMPT_ROLES} roles)
+ *
+ * @throws IllegalArgumentException
+ * If null is provided or the number of roles exceeds {@value AutoModRule#MAX_EXEMPT_ROLES}
+ *
+ * @return AutoModRuleManager for chaining convenience
+ */
+ @Nonnull
+ @CheckReturnValue
+ AutoModRuleManager setExemptRoles(@Nonnull Collection Roles added to the exemptions will allow all of its members to bypass this rule.
+ *
+ * @param roles
+ * The roles to exempt (up to {@value AutoModRule#MAX_EXEMPT_ROLES} roles)
+ *
+ * @throws IllegalArgumentException
+ * If null is provided or the number of roles exceeds {@value AutoModRule#MAX_EXEMPT_ROLES}
+ *
+ * @return AutoModRuleManager for chaining convenience
+ */
+ @Nonnull
+ @CheckReturnValue
+ default AutoModRuleManager setExemptRoles(@Nonnull Role... roles)
+ {
+ Checks.noneNull(roles, "Roles");
+ return setExemptRoles(Arrays.asList(roles));
+ }
+
+ /**
+ * Set which channels can bypass this rule.
+ *
+ * No messages sent in this channel will trigger the rule.
+ *
+ * @param channels
+ * The channels to add (up to {@value AutoModRule#MAX_EXEMPT_CHANNELS} channels)
+ *
+ * @throws IllegalArgumentException
+ * If null is provided or the number of channels exceeds {@value AutoModRule#MAX_EXEMPT_CHANNELS}
+ *
+ * @return AutoModRuleManager for chaining convenience
+ */
+ @Nonnull
+ @CheckReturnValue
+ AutoModRuleManager setExemptChannels(@Nonnull Collection extends GuildChannel> channels);
+
+ /**
+ * Set which channels can bypass this rule.
+ *
+ * No messages sent in this channel will trigger the rule.
+ *
+ * @param channels
+ * The channels to add (up to {@value AutoModRule#MAX_EXEMPT_CHANNELS} channels)
+ *
+ * @throws IllegalArgumentException
+ * If null is provided or the number of channels exceeds {@value AutoModRule#MAX_EXEMPT_CHANNELS}
+ *
+ * @return AutoModRuleManager for chaining convenience
+ */
+ @Nonnull
+ @CheckReturnValue
+ default AutoModRuleManager setExemptChannels(@Nonnull GuildChannel... channels)
+ {
+ Checks.noneNull(channels, "Channels");
+ return setExemptChannels(Arrays.asList(channels));
+ }
+
+ /**
+ * Change the {@link TriggerConfig} for this rule.
+ *
+ * @param config
+ * The new config
+ *
+ * @throws IllegalArgumentException
+ * If null is provided
+ *
+ * @return AutoModRuleManager for chaining convenience
+ */
+ @Nonnull
+ @CheckReturnValue
+ AutoModRuleManager setTriggerConfig(@Nonnull TriggerConfig config);
+}
diff --git a/src/main/java/net/dv8tion/jda/api/requests/ErrorResponse.java b/src/main/java/net/dv8tion/jda/api/requests/ErrorResponse.java
index e39190b742..f59c3a5c65 100644
--- a/src/main/java/net/dv8tion/jda/api/requests/ErrorResponse.java
+++ b/src/main/java/net/dv8tion/jda/api/requests/ErrorResponse.java
@@ -181,6 +181,9 @@ public enum ErrorResponse
MAX_LOTTIE_ANIMATION_DIMENSION( 170005, "Lottie animation maximum dimensions exceeded"),
STICKER_FPS_TOO_SMALL_OR_TOO_LARGE( 170006, "Sticker frame rate is either too small or too large"),
MAX_STICKER_ANIMATION_DURATION( 170007, "Sticker animation duration exceeds maximum of 5 seconds"),
+ MESSAGE_BLOCKED_BY_AUTOMOD( 200000, "Message was blocked by automatic moderation"),
+ TITLE_BLOCKED_BY_AUTOMOD( 200001, "Title was blocked by automatic moderation"),
+ MESSAGE_BLOCKED_BY_HARMFUL_LINK_FILTER( 240000, "Message blocked by harmful links filter"),
SERVER_ERROR( 0, "Discord encountered an internal server error! Not good!");
diff --git a/src/main/java/net/dv8tion/jda/api/requests/GatewayIntent.java b/src/main/java/net/dv8tion/jda/api/requests/GatewayIntent.java
index 51db8d7722..c7eb6f6a9f 100644
--- a/src/main/java/net/dv8tion/jda/api/requests/GatewayIntent.java
+++ b/src/main/java/net/dv8tion/jda/api/requests/GatewayIntent.java
@@ -22,6 +22,8 @@
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.events.GenericEvent;
+import net.dv8tion.jda.api.events.automod.AutoModExecutionEvent;
+import net.dv8tion.jda.api.events.automod.GenericAutoModRuleEvent;
import net.dv8tion.jda.api.events.emoji.GenericEmojiEvent;
import net.dv8tion.jda.api.events.guild.GuildAuditLogEntryCreateEvent;
import net.dv8tion.jda.api.events.guild.GuildBanEvent;
@@ -67,6 +69,10 @@
* > retrieveAutoModRules();
+
+ /**
+ * Retrieves the {@link AutoModRule} for the provided id.
+ *
+ * @param id
+ * The id of the rule
+ *
+ * @throws IllegalArgumentException
+ * If the provided id is not a valid snowflake
+ * @throws InsufficientPermissionException
+ * If the currently logged in account does not have the {@link net.dv8tion.jda.api.Permission#MANAGE_SERVER MANAGE_SERVER} permission
+ *
+ * @return {@link RestAction} - Type: {@link AutoModRule}
+ */
+ @Nonnull
+ @CheckReturnValue
+ RestAction
+ *
+ *
+ * @return {@link AuditableRestAction} - Type: {@link AutoModRule}
+ */
+ @Nonnull
+ @CheckReturnValue
+ AuditableRestAction
You modify multiple fields in one request by chaining setters before calling {@link net.dv8tion.jda.api.requests.RestAction#queue() RestAction.queue()}.
+ *
+ * @throws InsufficientPermissionException
+ * If the currently logged in account does not have the {@link net.dv8tion.jda.api.Permission#MANAGE_SERVER MANAGE_SERVER} permission.
+ *
+ * @return The manager instance
+ */
+ @Nonnull
+ @CheckReturnValue
+ AutoModRuleManager modifyAutoModRuleById(@Nonnull String id);
+
+ /**
+ * Returns an {@link AutoModRuleManager}, which can be used to modify the rule for the provided id.
+ *
You modify multiple fields in one request by chaining setters before calling {@link net.dv8tion.jda.api.requests.RestAction#queue() RestAction.queue()}.
+ *
+ * @throws InsufficientPermissionException
+ * If the currently logged in account does not have the {@link net.dv8tion.jda.api.Permission#MANAGE_SERVER MANAGE_SERVER} permission.
+ *
+ * @return The manager instance
+ */
+ @Nonnull
+ @CheckReturnValue
+ default AutoModRuleManager modifyAutoModRuleById(long id)
+ {
+ return modifyAutoModRuleById(Long.toUnsignedString(id));
+ }
+
+ /**
+ * Deletes the {@link AutoModRule} for the provided id.
+ *
+ * @param id
+ * The id of the rule
+ *
+ * @throws IllegalArgumentException
+ * If the provided id is not a valid snowflake
+ * @throws InsufficientPermissionException
+ * If the currently logged in account does not have the {@link net.dv8tion.jda.api.Permission#MANAGE_SERVER MANAGE_SERVER} permission
+ *
+ * @return {@link AuditableRestAction} - Type: {@link Void}
+ */
+ @Nonnull
+ @CheckReturnValue
+ AuditableRestAction
This requires an OAuth2 Access Token with the scope {@code guilds.join}.
diff --git a/src/main/java/net/dv8tion/jda/api/entities/Message.java b/src/main/java/net/dv8tion/jda/api/entities/Message.java
index 29dc086a9a..334c071747 100644
--- a/src/main/java/net/dv8tion/jda/api/entities/Message.java
+++ b/src/main/java/net/dv8tion/jda/api/entities/Message.java
@@ -1132,6 +1132,18 @@ default MessageEditAction editMessageAttachments(@Nonnull AttachedFile... attach
*
*
+ *
+ *
* @param stickers
* The 1-3 stickers to send
*
@@ -1172,6 +1184,18 @@ default MessageCreateAction replyStickers(@Nonnull Collection extends StickerS
*
*
If this message no longer exists
If this message was blocked by an {@link net.dv8tion.jda.api.entities.automod.AutoModRule AutoModRule}
If this message was blocked by the harmful link filter
+ *
+ *
* @param stickers
* The 1-3 stickers to send
*
@@ -1204,7 +1228,19 @@ default MessageCreateAction replyStickers(@Nonnull StickerSnowflake... stickers)
}
/**
- * Shortcut for {@code getChannel().sendMessage(content).setMessageReference(this)}-
+ * Shortcut for {@code getChannel().sendMessage(content).setMessageReference(this)}.
+ *
+ *
If this message no longer exists
If this message was blocked by an {@link net.dv8tion.jda.api.entities.automod.AutoModRule AutoModRule}
If this message was blocked by the harmful link filter
+ *
*
* @param content
* The reply content
@@ -1224,7 +1260,19 @@ default MessageCreateAction reply(@Nonnull CharSequence content)
}
/**
- * Shortcut for {@code getChannel().sendMessage(data).setMessageReference(this)}-
+ * Shortcut for {@code getChannel().sendMessage(data).setMessageReference(this)}.
+ *
+ *
If this message no longer exists
If this message was blocked by an {@link net.dv8tion.jda.api.entities.automod.AutoModRule AutoModRule}
If this message was blocked by the harmful link filter
+ *
*
* @param msg
* The {@link MessageCreateData} to send
@@ -1244,7 +1292,19 @@ default MessageCreateAction reply(@Nonnull MessageCreateData msg)
}
/**
- * Shortcut for {@code getChannel().sendMessageEmbeds(embed, other).setMessageReference(this)}-
+ * Shortcut for {@code getChannel().sendMessageEmbeds(embed, other).setMessageReference(this)}.
+ *
+ *
If this message no longer exists
If this message was blocked by an {@link net.dv8tion.jda.api.entities.automod.AutoModRule AutoModRule}
If this message was blocked by the harmful link filter
+ *
*
* @param embed
* The {@link MessageEmbed} to send
@@ -1271,7 +1331,19 @@ default MessageCreateAction replyEmbeds(@Nonnull MessageEmbed embed, @Nonnull Me
}
/**
- * Shortcut for {@code getChannel().sendMessageEmbeds(embeds).setMessageReference(this)}-
+ * Shortcut for {@code getChannel().sendMessageEmbeds(embeds).setMessageReference(this)}.
+ *
+ *
If this message no longer exists
If this message was blocked by an {@link net.dv8tion.jda.api.entities.automod.AutoModRule AutoModRule}
If this message was blocked by the harmful link filter
+ *
*
* @param embeds
* The {@link MessageEmbed MessageEmbeds} to send
@@ -1293,6 +1365,18 @@ default MessageCreateAction replyEmbeds(@Nonnull Collection extends MessageEmb
/**
* Shortcut for {@code getChannel().sendMessageComponents(component, other).setMessageReference(this)}.
*
+ *
If this message no longer exists
If this message was blocked by an {@link net.dv8tion.jda.api.entities.automod.AutoModRule AutoModRule}
If this message was blocked by the harmful link filter
+ *
+ *
* @param component
* The {@link LayoutComponent} to send
* @param other
@@ -1320,6 +1404,18 @@ default MessageCreateAction replyComponents(@Nonnull LayoutComponent component,
/**
* Shortcut for {@code getChannel().sendMessageComponents(components).setMessageReference(this)}.
*
+ *
If this message no longer exists
If this message was blocked by an {@link net.dv8tion.jda.api.entities.automod.AutoModRule AutoModRule}
If this message was blocked by the harmful link filter
+ *
+ *
* @param components
* The {@link LayoutComponent LayoutComponents} to send
*
@@ -1338,7 +1434,19 @@ default MessageCreateAction replyComponents(@Nonnull Collection extends Layout
}
/**
- * Shortcut for {@code getChannel().sendMessageFormat(format, args).setMessageReference(this)}-
+ * Shortcut for {@code getChannel().sendMessageFormat(format, args).setMessageReference(this)}.
+ *
+ *
If this message no longer exists
If this message was blocked by an {@link net.dv8tion.jda.api.entities.automod.AutoModRule AutoModRule}
If this message was blocked by the harmful link filter
+ *
*
* @param format
* The format string
@@ -1360,7 +1468,19 @@ default MessageCreateAction replyFormat(@Nonnull String format, @Nonnull Object.
}
/**
- * Shortcut for {@code getChannel().sendFiles(files).setMessageReference(this)}-
+ * Shortcut for {@code getChannel().sendFiles(files).setMessageReference(this)}.
+ *
+ *
If this message no longer exists
If this message was blocked by an {@link net.dv8tion.jda.api.entities.automod.AutoModRule AutoModRule}
If this message was blocked by the harmful link filter
+ *
*
* @param files
* The {@link FileUpload FileUploads} to send
@@ -1380,7 +1500,19 @@ default MessageCreateAction replyFiles(@Nonnull FileUpload... files)
}
/**
- * Shortcut for {@code getChannel().sendFiles(files).setMessageReference(this)}-
+ * Shortcut for {@code getChannel().sendFiles(files).setMessageReference(this)}.
+ *
+ *
If this message no longer exists
If this message was blocked by an {@link net.dv8tion.jda.api.entities.automod.AutoModRule AutoModRule}
If this message was blocked by the harmful link filter
+ *
*
* @param files
* The {@link FileUpload FileUploads} to send
diff --git a/src/main/java/net/dv8tion/jda/api/entities/WebhookClient.java b/src/main/java/net/dv8tion/jda/api/entities/WebhookClient.java
index 860f32d9b8..d0fe01f6d7 100644
--- a/src/main/java/net/dv8tion/jda/api/entities/WebhookClient.java
+++ b/src/main/java/net/dv8tion/jda/api/entities/WebhookClient.java
@@ -53,6 +53,12 @@ public interface WebhookClient
If this message no longer exists
If this message was blocked by an {@link net.dv8tion.jda.api.entities.automod.AutoModRule AutoModRule}
If this message was blocked by the harmful link filter
*
*
* @param content
@@ -76,6 +82,12 @@ public interface WebhookClient
The webhook is no longer available, either it was deleted or in case of interactions it expired.
If this message was blocked by an {@link net.dv8tion.jda.api.entities.automod.AutoModRule AutoModRule}
If this message was blocked by the harmful link filter
*
*
* @param message
@@ -101,6 +113,12 @@ public interface WebhookClient
The webhook is no longer available, either it was deleted or in case of interactions it expired.
If this message was blocked by an {@link net.dv8tion.jda.api.entities.automod.AutoModRule AutoModRule}
If this message was blocked by the harmful link filter
*
*
* @param format
@@ -130,6 +148,12 @@ default WebhookMessageCreateAction
The webhook is no longer available, either it was deleted or in case of interactions it expired.
If this message was blocked by an {@link net.dv8tion.jda.api.entities.automod.AutoModRule AutoModRule}
If this message was blocked by the harmful link filter
*
*
*
The webhook is no longer available, either it was deleted or in case of interactions it expired.
If this message was blocked by an {@link net.dv8tion.jda.api.entities.automod.AutoModRule AutoModRule}
If this message was blocked by the harmful link filter
*
*
*
The webhook is no longer available, either it was deleted or in case of interactions it expired.
If this message was blocked by an {@link net.dv8tion.jda.api.entities.automod.AutoModRule AutoModRule}
If this message was blocked by the harmful link filter
*
*
* @param components
@@ -245,6 +281,12 @@ default WebhookMessageCreateAction
The webhook is no longer available, either it was deleted or in case of interactions it expired.
If this message was blocked by an {@link net.dv8tion.jda.api.entities.automod.AutoModRule AutoModRule}
If this message was blocked by the harmful link filter
*
*
* @param component
@@ -297,6 +339,21 @@ default WebhookMessageCreateAction
The webhook is no longer available, either it was deleted or in case of interactions it expired.
If this message was blocked by an {@link net.dv8tion.jda.api.entities.automod.AutoModRule AutoModRule}
If this message was blocked by the harmful link filter
+ *
+ *
* @param files
* The {@link FileUpload FileUploads} to attach to the message
*
@@ -339,6 +396,21 @@ default WebhookMessageCreateAction
The webhook is no longer available, either it was deleted or in case of interactions it expired.
If this message was blocked by an {@link net.dv8tion.jda.api.entities.automod.AutoModRule AutoModRule}
If this message was blocked by the harmful link filter
If the total sum of uploaded bytes exceeds the guild's {@link Guild#getMaxFileSize() upload limit}
+ *
+ *
* @param files
* The {@link FileUpload FileUploads} to attach to the message
*
diff --git a/src/main/java/net/dv8tion/jda/api/entities/automod/AutoModEventType.java b/src/main/java/net/dv8tion/jda/api/entities/automod/AutoModEventType.java
new file mode 100644
index 0000000000..4b7f6967c8
--- /dev/null
+++ b/src/main/java/net/dv8tion/jda/api/entities/automod/AutoModEventType.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2015 Austin Keener, Michael Ritter, Florian Spieß, and the JDA contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dv8tion.jda.api.entities.automod;
+
+import net.dv8tion.jda.annotations.Incubating;
+import net.dv8tion.jda.api.entities.automod.build.AutoModRuleData;
+import net.dv8tion.jda.api.entities.automod.build.TriggerConfig;
+
+import javax.annotation.Nonnull;
+
+/**
+ * The type of event an {@link AutoModRule} is triggered by.
+ *
+ * @see AutoModRule#getEventType()
+ * @see AutoModRuleData#onMessage(String, TriggerConfig)
+ */
+public enum AutoModEventType
+{
+ /**
+ * The rule is triggered by a message being sent in a guild channel.
+ */
+ MESSAGE_SEND(1),
+
+ /**
+ * The rule is triggered when a member updates their profile.
+ *
+ * @incubating This has not been officially released yet
+ */
+ @Incubating
+ MEMBER_UPDATE(2),
+
+ /**
+ * Placeholder for unknown types which haven't been added yet.
+ */
+ UNKNOWN(-1);
+
+ private final int key;
+
+ AutoModEventType(int key)
+ {
+ this.key = key;
+ }
+
+ /**
+ * The raw value used by Discord to represent this type.
+ *
+ * @return The raw value
+ */
+ public int getKey()
+ {
+ return key;
+ }
+
+ /**
+ * The {@link AutoModEventType} represented by the provided key.
+ *
+ * @param key
+ * The raw key
+ *
+ * @return The {@link AutoModEventType} or {@link #UNKNOWN}
+ */
+ @Nonnull
+ public static AutoModEventType fromKey(int key)
+ {
+ for (AutoModEventType type : values())
+ {
+ if (type.key == key)
+ return type;
+ }
+ return UNKNOWN;
+ }
+}
diff --git a/src/main/java/net/dv8tion/jda/api/entities/automod/AutoModExecution.java b/src/main/java/net/dv8tion/jda/api/entities/automod/AutoModExecution.java
new file mode 100644
index 0000000000..50a4ac1807
--- /dev/null
+++ b/src/main/java/net/dv8tion/jda/api/entities/automod/AutoModExecution.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright 2015 Austin Keener, Michael Ritter, Florian Spieß, and the JDA contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dv8tion.jda.api.entities.automod;
+
+import net.dv8tion.jda.api.entities.Guild;
+import net.dv8tion.jda.api.entities.channel.unions.GuildMessageChannelUnion;
+import net.dv8tion.jda.api.requests.GatewayIntent;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+/**
+ * Event triggered by an {@link AutoModRule} activation.
+ */
+public interface AutoModExecution
+{
+ /**
+ * The {@link Guild} that this execution occurred in.
+ *
+ * @return The {@link Guild}
+ */
+ @Nonnull
+ Guild getGuild();
+
+ /**
+ * The {@link GuildMessageChannelUnion} that this execution occurred in.
+ *
+ *
The webhook is no longer available, either it was deleted or in case of interactions it expired.
If this message was blocked by an {@link net.dv8tion.jda.api.entities.automod.AutoModRule AutoModRule}
If this message was blocked by the harmful link filter
If the total sum of uploaded bytes exceeds the guild's {@link Guild#getMaxFileSize() upload limit}
You modify multiple fields in one request by chaining setters before calling {@link net.dv8tion.jda.api.requests.RestAction#queue() RestAction.queue()}.
+ *
+ * @throws InsufficientPermissionException
+ * If the currently logged in account does not have the {@link net.dv8tion.jda.api.Permission#MANAGE_SERVER MANAGE_SERVER} permission.
+ *
+ * @return The manager instance
+ */
+ @Nonnull
+ default AutoModRuleManager getManager()
+ {
+ return getGuild().modifyAutoModRuleById(getId());
+ }
+
+ /**
+ * Deletes this rule.
+ *
+ * @throws InsufficientPermissionException
+ * If the currently logged in account does not have the {@link net.dv8tion.jda.api.Permission#MANAGE_SERVER MANAGE_SERVER} permission.
+ *
+ * @return {@link net.dv8tion.jda.api.requests.RestAction RestAction} - Type: {@link Void}
+ */
+ @Nonnull
+ default AuditableRestAction
+ *
+ *
+ * @return The current config for chaining convenience
+ */
+ @Nonnull
+ public B addAllowList(@Nonnull String... keywords)
+ {
+ Checks.noneNull(keywords, "Keywords");
+ Checks.check(this.allowList.size() + keywords.length <= maxAllowListAmount(), "Cannot add more than %d keywords!", maxAllowListAmount());
+ Arrays.stream(keywords).forEach(AbstractKeywordTriggerConfig::checkKeyword);
+ Collections.addAll(allowList, keywords);
+ return (B) this;
+ }
+
+ /**
+ * Add keywords to the allow list.
+ *
+ *
+ *
+ * @return The current config for chaining convenience
+ */
+ @Nonnull
+ public B addAllowList(@Nonnull Collection
+ *
+ *
+ * @return The current config for chaining convenience
+ */
+ @Nonnull
+ public B setAllowList(@Nonnull Collection
+ *
+ * {@code
+ * TriggerConfig config = TriggerConfig.keywordFilter("discord.gg/*").addAllowList("gateway.discord.gg/*");
+ * AutoModRuleData data = AutoModRuleData.onMessage("Invite Block", config);
+ * data.addExemptRoles(guild.getRolesByName("Moderator", true));
+ * data.putResponse(AutoModResponse.blockMessage());
+ * }
+ *
+ *
+ *
+ *
+ * @see net.dv8tion.jda.api.entities.Guild#createAutoModRule(AutoModRuleData)
+ */
+public class AutoModRuleData implements SerializableData
+{
+ protected final AutoModEventType eventType;
+ protected String name;
+ protected boolean enabled = true;
+ protected TriggerConfig triggerMetadata;
+
+ protected final EnumMap
This is accumulative and adds ontop of the currently configured responses.
+ *
+ *
This is accumulative and adds ontop of the currently configured responses.
+ *
+ *
This replaces the currently configured responses, removing all previously configured responses.
+ *
+ *
Certain {@link AutoModResponse.Type Types} require additional permissions, such as {@link AutoModResponse.Type#TIMEOUT}.
+ * All rules require {@link Permission#MANAGE_SERVER} to be created.
+ *
+ * @return The required permissions to create this rule
+ */
+ @Nonnull
+ public EnumSet
Keywords are matched case-insensitively, and may also contain whitespace.
+ *
+ *
{@code "foo*"} can match {@code "foo"}, {@code "foobar"}, {@code "foo-bar"}, etc.
+ *
{@code "*foo*"} can match {@code "foo"}, {@code "foobar"}, {@code "barfoo"}, etc.
+ *
{@code "*foo"} can match {@code "foo"}, {@code "barfoo"}, {@code "bar-foo"}, etc.
+ *
+ *
+ *
+ *
+ * @return The current config for chaining convenience
+ */
+ @Nonnull
+ public CustomKeywordTriggerConfig addKeywords(@Nonnull String... keywords)
+ {
+ Checks.noneNull(keywords, "Keywords");
+ Checks.check(this.keywords.size() + keywords.length <= AutoModRule.MAX_KEYWORD_AMOUNT, "Cannot add more than %d keywords!", AutoModRule.MAX_KEYWORD_AMOUNT);
+ for (String keyword : keywords)
+ checkKeyword(keyword);
+
+ Collections.addAll(this.keywords, keywords);
+ return this;
+ }
+
+ /**
+ * Add more keywords match against.
+ *
Keywords are matched case-insensitively, and may also contain whitespace.
+ *
+ *
{@code "foo*"} can match {@code "foo"}, {@code "foobar"}, {@code "foo-bar"}, etc.
+ *
{@code "*foo*"} can match {@code "foo"}, {@code "foobar"}, {@code "barfoo"}, etc.
+ *
{@code "*foo"} can match {@code "foo"}, {@code "barfoo"}, {@code "bar-foo"}, etc.
+ *
+ *
+ *
+ *
+ * @return The current config for chaining convenience
+ */
+ @Nonnull
+ public CustomKeywordTriggerConfig addKeywords(@Nonnull Collection
Keywords are matched case-insensitively, and may also contain whitespace.
+ *
+ *
{@code "foo*"} can match {@code "foo"}, {@code "foobar"}, {@code "foo-bar"}, etc.
+ *
{@code "*foo*"} can match {@code "foo"}, {@code "foobar"}, {@code "barfoo"}, etc.
+ *
{@code "*foo"} can match {@code "foo"}, {@code "barfoo"}, {@code "bar-foo"}, etc.
+ *
+ *
+ *
+ *
+ * @return The current config for chaining convenience
+ */
+ @Nonnull
+ public CustomKeywordTriggerConfig setKeywords(@Nonnull Collection
Keyword patterns are matched case-insensitively, and may also contain whitespace.
+ *
+ *
+ *
+ *
+ * @return The current config for chaining convenience
+ */
+ @Nonnull
+ public CustomKeywordTriggerConfig addPatterns(@Nonnull String... patterns)
+ {
+ Checks.noneNull(patterns, "Patterns");
+ Checks.check(this.patterns.size() + patterns.length <= AutoModRule.MAX_PATTERN_AMOUNT, "Cannot add more than %d patterns!", AutoModRule.MAX_PATTERN_AMOUNT);
+ for (String pattern : patterns)
+ checkPattern(pattern);
+
+ Collections.addAll(this.patterns, patterns);
+ return this;
+ }
+
+ /**
+ * Add keywords regex patterns to match against.
+ *
Keyword patterns are matched case-insensitively, and may also contain whitespace.
+ *
+ *
+ *
+ *
+ * @return The current config for chaining convenience
+ */
+ @Nonnull
+ public CustomKeywordTriggerConfig addPatterns(@Nonnull Collection
Keyword patterns are matched case-insensitively, and may also contain whitespace.
+ *
+ *
+ *
+ *
+ * @return The current config for chaining convenience
+ */
+ @Nonnull
+ public CustomKeywordTriggerConfig setPatterns(@Nonnull Collection
+ *
+ *
+ *
+ * {@code
+ * AutoModRuleData rule = AutoModRule.onMessage("Invite Links",
+ * TriggerConfig.keywordFilter("discord.gg/*") // trigger on all invite links
+ * .setAllowList("discord.gg/discord-api") // except certain whitelisted ones
+ * );
+ * }
+ *
+ * @see AutoModRule
+ */
+public interface TriggerConfig extends SerializableData
+{
+ /**
+ * The type of trigger for this config.
+ *
+ * @return {@link AutoModTriggerType}
+ */
+ @Nonnull
+ AutoModTriggerType getType();
+
+ /**
+ * Trigger on mention thresholds in messages.
+ *
+ * @param mentionLimit
+ * The maximum number of unique mentions allowed in a message (1-{@value AutoModRule#MAX_MENTION_LIMIT})
+ *
+ * @throws IllegalArgumentException
+ * If the provided mention limit is not between 1 and {@value AutoModRule#MAX_MENTION_LIMIT}
+ *
+ * @return {@link MentionSpamTriggerConfig}
+ */
+ @Nonnull
+ static MentionSpamTriggerConfig mentionSpam(int mentionLimit)
+ {
+ return new MentionSpamTriggerConfig(mentionLimit);
+ }
+
+ /**
+ * Trigger on spam content in messages (classified by Discord magic).
+ *
+ * @return {@link AntiSpamTriggerConfig}
+ */
+ @Nonnull
+ static AntiSpamTriggerConfig antiSpam()
+ {
+ return new AntiSpamTriggerConfig();
+ }
+
+ /**
+ * Trigger on messages containing certain keywords or regex patterns.
+ *
Keywords are matched case-insensitively, and may also contain whitespace.
+ *
+ *
{@code "foo*"} can match {@code "foo"}, {@code "foobar"}, {@code "foo-bar"}, etc.
+ *
{@code "*foo*"} can match {@code "foo"}, {@code "foobar"}, {@code "barfoo"}, etc.
+ *
{@code "*foo"} can match {@code "foo"}, {@code "barfoo"}, {@code "bar-foo"}, etc.
+ *
+ *
+ *
+ *
+ * @return {@link CustomKeywordTriggerConfig}
+ */
+ @Nonnull
+ static CustomKeywordTriggerConfig keywordFilter(@Nonnull Collection
Keywords are matched case-insensitively, and may also contain whitespace.
+ *
+ *
{@code "foo*"} can match {@code "foo"}, {@code "foobar"}, {@code "foo-bar"}, etc.
+ *
{@code "*foo*"} can match {@code "foo"}, {@code "foobar"}, {@code "barfoo"}, etc.
+ *
{@code "*foo"} can match {@code "foo"}, {@code "barfoo"}, {@code "bar-foo"}, etc.
+ *
+ *
+ *
+ *
+ * @return {@link CustomKeywordTriggerConfig}
+ */
+ @Nonnull
+ static CustomKeywordTriggerConfig keywordFilter(@Nonnull String... keywords)
+ {
+ return new CustomKeywordTriggerConfig().addKeywords(keywords);
+ }
+
+ /**
+ * Trigger on messages containing certain keywords regex patterns.
+ *
Keyword patterns are matched case-insensitively, and may also contain whitespace.
+ *
+ *
+ *
+ *
+ * @return {@link CustomKeywordTriggerConfig}
+ */
+ @Nonnull
+ static CustomKeywordTriggerConfig patternFilter(@Nonnull Collection
Keyword patterns are matched case-insensitively, and may also contain whitespace.
+ *
+ *
+ *
+ *
+ * @return {@link CustomKeywordTriggerConfig}
+ */
+ @Nonnull
+ static CustomKeywordTriggerConfig patternFilter(@Nonnull String... patterns)
+ {
+ return new CustomKeywordTriggerConfig().addPatterns(patterns);
+ }
+
+ /**
+ * Trigger on keywords from predefined lists.
+ *
+ * @param presets
+ * The presets to enable
+ *
+ * @throws IllegalArgumentException
+ * If null or {@link KeywordPreset#UNKNOWN} is provided
+ *
+ * @return {@link PresetKeywordTriggerConfig}
+ */
+ @Nonnull
+ static PresetKeywordTriggerConfig presetKeywordFilter(@Nonnull Collection
*
*
* @param name
diff --git a/src/main/java/net/dv8tion/jda/api/entities/channel/middleman/MessageChannel.java b/src/main/java/net/dv8tion/jda/api/entities/channel/middleman/MessageChannel.java
index 92caba6fed..c325f09390 100644
--- a/src/main/java/net/dv8tion/jda/api/entities/channel/middleman/MessageChannel.java
+++ b/src/main/java/net/dv8tion/jda/api/entities/channel/middleman/MessageChannel.java
@@ -300,6 +300,12 @@ default List
If the forum channel was deleted
If this message was blocked by an {@link net.dv8tion.jda.api.entities.automod.AutoModRule AutoModRule}
If this message was blocked by the harmful link filter
If the total sum of uploaded bytes exceeds the guild's {@link Guild#getMaxFileSize() upload limit}
If the forum post name was blocked by an {@link net.dv8tion.jda.api.entities.automod.AutoModRule AutoModRule}
If this is a {@link net.dv8tion.jda.api.entities.channel.concrete.PrivateChannel PrivateChannel} and the currently logged in account
* does not share any Guilds with the recipient User
If this message was blocked by an {@link net.dv8tion.jda.api.entities.automod.AutoModRule AutoModRule}
If this message was blocked by the harmful link filter
If this is a {@link net.dv8tion.jda.api.entities.channel.concrete.PrivateChannel PrivateChannel} and the currently logged in account
* does not share any Guilds with the recipient User
If this message was blocked by an {@link net.dv8tion.jda.api.entities.automod.AutoModRule AutoModRule}
If this message was blocked by the harmful link filter
If this is a {@link net.dv8tion.jda.api.entities.channel.concrete.PrivateChannel PrivateChannel} and the currently logged in account
* does not share any Guilds with the recipient User
If this message was blocked by an {@link net.dv8tion.jda.api.entities.automod.AutoModRule AutoModRule}
If this message was blocked by the harmful link filter
If this is a {@link net.dv8tion.jda.api.entities.channel.concrete.PrivateChannel PrivateChannel} and the currently logged in account
* does not share any Guilds with the recipient User
If this message was blocked by an {@link net.dv8tion.jda.api.entities.automod.AutoModRule AutoModRule}
If this message was blocked by the harmful link filter
If this is a {@link PrivateChannel PrivateChannel} and the currently logged in account
* does not share any Guilds with the recipient User
If this message was blocked by an {@link net.dv8tion.jda.api.entities.automod.AutoModRule AutoModRule}
If this message was blocked by the harmful link filter
If this is a {@link PrivateChannel} and the currently logged in account
* does not share any Guilds with the recipient User
If this message was blocked by an {@link net.dv8tion.jda.api.entities.automod.AutoModRule AutoModRule}
If this message was blocked by the harmful link filter
If this is a {@link PrivateChannel} and the currently logged in account
* does not share any Guilds with the recipient User
If this message was blocked by an {@link net.dv8tion.jda.api.entities.automod.AutoModRule AutoModRule}
If this message was blocked by the harmful link filter
If this is a {@link net.dv8tion.jda.api.entities.channel.concrete.PrivateChannel PrivateChannel} and the currently logged in account
* does not share any Guilds with the recipient User
If this message was blocked by an {@link net.dv8tion.jda.api.entities.automod.AutoModRule AutoModRule}
If this message was blocked by the harmful link filter
If the total sum of uploaded bytes exceeds the guild's {@link Guild#getMaxFileSize() upload limit}
If this is a {@link PrivateChannel PrivateChannel} and the currently logged in account
* does not share any Guilds with the recipient User
If this message was blocked by an {@link net.dv8tion.jda.api.entities.automod.AutoModRule AutoModRule}
If this message was blocked by the harmful link filter
If the total sum of uploaded bytes exceeds the guild's {@link Guild#getMaxFileSize() upload limit}
+ * This event requires the {@link GatewayIntent#AUTO_MODERATION_EXECUTION AUTO_MODERATION_EXECUTION} intent to be enabled.
+ * Additionally, access to {@link #getContent()} and {@link #getMatchedContent()} requires the {@link GatewayIntent#MESSAGE_CONTENT MESSAGE_CONTENT} intent to be enabled.
+ */
+public class AutoModExecutionEvent extends Event implements AutoModExecution
+{
+ private final AutoModExecution execution;
+
+ public AutoModExecutionEvent(@Nonnull JDA api, long responseNumber, @Nonnull AutoModExecution execution)
+ {
+ super(api, responseNumber);
+ this.execution = execution;
+ }
+
+ @Nonnull
+ @Override
+ public Guild getGuild()
+ {
+ return execution.getGuild();
+ }
+
+ @Nullable
+ @Override
+ public GuildMessageChannelUnion getChannel()
+ {
+ return execution.getChannel();
+ }
+
+ @Nonnull
+ @Override
+ public AutoModResponse getResponse()
+ {
+ return execution.getResponse();
+ }
+
+ @Nonnull
+ @Override
+ public AutoModTriggerType getTriggerType()
+ {
+ return execution.getTriggerType();
+ }
+
+ @Override
+ public long getUserIdLong()
+ {
+ return execution.getUserIdLong();
+ }
+
+ @Override
+ public long getRuleIdLong()
+ {
+ return execution.getRuleIdLong();
+ }
+
+ @Override
+ public long getMessageIdLong()
+ {
+ return execution.getMessageIdLong();
+ }
+
+ @Override
+ public long getAlertMessageIdLong()
+ {
+ return execution.getAlertMessageIdLong();
+ }
+
+ @Nonnull
+ @Override
+ public String getContent()
+ {
+ return execution.getContent();
+ }
+
+ @Nullable
+ @Override
+ public String getMatchedContent()
+ {
+ return execution.getMatchedContent();
+ }
+
+ @Nullable
+ @Override
+ public String getMatchedKeyword()
+ {
+ return execution.getMatchedKeyword();
+ }
+}
diff --git a/src/main/java/net/dv8tion/jda/api/events/automod/AutoModRuleCreateEvent.java b/src/main/java/net/dv8tion/jda/api/events/automod/AutoModRuleCreateEvent.java
new file mode 100644
index 0000000000..40e19d0372
--- /dev/null
+++ b/src/main/java/net/dv8tion/jda/api/events/automod/AutoModRuleCreateEvent.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2015 Austin Keener, Michael Ritter, Florian Spieß, and the JDA contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dv8tion.jda.api.events.automod;
+
+import net.dv8tion.jda.api.JDA;
+import net.dv8tion.jda.api.entities.automod.AutoModRule;
+
+import javax.annotation.Nonnull;
+
+/**
+ * Indicates that a {@link AutoModRule} was created.
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
When the acknowledgement is sent after the interaction expired, you will receive {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_INTERACTION ErrorResponse.UNKNOWN_INTERACTION}.
*
+ *
+ *
* @param message
* The {@link MessageCreateData} to send
*
@@ -143,6 +156,18 @@ default ReplyCallbackAction reply(@Nonnull MessageCreateData message)
*
If the interaction has already been acknowledged or timed out
If this message was blocked by an {@link net.dv8tion.jda.api.entities.automod.AutoModRule AutoModRule}
If this message was blocked by the harmful link filter
When the acknowledgement is sent after the interaction expired, you will receive {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_INTERACTION ErrorResponse.UNKNOWN_INTERACTION}.
*
+ *
+ *
* @param content
* The message content to send
*
@@ -169,6 +194,18 @@ default ReplyCallbackAction reply(@Nonnull String content)
*
If the interaction has already been acknowledged or timed out
If this message was blocked by an {@link net.dv8tion.jda.api.entities.automod.AutoModRule AutoModRule}
If this message was blocked by the harmful link filter
When the acknowledgement is sent after the interaction expired, you will receive {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_INTERACTION ErrorResponse.UNKNOWN_INTERACTION}.
*
+ *
+ *
* @param embeds
* The {@link MessageEmbed MessageEmbeds} to send
*
@@ -194,6 +231,18 @@ default ReplyCallbackAction replyEmbeds(@Nonnull Collection extends MessageEmb
*
If the interaction has already been acknowledged or timed out
If this message was blocked by an {@link net.dv8tion.jda.api.entities.automod.AutoModRule AutoModRule}
If this message was blocked by the harmful link filter
When the acknowledgement is sent after the interaction expired, you will receive {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_INTERACTION ErrorResponse.UNKNOWN_INTERACTION}.
*
+ *
+ *
* @param embed
* The message embed to send
* @param embeds
@@ -223,6 +272,18 @@ default ReplyCallbackAction replyEmbeds(@Nonnull MessageEmbed embed, @Nonnull Me
*
If the interaction has already been acknowledged or timed out
If this message was blocked by an {@link net.dv8tion.jda.api.entities.automod.AutoModRule AutoModRule}
If this message was blocked by the harmful link filter
When the acknowledgement is sent after the interaction expired, you will receive {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_INTERACTION ErrorResponse.UNKNOWN_INTERACTION}.
*
+ *
+ *
* @param components
* The {@link LayoutComponent LayoutComponents} to send, such as {@link ActionRow}
*
@@ -248,6 +309,18 @@ default ReplyCallbackAction replyComponents(@Nonnull Collection extends Layout
*
If the interaction has already been acknowledged or timed out
If this message was blocked by an {@link net.dv8tion.jda.api.entities.automod.AutoModRule AutoModRule}
If this message was blocked by the harmful link filter
When the acknowledgement is sent after the interaction expired, you will receive {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_INTERACTION ErrorResponse.UNKNOWN_INTERACTION}.
*
+ *
+ *
* @param component
* The {@link LayoutComponent} to send
* @param other
@@ -280,6 +353,18 @@ default ReplyCallbackAction replyComponents(@Nonnull LayoutComponent component,
*
If the interaction has already been acknowledged or timed out
If this message was blocked by an {@link net.dv8tion.jda.api.entities.automod.AutoModRule AutoModRule}
If this message was blocked by the harmful link filter
When the acknowledgement is sent after the interaction expired, you will receive {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_INTERACTION ErrorResponse.UNKNOWN_INTERACTION}.
*
+ *
+ *
* @param format
* Format string for the message content
* @param args
@@ -313,6 +398,21 @@ default ReplyCallbackAction replyFormat(@Nonnull String format, @Nonnull Object.
* For instance, if an exception occurs after using {@link FileUpload#fromData(File)}, before calling {@link RestAction#queue()}.
* You can safely use a try-with-resources to handle this, since {@link FileUpload#close()} becomes ineffective once the request is handed off.
*
+ *
If the interaction has already been acknowledged or timed out
If this message was blocked by an {@link net.dv8tion.jda.api.entities.automod.AutoModRule AutoModRule}
If this message was blocked by the harmful link filter
+ *
+ *
* @param files
* The {@link FileUpload FileUploads} to attach to the message
*
@@ -346,6 +446,21 @@ default ReplyCallbackAction replyFiles(@Nonnull Collection extends FileUpload>
* For instance, if an exception occurs after using {@link FileUpload#fromData(File)}, before calling {@link RestAction#queue()}.
* You can safely use a try-with-resources to handle this, since {@link FileUpload#close()} becomes ineffective once the request is handed off.
*
+ *
If the interaction has already been acknowledged or timed out
If this message was blocked by an {@link net.dv8tion.jda.api.entities.automod.AutoModRule AutoModRule}
If this message was blocked by the harmful link filter
If the total sum of uploaded bytes exceeds the guild's {@link Guild#getMaxFileSize() upload limit}
+ *
+ *
* @param files
* The {@link FileUpload FileUploads} to attach to the message
*
diff --git a/src/main/java/net/dv8tion/jda/api/managers/AutoModRuleManager.java b/src/main/java/net/dv8tion/jda/api/managers/AutoModRuleManager.java
new file mode 100644
index 0000000000..72a6b36e3b
--- /dev/null
+++ b/src/main/java/net/dv8tion/jda/api/managers/AutoModRuleManager.java
@@ -0,0 +1,284 @@
+/*
+ * Copyright 2015 Austin Keener, Michael Ritter, Florian Spieß, and the JDA contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.dv8tion.jda.api.managers;
+
+import net.dv8tion.jda.api.entities.Guild;
+import net.dv8tion.jda.api.entities.Role;
+import net.dv8tion.jda.api.entities.automod.AutoModResponse;
+import net.dv8tion.jda.api.entities.automod.AutoModRule;
+import net.dv8tion.jda.api.entities.automod.build.TriggerConfig;
+import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel;
+import net.dv8tion.jda.internal.utils.Checks;
+
+import javax.annotation.CheckReturnValue;
+import javax.annotation.Nonnull;
+import java.util.Arrays;
+import java.util.Collection;
+
+/**
+ * Manager providing functionality to update one or more fields for an {@link AutoModRule}.
+ *
+ *
If the interaction has already been acknowledged or timed out
If this message was blocked by an {@link net.dv8tion.jda.api.entities.automod.AutoModRule AutoModRule}
If this message was blocked by the harmful link filter
If the total sum of uploaded bytes exceeds the guild's {@link Guild#getMaxFileSize() upload limit}{@code
+ * manager.setName("Discord Invites")
+ * .setEnables(false)
+ * .queue();
+ * manager.reset(AutoModRuleManager.NAME | AutoModRuleManager.ENABLED)
+ * .setName("Invites")
+ * .setEnabled(true)
+ * .queue();
+ * }
+ *
+ * @see Guild#modifyAutoModRuleById(long)
+ * @see Guild#modifyAutoModRuleById(String)
+ * @see AutoModRule#getManager()
+ */
+public interface AutoModRuleManager extends Manager
Example: {@code manager.reset(AutoModRuleManager.NAME | AutoModRuleManager.RESPONSE);}
+ *
+ *
+ *
+ *
+ * @param fields
+ * Integer value containing the flags to reset.
+ *
+ * @return AutoModRuleManager for chaining convenience
+ */
+ @Nonnull
+ @Override
+ AutoModRuleManager reset(long fields);
+
+ /**
+ * Resets the fields specified by the provided bit-flag pattern.
+ * You can specify a combination by using a bitwise OR concat of the flag constants.
+ *
Example: {@code manager.reset(AutoModRuleManager.NAME, AutoModRuleManager.RESPONSE);}
+ *
+ *
+ *
+ *
+ * @param fields
+ * Integer value containing the flags to reset.
+ *
+ * @return AutoModRuleManager for chaining convenience
+ */
+ @Nonnull
+ @Override
+ AutoModRuleManager reset(long... fields);
+
+ /**
+ * Sets the name of the selected {@link AutoModRule}.
+ *
+ *
+ *
+ *
+ * @return AutoModRuleManager for chaining convenience
+ */
+ @Nonnull
+ @CheckReturnValue
+ AutoModRuleManager setResponses(@Nonnull Collection extends AutoModResponse> responses);
+
+ /**
+ * Sets what the rule should do upon triggering.
+ *
+ *
+ *
+ *
+ * @return AutoModRuleManager for chaining convenience
+ */
+ @Nonnull
+ @CheckReturnValue
+ default AutoModRuleManager setResponses(@Nonnull AutoModResponse... responses)
+ {
+ Checks.noneNull(responses, "Responses");
+ return setResponses(Arrays.asList(responses));
+ }
+
+ /**
+ * Set which roles can bypass this rule.
+ *
+ * > retrieveAutoModRules()
+ {
+ checkPermission(Permission.MANAGE_SERVER);
+ Route.CompiledRoute route = Route.AutoModeration.LIST_RULES.compile(getId());
+ return new RestActionImpl<>(api, route, (response, request) ->
+ {
+ DataArray array = response.getArray();
+ List