Merge branch 'master' into seenCommand
# Conflicts: # src/main/java/com/alttd/commandManager/CommandManager.java
This commit is contained in:
commit
2d652bc780
|
|
@ -38,27 +38,23 @@ tasks {
|
|||
}
|
||||
}
|
||||
|
||||
// create<ConfigureShadowRelocation>("relocateJars") {
|
||||
// target = shadowJar.get()
|
||||
// prefix = "${project.name}.lib"
|
||||
// }
|
||||
//
|
||||
// shadowJar {
|
||||
// dependsOn(getByName("relocateJars") as ConfigureShadowRelocation)
|
||||
// archiveFileName.set("${project.name}-${project.version}.jar")
|
||||
// minimize()
|
||||
// configurations = listOf(project.configurations.shadow.get())
|
||||
// }
|
||||
//
|
||||
shadowJar {
|
||||
archiveFileName.set(rootProject.name + ".jar")
|
||||
}
|
||||
|
||||
build {
|
||||
dependsOn(shadowJar)
|
||||
}
|
||||
|
||||
jar {
|
||||
enabled = false
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// JDA
|
||||
implementation("net.dv8tion:JDA:5.0.0-alpha.19") {
|
||||
implementation("net.dv8tion:JDA:5.0.0-alpha.20") {
|
||||
exclude("opus-java") // exclude audio
|
||||
}
|
||||
// MySQL
|
||||
|
|
@ -67,4 +63,8 @@ dependencies {
|
|||
|
||||
// Configurate
|
||||
implementation("org.spongepowered:configurate-yaml:4.1.2")
|
||||
|
||||
|
||||
compileOnly("org.projectlombok:lombok:1.18.24")
|
||||
annotationProcessor("org.projectlombok:lombok:1.18.24")
|
||||
}
|
||||
34
example.requests.yml
Normal file
34
example.requests.yml
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
request:
|
||||
guild: '776590138296893480'
|
||||
category: '776590138296893481'
|
||||
channel: '1017787342561476709'
|
||||
message: '1017839462111256667'
|
||||
types:
|
||||
bug-report:
|
||||
category: '776590138296893481'
|
||||
channel: '820222354180800525'
|
||||
name: Bug report
|
||||
title: What should the title be?
|
||||
description: Report a new bug.
|
||||
message: Describe the bug.
|
||||
act-request:
|
||||
category: '776590138296893481'
|
||||
channel: '820222354180800525'
|
||||
name: Act request
|
||||
title: What should the title be?
|
||||
description: Make a new act request.
|
||||
message: Describe the act request.
|
||||
admin-act-request:
|
||||
category: '776590138296893481'
|
||||
channel: '820222354180800525'
|
||||
name: Admin act request
|
||||
title: What should the title be?
|
||||
description: Make a new admin act request.
|
||||
message: Describe the admin act request.
|
||||
feature-request:
|
||||
category: '776590138296893481'
|
||||
channel: '820222354180800525'
|
||||
name: Feature request
|
||||
title: What should the title be?
|
||||
description: Make a new feature request.
|
||||
message: Describe the feature request.
|
||||
|
|
@ -30,8 +30,8 @@ public class AltitudeBot {
|
|||
private void start() {
|
||||
Logger.info("Starting bot...");
|
||||
initConfigs();
|
||||
ConsoleCommandManager.startConsoleCommands(jda);
|
||||
jda = JDABuilder.createDefault(SettingsConfig.TOKEN).build();
|
||||
ConsoleCommandManager.startConsoleCommands(jda);
|
||||
DatabaseTables.createTables(Database.getDatabase().getConnection());
|
||||
// try {
|
||||
// jda.getPresence().setPresence(
|
||||
|
|
@ -41,7 +41,6 @@ public class AltitudeBot {
|
|||
// Logger.exception(e);
|
||||
// }
|
||||
initListeners();
|
||||
//TODO init permissionManager
|
||||
}
|
||||
|
||||
private void initListeners() {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
package com.alttd.buttonManager;
|
||||
|
||||
import com.alttd.buttonManager.buttons.remindMeConfirm.ButtonRemindMeCancel;
|
||||
import com.alttd.buttonManager.buttons.remindMeConfirm.ButtonRemindMeConfirm;
|
||||
import com.alttd.buttonManager.buttons.suggestionReview.ButtonSuggestionReviewAccept;
|
||||
import com.alttd.buttonManager.buttons.suggestionReview.ButtonSuggestionReviewDeny;
|
||||
import com.alttd.util.Util;
|
||||
|
|
@ -22,7 +24,9 @@ public class ButtonManager extends ListenerAdapter {
|
|||
public ButtonManager() {
|
||||
buttons = List.of(
|
||||
new ButtonSuggestionReviewAccept(),
|
||||
new ButtonSuggestionReviewDeny());
|
||||
new ButtonSuggestionReviewDeny(),
|
||||
new ButtonRemindMeCancel(),
|
||||
new ButtonRemindMeConfirm());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -0,0 +1,36 @@
|
|||
package com.alttd.buttonManager.buttons.remindMeConfirm;
|
||||
|
||||
import com.alttd.buttonManager.DiscordButton;
|
||||
import com.alttd.database.queries.QueriesReminders.Reminder;
|
||||
import com.alttd.util.Util;
|
||||
import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent;
|
||||
import net.dv8tion.jda.api.interactions.components.buttons.Button;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class ButtonRemindMeCancel extends DiscordButton {
|
||||
@Override
|
||||
public String getButtonId() {
|
||||
return "remind_me_cancel";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(ButtonInteractionEvent event) {
|
||||
HookAndReminder hookAndReminder = ButtonRemindMeConfirm.removeReminder(event.getUser().getIdLong());
|
||||
if (hookAndReminder == null) {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "Your reminder was already cancelled!"))
|
||||
.setEphemeral(true).queue();
|
||||
return;
|
||||
}
|
||||
event.replyEmbeds(Util.genericSuccessEmbed("Success", "Cancelled your reminder!"))
|
||||
.setEphemeral(true).queue();
|
||||
hookAndReminder.interactionHook().editOriginalComponents(List.of()).queue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Button getButton() {
|
||||
return Button.danger(getButtonId(), "Cancel");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
package com.alttd.buttonManager.buttons.remindMeConfirm;
|
||||
|
||||
import com.alttd.buttonManager.DiscordButton;
|
||||
import com.alttd.database.queries.QueriesReminders.QueriesReminders;
|
||||
import com.alttd.database.queries.QueriesReminders.Reminder;
|
||||
import com.alttd.reminders.ReminderScheduler;
|
||||
import com.alttd.util.Util;
|
||||
import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent;
|
||||
import net.dv8tion.jda.api.interactions.InteractionHook;
|
||||
import net.dv8tion.jda.api.interactions.components.buttons.Button;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
public class ButtonRemindMeConfirm extends DiscordButton {
|
||||
|
||||
private static final HashMap<Long, HookAndReminder> unconfirmedReminders = new HashMap<>();
|
||||
|
||||
public static synchronized void putReminder(long id, InteractionHook defer, Reminder reminder) {
|
||||
unconfirmedReminders.put(id, new HookAndReminder(reminder, defer));
|
||||
}
|
||||
|
||||
public static synchronized HookAndReminder removeReminder(long id) {
|
||||
return unconfirmedReminders.remove(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getButtonId() {
|
||||
return "remind_me_confirm";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(ButtonInteractionEvent event) {
|
||||
HookAndReminder hookAndReminder = removeReminder(event.getUser().getIdLong());
|
||||
|
||||
if (storeReminder(hookAndReminder.reminder(), event)) {
|
||||
event.replyEmbeds(Util.genericSuccessEmbed("Success", "Your reminder was successfully created!"))
|
||||
.setEphemeral(true).queue();
|
||||
}
|
||||
hookAndReminder.interactionHook().editOriginalComponents(List.of()).queue();
|
||||
}
|
||||
|
||||
private boolean storeReminder(Reminder reminder, ButtonInteractionEvent event) {
|
||||
if (reminder == null) {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "Unable to retrieve reminder data for this button"))
|
||||
.setEphemeral(true).queue();
|
||||
return false;
|
||||
}
|
||||
int id = QueriesReminders.storeReminder(reminder);
|
||||
if (id == 0) {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "Unable to store reminder in the database"))
|
||||
.setEphemeral(true).queue();
|
||||
return false;
|
||||
}
|
||||
|
||||
reminder = new Reminder(
|
||||
id,
|
||||
reminder.title(),
|
||||
reminder.description(),
|
||||
reminder.userId(),
|
||||
reminder.guildId(),
|
||||
reminder.channelId(),
|
||||
reminder.messageId(),
|
||||
reminder.shouldRepeat(),
|
||||
reminder.creationDate(),
|
||||
reminder.remindDate());
|
||||
|
||||
ReminderScheduler instance = ReminderScheduler.getInstance(event.getJDA());
|
||||
if (instance == null) {
|
||||
QueriesReminders.removeReminder(reminder.id());
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "Unable to start reminder, removing it from the database..."))
|
||||
.setEphemeral(true).queue();
|
||||
return false;
|
||||
}
|
||||
|
||||
instance.addReminder(reminder);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Button getButton() {
|
||||
return Button.success(getButtonId(), "Confirm");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
package com.alttd.buttonManager.buttons.remindMeConfirm;
|
||||
|
||||
import com.alttd.database.queries.QueriesReminders.Reminder;
|
||||
import net.dv8tion.jda.api.interactions.InteractionHook;
|
||||
|
||||
record HookAndReminder(Reminder reminder, InteractionHook interactionHook) {
|
||||
|
||||
}
|
||||
|
|
@ -8,10 +8,15 @@ import net.dv8tion.jda.api.EmbedBuilder;
|
|||
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.entities.channel.middleman.GuildMessageChannel;
|
||||
import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel;
|
||||
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
|
||||
import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel;
|
||||
import net.dv8tion.jda.api.entities.emoji.Emoji;
|
||||
import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent;
|
||||
import net.dv8tion.jda.api.interactions.components.buttons.Button;
|
||||
import net.dv8tion.jda.api.requests.RestAction;
|
||||
import net.dv8tion.jda.api.utils.messages.MessageCreateBuilder;
|
||||
import net.dv8tion.jda.api.utils.messages.MessageCreateData;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.List;
|
||||
|
|
@ -26,16 +31,6 @@ public class ButtonSuggestionReviewAccept extends DiscordButton {
|
|||
@Override
|
||||
public void execute(ButtonInteractionEvent event) {
|
||||
Message message = event.getMessage();
|
||||
long suggestionChannelId = CommandOutputChannels.getOutputChannel(message.getGuild().getIdLong(), OutputType.SUGGESTION);
|
||||
long modLogChannelId = CommandOutputChannels.getOutputChannel(message.getGuild().getIdLong(), OutputType.MOD_LOG);
|
||||
|
||||
List<MessageEmbed> embeds = message.getEmbeds();
|
||||
if (embeds.size() != 1) {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "This message contains no embeds, can't be a suggestion"))
|
||||
.setEphemeral(true).queue(RestAction.getDefaultSuccess(), Util::handleFailure);
|
||||
return;
|
||||
}
|
||||
|
||||
Guild guild = event.getGuild();
|
||||
if (guild == null) {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "Unable to retrieve guild"))
|
||||
|
|
@ -43,16 +38,9 @@ public class ButtonSuggestionReviewAccept extends DiscordButton {
|
|||
return;
|
||||
}
|
||||
|
||||
GuildMessageChannel suggestionChannel = guild.getChannelById(GuildMessageChannel.class, suggestionChannelId);
|
||||
if (suggestionChannel == null) {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "This server does not have a valid suggestion channel"))
|
||||
.setEphemeral(true).queue(RestAction.getDefaultSuccess(), Util::handleFailure);
|
||||
return;
|
||||
}
|
||||
|
||||
GuildMessageChannel modLogChannel = guild.getChannelById(GuildMessageChannel.class, modLogChannelId);
|
||||
if (modLogChannel == null) {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "This server does not have a valid suggestion channel"))
|
||||
List<MessageEmbed> embeds = message.getEmbeds();
|
||||
if (embeds.size() != 1) {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "This message contains no embeds, can't be a suggestion"))
|
||||
.setEphemeral(true).queue(RestAction.getDefaultSuccess(), Util::handleFailure);
|
||||
return;
|
||||
}
|
||||
|
|
@ -65,21 +53,86 @@ public class ButtonSuggestionReviewAccept extends DiscordButton {
|
|||
return;
|
||||
}
|
||||
|
||||
GuildChannel suggestionGuildChannel = CommandOutputChannels.getOutputChannel(message.getGuild(), OutputType.SUGGESTION);
|
||||
GuildChannel modLogGuildChannel = CommandOutputChannels.getOutputChannel(message.getGuild(), OutputType.MOD_LOG);
|
||||
|
||||
TextChannel modLogChannel = validModLogChannel(event, modLogGuildChannel);
|
||||
if (modLogChannel == null)
|
||||
return;
|
||||
|
||||
if (suggestionGuildChannel == null) {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "This server does not have a valid suggestion channel."))
|
||||
.setEphemeral(true).queue(RestAction.getDefaultSuccess(), Util::handleFailure);
|
||||
return;
|
||||
}
|
||||
|
||||
String mentionMember = reviewMessage.getDescription();
|
||||
if (mentionMember == null) {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "This message contains no description, can't be a suggestion"))
|
||||
.setEphemeral(true).queue(RestAction.getDefaultSuccess(), Util::handleFailure);
|
||||
return;
|
||||
}
|
||||
|
||||
MessageEmbed suggestionMessage = new EmbedBuilder(reviewMessage)
|
||||
.clearFields()
|
||||
.setColor(Color.GRAY)
|
||||
.setTitle(fields.get(0).getName())
|
||||
.setDescription(fields.get(0).getValue())
|
||||
.addField("Suggestion by", mentionMember, false)
|
||||
.build();
|
||||
|
||||
if (suggestionGuildChannel instanceof ForumChannel forumChannel) {
|
||||
sendSuggestionInForum(forumChannel, modLogChannel, fields.get(0), suggestionMessage, mentionMember, event);
|
||||
} else if (suggestionGuildChannel instanceof TextChannel forumChannel) {
|
||||
sendSuggestionEmbed(forumChannel, modLogChannel, suggestionMessage, event);
|
||||
} else {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", suggestionGuildChannel.getType().name() + " is not a valid suggestion channel"))
|
||||
.setEphemeral(true).queue(RestAction.getDefaultSuccess(), Util::handleFailure);
|
||||
}
|
||||
}
|
||||
|
||||
private TextChannel validModLogChannel(ButtonInteractionEvent event, GuildChannel guildChannel) {
|
||||
if (guildChannel == null) {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "This server does not have a valid mod log channel"))
|
||||
.setEphemeral(true).queue(RestAction.getDefaultSuccess(), Util::handleFailure);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!(guildChannel instanceof TextChannel channel)) {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "A mod log channel can't be of type: " + guildChannel.getType().name()))
|
||||
.setEphemeral(true).queue(RestAction.getDefaultSuccess(), Util::handleFailure);
|
||||
return null;
|
||||
}
|
||||
return channel;
|
||||
}
|
||||
|
||||
public void sendSuggestionEmbed(TextChannel suggestionChannel, TextChannel modLog, MessageEmbed suggestionMessage, ButtonInteractionEvent event) {
|
||||
suggestionChannel.sendMessageEmbeds(suggestionMessage).queue(success -> {
|
||||
message.delete().queue(RestAction.getDefaultSuccess(), Util::handleFailure);
|
||||
event.getMessage().delete().queue(RestAction.getDefaultSuccess(), Util::handleFailure);
|
||||
event.replyEmbeds(Util.genericSuccessEmbed("Success", "The suggestion was accepted and posted in the suggestion channel")).setEphemeral(true).queue();
|
||||
modLogChannel.sendMessageEmbeds(new EmbedBuilder(suggestionMessage).addField("Accepted", event.getUser().getAsMention(), false).setColor(Color.GREEN).build())
|
||||
.queue(RestAction.getDefaultSuccess(), Util::handleFailure);
|
||||
sendModLog(modLog, suggestionMessage, event);
|
||||
}, failure -> event.replyEmbeds(Util.genericErrorEmbed("Error", "Unable to send suggestion to the suggestion channel"))
|
||||
.setEphemeral(true).queue(RestAction.getDefaultSuccess(), Util::handleFailure));
|
||||
}
|
||||
|
||||
public void sendSuggestionInForum(ForumChannel forumChannel, TextChannel modLog, MessageEmbed.Field field, MessageEmbed suggestionMessage, String mentionMember, ButtonInteractionEvent event) {
|
||||
MessageCreateData messageCreateData = new MessageCreateBuilder().addContent("**Suggestion by: " + mentionMember + "**\n\n" + field.getValue() + "\u200B").build();
|
||||
|
||||
forumChannel.createForumPost(field.getName(), messageCreateData).queue(success -> {
|
||||
event.getMessage().delete().queue(RestAction.getDefaultSuccess(), Util::handleFailure);
|
||||
event.replyEmbeds(Util.genericSuccessEmbed("Success", "The suggestion was accepted and posted in the suggestion channel")).setEphemeral(true).queue();
|
||||
sendModLog(modLog, suggestionMessage, event);
|
||||
success.getMessage().addReaction(Emoji.fromUnicode("\uD83D\uDC4D")).queue(RestAction.getDefaultSuccess(), Util::handleFailure);
|
||||
success.getMessage().addReaction(Emoji.fromUnicode("\uD83D\uDC4E")).queue(RestAction.getDefaultSuccess(), Util::handleFailure);
|
||||
}, failure -> event.replyEmbeds(Util.genericErrorEmbed("Error", "Unable to send suggestion to the suggestion channel"))
|
||||
.setEphemeral(true).queue(RestAction.getDefaultSuccess(), Util::handleFailure));
|
||||
}
|
||||
|
||||
public void sendModLog(TextChannel modLog, MessageEmbed suggestionMessage, ButtonInteractionEvent event) {
|
||||
modLog.sendMessageEmbeds(new EmbedBuilder(suggestionMessage).addField("Accepted", event.getUser().getAsMention(), false).setColor(Color.GREEN).build())
|
||||
.queue(RestAction.getDefaultSuccess(), Util::handleFailure);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Button getButton() {
|
||||
return Button.success(getButtonId(), "Accept Suggestion");
|
||||
|
|
|
|||
|
|
@ -8,9 +8,11 @@ import net.dv8tion.jda.api.EmbedBuilder;
|
|||
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.entities.channel.middleman.GuildMessageChannel;
|
||||
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
|
||||
import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel;
|
||||
import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent;
|
||||
import net.dv8tion.jda.api.interactions.components.buttons.Button;
|
||||
import net.dv8tion.jda.api.requests.RestAction;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.List;
|
||||
|
|
@ -25,30 +27,30 @@ public class ButtonSuggestionReviewDeny extends DiscordButton {
|
|||
@Override
|
||||
public void execute(ButtonInteractionEvent event) {
|
||||
Message message = event.getMessage();
|
||||
long channelId = CommandOutputChannels.getOutputChannel(message.getGuild().getIdLong(), OutputType.MOD_LOG);
|
||||
GuildChannel guildChannel = CommandOutputChannels.getOutputChannel(message.getGuild(), OutputType.MOD_LOG);
|
||||
TextChannel channel = validModLogChannel(event, guildChannel);
|
||||
if (channel == null)
|
||||
return;
|
||||
|
||||
List<MessageEmbed> embeds = message.getEmbeds();
|
||||
if (embeds.size() != 1) {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "This message contains no embeds, can't be a suggestion")).setEphemeral(true).queue();
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "This message contains no embeds, can't be a suggestion"))
|
||||
.setEphemeral(true).queue(RestAction.getDefaultSuccess(), Util::handleFailure);
|
||||
return;
|
||||
}
|
||||
|
||||
Guild guild = event.getGuild();
|
||||
if (guild == null) {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "Unable to retrieve guild")).setEphemeral(true).queue();
|
||||
return;
|
||||
}
|
||||
|
||||
GuildMessageChannel channel = guild.getChannelById(GuildMessageChannel.class, channelId);
|
||||
if (channel == null) {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "This server does not have a valid mod log channel")).setEphemeral(true).queue();
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "Unable to retrieve guild"))
|
||||
.setEphemeral(true).queue(RestAction.getDefaultSuccess(), Util::handleFailure);
|
||||
return;
|
||||
}
|
||||
|
||||
MessageEmbed reviewMessage = embeds.get(0);
|
||||
List<MessageEmbed.Field> fields = reviewMessage.getFields();
|
||||
if (fields.size() != 1) {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "This message's embed does not contain a field, can't be a suggestion")).setEphemeral(true).queue();
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "This message's embed does not contain a field, can't be a suggestion"))
|
||||
.setEphemeral(true).queue(RestAction.getDefaultSuccess(), Util::handleFailure);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -60,12 +62,29 @@ public class ButtonSuggestionReviewDeny extends DiscordButton {
|
|||
.build();
|
||||
channel.sendMessageEmbeds(suggestionMessage).queue(success -> {
|
||||
message.delete().queue();
|
||||
event.replyEmbeds(Util.genericSuccessEmbed("Success", "The suggestion was denied and logged")).setEphemeral(true).queue();
|
||||
event.replyEmbeds(Util.genericSuccessEmbed("Success", "The suggestion was denied and logged"))
|
||||
.setEphemeral(true).queue(RestAction.getDefaultSuccess(), Util::handleFailure);
|
||||
}, failure -> {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "Unable to send suggestion to the suggestion channel")).setEphemeral(true).queue();
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "Unable to send suggestion to the suggestion channel"))
|
||||
.setEphemeral(true).queue(RestAction.getDefaultSuccess(), Util::handleFailure);
|
||||
});
|
||||
}
|
||||
|
||||
private TextChannel validModLogChannel(ButtonInteractionEvent event, GuildChannel guildChannel) {
|
||||
if (guildChannel == null) {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "This server does not have a valid mod log channel"))
|
||||
.setEphemeral(true).queue(RestAction.getDefaultSuccess(), Util::handleFailure);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!(guildChannel instanceof TextChannel channel)) {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "A mod log channel can't be of type: " + guildChannel.getType().name()))
|
||||
.setEphemeral(true).queue(RestAction.getDefaultSuccess(), Util::handleFailure);
|
||||
return null;
|
||||
}
|
||||
return channel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Button getButton() {
|
||||
return Button.danger(getButtonId(), "Deny Suggestion");
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package com.alttd.commandManager;
|
|||
import com.alttd.commandManager.commands.AddCommand.CommandManage;
|
||||
import com.alttd.commandManager.commands.*;
|
||||
import com.alttd.commandManager.commands.PollCommand.CommandPoll;
|
||||
import com.alttd.contextMenuManager.ContextMenuManager;
|
||||
import com.alttd.database.Database;
|
||||
import com.alttd.modalManager.ModalManager;
|
||||
import com.alttd.util.Logger;
|
||||
|
|
@ -29,12 +30,13 @@ public class CommandManager extends ListenerAdapter {
|
|||
private final List<DiscordCommand> commands;
|
||||
private final HashMap<String, List<ScopeInfo>> commandList = new HashMap<>();
|
||||
|
||||
public CommandManager(JDA jda, ModalManager modalManager) {
|
||||
public CommandManager(JDA jda, ModalManager modalManager, ContextMenuManager contextMenuManager) {
|
||||
commandList.put("manage", new ArrayList<>(List.of(new ScopeInfo(CommandScope.GLOBAL, 0))));
|
||||
loadCommands();
|
||||
Logger.info("Loading commands...");
|
||||
CommandSetToggleableRoles commandSetToggleableRoles = new CommandSetToggleableRoles(jda, this);
|
||||
commands = List.of(
|
||||
new CommandManage(jda, this),
|
||||
new CommandManage(jda, this, contextMenuManager),
|
||||
new CommandHelp(jda, this),
|
||||
new CommandPoll(jda, this),
|
||||
new CommandSuggestion(jda, modalManager, this),
|
||||
|
|
@ -43,8 +45,10 @@ public class CommandManager extends ListenerAdapter {
|
|||
new CommandEvidence(jda, modalManager, this),
|
||||
new CommandFlag(jda, this),
|
||||
new CommandHistory(jda, this),
|
||||
new CommandSeen(jda, this)
|
||||
);
|
||||
new CommandSeen(jda, this),
|
||||
commandSetToggleableRoles,
|
||||
new CommandToggleRole(commandSetToggleableRoles, jda, this),
|
||||
new CommandRemindMe(jda, this, modalManager));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import com.alttd.commandManager.CommandManager;
|
|||
import com.alttd.commandManager.DiscordCommand;
|
||||
import com.alttd.commandManager.SubCommand;
|
||||
import com.alttd.commandManager.SubOption;
|
||||
import com.alttd.contextMenuManager.ContextMenuManager;
|
||||
import com.alttd.util.Logger;
|
||||
import com.alttd.util.Util;
|
||||
import net.dv8tion.jda.api.JDA;
|
||||
|
|
@ -23,7 +24,7 @@ public class CommandManage extends DiscordCommand {
|
|||
private final HashMap<String, SubOption> subOptionsMap = new HashMap<>();
|
||||
private final CommandData commandData;
|
||||
|
||||
public CommandManage(JDA jda, CommandManager commandManager) {
|
||||
public CommandManage(JDA jda, CommandManager commandManager, ContextMenuManager contextMenuManager) {
|
||||
commandData = Commands.slash(getName(), "Enable commands and assign permissions")
|
||||
.addSubcommands(
|
||||
new SubcommandData("enable", "Enable a command in a channel")
|
||||
|
|
@ -34,8 +35,8 @@ public class CommandManage extends DiscordCommand {
|
|||
.setDefaultPermissions(DefaultMemberPermissions.enabledFor(Permission.ADMINISTRATOR))
|
||||
.setGuildOnly(true);
|
||||
Util.registerSubOptions(subOptionsMap,
|
||||
new SubCommandEnable(commandManager, null, this),
|
||||
new SubCommandEnable(commandManager, null, this)
|
||||
new SubCommandEnable(commandManager, contextMenuManager, null, this),
|
||||
new SubCommandDisable(commandManager, null, this)
|
||||
);
|
||||
Util.registerCommand(commandManager, jda, commandData, getName());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,20 +1,19 @@
|
|||
package com.alttd.commandManager.commands.AddCommand;
|
||||
|
||||
import com.alttd.commandManager.*;
|
||||
import com.alttd.contextMenuManager.ContextMenuManager;
|
||||
import com.alttd.contextMenuManager.DiscordContextMenu;
|
||||
import com.alttd.database.Database;
|
||||
import com.alttd.templates.Parser;
|
||||
import com.alttd.templates.Template;
|
||||
import com.alttd.util.Logger;
|
||||
import com.alttd.util.Util;
|
||||
import com.google.protobuf.GeneratedMessageV3;
|
||||
import com.mysql.cj.log.Log;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.events.interaction.command.CommandAutoCompleteInteractionEvent;
|
||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||
import net.dv8tion.jda.api.interactions.commands.OptionMapping;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
|
@ -23,10 +22,12 @@ import java.util.stream.Collectors;
|
|||
public class SubCommandEnable extends SubCommand {
|
||||
|
||||
private final CommandManager commandManager;
|
||||
private final ContextMenuManager contextMenuManager;
|
||||
|
||||
protected SubCommandEnable(CommandManager commandManager, SubCommandGroup parentGroup, DiscordCommand parent) {
|
||||
protected SubCommandEnable(CommandManager commandManager, ContextMenuManager contextMenuManager, SubCommandGroup parentGroup, DiscordCommand parent) {
|
||||
super(parentGroup, parent);
|
||||
this.commandManager = commandManager;
|
||||
this.contextMenuManager = contextMenuManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -50,11 +51,22 @@ public class SubCommandEnable extends SubCommand {
|
|||
|
||||
String commandName = option.getAsString();
|
||||
DiscordCommand command = commandManager.getCommand(commandName);
|
||||
if (command == null) {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "Unable to find a command called [" + commandName + "].")).setEphemeral(true).queue();
|
||||
if (command != null) {
|
||||
tryEnableCommand(command, guild, commandName, event);
|
||||
return;
|
||||
}
|
||||
|
||||
DiscordContextMenu contextMenu = contextMenuManager.getContext(commandName);
|
||||
if (contextMenu != null) {
|
||||
tryEnableContextMenu(contextMenu, guild, commandName, event);
|
||||
//todo stuff
|
||||
return;
|
||||
}
|
||||
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "Unable to find a command called [" + commandName + "].")).setEphemeral(true).queue();
|
||||
}
|
||||
|
||||
private void tryEnableCommand(DiscordCommand command, Guild guild, String commandName, SlashCommandInteractionEvent event) {
|
||||
if (enableCommand(command, guild.getIdLong())) {
|
||||
Util.registerCommand(guild, command.getCommandData(), command.getName());
|
||||
event.replyEmbeds(Util.genericSuccessEmbed("Enabled command",
|
||||
|
|
@ -71,6 +83,23 @@ public class SubCommandEnable extends SubCommand {
|
|||
}
|
||||
}
|
||||
|
||||
private void tryEnableContextMenu(DiscordContextMenu contextMenu, Guild guild, String commandName, SlashCommandInteractionEvent event) {
|
||||
if (enableContextMenu(contextMenu, guild.getIdLong())) {
|
||||
Util.registerCommand(guild, contextMenu.getUserContextInteraction(), contextMenu.getContextMenuId());
|
||||
event.replyEmbeds(Util.genericSuccessEmbed("Enabled command",
|
||||
Parser.parse("Successfully enabled <command> in <guild>!",
|
||||
Template.of("command", commandName.toLowerCase()),
|
||||
Template.of("guild", guild.getName())
|
||||
))).setEphemeral(true).queue();
|
||||
} else {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Failed to enable command",
|
||||
Parser.parse("Unable to enable <command> in <guild>, is it already enabled?",
|
||||
Template.of("command", commandName.toLowerCase()),
|
||||
Template.of("guild", guild.getName())
|
||||
))).setEphemeral(true).queue();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean enableCommand(DiscordCommand command, long guildId) {
|
||||
if (!commandManager.enableCommand(command.getName(), new ScopeInfo(CommandScope.GUILD, guildId)))
|
||||
return false;
|
||||
|
|
@ -100,6 +129,35 @@ public class SubCommandEnable extends SubCommand {
|
|||
return true;
|
||||
}
|
||||
|
||||
private boolean enableContextMenu(DiscordContextMenu contextMenu, long guildId) {
|
||||
if (!commandManager.enableCommand(contextMenu.getContextMenuId(), new ScopeInfo(CommandScope.GUILD, guildId)))
|
||||
return false;
|
||||
String sql = "INSERT INTO commands (command_name, scope, location_id) VALUES(?, ?, ?)";
|
||||
PreparedStatement statement = null;
|
||||
|
||||
try {
|
||||
statement = Database.getDatabase().getConnection().prepareStatement(sql);
|
||||
statement.setString(1, contextMenu.getContextMenuId());
|
||||
statement.setString(2, "GUILD");
|
||||
statement.setLong(3, guildId);
|
||||
if (statement.executeUpdate() == 0) {
|
||||
Logger.warning("Unable to enable command: % for guild: %", contextMenu.getContextMenuId(), String.valueOf(guildId));
|
||||
return false;
|
||||
}
|
||||
} catch (SQLException exception) {
|
||||
Logger.sql(exception);
|
||||
return false;
|
||||
} finally {
|
||||
try {
|
||||
if (statement != null)
|
||||
statement.close();
|
||||
} catch (SQLException exception) {
|
||||
Logger.sql(exception);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void suggest(CommandAutoCompleteInteractionEvent event) {
|
||||
OptionMapping option = event.getOption("command");
|
||||
|
|
@ -110,13 +168,21 @@ public class SubCommandEnable extends SubCommand {
|
|||
}
|
||||
String commandName = option.getAsString().toLowerCase();
|
||||
ScopeInfo scopeInfo = new ScopeInfo(CommandScope.GLOBAL, event.getGuild().getIdLong());
|
||||
event.replyChoiceStrings(commandManager.getCommands().stream()
|
||||
.map(DiscordCommand::getName)
|
||||
.filter(name -> name.toLowerCase().startsWith(commandName))
|
||||
.filter(name -> !commandManager.getActiveLocations(name).contains(scopeInfo))
|
||||
.limit(25)
|
||||
.collect(Collectors.toList()))
|
||||
.queue();
|
||||
List<String> collect = commandManager.getCommands().stream()
|
||||
.map(DiscordCommand::getName)
|
||||
.filter(name -> name.toLowerCase().startsWith(commandName))
|
||||
.filter(name -> !commandManager.getActiveLocations(name).contains(scopeInfo))
|
||||
.limit(25)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
collect.addAll(contextMenuManager.getContexts().stream()
|
||||
.map(DiscordContextMenu::getContextMenuId)
|
||||
.filter(name -> name.toLowerCase().startsWith(commandName))
|
||||
.filter(name -> !commandManager.getActiveLocations(name).contains(scopeInfo))
|
||||
.limit(25)
|
||||
.collect(Collectors.toList()));
|
||||
|
||||
event.replyChoiceStrings(collect).queue();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -1,4 +1,186 @@
|
|||
package com.alttd.commandManager.commands;
|
||||
|
||||
public class CommandRemindMe {
|
||||
import com.alttd.commandManager.CommandManager;
|
||||
import com.alttd.commandManager.DiscordCommand;
|
||||
import com.alttd.modalManager.ModalManager;
|
||||
import com.alttd.modalManager.modals.ModalRemindMe;
|
||||
import com.alttd.util.Util;
|
||||
import net.dv8tion.jda.api.JDA;
|
||||
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
|
||||
import net.dv8tion.jda.api.entities.channel.unions.GuildChannelUnion;
|
||||
import net.dv8tion.jda.api.events.interaction.command.CommandAutoCompleteInteractionEvent;
|
||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||
import net.dv8tion.jda.api.interactions.AutoCompleteQuery;
|
||||
import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions;
|
||||
import net.dv8tion.jda.api.interactions.commands.OptionMapping;
|
||||
import net.dv8tion.jda.api.interactions.commands.OptionType;
|
||||
import net.dv8tion.jda.api.interactions.commands.build.CommandData;
|
||||
import net.dv8tion.jda.api.interactions.commands.build.Commands;
|
||||
import net.dv8tion.jda.api.interactions.components.Modal;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class CommandRemindMe extends DiscordCommand {
|
||||
|
||||
private final CommandData commandData;
|
||||
private final ModalManager modalManager;
|
||||
|
||||
public CommandRemindMe(JDA jda, CommandManager commandManager, ModalManager modalManager) {
|
||||
this.modalManager = modalManager;
|
||||
commandData = Commands.slash(getName(), "Create a reminder")
|
||||
.addOption(OptionType.CHANNEL, "channel", "The channel to send the reminder in", true)
|
||||
.addOption(OptionType.STRING, "fromnow", "How long from now the reminder should send", true, true)
|
||||
.setDefaultPermissions(DefaultMemberPermissions.ENABLED)
|
||||
.setGuildOnly(true);
|
||||
|
||||
Util.registerCommand(commandManager, jda, commandData, getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "remindme";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(SlashCommandInteractionEvent event) {
|
||||
TextChannel channel = getValidChannel(
|
||||
event.getInteraction().getOption("channel", OptionMapping::getAsChannel), event);
|
||||
if (channel == null)
|
||||
return;
|
||||
|
||||
Long fromNow = getFromNow(event.getInteraction().getOption("fromnow", OptionMapping::getAsString), event);
|
||||
if (fromNow == null)
|
||||
return;
|
||||
|
||||
Modal modal = modalManager.getModalFor("remindme");
|
||||
if (modal == null) {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "Unable to retrieve remind me modal"))
|
||||
.setEphemeral(true).queue();
|
||||
return;
|
||||
}
|
||||
|
||||
ModalRemindMe.putData(event.getUser().getIdLong(), channel, fromNow);
|
||||
event.replyModal(modal).queue();
|
||||
}
|
||||
|
||||
private TextChannel getValidChannel(GuildChannelUnion channel, SlashCommandInteractionEvent event) {
|
||||
if (channel == null) {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "Couldn't find channel"))
|
||||
.setEphemeral(true).queue();
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!(channel instanceof TextChannel textChannel)) {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "Not a valid TextChannel"))
|
||||
.setEphemeral(true).queue();
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!textChannel.canTalk()) {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "I can't talk in this channel"))
|
||||
.setEphemeral(true).queue();
|
||||
return null;
|
||||
}
|
||||
return textChannel;
|
||||
}
|
||||
|
||||
private Long getFromNow(String fromNow, SlashCommandInteractionEvent event) {
|
||||
if (fromNow == null) {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "Couldn't find from now option"))
|
||||
.setEphemeral(true).queue();
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!fromNow.matches("[1-9][0-9]*[hdmy]")) {
|
||||
return fromNowTimestamp(fromNow, event);
|
||||
}
|
||||
|
||||
int i;
|
||||
try {
|
||||
i = Integer.parseInt(fromNow.substring(0, fromNow.length() - 1));
|
||||
} catch (NumberFormatException e) {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "Invalid number"))
|
||||
.setEphemeral(true).queue();
|
||||
return null;
|
||||
}
|
||||
|
||||
switch (fromNow.substring(fromNow.length() - 1)) {
|
||||
case "h" -> {
|
||||
return TimeUnit.HOURS.toMillis(i) + new Date().getTime();
|
||||
}
|
||||
case "d" -> {
|
||||
return TimeUnit.DAYS.toMillis(i) + new Date().getTime();
|
||||
}
|
||||
case "m" -> {
|
||||
Calendar instance = Calendar.getInstance();
|
||||
instance.setTime(new Date());
|
||||
instance.add(Calendar.MONTH, i);
|
||||
return instance.getTimeInMillis();
|
||||
}
|
||||
case "y" -> {
|
||||
Calendar instance = Calendar.getInstance();
|
||||
instance.setTime(new Date());
|
||||
instance.add(Calendar.YEAR, i);
|
||||
return instance.getTimeInMillis();
|
||||
}
|
||||
default -> {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "Invalid format? This shouldn't be possible..."))
|
||||
.setEphemeral(true).queue();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Long fromNowTimestamp(String fromNow, SlashCommandInteractionEvent event) {
|
||||
if (!fromNow.matches("t:[1-9][0-9]*")) {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "Invalid from now format ex: `1d`"))
|
||||
.setEphemeral(true).queue();
|
||||
return null;
|
||||
}
|
||||
long l;
|
||||
try {
|
||||
l = Long.parseLong(fromNow.substring(2));
|
||||
} catch (NumberFormatException e) {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "Invalid number"))
|
||||
.setEphemeral(true).queue();
|
||||
return null;
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void suggest(CommandAutoCompleteInteractionEvent event) {
|
||||
AutoCompleteQuery focusedOption = event.getFocusedOption();
|
||||
if (!focusedOption.getName().equals("fromnow")) {
|
||||
event.replyChoices(Collections.emptyList()).queue();
|
||||
return;
|
||||
}
|
||||
|
||||
String value = focusedOption.getValue();
|
||||
if (value.isBlank()) {
|
||||
event.replyChoiceStrings(List.of("1h", "1d", "1m", "1y", "t:" + new Date().getTime())).queue();
|
||||
return;
|
||||
}
|
||||
|
||||
if (value.matches("[0-9]+"))
|
||||
event.replyChoiceStrings(List.of(value + "h", value + "d", value + "m", value + "y")).queue();
|
||||
else if (value.startsWith("t:"))
|
||||
event.replyChoiceStrings(List.of(value)).queue();
|
||||
else
|
||||
event.replyChoices(Collections.emptyList()).queue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelpMessage() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandData getCommandData() {
|
||||
return commandData;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import com.alttd.util.Util;
|
|||
import net.dv8tion.jda.api.JDA;
|
||||
import net.dv8tion.jda.api.Permission;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.entities.channel.ChannelType;
|
||||
import net.dv8tion.jda.api.entities.channel.unions.GuildChannelUnion;
|
||||
import net.dv8tion.jda.api.events.interaction.command.CommandAutoCompleteInteractionEvent;
|
||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||
|
|
@ -71,10 +72,11 @@ public class CommandSetOutputChannel extends DiscordCommand {
|
|||
return;
|
||||
}
|
||||
|
||||
GuildChannelUnion channel = option.getAsChannel();
|
||||
switch (channel.getType()) {
|
||||
case TEXT, NEWS, GUILD_NEWS_THREAD, GUILD_PUBLIC_THREAD, GUILD_PRIVATE_THREAD -> {
|
||||
boolean success = CommandOutputChannels.setOutputChannel(guild.getIdLong(), outputType, channel.getIdLong());
|
||||
ChannelType channelType = option.getChannelType();
|
||||
switch (channelType) {
|
||||
case TEXT, NEWS, GUILD_NEWS_THREAD, GUILD_PUBLIC_THREAD, GUILD_PRIVATE_THREAD, FORUM -> {
|
||||
GuildChannelUnion channel = option.getAsChannel();
|
||||
boolean success = CommandOutputChannels.setOutputChannel(guild.getIdLong(), outputType, channel.getIdLong(), channelType);
|
||||
if (success)
|
||||
event.replyEmbeds(Util.genericSuccessEmbed("Success", "Set channel " + channel.getAsMention() + " as the output channel for " + outputType.name() + "."))
|
||||
.setEphemeral(true).queue(RestAction.getDefaultSuccess(), Util::handleFailure);
|
||||
|
|
@ -82,7 +84,7 @@ public class CommandSetOutputChannel extends DiscordCommand {
|
|||
event.replyEmbeds(Util.genericErrorEmbed("Error", "Unable to store the new channel output in the database"))
|
||||
.setEphemeral(true).queue(RestAction.getDefaultSuccess(), Util::handleFailure);
|
||||
}
|
||||
default -> event.replyEmbeds(Util.genericErrorEmbed("Error", "The channel type " + channel.getType().name() + " is not a valid output channel type"))
|
||||
default -> event.replyEmbeds(Util.genericErrorEmbed("Error", "The channel type " + channelType.name() + " is not a valid output channel type"))
|
||||
.setEphemeral(true).queue(RestAction.getDefaultSuccess(), Util::handleFailure);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,147 @@
|
|||
package com.alttd.commandManager.commands;
|
||||
|
||||
import com.alttd.commandManager.CommandManager;
|
||||
import com.alttd.commandManager.DiscordCommand;
|
||||
import com.alttd.database.queries.QueriesToggleableRoles;
|
||||
import com.alttd.util.Util;
|
||||
import net.dv8tion.jda.api.EmbedBuilder;
|
||||
import net.dv8tion.jda.api.JDA;
|
||||
import net.dv8tion.jda.api.Permission;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||
import net.dv8tion.jda.api.entities.Role;
|
||||
import net.dv8tion.jda.api.events.interaction.command.CommandAutoCompleteInteractionEvent;
|
||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||
import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions;
|
||||
import net.dv8tion.jda.api.interactions.commands.OptionMapping;
|
||||
import net.dv8tion.jda.api.interactions.commands.OptionType;
|
||||
import net.dv8tion.jda.api.interactions.commands.build.CommandData;
|
||||
import net.dv8tion.jda.api.interactions.commands.build.Commands;
|
||||
import net.dv8tion.jda.api.requests.RestAction;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class CommandSetToggleableRoles extends DiscordCommand {
|
||||
|
||||
private final HashMap<Long, HashSet<Long>> guildToRolesMap;
|
||||
private final CommandData commandData;
|
||||
|
||||
public CommandSetToggleableRoles(JDA jda, CommandManager commandManager) {
|
||||
guildToRolesMap = QueriesToggleableRoles.getToggleableRoles();
|
||||
|
||||
commandData = Commands.slash(getName(), "Set which roles can be toggled")
|
||||
.addOption(OptionType.ROLE, "role", "The role you want to toggle on/off", false)
|
||||
.setDefaultPermissions(DefaultMemberPermissions.DISABLED);
|
||||
|
||||
Util.registerCommand(commandManager, jda, commandData, getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "settoggleableroles";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(SlashCommandInteractionEvent event) {
|
||||
Guild guild = event.getGuild();
|
||||
if (guild == null) {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "This command has to be ran in a guild"))
|
||||
.setEphemeral(true).queue(RestAction.getDefaultSuccess(), Util::handleFailure);
|
||||
return;
|
||||
}
|
||||
List<OptionMapping> options = event.getInteraction().getOptions();
|
||||
if (options.size() == 0) {
|
||||
String toggleableRoles = getToggleableRoles(guild);
|
||||
MessageEmbed messageEmbed = new EmbedBuilder()
|
||||
.setTitle("Active roles")
|
||||
.setColor(Color.GREEN)
|
||||
.setDescription(toggleableRoles)
|
||||
.build();
|
||||
|
||||
event.replyEmbeds(messageEmbed).setEphemeral(true).queue(RestAction.getDefaultSuccess(), Util::handleFailure);
|
||||
return;
|
||||
}
|
||||
OptionMapping optionMapping = options.get(0);
|
||||
Role role = optionMapping.getAsRole();
|
||||
if (containsRole(role)) {
|
||||
if (!QueriesToggleableRoles.removeRoleToggleable(role)) {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "Unable to remove role from the database"))
|
||||
.setEphemeral(true).queue(RestAction.getDefaultSuccess(), Util::handleFailure);
|
||||
return;
|
||||
}
|
||||
removeRole(role);
|
||||
event.replyEmbeds(Util.genericSuccessEmbed("Success", "Removed " + role.getAsMention() + " from the toggleable roles"))
|
||||
.setEphemeral(true).queue(RestAction.getDefaultSuccess(), Util::handleFailure);
|
||||
} else {
|
||||
if (role.hasPermission(Permission.ADMINISTRATOR) ||
|
||||
role.hasPermission(Permission.MANAGE_ROLES) ||
|
||||
role.hasPermission(Permission.MANAGE_CHANNEL) ||
|
||||
role.hasPermission(Permission.MANAGE_THREADS) ||
|
||||
role.hasPermission(Permission.MANAGE_WEBHOOKS) ||
|
||||
role.hasPermission(Permission.MANAGE_SERVER) ||
|
||||
role.hasPermission(Permission.MANAGE_PERMISSIONS) ||
|
||||
role.hasPermission(Permission.MESSAGE_MANAGE) ||
|
||||
role.hasPermission(Permission.MODERATE_MEMBERS)) {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "For safety reason this bot can not add roles which have a manage or moderator permission"))
|
||||
.setEphemeral(true).queue(RestAction.getDefaultSuccess(), Util::handleFailure);
|
||||
return;
|
||||
}
|
||||
if (!QueriesToggleableRoles.addRoleToggleable(role)) {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "Unable to store role in the database"))
|
||||
.setEphemeral(true).queue(RestAction.getDefaultSuccess(), Util::handleFailure);
|
||||
return;
|
||||
}
|
||||
addRole(role);
|
||||
event.replyEmbeds(Util.genericSuccessEmbed("Success", "Added " + role.getAsMention() + " to the toggleable roles"))
|
||||
.setEphemeral(true).queue(RestAction.getDefaultSuccess(), Util::handleFailure);
|
||||
}
|
||||
}
|
||||
|
||||
private void addRole(Role role) {
|
||||
long guild = role.getGuild().getIdLong();
|
||||
HashSet<Long> set = guildToRolesMap.getOrDefault(guild, new HashSet<>());
|
||||
set.add(role.getIdLong());
|
||||
guildToRolesMap.put(guild, set);
|
||||
}
|
||||
|
||||
private void removeRole(Role role) {
|
||||
long guild = role.getGuild().getIdLong();
|
||||
HashSet<Long> set = guildToRolesMap.getOrDefault(guild, new HashSet<>());
|
||||
if (set.isEmpty())
|
||||
return;
|
||||
set.remove(role.getIdLong());
|
||||
guildToRolesMap.put(guild, set);
|
||||
}
|
||||
|
||||
public boolean containsRole(Role role) {
|
||||
return guildToRolesMap.getOrDefault(role.getGuild().getIdLong(), new HashSet<>()).contains(role.getIdLong());
|
||||
}
|
||||
|
||||
public String getToggleableRoles(Guild guild) {
|
||||
HashSet<Long> roleIds = guildToRolesMap.get(guild.getIdLong());
|
||||
return guild.getRoles().stream()
|
||||
.filter(role -> roleIds.contains(role.getIdLong()))
|
||||
.map(Role::getAsMention)
|
||||
.collect(Collectors.joining("\n"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void suggest(CommandAutoCompleteInteractionEvent event) {
|
||||
event.replyChoices(Collections.emptyList()).queue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelpMessage() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandData getCommandData() {
|
||||
return commandData;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,108 @@
|
|||
package com.alttd.commandManager.commands;
|
||||
|
||||
import com.alttd.commandManager.CommandManager;
|
||||
import com.alttd.commandManager.DiscordCommand;
|
||||
import com.alttd.util.Util;
|
||||
import net.dv8tion.jda.api.EmbedBuilder;
|
||||
import net.dv8tion.jda.api.JDA;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||
import net.dv8tion.jda.api.entities.Role;
|
||||
import net.dv8tion.jda.api.events.interaction.command.CommandAutoCompleteInteractionEvent;
|
||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||
import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions;
|
||||
import net.dv8tion.jda.api.interactions.commands.OptionMapping;
|
||||
import net.dv8tion.jda.api.interactions.commands.OptionType;
|
||||
import net.dv8tion.jda.api.interactions.commands.build.CommandData;
|
||||
import net.dv8tion.jda.api.interactions.commands.build.Commands;
|
||||
import net.dv8tion.jda.api.requests.RestAction;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class CommandToggleRole extends DiscordCommand {
|
||||
|
||||
private final CommandSetToggleableRoles commandSetToggleableRoles;
|
||||
private final CommandData commandData;
|
||||
|
||||
public CommandToggleRole(CommandSetToggleableRoles commandSetToggleableRoles, JDA jda, CommandManager commandManager) {
|
||||
this.commandSetToggleableRoles = commandSetToggleableRoles;
|
||||
commandData = Commands.slash(getName(), "Toggle a role")
|
||||
.addOption(OptionType.ROLE, "role", "The role you want to toggle on/off (run the command without this option to see all available roles)", false)
|
||||
.setDefaultPermissions(DefaultMemberPermissions.ENABLED);
|
||||
|
||||
Util.registerCommand(commandManager, jda, commandData, getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "togglerole";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(SlashCommandInteractionEvent event) {
|
||||
Guild guild = event.getGuild();
|
||||
if (guild == null) {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "This command has to be ran in a guild"))
|
||||
.setEphemeral(true).queue(RestAction.getDefaultSuccess(), Util::handleFailure);
|
||||
return;
|
||||
}
|
||||
List<OptionMapping> options = event.getInteraction().getOptions();
|
||||
if (options.size() == 0) {
|
||||
String toggleableRoles = commandSetToggleableRoles.getToggleableRoles(guild);
|
||||
MessageEmbed messageEmbed = new EmbedBuilder()
|
||||
.setTitle("Toggleable roles")
|
||||
.setColor(Color.GREEN)
|
||||
.setDescription(toggleableRoles)
|
||||
.build();
|
||||
|
||||
event.replyEmbeds(messageEmbed).setEphemeral(true).queue(RestAction.getDefaultSuccess(), Util::handleFailure);
|
||||
return;
|
||||
}
|
||||
OptionMapping optionMapping = options.get(0);
|
||||
Role role = optionMapping.getAsRole();
|
||||
if (!commandSetToggleableRoles.containsRole(role)) {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "This role is not toggleable!"))
|
||||
.setEphemeral(true).queue(RestAction.getDefaultSuccess(), Util::handleFailure);
|
||||
return;
|
||||
}
|
||||
|
||||
Member member = event.getMember();
|
||||
if (member == null) {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "This command has to be ran in a guild"))
|
||||
.setEphemeral(true).queue(RestAction.getDefaultSuccess(), Util::handleFailure);
|
||||
return;
|
||||
}
|
||||
|
||||
if (member.getRoles().contains(role)) {
|
||||
guild.removeRoleFromMember(member, role).queue(success ->
|
||||
event.replyEmbeds(Util.genericSuccessEmbed("Role removed", "You no longer have " + role.getAsMention() + "."))
|
||||
.setEphemeral(true).queue(RestAction.getDefaultSuccess(), Util::handleFailure),
|
||||
error -> event.replyEmbeds(Util.genericErrorEmbed("Error", "Unable to manage your roles."))
|
||||
.setEphemeral(true).queue(RestAction.getDefaultSuccess(), Util::handleFailure));
|
||||
} else {
|
||||
guild.addRoleToMember(member, role).queue(success ->
|
||||
event.replyEmbeds(Util.genericSuccessEmbed("Role add", "You now have " + role.getAsMention() + "."))
|
||||
.setEphemeral(true).queue(RestAction.getDefaultSuccess(), Util::handleFailure),
|
||||
error -> event.replyEmbeds(Util.genericErrorEmbed("Error", "Unable to manage your roles."))
|
||||
.setEphemeral(true).queue(RestAction.getDefaultSuccess(), Util::handleFailure));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void suggest(CommandAutoCompleteInteractionEvent event) {
|
||||
event.replyChoices(Collections.emptyList()).queue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelpMessage() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandData getCommandData() {
|
||||
return commandData;
|
||||
}
|
||||
}
|
||||
|
|
@ -22,14 +22,14 @@ import java.util.Map;
|
|||
import java.util.regex.Pattern;
|
||||
|
||||
@SuppressWarnings({"unused", "SameParameterValue"})
|
||||
abstract class AbstractConfig {
|
||||
public abstract class AbstractConfig {
|
||||
private static final Pattern PATH_PATTERN = Pattern.compile("\\.");
|
||||
private static final String HEADER = "";
|
||||
|
||||
private YamlConfigurationLoader configLoader;
|
||||
private ConfigurationNode config;
|
||||
|
||||
AbstractConfig(String filename) {
|
||||
protected AbstractConfig(String filename) {
|
||||
init(new File(new File(AltitudeBot.getInstance().getDataFolder()).getParentFile(), filename), filename);
|
||||
}
|
||||
|
||||
|
|
@ -60,7 +60,7 @@ abstract class AbstractConfig {
|
|||
}
|
||||
}
|
||||
|
||||
void readConfig(Class<?> clazz, Object instance) {
|
||||
protected void readConfig(Class<?> clazz, Object instance) {
|
||||
for (Method method : clazz.getDeclaredMethods()) {
|
||||
if (Modifier.isPrivate(method.getModifiers())) {
|
||||
if (method.getParameterTypes().length == 0 && method.getReturnType() == Void.TYPE) {
|
||||
|
|
@ -80,7 +80,7 @@ abstract class AbstractConfig {
|
|||
save();
|
||||
}
|
||||
|
||||
private void save() {
|
||||
protected void save() {
|
||||
try {
|
||||
configLoader.save(config);
|
||||
} catch (IOException ex) {
|
||||
|
|
@ -101,6 +101,17 @@ abstract class AbstractConfig {
|
|||
}
|
||||
}
|
||||
|
||||
protected void update(String path, Object def) {
|
||||
if(config.node(splitPath(path)).virtual()) {
|
||||
set(path, def);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
config.node(splitPath(path)).set(def);
|
||||
} catch (SerializationException e) {
|
||||
}
|
||||
}
|
||||
|
||||
protected void setString(String path, String def) {
|
||||
try {
|
||||
if(config.node(splitPath(path)).virtual())
|
||||
|
|
|
|||
|
|
@ -0,0 +1,76 @@
|
|||
package com.alttd.contextMenuManager;
|
||||
|
||||
import com.alttd.contextMenuManager.contextMenus.ContextMenuRespondSuggestion;
|
||||
import com.alttd.modalManager.ModalManager;
|
||||
import com.alttd.util.Util;
|
||||
import net.dv8tion.jda.api.EmbedBuilder;
|
||||
import net.dv8tion.jda.api.events.interaction.command.MessageContextInteractionEvent;
|
||||
import net.dv8tion.jda.api.events.interaction.command.UserContextInteractionEvent;
|
||||
import net.dv8tion.jda.api.hooks.ListenerAdapter;
|
||||
import net.dv8tion.jda.api.requests.RestAction;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.awt.*;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public class ContextMenuManager extends ListenerAdapter {
|
||||
|
||||
private final List<DiscordContextMenu> contextMenus;
|
||||
|
||||
public ContextMenuManager(ModalManager modalManager) {
|
||||
contextMenus = List.of(
|
||||
new ContextMenuRespondSuggestion(modalManager)
|
||||
);
|
||||
}
|
||||
|
||||
public DiscordContextMenu getContext(String name) {
|
||||
for (DiscordContextMenu contextMenu : contextMenus) {
|
||||
if (contextMenu.getContextMenuId().equalsIgnoreCase(name))
|
||||
return contextMenu;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<DiscordContextMenu> getContexts() {
|
||||
return contextMenus;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUserContextInteraction(@Nonnull UserContextInteractionEvent event) {
|
||||
String name = event.getInteraction().getName();
|
||||
Optional<DiscordContextMenu> first = contextMenus.stream()
|
||||
.filter(discordModal -> discordModal.getContextMenuId().equalsIgnoreCase(name))
|
||||
.findFirst();
|
||||
if (first.isEmpty()) {
|
||||
event.replyEmbeds(new EmbedBuilder()
|
||||
.setTitle("Invalid command")
|
||||
.setDescription("Unable to process user context interaction with id: [" + name + "].")
|
||||
.setColor(Color.RED)
|
||||
.build())
|
||||
.setEphemeral(true)
|
||||
.queue(RestAction.getDefaultSuccess(), Util::handleFailure);
|
||||
return;
|
||||
}
|
||||
first.get().execute(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMessageContextInteraction(@Nonnull MessageContextInteractionEvent event) {
|
||||
String name = event.getInteraction().getName();
|
||||
Optional<DiscordContextMenu> first = contextMenus.stream()
|
||||
.filter(discordModal -> discordModal.getContextMenuId().equalsIgnoreCase(name))
|
||||
.findFirst();
|
||||
if (first.isEmpty()) {
|
||||
event.replyEmbeds(new EmbedBuilder()
|
||||
.setTitle("Invalid command")
|
||||
.setDescription("Unable to process user context interaction with id: [" + name + "].")
|
||||
.setColor(Color.RED)
|
||||
.build())
|
||||
.setEphemeral(true)
|
||||
.queue(RestAction.getDefaultSuccess(), Util::handleFailure);
|
||||
return;
|
||||
}
|
||||
first.get().execute(event);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
package com.alttd.contextMenuManager;
|
||||
|
||||
import net.dv8tion.jda.api.events.interaction.command.MessageContextInteractionEvent;
|
||||
import net.dv8tion.jda.api.events.interaction.command.UserContextInteractionEvent;
|
||||
import net.dv8tion.jda.api.interactions.commands.build.CommandData;
|
||||
|
||||
public abstract class DiscordContextMenu {
|
||||
|
||||
public abstract String getContextMenuId();
|
||||
|
||||
public abstract void execute(UserContextInteractionEvent event);
|
||||
|
||||
public abstract void execute(MessageContextInteractionEvent event);
|
||||
|
||||
public abstract CommandData getUserContextInteraction();
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
package com.alttd.contextMenuManager.contextMenus;
|
||||
|
||||
import com.alttd.contextMenuManager.DiscordContextMenu;
|
||||
import com.alttd.database.queries.commandOutputChannels.CommandOutputChannels;
|
||||
import com.alttd.database.queries.commandOutputChannels.OutputType;
|
||||
import com.alttd.modalManager.ModalManager;
|
||||
import com.alttd.modalManager.modals.ModalReplySuggestion;
|
||||
import com.alttd.util.Util;
|
||||
import net.dv8tion.jda.api.Permission;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.entities.channel.ChannelType;
|
||||
import net.dv8tion.jda.api.entities.channel.concrete.ThreadChannel;
|
||||
import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel;
|
||||
import net.dv8tion.jda.api.entities.channel.unions.IThreadContainerUnion;
|
||||
import net.dv8tion.jda.api.entities.channel.unions.MessageChannelUnion;
|
||||
import net.dv8tion.jda.api.events.interaction.command.MessageContextInteractionEvent;
|
||||
import net.dv8tion.jda.api.events.interaction.command.UserContextInteractionEvent;
|
||||
import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions;
|
||||
import net.dv8tion.jda.api.interactions.commands.build.CommandData;
|
||||
import net.dv8tion.jda.api.interactions.commands.build.Commands;
|
||||
import net.dv8tion.jda.api.interactions.components.Modal;
|
||||
import net.dv8tion.jda.api.requests.RestAction;
|
||||
|
||||
public class ContextMenuRespondSuggestion extends DiscordContextMenu {
|
||||
|
||||
private final ModalManager modalManager;
|
||||
|
||||
public ContextMenuRespondSuggestion(ModalManager modalManager) {
|
||||
this.modalManager = modalManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getContextMenuId() {
|
||||
return "Respond To Suggestion";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(UserContextInteractionEvent event) {
|
||||
event.getInteraction().replyEmbeds(Util.genericErrorEmbed("Error", "This interaction should have been a message interaction"))
|
||||
.setEphemeral(true).queue(RestAction.getDefaultSuccess(), Util::handleFailure);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(MessageContextInteractionEvent event) {
|
||||
Message message = event.getInteraction().getTarget();
|
||||
if (!isSuggestion(message)) {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "This is not a suggestion"))
|
||||
.setEphemeral(true).queue(RestAction.getDefaultSuccess(), Util::handleFailure);
|
||||
return;
|
||||
}
|
||||
|
||||
Modal replySuggestion = modalManager.getModalFor("reply_suggestion");
|
||||
if (replySuggestion == null) {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "Unable to find reply suggestion modal"))
|
||||
.setEphemeral(true).queue(RestAction.getDefaultSuccess(), Util::handleFailure);
|
||||
return;
|
||||
}
|
||||
|
||||
ModalReplySuggestion.putMessage(event.getUser().getIdLong(), message); //TODO find a better way to do this
|
||||
event.replyModal(replySuggestion).queue(RestAction.getDefaultSuccess(), Util::handleFailure);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandData getUserContextInteraction() {
|
||||
return Commands.message(getContextMenuId())
|
||||
.setGuildOnly(true)
|
||||
.setDefaultPermissions(DefaultMemberPermissions.enabledFor(Permission.ADMINISTRATOR));
|
||||
}
|
||||
|
||||
public boolean isSuggestion(Message message) {
|
||||
GuildChannel channel = CommandOutputChannels.getOutputChannel(message.getGuild(), OutputType.SUGGESTION);
|
||||
if (channel == null)
|
||||
return false;
|
||||
MessageChannelUnion messageChannel = message.getChannel();
|
||||
if (channel.getType().equals(ChannelType.FORUM)) {
|
||||
if (messageChannel.getType() != ChannelType.GUILD_PUBLIC_THREAD) {
|
||||
return false;
|
||||
}
|
||||
ThreadChannel threadChannel = messageChannel.asThreadChannel();
|
||||
IThreadContainerUnion parentChannel = threadChannel.getParentChannel();
|
||||
if (!parentChannel.getType().equals(ChannelType.FORUM))
|
||||
return false;
|
||||
|
||||
return message.getIdLong() == messageChannel.getIdLong() && message.getAuthor().equals(message.getJDA().getSelfUser());
|
||||
} else {
|
||||
return channel.equals(messageChannel);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -65,7 +65,7 @@ public class DatabaseTables {
|
|||
connection.prepareStatement(sql).executeUpdate();
|
||||
} catch (SQLException e) {
|
||||
Logger.sql(e);
|
||||
Logger.severe("Unable to create polls table, shutting down...");
|
||||
Logger.severe("Unable to create commands table, shutting down...");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -74,13 +74,50 @@ public class DatabaseTables {
|
|||
"guild BIGINT NOT NULL, " +
|
||||
"output_type VARCHAR(64) NOT NULL, " +
|
||||
"channel BIGINT NOT NULL, " +
|
||||
"channel_type VARCHAR(64) NOT NULL, " +
|
||||
"PRIMARY KEY (guild, output_type, channel)" +
|
||||
")";
|
||||
try {
|
||||
connection.prepareStatement(sql).executeUpdate();
|
||||
} catch (SQLException e) {
|
||||
Logger.sql(e);
|
||||
Logger.severe("Unable to create polls table, shutting down...");
|
||||
Logger.severe("Unable to create output channel table, shutting down...");
|
||||
}
|
||||
}
|
||||
|
||||
private void createToggleableRolesTable() {
|
||||
String sql = "CREATE TABLE IF NOT EXISTS toggleable_roles(" +
|
||||
"guild BIGINT NOT NULL, " +
|
||||
"role BIGINT NOT NULL, " +
|
||||
"PRIMARY KEY (guild, role)" +
|
||||
")";
|
||||
try {
|
||||
connection.prepareStatement(sql).executeUpdate();
|
||||
} catch (SQLException e) {
|
||||
Logger.sql(e);
|
||||
Logger.severe("Unable to create toggleable roles table, shutting down...");
|
||||
}
|
||||
}
|
||||
|
||||
private void createReminderTable() {
|
||||
String sql = "CREATE TABLE IF NOT EXISTS new_reminders(" +
|
||||
"id INT NOT NULL AUTO_INCREMENT, " +
|
||||
"title VARCHAR(256) NOT NULL, " +
|
||||
"description VARCHAR(4096) NOT NULL, " +
|
||||
"user_id LONG NOT NULL, " +
|
||||
"guild_id LONG NOT NULL, " +
|
||||
"channel_id LONG NOT NULL, " +
|
||||
"message_id LONG NOT NULL, " +
|
||||
"should_repeat TINYINT(1) NOT NULL, " +
|
||||
"creation_date LONG NOT NULL, " +
|
||||
"remind_date LONG NOT NULL, " +
|
||||
"PRIMARY KEY (id)" +
|
||||
")";
|
||||
try {
|
||||
connection.prepareStatement(sql).executeUpdate();
|
||||
} catch (SQLException e) {
|
||||
Logger.sql(e);
|
||||
Logger.severe("Unable to create reminders table, shutting down...");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,90 @@
|
|||
package com.alttd.database.queries.QueriesReminders;
|
||||
|
||||
import com.alttd.database.Database;
|
||||
import com.alttd.util.Logger;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class QueriesReminders {
|
||||
|
||||
public static int storeReminder(Reminder reminder) {
|
||||
String sql = "INSERT INTO new_reminders " +
|
||||
"(title, description, user_id, guild_id, channel_id, message_id, should_repeat, creation_date, remind_date) " +
|
||||
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)";
|
||||
try {
|
||||
PreparedStatement preparedStatement = Database.getDatabase().getConnection().prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
|
||||
|
||||
preparedStatement.setString(1, reminder.title());
|
||||
preparedStatement.setString(2, reminder.description());
|
||||
preparedStatement.setLong(3, reminder.userId());
|
||||
preparedStatement.setLong(4, reminder.guildId());
|
||||
preparedStatement.setLong(5, reminder.channelId());
|
||||
preparedStatement.setLong(6, 0);
|
||||
preparedStatement.setInt(7, reminder.shouldRepeat() ? 1 : 0);
|
||||
preparedStatement.setLong(8, reminder.creationDate());
|
||||
preparedStatement.setLong(9, reminder.remindDate());
|
||||
|
||||
if (preparedStatement.executeUpdate() == 1) {
|
||||
ResultSet generatedKeys = preparedStatement.getGeneratedKeys();
|
||||
if (generatedKeys.next()) {
|
||||
return generatedKeys.getInt(1);
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
} catch (SQLException e) {
|
||||
Logger.exception(e);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static boolean removeReminder(int id) {
|
||||
String sql = "DELETE FROM new_reminders WHERE id = ?";
|
||||
try {
|
||||
PreparedStatement preparedStatement = Database.getDatabase().getConnection().prepareStatement(sql);
|
||||
|
||||
preparedStatement.setInt(1, id);
|
||||
|
||||
return preparedStatement.executeUpdate() == 1;
|
||||
} catch (SQLException e) {
|
||||
Logger.exception(e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static ArrayList<Reminder> getReminders() {
|
||||
String sql = "SELECT * FROM new_reminders";
|
||||
try {
|
||||
ArrayList<Reminder> reminders = new ArrayList<>();
|
||||
PreparedStatement preparedStatement = Database.getDatabase().getConnection().prepareStatement(sql);
|
||||
|
||||
ResultSet resultSet = preparedStatement.executeQuery();
|
||||
while (resultSet.next()) {
|
||||
reminders.add(getReminder(resultSet));
|
||||
}
|
||||
return reminders;
|
||||
} catch (SQLException e) {
|
||||
Logger.exception(e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Reminder getReminder(ResultSet resultSet) throws SQLException {
|
||||
int id = resultSet.getInt("id");
|
||||
String title = resultSet.getString("title");
|
||||
String desc = resultSet.getString("description");
|
||||
long userId = resultSet.getLong("user_id");
|
||||
long guildId = resultSet.getLong("guild_id");
|
||||
long channelId = resultSet.getLong("channel_id");
|
||||
long messageId = resultSet.getLong("message_id");
|
||||
boolean shouldRepeat = resultSet.getInt("should_repeat") == 1;
|
||||
long creationDate = resultSet.getLong("creation_date");
|
||||
long remindDate = resultSet.getLong("remind_date");
|
||||
return new Reminder(id, title, desc, userId, guildId, channelId, messageId, shouldRepeat, creationDate, remindDate);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
package com.alttd.database.queries.QueriesReminders;
|
||||
|
||||
import com.alttd.util.Logger;
|
||||
import net.dv8tion.jda.api.JDA;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
|
||||
|
||||
public record Reminder (int id, String title, String description, long userId, long guildId, long channelId,
|
||||
long messageId, boolean shouldRepeat, long creationDate, long remindDate) {
|
||||
public TextChannel getChannel(JDA jda) {
|
||||
Guild guildById = getGuild(jda);
|
||||
if (guildById == null)
|
||||
return null;
|
||||
|
||||
TextChannel textChannelById = guildById.getTextChannelById(this.channelId);
|
||||
if (textChannelById == null) {
|
||||
Logger.warning("Unable to find text channel for reminder, text channel id: [" + channelId + "]");
|
||||
return null;
|
||||
}
|
||||
|
||||
return textChannelById;
|
||||
}
|
||||
|
||||
public Guild getGuild(JDA jda) {
|
||||
Guild guildById = jda.getGuildById(guildId);
|
||||
if (guildById == null) {
|
||||
Logger.warning("Unable to find guild for reminder, guild id: [" + guildId + "]");
|
||||
return null;
|
||||
}
|
||||
|
||||
return guildById;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
package com.alttd.database.queries;
|
||||
|
||||
import com.alttd.database.Database;
|
||||
import net.dv8tion.jda.api.entities.Role;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
|
||||
public class QueriesToggleableRoles {
|
||||
|
||||
public static boolean addRoleToggleable(Role role) {
|
||||
String sql = "INSERT INTO toggleable_roles (guild, role) VALUES (?, ?)";
|
||||
try {
|
||||
PreparedStatement preparedStatement = Database.getDatabase().getConnection().prepareStatement(sql);
|
||||
|
||||
preparedStatement.setLong(1, role.getGuild().getIdLong());
|
||||
preparedStatement.setLong(2, role.getIdLong());
|
||||
|
||||
return preparedStatement.executeUpdate() == 1;
|
||||
} catch (SQLException exception) {
|
||||
exception.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean removeRoleToggleable(Role role) {
|
||||
String sql = "DELETE FROM toggleable_roles WHERE guild = ? AND role = ?";
|
||||
try {
|
||||
PreparedStatement preparedStatement = Database.getDatabase().getConnection().prepareStatement(sql);
|
||||
|
||||
preparedStatement.setLong(1, role.getGuild().getIdLong());
|
||||
preparedStatement.setLong(2, role.getIdLong());
|
||||
|
||||
return preparedStatement.executeUpdate() == 1;
|
||||
} catch (SQLException exception) {
|
||||
exception.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static HashMap<Long, HashSet<Long>> getToggleableRoles() {
|
||||
String sql = "SELECT * FROM toggleable_roles";
|
||||
try {
|
||||
HashMap<Long, HashSet<Long>> map = new HashMap<>();
|
||||
PreparedStatement preparedStatement = Database.getDatabase().getConnection().prepareStatement(sql);
|
||||
|
||||
ResultSet resultSet = preparedStatement.executeQuery();
|
||||
|
||||
while (resultSet.next()) {
|
||||
long guild = resultSet.getLong("guild");
|
||||
long role = resultSet.getLong("role");
|
||||
HashSet<Long> roles = map.getOrDefault(guild, new HashSet<>());
|
||||
roles.add(role);
|
||||
map.put(guild, roles);
|
||||
}
|
||||
|
||||
return map;
|
||||
} catch (SQLException exception) {
|
||||
exception.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -2,6 +2,9 @@ package com.alttd.database.queries.commandOutputChannels;
|
|||
|
||||
import com.alttd.database.Database;
|
||||
import com.alttd.util.Logger;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.entities.channel.ChannelType;
|
||||
import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
|
|
@ -9,14 +12,15 @@ import java.sql.SQLException;
|
|||
|
||||
public class CommandOutputChannels {
|
||||
|
||||
public static boolean setOutputChannel(long guildId, OutputType outputType, long channelId) {
|
||||
String sql = "INSERT INTO output_channels (guild, output_type, channel) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE channel = ?";
|
||||
public static boolean setOutputChannel(long guildId, OutputType outputType, long channelId, ChannelType channelType) {
|
||||
String sql = "INSERT INTO output_channels (guild, output_type, channel, channel_type) VALUES (?, ?, ?, ?) ON DUPLICATE KEY UPDATE channel = ?";
|
||||
try {
|
||||
PreparedStatement preparedStatement = Database.getDatabase().getConnection().prepareStatement(sql);
|
||||
preparedStatement.setLong(1, guildId);
|
||||
preparedStatement.setString(2, outputType.name());
|
||||
preparedStatement.setLong(3, channelId);
|
||||
preparedStatement.setLong(4, channelId);
|
||||
preparedStatement.setString(4, channelType.name());
|
||||
preparedStatement.setLong(5, channelId);
|
||||
|
||||
return preparedStatement.executeUpdate() == 1;
|
||||
} catch (SQLException e) {
|
||||
|
|
@ -27,26 +31,46 @@ public class CommandOutputChannels {
|
|||
|
||||
/**
|
||||
* Retrieve the channelId of the channel in the specified guild for the specified output type
|
||||
* @param guildId id of the guild to check in
|
||||
* @param guild guild to get the channel for
|
||||
* @param outputType output type to check for
|
||||
* @return long channel id or 0 if it errors or can't be found
|
||||
*/
|
||||
public static long getOutputChannel(long guildId, OutputType outputType) {
|
||||
String sql = "SELECT channel FROM output_channels WHERE guild = ? AND output_type = ?";
|
||||
public static GuildChannel getOutputChannel(Guild guild, OutputType outputType) {
|
||||
String sql = "SELECT channel, channel_type FROM output_channels WHERE guild = ? AND output_type = ?";
|
||||
try {
|
||||
PreparedStatement preparedStatement = Database.getDatabase().getConnection().prepareStatement(sql);
|
||||
preparedStatement.setLong(1, guildId);
|
||||
preparedStatement.setLong(1, guild.getIdLong());
|
||||
preparedStatement.setString(2, outputType.name());
|
||||
ResultSet resultSet = preparedStatement.executeQuery();
|
||||
|
||||
if (resultSet.next())
|
||||
return resultSet.getLong("channel");
|
||||
else
|
||||
return 0L;
|
||||
if (resultSet.next()) {
|
||||
String stringChannelType = resultSet.getString("channel_type");
|
||||
ChannelType channelType;
|
||||
try {
|
||||
channelType = ChannelType.valueOf(stringChannelType);
|
||||
} catch (IllegalArgumentException exception) {
|
||||
return null;
|
||||
}
|
||||
long channelId = resultSet.getLong("channel");
|
||||
switch (channelType) {
|
||||
case TEXT, NEWS -> {
|
||||
return guild.getTextChannelById(channelId);
|
||||
}
|
||||
case GUILD_NEWS_THREAD, GUILD_PUBLIC_THREAD, GUILD_PRIVATE_THREAD -> {
|
||||
return guild.getThreadChannelById(channelId);
|
||||
}
|
||||
case FORUM -> {
|
||||
return guild.getForumChannelById(channelId);
|
||||
}
|
||||
default -> {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
Logger.exception(e);
|
||||
return 0L;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,10 +2,16 @@ package com.alttd.listeners;
|
|||
|
||||
import com.alttd.buttonManager.ButtonManager;
|
||||
import com.alttd.commandManager.CommandManager;
|
||||
import com.alttd.contextMenuManager.ContextMenuManager;
|
||||
import com.alttd.modalManager.ModalManager;
|
||||
import com.alttd.reminders.ReminderScheduler;
|
||||
import com.alttd.request.RequestManager;
|
||||
import com.alttd.util.Logger;
|
||||
import net.dv8tion.jda.api.JDA;
|
||||
import net.dv8tion.jda.api.events.ReadyEvent;
|
||||
import net.dv8tion.jda.api.events.interaction.ModalInteractionEvent;
|
||||
import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent;
|
||||
import net.dv8tion.jda.api.events.interaction.component.SelectMenuInteractionEvent;
|
||||
import net.dv8tion.jda.api.hooks.ListenerAdapter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
|
|
@ -22,8 +28,38 @@ public class JDAListener extends ListenerAdapter {
|
|||
Logger.info("JDA ready to register commands.");
|
||||
ButtonManager buttonManager = new ButtonManager();
|
||||
ModalManager modalManager = new ModalManager(buttonManager);
|
||||
CommandManager commandManager = new CommandManager(jda, modalManager);
|
||||
jda.addEventListener(buttonManager, modalManager, commandManager);
|
||||
ContextMenuManager contextMenuManager = new ContextMenuManager(modalManager);
|
||||
CommandManager commandManager = new CommandManager(jda, modalManager, contextMenuManager);
|
||||
jda.addEventListener(buttonManager, modalManager, commandManager, contextMenuManager);
|
||||
ReminderScheduler reminderScheduler = ReminderScheduler.getInstance(jda);
|
||||
if (reminderScheduler == null) {
|
||||
Logger.severe("Unable to start reminder scheduler!");
|
||||
}
|
||||
// RequestManager.init();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSelectMenuInteraction(@NotNull SelectMenuInteractionEvent event) {
|
||||
String s = event.getComponentId();
|
||||
if (s.startsWith("request:")) {
|
||||
RequestManager.onSelectMenuInteraction(event);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onModalInteraction(@NotNull ModalInteractionEvent event) {
|
||||
String s = event.getModalId();
|
||||
if (s.startsWith("request:")) {
|
||||
RequestManager.onModalInteractionEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onButtonInteraction(ButtonInteractionEvent event) {
|
||||
String s = event.getComponentId();
|
||||
if (s.startsWith("request:")) {
|
||||
RequestManager.onButtonInteractionEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@ package com.alttd.modalManager;
|
|||
|
||||
import com.alttd.buttonManager.ButtonManager;
|
||||
import com.alttd.modalManager.modals.ModalEvidence;
|
||||
import com.alttd.modalManager.modals.ModalRemindMe;
|
||||
import com.alttd.modalManager.modals.ModalReplySuggestion;
|
||||
import com.alttd.modalManager.modals.ModalSuggestion;
|
||||
import com.alttd.util.Util;
|
||||
import net.dv8tion.jda.api.EmbedBuilder;
|
||||
|
|
@ -23,7 +25,9 @@ public class ModalManager extends ListenerAdapter {
|
|||
public ModalManager(ButtonManager buttonManager) {
|
||||
modals = List.of(
|
||||
new ModalSuggestion(buttonManager),
|
||||
new ModalEvidence());
|
||||
new ModalEvidence(),
|
||||
new ModalReplySuggestion(),
|
||||
new ModalRemindMe(buttonManager));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import net.dv8tion.jda.api.EmbedBuilder;
|
|||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||
import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel;
|
||||
import net.dv8tion.jda.api.entities.channel.middleman.GuildMessageChannel;
|
||||
import net.dv8tion.jda.api.events.interaction.ModalInteractionEvent;
|
||||
import net.dv8tion.jda.api.interactions.components.ActionRow;
|
||||
|
|
@ -48,9 +49,15 @@ public class ModalEvidence extends DiscordModal {
|
|||
return;
|
||||
}
|
||||
|
||||
GuildMessageChannel channel = guild.getChannelById(GuildMessageChannel.class, CommandOutputChannels.getOutputChannel(guild.getIdLong(), OutputType.EVIDENCE));
|
||||
if (channel == null) {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "This guild does not have a suggestion review channel or it's not the right channel type"))
|
||||
GuildChannel outputChannel = CommandOutputChannels.getOutputChannel(guild, OutputType.EVIDENCE);
|
||||
if (outputChannel == null) {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "This guild does not have an evidence channel or it's not the right channel type"))
|
||||
.setEphemeral(true).queue(RestAction.getDefaultSuccess(), Util::handleFailure);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(outputChannel instanceof GuildMessageChannel channel)) {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "Invalid Evidence channel type: " + outputChannel.getType()))
|
||||
.setEphemeral(true).queue(RestAction.getDefaultSuccess(), Util::handleFailure);
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
137
src/main/java/com/alttd/modalManager/modals/ModalRemindMe.java
Normal file
137
src/main/java/com/alttd/modalManager/modals/ModalRemindMe.java
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
package com.alttd.modalManager.modals;
|
||||
|
||||
import com.alttd.buttonManager.ButtonManager;
|
||||
import com.alttd.buttonManager.buttons.remindMeConfirm.ButtonRemindMeConfirm;
|
||||
import com.alttd.database.queries.QueriesReminders.Reminder;
|
||||
import com.alttd.modalManager.DiscordModal;
|
||||
import com.alttd.util.Util;
|
||||
import net.dv8tion.jda.api.EmbedBuilder;
|
||||
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
|
||||
import net.dv8tion.jda.api.events.interaction.ModalInteractionEvent;
|
||||
import net.dv8tion.jda.api.interactions.components.ActionRow;
|
||||
import net.dv8tion.jda.api.interactions.components.Modal;
|
||||
import net.dv8tion.jda.api.interactions.components.buttons.Button;
|
||||
import net.dv8tion.jda.api.interactions.components.text.TextInput;
|
||||
import net.dv8tion.jda.api.interactions.components.text.TextInputStyle;
|
||||
import net.dv8tion.jda.api.interactions.modals.ModalMapping;
|
||||
import net.dv8tion.jda.api.requests.RestAction;
|
||||
import net.dv8tion.jda.api.utils.TimeUtil;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class ModalRemindMe extends DiscordModal {
|
||||
|
||||
private static final HashMap<Long, RemindMeData> userToRemindMeMap = new HashMap<>();
|
||||
|
||||
public static synchronized void putData(long userId, TextChannel channel, long timestamp) {
|
||||
userToRemindMeMap.put(userId, new RemindMeData(channel, timestamp));
|
||||
}
|
||||
|
||||
private static synchronized RemindMeData pullData(long userId) {
|
||||
return userToRemindMeMap.remove(userId);
|
||||
}
|
||||
|
||||
private final ButtonManager buttonManager;
|
||||
|
||||
public ModalRemindMe(ButtonManager buttonManager) {
|
||||
this.buttonManager = buttonManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getModalId() {
|
||||
return "remindme";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(ModalInteractionEvent event) {
|
||||
String title = getValidString(event.getValue("title"), event, true);
|
||||
if (title == null)
|
||||
return;
|
||||
|
||||
String desc = getValidString(event.getValue("description"), event, false);
|
||||
if (desc == null)
|
||||
desc = "";
|
||||
|
||||
long userId = event.getUser().getIdLong();
|
||||
RemindMeData remindMeData = pullData(userId);
|
||||
if (remindMeData == null) {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "Couldn't find the data from the command that triggered this modal"))
|
||||
.setEphemeral(true).queue();
|
||||
return;
|
||||
}
|
||||
|
||||
Reminder reminder = new Reminder(
|
||||
-1,
|
||||
title,
|
||||
desc,
|
||||
userId,
|
||||
remindMeData.textChannel.getGuild().getIdLong(),
|
||||
remindMeData.textChannel.getIdLong(),
|
||||
0,
|
||||
false,
|
||||
new Date().getTime(),
|
||||
remindMeData.timestamp);
|
||||
|
||||
Button remindMeConfirm = buttonManager.getButtonFor("remind_me_confirm");
|
||||
Button remindMeCancel = buttonManager.getButtonFor("remind_me_cancel");
|
||||
if (remindMeConfirm == null || remindMeCancel == null) {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "Unable to retrieve continue/cancel buttons"))
|
||||
.setEphemeral(true).queue();
|
||||
return;
|
||||
}
|
||||
|
||||
MessageEmbed messageEmbed = new EmbedBuilder()
|
||||
.setTitle(reminder.title())
|
||||
.setDescription(reminder.description())
|
||||
.appendDescription("\n\nWill remind <t:" + TimeUnit.MILLISECONDS.toSeconds(reminder.remindDate()) + ":R>")
|
||||
.build();
|
||||
event.deferReply().setEphemeral(true).queue(defer -> {
|
||||
ButtonRemindMeConfirm.putReminder(userId, defer, reminder);
|
||||
defer.editOriginalEmbeds(messageEmbed).queue(message ->
|
||||
defer.editOriginalComponents().setActionRow(remindMeConfirm, remindMeCancel)
|
||||
.queue(RestAction.getDefaultSuccess(), Util::handleFailure));
|
||||
});
|
||||
}
|
||||
|
||||
public String getValidString(ModalMapping modalMapping, ModalInteractionEvent event, boolean required) {
|
||||
if (modalMapping == null) {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "Couldn't find modal"))
|
||||
.setEphemeral(true).queue();
|
||||
return null;
|
||||
}
|
||||
|
||||
String string = modalMapping.getAsString();
|
||||
if (string.isEmpty()) {
|
||||
if (required)
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "Couldn't find contents of modal"))
|
||||
.setEphemeral(true).queue();
|
||||
return null;
|
||||
}
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Modal getModal() {
|
||||
TextInput title = TextInput.create("title", "Title", TextInputStyle.SHORT)
|
||||
.setPlaceholder("reminder title")
|
||||
.setRequiredRange(1, 256)
|
||||
.setRequired(true)
|
||||
.build();
|
||||
|
||||
TextInput desc = TextInput.create("description", "Description", TextInputStyle.PARAGRAPH)
|
||||
.setPlaceholder("optional reminder description")
|
||||
.setRequiredRange(1, 4000)
|
||||
.setRequired(false)
|
||||
.build();
|
||||
|
||||
return Modal.create(getModalId(), "Remind Me")
|
||||
.addActionRows(ActionRow.of(title), ActionRow.of(desc))
|
||||
.build();
|
||||
}
|
||||
|
||||
private record RemindMeData(TextChannel textChannel, long timestamp) {}
|
||||
}
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
package com.alttd.modalManager.modals;
|
||||
|
||||
import com.alttd.modalManager.DiscordModal;
|
||||
import com.alttd.util.Util;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.events.interaction.ModalInteractionEvent;
|
||||
import net.dv8tion.jda.api.interactions.components.ActionRow;
|
||||
import net.dv8tion.jda.api.interactions.components.Modal;
|
||||
import net.dv8tion.jda.api.interactions.components.text.TextInput;
|
||||
import net.dv8tion.jda.api.interactions.components.text.TextInputStyle;
|
||||
import net.dv8tion.jda.api.interactions.modals.ModalMapping;
|
||||
import net.dv8tion.jda.api.requests.RestAction;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
public class ModalReplySuggestion extends DiscordModal {
|
||||
|
||||
private static final HashMap<Long, Message> userToMessageMap = new HashMap<>();
|
||||
|
||||
public static synchronized void putMessage(long userId, Message message) {
|
||||
userToMessageMap.put(userId, message);
|
||||
}
|
||||
|
||||
private static synchronized Message pullMessage(long userId) {
|
||||
return userToMessageMap.remove(userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getModalId() {
|
||||
return "reply_suggestion";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(ModalInteractionEvent event) {
|
||||
ModalMapping modalMapping = event.getInteraction().getValue("response");
|
||||
if (modalMapping == null) {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "Unable to find response in modal"))
|
||||
.setEphemeral(true).queue(RestAction.getDefaultSuccess(), Util::handleFailure);
|
||||
return;
|
||||
}
|
||||
|
||||
String response = modalMapping.getAsString();
|
||||
if (response.isEmpty()) {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "Response in modal is empty"))
|
||||
.setEphemeral(true).queue(RestAction.getDefaultSuccess(), Util::handleFailure);
|
||||
return;
|
||||
}
|
||||
|
||||
Member member = event.getMember();
|
||||
if (member == null) {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "This modal only works from within a guild"))
|
||||
.setEphemeral(true).queue(RestAction.getDefaultSuccess(), Util::handleFailure);
|
||||
return;
|
||||
}
|
||||
|
||||
Message message = pullMessage(member.getIdLong());
|
||||
if (message == null) {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "Unable to find a message for this modal"))
|
||||
.setEphemeral(true).queue(RestAction.getDefaultSuccess(), Util::handleFailure);
|
||||
return;
|
||||
}
|
||||
|
||||
String[] split = message.getContentRaw().split("\u200B");
|
||||
if (split.length == 0) {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "The suggestion to be edited has no content"))
|
||||
.setEphemeral(true).queue(RestAction.getDefaultSuccess(), Util::handleFailure);
|
||||
return;
|
||||
}
|
||||
|
||||
message.editMessage(split[0] + "\u200B\n\n" + "**Response by: " + member.getAsMention() + "**\n_" + response.replaceAll("\u200B", "") + "_")
|
||||
.queue(success -> event.replyEmbeds(Util.genericSuccessEmbed("Success", "Responded to the suggestion!"))
|
||||
.setEphemeral(true).queue(RestAction.getDefaultSuccess(), Util::handleFailure),
|
||||
failure -> event.replyEmbeds(Util.genericErrorEmbed("Error", "Unable to edit the suggestion"))
|
||||
.setEphemeral(true).queue(RestAction.getDefaultSuccess(), Util::handleFailure));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Modal getModal() {
|
||||
TextInput body = TextInput.create("response", "Response", TextInputStyle.PARAGRAPH)
|
||||
.setPlaceholder("Response...")
|
||||
.setRequiredRange(10, 1024)
|
||||
.setRequired(true)
|
||||
.build();
|
||||
|
||||
return Modal.create(getModalId(), "Suggestion Response")
|
||||
.addActionRows(ActionRow.of(body))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
|
@ -10,6 +10,7 @@ import net.dv8tion.jda.api.entities.Guild;
|
|||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||
import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel;
|
||||
import net.dv8tion.jda.api.entities.channel.middleman.GuildMessageChannel;
|
||||
import net.dv8tion.jda.api.events.interaction.ModalInteractionEvent;
|
||||
import net.dv8tion.jda.api.interactions.components.ActionRow;
|
||||
|
|
@ -44,8 +45,8 @@ public class ModalSuggestion extends DiscordModal {
|
|||
.setEphemeral(true).queue(RestAction.getDefaultSuccess(), Util::handleFailure);
|
||||
return;
|
||||
}
|
||||
String title = modalMappings.get(0).getAsString();
|
||||
String desc = modalMappings.get(1).getAsString();
|
||||
String title = modalMappings.get(0).getAsString().replaceAll("\u200B", "");
|
||||
String desc = modalMappings.get(1).getAsString().replaceAll("\u200B", "");
|
||||
|
||||
Guild guild = event.getGuild();
|
||||
if (guild == null) {
|
||||
|
|
@ -54,13 +55,19 @@ public class ModalSuggestion extends DiscordModal {
|
|||
return;
|
||||
}
|
||||
|
||||
GuildMessageChannel channel = guild.getChannelById(GuildMessageChannel.class, CommandOutputChannels.getOutputChannel(guild.getIdLong(), OutputType.SUGGESTION_REVIEW));
|
||||
if (channel == null) {
|
||||
GuildChannel outputChannel = CommandOutputChannels.getOutputChannel(guild, OutputType.SUGGESTION_REVIEW);
|
||||
if (outputChannel == null) {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "This guild does not have a suggestion review channel or it's not the right channel type"))
|
||||
.setEphemeral(true).queue(RestAction.getDefaultSuccess(), Util::handleFailure);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(outputChannel instanceof GuildMessageChannel channel)) {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", outputChannel.getType().name() + " is not a valid suggestion review channel type"))
|
||||
.setEphemeral(true).queue(RestAction.getDefaultSuccess(), Util::handleFailure);
|
||||
return;
|
||||
}
|
||||
|
||||
Member member = event.getMember();
|
||||
if (member == null) {
|
||||
event.replyEmbeds(Util.genericErrorEmbed("Error", "This command should only be executed from a guild"))
|
||||
|
|
@ -101,7 +108,7 @@ public class ModalSuggestion extends DiscordModal {
|
|||
@Override
|
||||
public Modal getModal() {
|
||||
TextInput title = TextInput.create("title", "Title", TextInputStyle.SHORT)
|
||||
.setPlaceholder("You suggestion in one sentence")
|
||||
.setPlaceholder("Your suggestion in one sentence")
|
||||
.setRequiredRange(10, 100)
|
||||
.setRequired(true)
|
||||
.build();
|
||||
|
|
|
|||
113
src/main/java/com/alttd/reminders/ReminderScheduler.java
Normal file
113
src/main/java/com/alttd/reminders/ReminderScheduler.java
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
package com.alttd.reminders;
|
||||
|
||||
import com.alttd.database.queries.QueriesReminders.QueriesReminders;
|
||||
import com.alttd.database.queries.QueriesReminders.Reminder;
|
||||
import com.alttd.util.Logger;
|
||||
import com.alttd.util.Util;
|
||||
import net.dv8tion.jda.api.EmbedBuilder;
|
||||
import net.dv8tion.jda.api.JDA;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
|
||||
import net.dv8tion.jda.api.requests.RestAction;
|
||||
import net.dv8tion.jda.api.utils.TimeUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class ReminderScheduler {
|
||||
|
||||
private static ReminderScheduler instance = null;
|
||||
private final ArrayList<Reminder> reminders;
|
||||
private Reminder nextReminder;
|
||||
private final JDA jda;
|
||||
|
||||
private ReminderScheduler(JDA jda) {
|
||||
instance = this;
|
||||
this.jda = jda;
|
||||
reminders = QueriesReminders.getReminders();
|
||||
if (reminders == null) {
|
||||
Logger.severe("Unable to retrieve reminders");
|
||||
instance = null;
|
||||
return;
|
||||
}
|
||||
reminders.sort(Comparator.comparingLong(Reminder::remindDate));
|
||||
if (reminders.size() == 0)
|
||||
nextReminder = null;
|
||||
else
|
||||
nextReminder = reminders.get(0);
|
||||
ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
|
||||
scheduledExecutorService.scheduleWithFixedDelay(new ReminderRun(), 0, 1, TimeUnit.MINUTES);
|
||||
|
||||
}
|
||||
|
||||
public static ReminderScheduler getInstance(JDA jda) {
|
||||
if (instance == null)
|
||||
instance = new ReminderScheduler(jda);
|
||||
return instance;
|
||||
}
|
||||
|
||||
public synchronized void addReminder(Reminder reminder) {
|
||||
reminders.add(reminder);
|
||||
reminders.sort(Comparator.comparingLong(Reminder::remindDate));
|
||||
nextReminder = reminders.get(0);
|
||||
}
|
||||
|
||||
public synchronized void removeReminder(Reminder reminder) {
|
||||
reminders.remove(reminder);
|
||||
if (reminders.size() == 0)
|
||||
nextReminder = null;
|
||||
else
|
||||
nextReminder = reminders.get(0);
|
||||
QueriesReminders.removeReminder(reminder.id());
|
||||
}
|
||||
|
||||
private class ReminderRun implements Runnable {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
long time = new Date().getTime();
|
||||
while (nextReminder != null && time > nextReminder.remindDate()) {
|
||||
//TODO run reminder
|
||||
TextChannel channel = nextReminder.getChannel(jda);
|
||||
if (channel == null || !channel.canTalk()) {
|
||||
Logger.warning("Unable to run reminder: " + nextReminder.id() +
|
||||
"\ntitle: [" + nextReminder.title() +
|
||||
"]\ndescription: [" + nextReminder.description() + "]");
|
||||
return;
|
||||
}
|
||||
sendEmbed(nextReminder, channel);
|
||||
removeReminder(nextReminder);
|
||||
}
|
||||
}
|
||||
|
||||
private void sendEmbed(Reminder reminder, TextChannel channel) {
|
||||
EmbedBuilder embedBuilder = new EmbedBuilder()
|
||||
.setTitle(reminder.title())
|
||||
.setDescription(reminder.description())
|
||||
.appendDescription("\n\nRequested <t:" + TimeUnit.MILLISECONDS.toSeconds(reminder.creationDate()) + ":R>");
|
||||
Guild guild = reminder.getGuild(jda);
|
||||
if (guild == null) {
|
||||
sendEmbed(reminder, channel, embedBuilder);
|
||||
return;
|
||||
}
|
||||
guild.retrieveMemberById(reminder.userId()).queue(
|
||||
member -> sendEmbed(reminder, channel, embedBuilder, member),
|
||||
failed -> sendEmbed(reminder, channel, embedBuilder));
|
||||
}
|
||||
|
||||
private void sendEmbed(Reminder reminder, TextChannel channel, EmbedBuilder embedBuilder, Member member) {
|
||||
embedBuilder.setAuthor(member.getEffectiveName(), null, member.getEffectiveAvatarUrl());
|
||||
channel.sendMessageEmbeds(embedBuilder.build()).queue(RestAction.getDefaultSuccess(), Util::handleFailure);
|
||||
}
|
||||
|
||||
private void sendEmbed(Reminder reminder, TextChannel channel, EmbedBuilder embedBuilder) {
|
||||
embedBuilder.setAuthor(reminder.userId() + "");
|
||||
channel.sendMessageEmbeds(embedBuilder.build()).queue(RestAction.getDefaultSuccess(), Util::handleFailure);
|
||||
}
|
||||
}
|
||||
}
|
||||
88
src/main/java/com/alttd/request/Request.java
Normal file
88
src/main/java/com/alttd/request/Request.java
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
package com.alttd.request;
|
||||
|
||||
import com.alttd.AltitudeBot;
|
||||
import com.alttd.util.Pair;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import net.dv8tion.jda.api.EmbedBuilder;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
|
||||
import net.dv8tion.jda.api.entities.channel.concrete.ThreadChannel;
|
||||
import net.dv8tion.jda.api.interactions.components.ActionRow;
|
||||
import net.dv8tion.jda.api.interactions.components.Modal;
|
||||
import net.dv8tion.jda.api.interactions.components.buttons.Button;
|
||||
import net.dv8tion.jda.api.interactions.components.text.TextInput;
|
||||
import net.dv8tion.jda.api.interactions.components.text.TextInputStyle;
|
||||
import net.dv8tion.jda.api.requests.restaction.ThreadChannelAction;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
@AllArgsConstructor
|
||||
public class Request {
|
||||
// TODO check if all labels on the modal are max 45 in length
|
||||
@Getter
|
||||
private String id, category, channel, name, title, description, message;
|
||||
|
||||
public Modal modal(Member member) {
|
||||
TextInput requestTitle = TextInput
|
||||
.create("title", title, TextInputStyle.SHORT)
|
||||
.setPlaceholder(id)
|
||||
.setRequired(false)
|
||||
.build();
|
||||
|
||||
TextInput requestMessage = TextInput
|
||||
.create("request", message, TextInputStyle.PARAGRAPH)
|
||||
.build();
|
||||
|
||||
return Modal.create("request:" + id, name)
|
||||
.addActionRow(requestTitle)
|
||||
.addActionRow(requestMessage)
|
||||
.build();
|
||||
}
|
||||
|
||||
public void createThread(Member member, String title, String request) {
|
||||
TextChannel channel = AltitudeBot.getInstance().getJDA().getGuildById(RequestConfig.REQUEST_GUILD_ID).getTextChannelById(getChannel());
|
||||
if (title == null || title.isEmpty()) title = id;
|
||||
String finalTitle = title;
|
||||
ThreadChannelAction threadChannelAction = channel.createThreadChannel(finalTitle);
|
||||
threadChannelAction.queue(threadChannel -> {
|
||||
threadChannel.addThreadMember(member).queue();
|
||||
sendEmbed(threadChannel, finalTitle, request);
|
||||
channel.deleteMessageById(threadChannel.getId()).queue();
|
||||
// TODO store the request somewhere so it can be grabbed later
|
||||
});
|
||||
}
|
||||
|
||||
public void sendEmbed(ThreadChannel channel, String title, String request) {
|
||||
// Pair<EmbedBuilder, ActionRow> pair = getRequestEmbed(channel.getId(), title, request);
|
||||
// pairs are not really possible here :(
|
||||
EmbedBuilder embedBuilder = new EmbedBuilder();
|
||||
embedBuilder.setTitle(title)
|
||||
.addField(getName(), request, false)
|
||||
.setColor(new Color(41, 43, 47));
|
||||
channel.sendMessageEmbeds(embedBuilder.build()).queue(message1 ->
|
||||
channel.editMessageEmbedsById(message1.getId(), embedBuilder.build())
|
||||
.setActionRow(
|
||||
Button.primary("request:" + getId() + ":" + channel.getId() + ":" + message1.getId() + ":progress", "in progress"),
|
||||
Button.success("request:" + getId() + ":" + channel.getId() + ":" + message1.getId() + ":complete", "complete"),
|
||||
Button.danger("request:" + getId() + ":" + channel.getId() + ":" + message1.getId() + ":denied", "denied")
|
||||
).queue()
|
||||
);
|
||||
}
|
||||
|
||||
public Pair<EmbedBuilder, ActionRow> getRequestEmbed(String channellId, String title, String request) {
|
||||
EmbedBuilder embedBuilder = new EmbedBuilder();
|
||||
embedBuilder.setTitle("title")
|
||||
.addField(getName(), request, false)
|
||||
.setColor(new Color(41, 43, 47));
|
||||
|
||||
ActionRow actionRow = ActionRow.of(
|
||||
Button.primary("request:" + getId() + ":" + channellId + ":progress", "in progress"),
|
||||
Button.success("request:" + getId() + ":" + channellId + ":complete", "complete"),
|
||||
Button.danger("request:" + getId() + ":" + channellId + ":denied", "denied")
|
||||
);
|
||||
|
||||
return new Pair<>(embedBuilder, actionRow);
|
||||
}
|
||||
|
||||
}
|
||||
58
src/main/java/com/alttd/request/RequestConfig.java
Normal file
58
src/main/java/com/alttd/request/RequestConfig.java
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
package com.alttd.request;
|
||||
|
||||
import com.alttd.config.AbstractConfig;
|
||||
import com.alttd.util.Logger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class RequestConfig extends AbstractConfig {
|
||||
|
||||
static RequestConfig requestConfig;
|
||||
|
||||
public RequestConfig() {
|
||||
super("requests.yml");
|
||||
}
|
||||
|
||||
public static void reload() {
|
||||
requestConfig = new RequestConfig();
|
||||
requestConfig.readConfig(RequestConfig.class, requestConfig);
|
||||
}
|
||||
|
||||
public static String REQUEST_GUILD_ID = "776590138296893480";
|
||||
public static String REQUEST_CATEGORY = "776590138296893481";
|
||||
public static String REQUEST_CHANNEL = "1017787342561476709";
|
||||
public static String REQUEST_MESSAGE = "";
|
||||
private void settings() {
|
||||
REQUEST_GUILD_ID = requestConfig.getString("request.guild", REQUEST_GUILD_ID);
|
||||
REQUEST_CATEGORY = requestConfig.getString("request.category", REQUEST_CATEGORY);
|
||||
REQUEST_CHANNEL = requestConfig.getString("request.channel", REQUEST_CHANNEL);
|
||||
REQUEST_MESSAGE = requestConfig.getString("request.message", REQUEST_MESSAGE);
|
||||
}
|
||||
|
||||
public static void setRequestMessage(String messageId) {
|
||||
REQUEST_MESSAGE = messageId;
|
||||
requestConfig.update("request.message", REQUEST_MESSAGE);
|
||||
requestConfig.save();
|
||||
}
|
||||
|
||||
public static final List<Request> requests = new ArrayList<>();
|
||||
private void loadRequests() {
|
||||
requests.clear();
|
||||
requestConfig.getNode("types").childrenMap().forEach((key, value) -> {
|
||||
String id = key.toString();
|
||||
String category = value.node("category").getString();
|
||||
String channel = value.node("channel").getString();
|
||||
String name = value.node("name").getString();
|
||||
String title = value.node("title").getString();
|
||||
String description = value.node("description").getString();
|
||||
String message = value.node("message").getString();
|
||||
if (id == null || category == null || channel == null || name == null || description == null || message == null) {
|
||||
Logger.warning("Requests are set up incorrectly!");
|
||||
} else {
|
||||
requests.add(new Request(id, category, channel, name, title, description, message));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
110
src/main/java/com/alttd/request/RequestManager.java
Normal file
110
src/main/java/com/alttd/request/RequestManager.java
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
package com.alttd.request;
|
||||
|
||||
import com.alttd.AltitudeBot;
|
||||
import com.alttd.util.Pair;
|
||||
import net.dv8tion.jda.api.EmbedBuilder;
|
||||
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
|
||||
import net.dv8tion.jda.api.entities.channel.concrete.ThreadChannel;
|
||||
import net.dv8tion.jda.api.events.interaction.ModalInteractionEvent;
|
||||
import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent;
|
||||
import net.dv8tion.jda.api.events.interaction.component.SelectMenuInteractionEvent;
|
||||
import net.dv8tion.jda.api.interactions.components.selections.SelectMenu;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
public class RequestManager {
|
||||
|
||||
public static void init() {
|
||||
RequestConfig.reload();
|
||||
if (RequestConfig.REQUEST_MESSAGE == null || RequestConfig.REQUEST_MESSAGE.isEmpty())
|
||||
sendRequestMessage();
|
||||
}
|
||||
|
||||
public static Pair<EmbedBuilder, SelectMenu.Builder> getRequestEmbed() {
|
||||
EmbedBuilder embedBuilder = new EmbedBuilder();
|
||||
SelectMenu.Builder selectMenuBuilder = SelectMenu.create("request:create");
|
||||
embedBuilder.setDescription("Select an option below to open a request!\n")
|
||||
.setTitle("Create a new request.")
|
||||
.setColor(new Color(41, 43, 47));
|
||||
|
||||
for (Request request : RequestConfig.requests) {
|
||||
embedBuilder.addField(request.getName(), request.getDescription(), false);
|
||||
selectMenuBuilder.addOption(request.getName(), "request:open:" + request.getId(), request.getDescription(), null);
|
||||
}
|
||||
|
||||
return new Pair<>(embedBuilder, selectMenuBuilder);
|
||||
}
|
||||
|
||||
public static void sendRequestMessage() {
|
||||
TextChannel channel = AltitudeBot.getInstance().getJDA().getGuildById(RequestConfig.REQUEST_GUILD_ID).getTextChannelById(RequestConfig.REQUEST_CHANNEL);
|
||||
Pair<EmbedBuilder, SelectMenu.Builder> pair = getRequestEmbed();
|
||||
channel.sendMessageEmbeds(pair.getValue0().build()).setActionRow(
|
||||
pair.getValue1().build()
|
||||
).queue(m -> RequestConfig.setRequestMessage(m.getId()));
|
||||
}
|
||||
|
||||
public static void updateRequestMessage() {
|
||||
TextChannel channel = AltitudeBot.getInstance().getJDA().getGuildById(RequestConfig.REQUEST_GUILD_ID).getTextChannelById(RequestConfig.REQUEST_CHANNEL);
|
||||
Pair<EmbedBuilder, SelectMenu.Builder> pair = getRequestEmbed();
|
||||
channel.editMessageEmbedsById(RequestConfig.REQUEST_MESSAGE, pair.getValue0().build())
|
||||
.setActionRow(
|
||||
pair.getValue1().build()
|
||||
).queue(m -> RequestConfig.setRequestMessage(m.getId()));
|
||||
}
|
||||
|
||||
public static Request getRequestById(String id) {
|
||||
return RequestConfig.requests.stream().filter(request -> request.getId().equalsIgnoreCase(id)).findFirst().orElse(null);
|
||||
}
|
||||
|
||||
public static void onSelectMenuInteraction(SelectMenuInteractionEvent event) {
|
||||
String[] actions = event.getComponentId().split(":");
|
||||
if (actions[1].equals("create")) {
|
||||
String[] selection = event.getSelectedOptions().get(0).getValue().split(":");
|
||||
if (selection[0].equals("request") && selection[1].equals("open")) {
|
||||
String id = selection[2];
|
||||
event.replyModal(getRequestById(id).modal(event.getMember())).queue();
|
||||
updateRequestMessage(); // You can't use a select menu option twice in a row, updating it fixes that.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void onModalInteractionEvent(ModalInteractionEvent event) {
|
||||
String s = event.getModalId();
|
||||
String[] strings = s.split(":", 2);
|
||||
getRequestById(strings[1]).createThread(event.getMember(), event.getValue("title").getAsString(), event.getValue("request").getAsString());
|
||||
event.reply("Thanks for your request!").setEphemeral(true).queue();
|
||||
}
|
||||
|
||||
public static void onButtonInteractionEvent(ButtonInteractionEvent event) {
|
||||
String s = event.getComponentId();
|
||||
String[] strings = s.split(":", 5);
|
||||
String requestId = strings[1];
|
||||
String threadId = strings[2];
|
||||
String messageId = strings[3];
|
||||
String type = strings[4]; // progress, complete, denied
|
||||
|
||||
// TODO update the stored request in the database
|
||||
switch (type) {
|
||||
case "denied" -> {
|
||||
// TODO open a new modal to input a reason?
|
||||
// could also do this by command?
|
||||
event.reply("This request has been denied by " + event.getMember().getAsMention()).queue();
|
||||
ThreadChannel threadChannel = AltitudeBot.getInstance().getJDA().getGuildById(RequestConfig.REQUEST_GUILD_ID).getThreadChannelById(threadId);
|
||||
threadChannel.getManager().setArchived(true).setLocked(true).queue();
|
||||
}
|
||||
case "complete" -> {
|
||||
// TODO open a new modal to input a reason?
|
||||
// could also do this by command?
|
||||
event.reply("This request has been completed by " + event.getMember().getAsMention()).queue();
|
||||
ThreadChannel threadChannel = AltitudeBot.getInstance().getJDA().getGuildById(RequestConfig.REQUEST_GUILD_ID).getThreadChannelById(threadId);
|
||||
threadChannel.getManager().setArchived(true).setLocked(true).queue();
|
||||
}
|
||||
case "progress" -> {
|
||||
// TODO open a new modal to input a reason?
|
||||
// edit the message to show who is working on it?
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
21
src/main/java/com/alttd/util/Pair.java
Normal file
21
src/main/java/com/alttd/util/Pair.java
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
package com.alttd.util;
|
||||
|
||||
public class Pair<X, Y> {
|
||||
|
||||
private final X x;
|
||||
private final Y y;
|
||||
|
||||
public Pair(X x, Y y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
public X getValue0() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public Y getValue1() {
|
||||
return y;
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user