Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added Cooldown-Types #84

Draft
wants to merge 25 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
375cd2a
added cooldown types
DenuxPlays Nov 15, 2022
c042e11
first implementations of Cooldown types
DenuxPlays Nov 15, 2022
966f8ec
Merge branch 'main' into denux/cooldown_types
DenuxPlays Nov 15, 2022
c494a51
fixes bug
DenuxPlays Nov 15, 2022
78f8686
more bug fixing
DenuxPlays Nov 15, 2022
d51d9bd
even more bug fixing
DenuxPlays Nov 16, 2022
3f8203b
added java docs in `Pair.java`
DenuxPlays Nov 16, 2022
e95c62d
added more java docs
DenuxPlays Nov 16, 2022
be0fd94
removed debug prints
DenuxPlays Nov 16, 2022
06e1b08
javadocs + optimized imports
DenuxPlays Nov 16, 2022
05e6231
updated cooldown example
DenuxPlays Nov 16, 2022
e975659
Merge branch 'main' into denux/cooldown_types
DenuxPlays Nov 28, 2022
6b07d6d
Merge remote-tracking branch 'DIH4JDA/main' into denux/cooldown_types
DenuxPlays Dec 5, 2022
0f0dbdc
resolved merge conflicts
DenuxPlays Feb 11, 2023
ca519c3
Merge branch 'main' into denux/cooldown_types
DenuxPlays Feb 14, 2023
8beadf6
first implementation of cooldown types (v2)
DenuxPlays Feb 14, 2023
a8731ad
added missing java docs
DenuxPlays Feb 14, 2023
af228c5
fixed some bugs
DenuxPlays Feb 14, 2023
e402518
fixed leftover bugs
DenuxPlays Feb 14, 2023
8ff1082
optimized imports
DenuxPlays Feb 14, 2023
494bd5f
improved java docs
DenuxPlays Feb 14, 2023
bd16409
change names
DenuxPlays Feb 14, 2023
d0c12a9
Update InteractionHandler.java
DenuxPlays Feb 20, 2023
7820040
Merge branch 'main' into denux/cooldown_types
DenuxPlays Apr 27, 2023
3704cd3
Merge branch 'main' into denux/cooldown_types
DenuxPlays Sep 19, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ dependencies {
testImplementation("org.junit.jupiter:junit-jupiter-engine:5.10.0")
testImplementation("org.junit.jupiter:junit-jupiter-engine:5.10.0")
testImplementation("ch.qos.logback:logback-classic:1.4.11")
//needed for reasons...
testCompileOnly("com.google.code.findbugs:jsr305:3.0.2")
DenuxPlays marked this conversation as resolved.
Show resolved Hide resolved

api("net.dv8tion:JDA:5.0.0-beta.13") {
exclude(module = "opus-java")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import net.dv8tion.jda.api.interactions.commands.build.Commands;
import net.dv8tion.jda.api.interactions.components.buttons.Button;
import org.jetbrains.annotations.NotNull;
import xyz.dynxsty.dih4jda.interactions.commands.application.CooldownScope;
import xyz.dynxsty.dih4jda.interactions.commands.application.SlashCommand;
import xyz.dynxsty.dih4jda.interactions.components.ButtonHandler;
import xyz.dynxsty.dih4jda.util.ComponentIdBuilder;
Expand All @@ -20,7 +21,7 @@ public class PollCommand extends SlashCommand implements ButtonHandler {
public PollCommand() {
setCommandData(Commands.slash("poll", "Creates a poll with 2 options."));
setRequiredPermissions(Permission.MESSAGE_MANAGE);
setCommandCooldown(Duration.of(1, ChronoUnit.MINUTES)); // Add cooldown to prevent spam by users
setCommandCooldown(Duration.of(1, ChronoUnit.MINUTES), CooldownScope.USER_GLOBAL); // Add cooldown to prevent spam by users
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import xyz.dynxsty.dih4jda.events.DIH4JDAEventListener;

import javax.annotation.Nonnull;
import java.time.ZoneId;

public class DIH4JDAListener implements DIH4JDAEventListener {

Expand All @@ -18,8 +19,8 @@ public void onCommandException(@Nonnull CommandExceptionEvent event) {

@Override
public void onCommandCooldown(@Nonnull CommandCooldownEvent event) {
event.getInteraction().getMessageChannel().sendMessageFormat("Seems like you have to wait before you use the " +
"command again.\n You can try again in: <t:%s:R>", event.getCooldown().getNextUse().toEpochMilli()).queue();
event.getInteraction().replyFormat("You are on cooldown. Next use <t:%s:R>",
event.getCooldown().getNextUse().atZone(ZoneId.systemDefault()).toEpochSecond()).queue();
}

// add more events if you need to
Expand Down
115 changes: 71 additions & 44 deletions src/main/java/xyz/dynxsty/dih4jda/InteractionHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import xyz.dynxsty.dih4jda.interactions.commands.RestrictedCommand;
import xyz.dynxsty.dih4jda.interactions.commands.application.BaseApplicationCommand;
import xyz.dynxsty.dih4jda.interactions.commands.application.ContextCommand;
import xyz.dynxsty.dih4jda.interactions.commands.application.CooldownScope;
import xyz.dynxsty.dih4jda.interactions.commands.application.RegistrationType;
import xyz.dynxsty.dih4jda.interactions.commands.application.SlashCommand;
import xyz.dynxsty.dih4jda.interactions.components.ButtonHandler;
Expand Down Expand Up @@ -578,57 +579,83 @@ private void handleMessageContextCommand(@Nonnull MessageContextInteractionEvent
}
}

/**
* Checks if the given {@link CommandInteraction} passes the
* {@link RestrictedCommand} requirements.
* If not, this will then fire the corresponding event using {@link DIH4JDAEvent#fire(DIH4JDAEvent)}
*
* @param interaction The {@link CommandInteraction}.
* @param command The {@link RestrictedCommand} which contains the (possible) restrictions.
* @param type The {@link RegistrationType} of the {@link BaseApplicationCommand}.
* @return Whether the event was fired.
* @since v1.5
*/
private boolean passesRequirements(@Nonnull CommandInteraction interaction, @Nonnull RestrictedCommand command,
@Nonnull RegistrationType type) {
long userId = interaction.getUser().getIdLong();
Long[] guildIds = command.getRequiredGuilds();
Permission[] permissions = command.getRequiredPermissions();
Long[] userIds = command.getRequiredUsers();
Long[] roleIds = command.getRequiredRoles();
if (type == RegistrationType.GUILD && guildIds.length != 0 && interaction.isFromGuild() &&
!Arrays.asList(guildIds).contains(interaction.getGuild().getIdLong())
) {
DIH4JDAEvent.fire(new InvalidGuildEvent(dih4jda, interaction, Set.of(guildIds)));
return false;
}
if (permissions.length != 0 && interaction.isFromGuild() &&
interaction.getMember() != null && !interaction.getMember().hasPermission(permissions)) {
DIH4JDAEvent.fire(new InsufficientPermissionsEvent(dih4jda, interaction, Set.of(permissions)));
return false;
}
if (userIds.length != 0 && !Arrays.asList(userIds).contains(userId)) {
DIH4JDAEvent.fire(new InvalidUserEvent(dih4jda, interaction, Set.of(userIds)));
return false;
}
if (interaction.isFromGuild() && interaction.getMember() != null) {
Member member = interaction.getMember();
if (roleIds.length != 0 && !member.getRoles().isEmpty() &&
member.getRoles().stream().noneMatch(r -> Arrays.asList(roleIds).contains(r.getIdLong()))) {
DIH4JDAEvent.fire(new InvalidRoleEvent(dih4jda, interaction, Set.of(roleIds)));
return false;
}
}
return !hasCooldown(interaction, command);
}

/**
* Checks if the given {@link CommandInteraction} passes the
* {@link RestrictedCommand} requirements.
* If not, this will then fire the corresponding event using {@link DIH4JDAEvent#fire(DIH4JDAEvent)}
*
* Checks if the given {@link CommandInteraction} and {@link net.dv8tion.jda.api.entities.User} has a cooldown.
* @param interaction The {@link CommandInteraction}.
* @param command The {@link RestrictedCommand} which contains the (possible) restrictions.
* @param type The {@link RegistrationType} of the {@link BaseApplicationCommand}.
* @return Whether the event was fired.
* @since v1.5
*/
private boolean passesRequirements(@Nonnull CommandInteraction interaction, @Nonnull RestrictedCommand command,
@Nonnull RegistrationType type) {
long userId = interaction.getUser().getIdLong();
Long[] guildIds = command.getRequiredGuilds();
Permission[] permissions = command.getRequiredPermissions();
Long[] userIds = command.getRequiredUsers();
Long[] roleIds = command.getRequiredRoles();
if (type == RegistrationType.GUILD && guildIds.length != 0 && interaction.isFromGuild() &&
interaction.isFromGuild() && !List.of(guildIds).contains(interaction.getGuild().getIdLong())
) {
DIH4JDAEvent.fire(new InvalidGuildEvent(dih4jda, interaction, Set.of(guildIds)));
return false;
}
if (permissions.length != 0 && interaction.isFromGuild() &&
interaction.getMember() != null && !interaction.getMember().hasPermission(permissions)) {
DIH4JDAEvent.fire(new InsufficientPermissionsEvent(dih4jda, interaction, Set.of(permissions)));
return false;
}
if (userIds.length != 0 && !List.of(userIds).contains(userId)) {
DIH4JDAEvent.fire(new InvalidUserEvent(dih4jda, interaction, Set.of(userIds)));
* @param command The {@link RestrictedCommand} which contains the cooldown.
* @return true if the command and user has a cooldown, false otherwise.
*/
private boolean hasCooldown(@Nonnull CommandInteraction interaction, @Nonnull RestrictedCommand command) {
// check if the command has enabled some sort of cooldown
Pair<Duration, CooldownScope> cooldownPair = command.getCooldownConfiguration();
if (cooldownPair.getFirst().equals(Duration.ZERO) || cooldownPair.getSecond().equals(CooldownScope.NONE)) {
return false;
}
if (interaction.isFromGuild() && interaction.getMember() != null) {
Member member = interaction.getMember();
if (roleIds.length != 0 && !member.getRoles().isEmpty() &&
member.getRoles().stream().noneMatch(r -> List.of(roleIds).contains(r.getIdLong()))) {
DIH4JDAEvent.fire(new InvalidRoleEvent(dih4jda, interaction, Set.of(roleIds)));
return false;
RestrictedCommand.Cooldown cooldown = command.getCooldown(interaction.getUser(), interaction.getGuild());
if (interaction.isFromGuild()) {
if (command.hasCooldown(interaction.getMember())) {
DIH4JDAEvent.fire(new CommandCooldownEvent(dih4jda, interaction, cooldown));
return true;
}
}
// check if the command has enabled some sort of cooldown
if (!command.getCommandCooldown().equals(Duration.ZERO)) {
if (command.hasCooldown(userId)) {
DIH4JDAEvent.fire(new CommandCooldownEvent(dih4jda, interaction, command.retrieveCooldown(userId)));
return false;
} else {
command.applyCooldown(userId, Instant.now().plus(command.getCommandCooldown()));
Instant nextUse = Instant.now().plus(cooldownPair.getFirst());
switch (cooldownPair.getSecond()) {
case USER_GLOBAL: command.applyCooldown(interaction.getUser(), nextUse); break;
case MEMBER_GUILD: command.applyCooldown(interaction.getUser(), interaction.getGuild(), nextUse); break;
case GUILD: command.applyCooldown(interaction.getGuild(), nextUse); break;
}
} else {
if (command.hasCooldown(interaction.getUser())) {
DIH4JDAEvent.fire(new CommandCooldownEvent(dih4jda, interaction, cooldown));
return true;
}
Instant nextUse = Instant.now().plus(cooldownPair.getFirst());
command.applyCooldown(interaction.getUser(), nextUse);
}
return true;
return false;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,18 @@
import net.dv8tion.jda.api.interactions.commands.CommandInteraction;
import xyz.dynxsty.dih4jda.DIH4JDA;
import xyz.dynxsty.dih4jda.interactions.commands.RestrictedCommand;
import xyz.dynxsty.dih4jda.interactions.commands.application.CooldownScope;

import javax.annotation.Nonnull;
import java.time.Duration;

/**
* An event that gets fired when the user, which invoked the command, is not yet able to use this command due to
* a specified {@link RestrictedCommand#setCommandCooldown(Duration) Command Cooldown}
* a specified {@link RestrictedCommand#setCommandCooldown(Duration, CooldownScope)} Command Cooldown}
*
* <b>Command Cooldowns DO NOT persist between sessions!</b>
*
* @see RestrictedCommand#setCommandCooldown(Duration)
* @see RestrictedCommand#setCommandCooldown(Duration, CooldownScope)
*/
public class CommandCooldownEvent extends DIH4JDAEvent<CommandInteraction> {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import xyz.dynxsty.dih4jda.interactions.AutoCompletable;
import xyz.dynxsty.dih4jda.interactions.commands.RestrictedCommand;
import xyz.dynxsty.dih4jda.interactions.commands.application.ContextCommand;
import xyz.dynxsty.dih4jda.interactions.commands.application.CooldownScope;
import xyz.dynxsty.dih4jda.interactions.commands.application.SlashCommand;

import javax.annotation.Nonnull;
Expand Down Expand Up @@ -84,12 +85,12 @@ default void onInvalidGuild(@Nonnull InvalidGuildEvent event) {}

/**
* An event that gets fired when the user, which invoked the command, is not yet able to use this command due to
* a specified {@link RestrictedCommand#setCommandCooldown(Duration) Command Cooldown}<br>
* a specified {@link RestrictedCommand#setCommandCooldown(Duration, CooldownScope) Command Cooldown}<br>
*
* <b>Command Cooldowns DO NOT persist between sessions!</b><br>
*
* @param event The {@link CommandCooldownEvent} that was fired.
* @see RestrictedCommand#setCommandCooldown(Duration)
* @see RestrictedCommand#setCommandCooldown(Duration, CooldownScope)
*/
default void onCommandCooldown(@Nonnull CommandCooldownEvent event) {}
}
Expand Down
Loading