forked from Fascinated/Bat
impl drag feature
This commit is contained in:
parent
bd9ac1e138
commit
7083bebef1
5
pom.xml
5
pom.xml
@ -159,6 +159,11 @@
|
|||||||
<artifactId>spotify-web-api-java</artifactId>
|
<artifactId>spotify-web-api-java</artifactId>
|
||||||
<version>8.4.0</version>
|
<version>8.4.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.ben-manes.caffeine</groupId>
|
||||||
|
<artifactId>caffeine</artifactId>
|
||||||
|
<version>3.1.8</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- Test Dependencies -->
|
<!-- Test Dependencies -->
|
||||||
<dependency>
|
<dependency>
|
||||||
|
@ -0,0 +1,23 @@
|
|||||||
|
package cc.fascinated.bat.features.drag;
|
||||||
|
|
||||||
|
import cc.fascinated.bat.command.Category;
|
||||||
|
import cc.fascinated.bat.features.Feature;
|
||||||
|
import cc.fascinated.bat.features.drag.command.DragCommand;
|
||||||
|
import cc.fascinated.bat.service.CommandService;
|
||||||
|
import lombok.NonNull;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Fascinated (fascinated7)
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class DragFeature extends Feature {
|
||||||
|
@Autowired
|
||||||
|
public DragFeature(@NonNull ApplicationContext context, @NonNull CommandService commandService) {
|
||||||
|
super("Drag", true,Category.GENERAL);
|
||||||
|
|
||||||
|
super.registerCommand(commandService, context.getBean(DragCommand.class));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,50 @@
|
|||||||
|
package cc.fascinated.bat.features.drag;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
import net.dv8tion.jda.api.entities.Member;
|
||||||
|
import net.dv8tion.jda.api.entities.Message;
|
||||||
|
import net.dv8tion.jda.api.entities.channel.concrete.VoiceChannel;
|
||||||
|
import net.dv8tion.jda.api.interactions.InteractionHook;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Fascinated (fascinated7)
|
||||||
|
*/
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@Getter @Setter
|
||||||
|
public class DragRequest {
|
||||||
|
/**
|
||||||
|
* The date the request was made
|
||||||
|
*/
|
||||||
|
private final Date requestDate = new Date();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The user that wants to join the voice channel
|
||||||
|
*/
|
||||||
|
private final Member member;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The user that the member wants to join
|
||||||
|
*/
|
||||||
|
private final Member target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The voice channel the user wants to join
|
||||||
|
*/
|
||||||
|
private final VoiceChannel voiceChannel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The interaction hook that the request was made from
|
||||||
|
*/
|
||||||
|
private final InteractionHook interactionHook;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The request message sent in the voice channel
|
||||||
|
*/
|
||||||
|
private Message requestMessage;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
package cc.fascinated.bat.features.drag.command;
|
||||||
|
|
||||||
|
import cc.fascinated.bat.command.BatCommand;
|
||||||
|
import cc.fascinated.bat.command.CommandInfo;
|
||||||
|
import io.sentry.protocol.App;
|
||||||
|
import lombok.NonNull;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Fascinated (fascinated7)
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
@CommandInfo(name = "drag", description = "Drag command")
|
||||||
|
public class DragCommand extends BatCommand {
|
||||||
|
@Autowired
|
||||||
|
public DragCommand(@NonNull ApplicationContext context) {
|
||||||
|
super.addSubCommand(context.getBean(RequestSubCommand.class));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,152 @@
|
|||||||
|
package cc.fascinated.bat.features.drag.command;
|
||||||
|
|
||||||
|
import cc.fascinated.bat.command.BatSubCommand;
|
||||||
|
import cc.fascinated.bat.command.CommandInfo;
|
||||||
|
import cc.fascinated.bat.common.EmbedUtils;
|
||||||
|
import cc.fascinated.bat.common.TimerUtils;
|
||||||
|
import cc.fascinated.bat.event.EventListener;
|
||||||
|
import cc.fascinated.bat.features.drag.DragRequest;
|
||||||
|
import cc.fascinated.bat.model.BatGuild;
|
||||||
|
import cc.fascinated.bat.model.BatUser;
|
||||||
|
import lombok.NonNull;
|
||||||
|
import net.dv8tion.jda.api.entities.GuildVoiceState;
|
||||||
|
import net.dv8tion.jda.api.entities.Member;
|
||||||
|
import net.dv8tion.jda.api.entities.channel.concrete.VoiceChannel;
|
||||||
|
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
|
||||||
|
import net.dv8tion.jda.api.interactions.commands.OptionMapping;
|
||||||
|
import net.dv8tion.jda.api.interactions.commands.OptionType;
|
||||||
|
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
|
||||||
|
import net.dv8tion.jda.api.interactions.components.ActionRow;
|
||||||
|
import net.dv8tion.jda.api.interactions.components.buttons.Button;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles requests to be moved to a voice channel.
|
||||||
|
* Author: Fascinated (fascinated7)
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
@CommandInfo(name = "request", description = "Request to be moved to a voice channel")
|
||||||
|
public class RequestSubCommand extends BatSubCommand implements EventListener {
|
||||||
|
/**
|
||||||
|
* A list of join requests
|
||||||
|
*/
|
||||||
|
public static final Set<DragRequest> JOIN_REQUESTS = new HashSet<>();
|
||||||
|
|
||||||
|
private final long requestTimeout = Duration.ofMinutes(30).toMillis();
|
||||||
|
private final long checkInterval = Duration.ofSeconds(10).toMillis();
|
||||||
|
|
||||||
|
public RequestSubCommand() {
|
||||||
|
super.addOption(OptionType.USER, "user", "The user you want to join", true);
|
||||||
|
|
||||||
|
TimerUtils.scheduleRepeating(() -> {
|
||||||
|
Set<DragRequest> toRemove = new HashSet<>();
|
||||||
|
for (DragRequest joinRequest : JOIN_REQUESTS) {
|
||||||
|
if (System.currentTimeMillis() - joinRequest.getRequestDate().getTime() < requestTimeout) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// The request has timed out
|
||||||
|
joinRequest.getInteractionHook().editOriginalEmbeds(EmbedUtils.errorEmbed()
|
||||||
|
.setDescription("The request to join %s's voice channel has timed out.".formatted(joinRequest.getTarget().getAsMention()))
|
||||||
|
.build()).queue();
|
||||||
|
joinRequest.getVoiceChannel().sendMessageEmbeds(EmbedUtils.errorEmbed()
|
||||||
|
.setDescription("%s's request to join your voice channel has timed out.".formatted(joinRequest.getMember().getAsMention()))
|
||||||
|
.build()).queue();
|
||||||
|
joinRequest.getRequestMessage().delete().queue();
|
||||||
|
toRemove.add(joinRequest);
|
||||||
|
}
|
||||||
|
JOIN_REQUESTS.removeAll(toRemove);
|
||||||
|
}, checkInterval, checkInterval);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) {
|
||||||
|
GuildVoiceState voiceState = member.getVoiceState();
|
||||||
|
// Check if the user is in a voice channel
|
||||||
|
if (voiceState == null || voiceState.getChannel() == null) {
|
||||||
|
event.replyEmbeds(EmbedUtils.errorEmbed()
|
||||||
|
.setDescription("You are not in a voice channel.")
|
||||||
|
.build())
|
||||||
|
.setEphemeral(true)
|
||||||
|
.queue();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
OptionMapping userOption = event.getOption("user");
|
||||||
|
if (userOption == null) return;
|
||||||
|
|
||||||
|
// Check if the user is in a voice channel
|
||||||
|
Member target = userOption.getAsMember();
|
||||||
|
if (target == null || target.getId().equals(member.getId())) {
|
||||||
|
event.replyEmbeds(EmbedUtils.errorEmbed()
|
||||||
|
.setDescription("You cannot request to join your own voice channel.")
|
||||||
|
.build())
|
||||||
|
.setEphemeral(true)
|
||||||
|
.queue();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the target user is in a voice channel
|
||||||
|
GuildVoiceState targetVoiceState = target.getVoiceState();
|
||||||
|
if (targetVoiceState == null || targetVoiceState.getChannel() == null) {
|
||||||
|
event.replyEmbeds(EmbedUtils.errorEmbed()
|
||||||
|
.setDescription("The user %s is not in a voice channel.".formatted(target.getAsMention()))
|
||||||
|
.build())
|
||||||
|
.setEphemeral(true)
|
||||||
|
.queue();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
VoiceChannel targetChannel = targetVoiceState.getChannel().asVoiceChannel();
|
||||||
|
|
||||||
|
// User is already in the target channel
|
||||||
|
if (voiceState.getChannel().getId().equals(targetChannel.getId())) {
|
||||||
|
event.replyEmbeds(EmbedUtils.errorEmbed()
|
||||||
|
.setDescription("You are already in the voice channel %s.".formatted(voiceState.getChannel().getAsMention()))
|
||||||
|
.build())
|
||||||
|
.setEphemeral(true)
|
||||||
|
.queue();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the user has already requested to join the target channel
|
||||||
|
DragRequest existingRequest = JOIN_REQUESTS.stream()
|
||||||
|
.filter(request -> request.getMember().getId().equals(member.getId()) && request.getVoiceChannel().getId().equals(targetChannel.getId()))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
if (existingRequest != null) {
|
||||||
|
event.replyEmbeds(EmbedUtils.errorEmbed()
|
||||||
|
.setDescription("You have already requested to join %s's voice channel.".formatted(target.getAsMention()))
|
||||||
|
.build())
|
||||||
|
.setEphemeral(true)
|
||||||
|
.queue();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the request to the list
|
||||||
|
JOIN_REQUESTS.add(new DragRequest(member, target, targetChannel, event.getHook()));
|
||||||
|
|
||||||
|
// Send the request to the target user
|
||||||
|
targetChannel.sendMessage(target.getAsMention()).queue();
|
||||||
|
targetChannel.sendMessageEmbeds(EmbedUtils.successEmbed()
|
||||||
|
.setDescription("User %s has requested to join your voice channel.".formatted(member.getAsMention()))
|
||||||
|
.build())
|
||||||
|
.addComponents(ActionRow.of(
|
||||||
|
Button.primary("drag-request-accept", "Accept"),
|
||||||
|
Button.danger("drag-request-decline", "Decline")
|
||||||
|
))
|
||||||
|
.queue(message -> {
|
||||||
|
JOIN_REQUESTS.stream()
|
||||||
|
.filter(r -> r.getVoiceChannel().getId().equals(targetChannel.getId()))
|
||||||
|
.findFirst().ifPresent(request -> request.setRequestMessage(message));
|
||||||
|
});
|
||||||
|
event.replyEmbeds(EmbedUtils.successEmbed()
|
||||||
|
.setDescription("Request to join %s's voice channel has been sent.".formatted(target.getAsMention()))
|
||||||
|
.build())
|
||||||
|
.setComponents(ActionRow.of(Button.secondary("drag-request-cancel", "Cancel")))
|
||||||
|
.queue();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
package cc.fascinated.bat.features.drag.listeners.request;
|
||||||
|
|
||||||
|
import cc.fascinated.bat.common.EmbedUtils;
|
||||||
|
import cc.fascinated.bat.event.EventListener;
|
||||||
|
import cc.fascinated.bat.features.drag.DragRequest;
|
||||||
|
import cc.fascinated.bat.features.drag.command.RequestSubCommand;
|
||||||
|
import cc.fascinated.bat.model.BatGuild;
|
||||||
|
import cc.fascinated.bat.model.BatUser;
|
||||||
|
import lombok.NonNull;
|
||||||
|
import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent;
|
||||||
|
import net.dv8tion.jda.api.interactions.InteractionHook;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Fascinated (fascinated7)
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class RequestListener implements EventListener {
|
||||||
|
@Override
|
||||||
|
public void onButtonInteraction(BatGuild guild, @NonNull BatUser user, @NonNull ButtonInteractionEvent event) {
|
||||||
|
if (!event.getComponentId().equals("drag-request-cancel")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Optional<DragRequest> optionalDragRequest = RequestSubCommand.JOIN_REQUESTS.stream()
|
||||||
|
.filter(request -> request.getMember().getId().equals(event.getUser().getId()))
|
||||||
|
.findFirst();
|
||||||
|
if (optionalDragRequest.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
DragRequest dragRequest = optionalDragRequest.get();
|
||||||
|
InteractionHook interactionHook = dragRequest.getInteractionHook();
|
||||||
|
interactionHook.editOriginalEmbeds(EmbedUtils.errorEmbed()
|
||||||
|
.setDescription("You have cancelled your request to join %s's voice channel.".formatted(dragRequest.getTarget().getAsMention()))
|
||||||
|
.build()).queue(message -> message.editMessageComponents().queue());
|
||||||
|
dragRequest.getVoiceChannel().sendMessageEmbeds(EmbedUtils.errorEmbed()
|
||||||
|
.setDescription("%s has cancelled their request to join your voice channel.".formatted(dragRequest.getMember().getAsMention()))
|
||||||
|
.build()).queue();
|
||||||
|
dragRequest.getRequestMessage().delete().queue();
|
||||||
|
RequestSubCommand.JOIN_REQUESTS.remove(dragRequest);
|
||||||
|
}
|
||||||
|
}
|
54
src/main/java/cc/fascinated/bat/features/drag/listeners/request/TargetChannelListener.java
Normal file
54
src/main/java/cc/fascinated/bat/features/drag/listeners/request/TargetChannelListener.java
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
package cc.fascinated.bat.features.drag.listeners.request;
|
||||||
|
|
||||||
|
import cc.fascinated.bat.common.EmbedUtils;
|
||||||
|
import cc.fascinated.bat.event.EventListener;
|
||||||
|
import cc.fascinated.bat.features.drag.DragRequest;
|
||||||
|
import cc.fascinated.bat.features.drag.command.RequestSubCommand;
|
||||||
|
import cc.fascinated.bat.model.BatGuild;
|
||||||
|
import cc.fascinated.bat.model.BatUser;
|
||||||
|
import lombok.NonNull;
|
||||||
|
import net.dv8tion.jda.api.entities.Member;
|
||||||
|
import net.dv8tion.jda.api.entities.User;
|
||||||
|
import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Fascinated (fascinated7)
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class TargetChannelListener implements EventListener {
|
||||||
|
@Override
|
||||||
|
public void onButtonInteraction(BatGuild guild, @NonNull BatUser user, @NonNull ButtonInteractionEvent event) {
|
||||||
|
User buttonUser = event.getUser();
|
||||||
|
Member member = guild.getDiscordGuild().getMember(buttonUser);
|
||||||
|
if (member == null) return;
|
||||||
|
|
||||||
|
DragRequest joinRequest = RequestSubCommand.JOIN_REQUESTS.stream()
|
||||||
|
.filter(request -> request.getVoiceChannel().getId().equals(event.getChannel().getId()))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
if (joinRequest == null) return;
|
||||||
|
|
||||||
|
if (event.getComponentId().equals("drag-request-accept")) {
|
||||||
|
joinRequest.getVoiceChannel().getGuild().moveVoiceMember(joinRequest.getMember(), joinRequest.getVoiceChannel()).queue();
|
||||||
|
event.replyEmbeds(EmbedUtils.successEmbed()
|
||||||
|
.setDescription("You have accepted %s's request to join your voice channel!".formatted(joinRequest.getMember().getAsMention()))
|
||||||
|
.build())
|
||||||
|
.queue();
|
||||||
|
} else if (event.getComponentId().equals("drag-request-decline")) {
|
||||||
|
event.replyEmbeds(EmbedUtils.errorEmbed()
|
||||||
|
.setDescription("You have declined %s's request to join your voice channel!".formatted(joinRequest.getMember().getAsMention()))
|
||||||
|
.build())
|
||||||
|
.queue();
|
||||||
|
joinRequest.getInteractionHook().retrieveOriginal().queue(message -> {
|
||||||
|
message.editMessageEmbeds(EmbedUtils.errorEmbed()
|
||||||
|
.setDescription("%s has declined your request to join their voice channel.".formatted(joinRequest.getTarget().getAsMention()))
|
||||||
|
.build()).queue();
|
||||||
|
message.editMessageComponents().queue();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
RequestSubCommand.JOIN_REQUESTS.remove(joinRequest);
|
||||||
|
// Remove the buttons from the embed
|
||||||
|
event.getInteraction().getMessage().editMessageComponents().queue();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user