diff --git a/src/main/java/com/alttd/buttonManager/buttons/suggestionReview/ButtonSuggestionReviewAccept.java b/src/main/java/com/alttd/buttonManager/buttons/suggestionReview/ButtonSuggestionReviewAccept.java index 7f2a3c1..4231747 100644 --- a/src/main/java/com/alttd/buttonManager/buttons/suggestionReview/ButtonSuggestionReviewAccept.java +++ b/src/main/java/com/alttd/buttonManager/buttons/suggestionReview/ButtonSuggestionReviewAccept.java @@ -8,10 +8,14 @@ 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.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 +30,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 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 +37,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 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 +52,76 @@ 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; + } + MessageEmbed suggestionMessage = new EmbedBuilder(reviewMessage) .clearFields() .setColor(Color.GRAY) .setTitle(fields.get(0).getName()) .setDescription(fields.get(0).getValue()) .build(); + + if (suggestionGuildChannel instanceof ForumChannel forumChannel) { + sendSuggestionInForum(forumChannel, modLogChannel, fields.get(0), suggestionMessage, 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, ButtonInteractionEvent event) { + MessageCreateData messageCreateData = new MessageCreateBuilder().addContent(field.getValue()).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); + }, 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"); diff --git a/src/main/java/com/alttd/buttonManager/buttons/suggestionReview/ButtonSuggestionReviewDeny.java b/src/main/java/com/alttd/buttonManager/buttons/suggestionReview/ButtonSuggestionReviewDeny.java index 48b149c..74dd9d9 100644 --- a/src/main/java/com/alttd/buttonManager/buttons/suggestionReview/ButtonSuggestionReviewDeny.java +++ b/src/main/java/com/alttd/buttonManager/buttons/suggestionReview/ButtonSuggestionReviewDeny.java @@ -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 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 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"); diff --git a/src/main/java/com/alttd/commandManager/commands/CommandSetOutputChannel.java b/src/main/java/com/alttd/commandManager/commands/CommandSetOutputChannel.java index f44dbe1..75a21c8 100644 --- a/src/main/java/com/alttd/commandManager/commands/CommandSetOutputChannel.java +++ b/src/main/java/com/alttd/commandManager/commands/CommandSetOutputChannel.java @@ -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; @@ -70,10 +71,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); @@ -81,7 +83,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); } diff --git a/src/main/java/com/alttd/database/DatabaseTables.java b/src/main/java/com/alttd/database/DatabaseTables.java index 683b837..546dd78 100644 --- a/src/main/java/com/alttd/database/DatabaseTables.java +++ b/src/main/java/com/alttd/database/DatabaseTables.java @@ -74,6 +74,7 @@ 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 { diff --git a/src/main/java/com/alttd/database/queries/commandOutputChannels/CommandOutputChannels.java b/src/main/java/com/alttd/database/queries/commandOutputChannels/CommandOutputChannels.java index b1a38a3..b15946b 100644 --- a/src/main/java/com/alttd/database/queries/commandOutputChannels/CommandOutputChannels.java +++ b/src/main/java/com/alttd/database/queries/commandOutputChannels/CommandOutputChannels.java @@ -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; } } diff --git a/src/main/java/com/alttd/modalManager/modals/ModalEvidence.java b/src/main/java/com/alttd/modalManager/modals/ModalEvidence.java index 0ad1f2c..fb7a06a 100644 --- a/src/main/java/com/alttd/modalManager/modals/ModalEvidence.java +++ b/src/main/java/com/alttd/modalManager/modals/ModalEvidence.java @@ -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; } diff --git a/src/main/java/com/alttd/modalManager/modals/ModalSuggestion.java b/src/main/java/com/alttd/modalManager/modals/ModalSuggestion.java index ce113d0..3fd9ce1 100644 --- a/src/main/java/com/alttd/modalManager/modals/ModalSuggestion.java +++ b/src/main/java/com/alttd/modalManager/modals/ModalSuggestion.java @@ -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; @@ -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"))