diff --git a/src/examples/java/SlashBotExample.java b/src/examples/java/SlashBotExample.java index fec4195a4c..629174e928 100644 --- a/src/examples/java/SlashBotExample.java +++ b/src/examples/java/SlashBotExample.java @@ -33,6 +33,7 @@ import net.dv8tion.jda.api.requests.restaction.CommandListUpdateAction; import java.util.EnumSet; +import java.util.concurrent.TimeUnit; import static net.dv8tion.jda.api.interactions.commands.OptionType.*; @@ -170,10 +171,10 @@ public void ban(SlashCommandInteractionEvent event, User user, Member member) OptionMapping::getAsString); // used if getOption("reason") is not null (provided) // Ban the user and send a success response - event.getGuild().ban(user, delDays, reason) - .reason(reason) // audit-log reason - .flatMap(v -> hook.sendMessage("Banned user " + user.getAsTag())) - .queue(); + event.getGuild().ban(user, delDays, TimeUnit.DAYS) + .reason(reason) // audit-log ban reason (sets X-AuditLog-Reason header) + .flatMap(v -> hook.sendMessage("Banned user " + user.getAsTag())) // chain a followup message after the ban is executed + .queue(); // execute the entire call chain } public void say(SlashCommandInteractionEvent event, String content) 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 d94e7fc73c..46b11af8f7 100644 --- a/src/main/java/net/dv8tion/jda/api/entities/Guild.java +++ b/src/main/java/net/dv8tion/jda/api/entities/Guild.java @@ -15,6 +15,9 @@ */ package net.dv8tion.jda.api.entities; +import net.dv8tion.jda.annotations.DeprecatedSince; +import net.dv8tion.jda.annotations.ForRemoval; +import net.dv8tion.jda.annotations.ReplaceWith; import net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.Permission; import net.dv8tion.jda.api.Region; @@ -57,6 +60,9 @@ import net.dv8tion.jda.internal.utils.Helpers; import net.dv8tion.jda.internal.utils.concurrent.task.GatewayTask; +import javax.annotation.CheckReturnValue; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; import java.time.Duration; import java.time.temporal.TemporalAccessor; import java.util.*; @@ -65,10 +71,6 @@ import java.util.function.Consumer; import java.util.function.Predicate; -import javax.annotation.CheckReturnValue; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - /** * Represents a Discord {@link net.dv8tion.jda.api.entities.Guild Guild}. * This should contain all information provided from Discord about a Guild. @@ -538,7 +540,6 @@ default ImageProxy getIcon() *

* List of Features * - * * @return Never-null, unmodifiable Set containing all of the Guild's features. */ @Nonnull @@ -1895,7 +1896,7 @@ default RestAction retrieveEmoji(@Nonnull CustomEmoji emoji) /** * Retrieves an immutable list of the currently banned {@link net.dv8tion.jda.api.entities.User Users}. - *
If you wish to ban or unban a user, use either {@link #ban(UserSnowflake, int)} or + *
If you wish to ban or unban a user, use either {@link #ban(UserSnowflake, int, TimeUnit)} or * {@link #unban(UserSnowflake)}. * *

Possible {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} caused by @@ -1917,7 +1918,7 @@ default RestAction retrieveEmoji(@Nonnull CustomEmoji emoji) /** * Retrieves a {@link net.dv8tion.jda.api.entities.Guild.Ban Ban} of the provided {@link UserSnowflake}. - *
If you wish to ban or unban a user, use either {@link #ban(UserSnowflake, int)} or {@link #unban(UserSnowflake)}. + *
If you wish to ban or unban a user, use either {@link #ban(UserSnowflake, int, TimeUnit)} or {@link #unban(UserSnowflake)}. * *

Possible {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} caused by * the returned {@link RestAction RestAction} include the following: @@ -3182,10 +3183,20 @@ default AuditableRestAction prune(int days, @Nonnull Role... roles) * * * @return {@link net.dv8tion.jda.api.requests.restaction.AuditableRestAction AuditableRestAction} + * + * @deprecated + * Use {@link #kick(UserSnowflake)} and {@link AuditableRestAction#reason(String)} instead. */ @Nonnull @CheckReturnValue - AuditableRestAction kick(@Nonnull UserSnowflake user, @Nullable String reason); + @Deprecated + @ForRemoval + @ReplaceWith("kick(user).reason(reason)") + @DeprecatedSince("5.0.0") + default AuditableRestAction kick(@Nonnull UserSnowflake user, @Nullable String reason) + { + return kick(user).reason(reason); + } /** * Kicks a {@link net.dv8tion.jda.api.entities.Member Member} from the {@link net.dv8tion.jda.api.entities.Guild Guild}. @@ -3219,14 +3230,12 @@ default AuditableRestAction prune(int days, @Nonnull Role... roles) */ @Nonnull @CheckReturnValue - default AuditableRestAction kick(@Nonnull UserSnowflake user) - { - return kick(user, null); - } + AuditableRestAction kick(@Nonnull UserSnowflake user); /** - * Bans the user specified by the provided {@link UserSnowflake} and deletes messages sent by the user based on the amount of delDays. - *
If you wish to ban a user without deleting any messages, provide delDays with a value of 0. + * Bans the user specified by the provided {@link UserSnowflake} and deletes messages sent by the user based on the {@code deletionTimeframe}. + *
If you wish to ban a user without deleting any messages, provide {@code deletionTimeframe} with a value of 0. + * To set a ban reason, use {@link AuditableRestAction#reason(String)}. * *

You can unban a user with {@link net.dv8tion.jda.api.entities.Guild#unban(UserSnowflake) Guild.unban(UserReference)}. * @@ -3234,6 +3243,20 @@ default AuditableRestAction kick(@Nonnull UserSnowflake user) * {@link net.dv8tion.jda.api.entities.Member Member} object (if the User was in the Guild) * until Discord sends the {@link net.dv8tion.jda.api.events.guild.member.GuildMemberRemoveEvent GuildMemberRemoveEvent}. * + *

Examples
+ * Banning a user without deleting any messages: + *

{@code
+     * guild.ban(user, 0, TimeUnit.SECONDS)
+     *      .reason("Banned for rude behavior")
+     *      .queue();
+     * }
+ * Banning a user and deleting messages from the past hour: + *
{@code
+     * guild.ban(user, 1, TimeUnit.HOURS)
+     *      .reason("Banned for spamming")
+     *      .queue();
+     * }
+ * *

Possible {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} caused by * the returned {@link RestAction RestAction} include the following: *

* * @param user diff --git a/src/main/java/net/dv8tion/jda/api/entities/Member.java b/src/main/java/net/dv8tion/jda/api/entities/Member.java index 27fe4df977..838e943d14 100644 --- a/src/main/java/net/dv8tion/jda/api/entities/Member.java +++ b/src/main/java/net/dv8tion/jda/api/entities/Member.java @@ -16,7 +16,10 @@ package net.dv8tion.jda.api.entities; +import net.dv8tion.jda.annotations.DeprecatedSince; +import net.dv8tion.jda.annotations.ForRemoval; import net.dv8tion.jda.annotations.Incubating; +import net.dv8tion.jda.annotations.ReplaceWith; import net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.OnlineStatus; import net.dv8tion.jda.api.entities.channel.unions.DefaultGuildChannelUnion; @@ -439,7 +442,8 @@ default ImageProxy getEffectiveAvatar() /** * Bans this Member and deletes messages sent by the user based on the amount of delDays. - *
If you wish to ban a member without deleting any messages, provide delDays with a value of 0. + *
If you wish to ban a user without deleting any messages, provide {@code deletionTimeframe} with a value of 0. + * To set a ban reason, use {@link AuditableRestAction#reason(String)}. * *

You can unban a user with {@link net.dv8tion.jda.api.entities.Guild#unban(UserSnowflake) Guild.unban(UserSnowflake)}. * @@ -453,59 +457,14 @@ default ImageProxy getEffectiveAvatar() *

  • {@link net.dv8tion.jda.api.requests.ErrorResponse#MISSING_PERMISSIONS MISSING_PERMISSIONS} *
    The target Member cannot be banned due to a permission discrepancy
  • * - *
  • {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_MEMBER UNKNOWN_MEMBER} - *
    The specified Member was removed from the Guild before finishing the task
  • + *
  • {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_USER UNKNOWN_USER} + *
    The user no longer exists
  • * * - * @param delDays - * The history of messages, in days, that will be deleted. - * - * @throws net.dv8tion.jda.api.exceptions.InsufficientPermissionException - * If the logged in account does not have the {@link net.dv8tion.jda.api.Permission#BAN_MEMBERS} permission. - * @throws net.dv8tion.jda.api.exceptions.HierarchyException - * If the logged in account cannot ban the other user due to permission hierarchy position. - *
    See {@link Member#canInteract(Member)} - * @throws java.lang.IllegalArgumentException - * - * - * @return {@link net.dv8tion.jda.api.requests.restaction.AuditableRestAction AuditableRestAction} - * - * @since 4.0.0 - */ - @Nonnull - @CheckReturnValue - default AuditableRestAction ban(int delDays) - { - return getGuild().ban(this, delDays); - } - - /** - * Bans this Member and deletes messages sent by the user based on the amount of delDays. - *
    If you wish to ban a member without deleting any messages, provide delDays with a value of 0. - * - *

    You can unban a user with {@link net.dv8tion.jda.api.entities.Guild#unban(UserSnowflake) Guild.unban(UserSnowflake)}. - * - *

    Note: {@link net.dv8tion.jda.api.entities.Guild#getMembers()} will still contain the - * {@link net.dv8tion.jda.api.entities.Member Member} until Discord sends the - * {@link net.dv8tion.jda.api.events.guild.member.GuildMemberRemoveEvent GuildMemberRemoveEvent}. - * - *

    Possible {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} caused by - * the returned {@link net.dv8tion.jda.api.requests.RestAction RestAction} include the following: - *

    - * - * @param delDays - * The history of messages, in days, that will be deleted. - * @param reason - * The reason for this action or {@code null} if there is no specified reason + * @param deletionTimeframe + * The timeframe for the history of messages that will be deleted. (seconds precision) + * @param unit + * Timeframe unit as a {@link TimeUnit} (for example {@code member.ban(7, TimeUnit.DAYS)}). * * @throws net.dv8tion.jda.api.exceptions.InsufficientPermissionException * If the logged in account does not have the {@link net.dv8tion.jda.api.Permission#BAN_MEMBERS} permission. @@ -514,21 +473,21 @@ default AuditableRestAction ban(int delDays) *
    See {@link Member#canInteract(Member)} * @throws java.lang.IllegalArgumentException * * + * @return {@link AuditableRestAction} * - * @return {@link net.dv8tion.jda.api.requests.restaction.AuditableRestAction AuditableRestAction} - * - * @since 4.0.0 + * @see Guild#ban(UserSnowflake, int, TimeUnit) + * @see AuditableRestAction#reason(String) */ @Nonnull @CheckReturnValue - default AuditableRestAction ban(int delDays, @Nullable String reason) + default AuditableRestAction ban(int deletionTimeframe, @Nonnull TimeUnit unit) { - return getGuild().ban(this, delDays, reason); + return getGuild().ban(this, deletionTimeframe, unit); } /** @@ -595,10 +554,15 @@ default AuditableRestAction kick() * @return {@link net.dv8tion.jda.api.requests.restaction.AuditableRestAction AuditableRestAction} * Kicks the provided Member from the current Guild * - * @since 4.0.0 + * @deprecated + * Use {@link #kick()} and {@link AuditableRestAction#reason(String)} instead */ @Nonnull @CheckReturnValue + @Deprecated + @ForRemoval + @ReplaceWith("kick().reason(reason)") + @DeprecatedSince("5.0.0") default AuditableRestAction kick(@Nullable String reason) { return getGuild().kick(this, reason); diff --git a/src/main/java/net/dv8tion/jda/api/requests/restaction/AuditableRestAction.java b/src/main/java/net/dv8tion/jda/api/requests/restaction/AuditableRestAction.java index 671d803a5e..ba6d7b8b37 100644 --- a/src/main/java/net/dv8tion/jda/api/requests/restaction/AuditableRestAction.java +++ b/src/main/java/net/dv8tion/jda/api/requests/restaction/AuditableRestAction.java @@ -17,6 +17,7 @@ package net.dv8tion.jda.api.requests.restaction; import net.dv8tion.jda.api.audit.ThreadLocalReason; +import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.UserSnowflake; import net.dv8tion.jda.api.requests.RestAction; import net.dv8tion.jda.api.requests.restaction.pagination.AuditLogPaginationAction; @@ -39,21 +40,26 @@ */ public interface AuditableRestAction extends RestAction { + /** + * The maximum length of an audit-log reason + */ + int MAX_REASON_LENGTH = 512; + /** * Applies the specified reason as audit-log reason field. *
    When the provided reason is empty or {@code null} it will be treated as not set. + * If the provided reason is longer than {@value #MAX_REASON_LENGTH} characters, it will be truncated to fit the limit. * *

    Reasons for any AuditableRestAction may be retrieved * via {@link net.dv8tion.jda.api.audit.AuditLogEntry#getReason() AuditLogEntry.getReason()} * in iterable {@link AuditLogPaginationAction AuditLogPaginationActions} * from {@link net.dv8tion.jda.api.entities.Guild#retrieveAuditLogs() Guild.retrieveAuditLogs()}! + * For {@link net.dv8tion.jda.api.entities.Guild#ban(UserSnowflake, int, TimeUnit) guild bans}, this is also accessible via {@link Guild.Ban#getReason()}. * *

    This will specify the reason via the {@code X-Audit-Log-Reason} Request Header. - *
    Using methods with a reason parameter will always work and override this header. - * (ct. {@link net.dv8tion.jda.api.entities.Guild#ban(UserSnowflake, int, String) Guild.ban(UserSnowflake, int, String)}) * * @param reason - * The reason for this action which should be logged in the Guild's AuditLogs + * The reason for this action which should be logged in the Guild's AuditLogs (up to {@value #MAX_REASON_LENGTH} characters) * * @return The current AuditableRestAction instance for chaining convenience * diff --git a/src/main/java/net/dv8tion/jda/internal/entities/GuildImpl.java b/src/main/java/net/dv8tion/jda/internal/entities/GuildImpl.java index 3e5a016648..0f87c99947 100644 --- a/src/main/java/net/dv8tion/jda/internal/entities/GuildImpl.java +++ b/src/main/java/net/dv8tion/jda/internal/entities/GuildImpl.java @@ -86,6 +86,7 @@ import java.time.temporal.TemporalAccessor; import java.util.*; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; import java.util.function.Consumer; import java.util.function.Predicate; import java.util.stream.Collectors; @@ -1383,7 +1384,7 @@ public AuditableRestAction prune(int days, boolean wait, @Nonnull Role. @Nonnull @Override - public AuditableRestAction kick(@Nonnull UserSnowflake user, String reason) + public AuditableRestAction kick(@Nonnull UserSnowflake user) { Checks.notNull(user, "User"); checkPermission(Permission.KICK_MEMBERS); @@ -1393,23 +1394,17 @@ public AuditableRestAction kick(@Nonnull UserSnowflake user, String reason checkPosition(member); Route.CompiledRoute route = Route.Guilds.KICK_MEMBER.compile(getId(), user.getId()); - - AuditableRestAction action = new AuditableRestActionImpl<>(getJDA(), route); - if (!Helpers.isBlank(reason)) - { - Checks.check(reason.length() <= 512, "Reason cannot be longer than 512 characters."); - return action.reason(reason); - } - return action; + return new AuditableRestActionImpl<>(getJDA(), route); } @Nonnull @Override - public AuditableRestAction ban(@Nonnull UserSnowflake user, int delDays, String reason) + public AuditableRestAction ban(@Nonnull UserSnowflake user, int duration, @Nonnull TimeUnit unit) { Checks.notNull(user, "User"); - Checks.notNegative(delDays, "Deletion Days"); - Checks.check(delDays <= 7, "Deletion Days must not be bigger than 7."); + Checks.notNull(unit, "TimeUnit"); + Checks.notNegative(duration, "Deletion Timeframe"); + Checks.check(unit.toDays(duration) <= 7, "Deletion timeframe must not be larger than 7 days"); checkPermission(Permission.BAN_MEMBERS); Checks.check(user.getIdLong() != ownerId, "Cannot ban the owner of a guild!"); @@ -1420,16 +1415,10 @@ public AuditableRestAction ban(@Nonnull UserSnowflake user, int delDays, S Route.CompiledRoute route = Route.Guilds.BAN.compile(getId(), user.getId()); DataObject params = DataObject.empty(); - if (delDays > 0) - params.put("delete_message_days", delDays); + if (duration > 0) + params.put("delete_message_seconds", unit.toSeconds(duration)); - AuditableRestAction action = new AuditableRestActionImpl<>(getJDA(), route, params); - if (!Helpers.isBlank(reason)) - { - Checks.check(reason.length() <= 512, "Reason cannot be longer than 512 characters."); - return action.reason(reason); - } - return action; + return new AuditableRestActionImpl<>(getJDA(), route, params); } @Nonnull