From 1f4a607adb4e497e26cbbb43d243052cd948978e Mon Sep 17 00:00:00 2001 From: pixtaded Date: Wed, 19 Mar 2025 23:36:46 +0300 Subject: [PATCH] Fix polls not surviving bot restarts --- src/main/java/ru/emotilt/antiplatka/Bot.java | 7 +++ .../emotilt/antiplatka/command/PollMute.java | 5 +-- .../ru/emotilt/antiplatka/db/Database.java | 43 +++++++++---------- .../event/OnMessageReceivedEvent.java | 4 +- .../ru/emotilt/antiplatka/poll/BotPoll.java | 2 + 5 files changed, 33 insertions(+), 28 deletions(-) diff --git a/src/main/java/ru/emotilt/antiplatka/Bot.java b/src/main/java/ru/emotilt/antiplatka/Bot.java index f3effa8..562cf60 100644 --- a/src/main/java/ru/emotilt/antiplatka/Bot.java +++ b/src/main/java/ru/emotilt/antiplatka/Bot.java @@ -57,9 +57,16 @@ public class Bot { logger.info("Database shutdown complete."); })); jda.awaitReady(); + initinalizeDatabaze(); registerCommands(); } + private static void initinalizeDatabaze() { + logger.info("Initializing the database..."); + Database.initializeDatabase(); + Database.loadPolls(); + } + private static Config readConfig() { File file = new File("./config.json"); diff --git a/src/main/java/ru/emotilt/antiplatka/command/PollMute.java b/src/main/java/ru/emotilt/antiplatka/command/PollMute.java index cf53403..44e4717 100644 --- a/src/main/java/ru/emotilt/antiplatka/command/PollMute.java +++ b/src/main/java/ru/emotilt/antiplatka/command/PollMute.java @@ -1,6 +1,5 @@ package ru.emotilt.antiplatka.command; -import java.time.Duration; import java.util.Objects; import net.dv8tion.jda.api.entities.Member; @@ -38,14 +37,14 @@ public class PollMute extends Command { BotPollMute.Builder pollbuilder = new BotPollMute.Builder() .targetUser(member) - .endTimestamp(System.currentTimeMillis() + (Duration.ofMinutes(Bot.config.pollDurations.mute).toMinutes() * 60 * 1000)); + .endTimestamp(System.currentTimeMillis() + ((long) Bot.config.pollDurations.mute * 60 * 1000)); interaction .reply(pollbuilder.buildMessage(String.format("Голосование за мут %s", member.getAsMention())).build()) .queue(i -> i.retrieveOriginal().queue(message -> { pollbuilder.channel(interaction.getChannel()).message(message); BotPoll poll = pollbuilder.build(); - Database.addPoll(message.getId(), poll); + Database.addPoll(message.getId(), poll, "mute"); })); } diff --git a/src/main/java/ru/emotilt/antiplatka/db/Database.java b/src/main/java/ru/emotilt/antiplatka/db/Database.java index ae9083e..be96afd 100644 --- a/src/main/java/ru/emotilt/antiplatka/db/Database.java +++ b/src/main/java/ru/emotilt/antiplatka/db/Database.java @@ -4,8 +4,9 @@ import java.sql.*; import java.util.Map; import java.util.Objects; import java.util.concurrent.*; -import java.util.concurrent.atomic.AtomicReference; +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.channel.concrete.TextChannel; import ru.emotilt.antiplatka.Bot; @@ -17,19 +18,15 @@ public class Database { private static final Map currentPolls = new ConcurrentHashMap<>(); private static final ExecutorService asyncWriter = Executors.newCachedThreadPool(); - static { - initializeDatabase(); - loadPolls(); - } - - private static void initializeDatabase() { + public static void initializeDatabase() { try (Connection conn = DriverManager.getConnection(DB_URL)) { String table = """ CREATE TABLE IF NOT EXISTS polls ( id TEXT PRIMARY KEY, channelId TEXT, endTimestamp INTEGER, - type TEXT + type TEXT, + userId TEXT ) """; conn.createStatement().execute(table); @@ -38,9 +35,9 @@ public class Database { } } - public static void addPoll(String id, BotPoll poll) { + public static void addPoll(String id, BotPoll poll, String type) { currentPolls.put(id, poll); - asyncWriter.submit(() -> writePollToDatabase(id, poll)); + asyncWriter.submit(() -> writePollToDatabase(id, poll, type)); } public static void removePoll(String id) { @@ -49,9 +46,9 @@ public class Database { } @SuppressWarnings("SwitchStatementWithTooFewBranches") - private static void loadPolls() { + public static void loadPolls() { try (Connection conn = DriverManager.getConnection(DB_URL)) { - String selectSQL = "SELECT id, channelId, endTimestamp, type FROM polls"; + String selectSQL = "SELECT id, channelId, endTimestamp, type, userId FROM polls"; try (Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(selectSQL)) { while (rs.next()) { @@ -59,17 +56,16 @@ public class Database { String channelId = rs.getString("channelId"); long endTimestamp = rs.getLong("endTimestamp"); String type = rs.getString("type"); - AtomicReference messageReference = new AtomicReference<>(); - TextChannel channel = Objects.requireNonNull(Bot.getJda().getChannelById(TextChannel.class, channelId)); - channel.retrieveMessageById(id).queue(messageReference::set); - Message message = messageReference.get(); - + Guild guild = Objects.requireNonNull(Bot.getJda().getGuildById(Bot.config.guildId)); + Member member = guild.getMemberById(rs.getString("userId")); + TextChannel channel = guild.getChannelById(TextChannel.class, channelId); + Message message = Objects.requireNonNull(channel).retrieveMessageById(id).complete(); BotPoll poll; switch (type) { - case "PollMute" -> poll = new BotPollMute.Builder() + case "mute" -> poll = new BotPollMute.Builder() .message(message) - .targetUser(message.getMentions().getMembers().get(0)) + .targetUser(member) .channel(channel) .endTimestamp(endTimestamp) .build(); @@ -83,14 +79,15 @@ public class Database { } } - private static void writePollToDatabase(String id, BotPoll poll) { + private static void writePollToDatabase(String id, BotPoll poll, String type) { try (Connection conn = DriverManager.getConnection(DB_URL)) { - String insertSQL = "INSERT OR REPLACE INTO polls (id, channelId, endTimestamp, type) VALUES (?, ?, ?, ?)"; + String insertSQL = "INSERT OR REPLACE INTO polls (id, channelId, endTimestamp, type, userId) VALUES (?, ?, ?, ?, ?)"; try (PreparedStatement pstmt = conn.prepareStatement(insertSQL)) { pstmt.setString(1, id); pstmt.setString(2, Objects.requireNonNull(poll.channel).getId()); - pstmt.setString(3, Objects.requireNonNull(poll.message).getId()); - pstmt.setString(4, poll.getClass().getName()); + pstmt.setLong(3, poll.endTimestamp); + pstmt.setString(4, Objects.requireNonNull(type)); + pstmt.setString(5, poll.targetUser.getId()); pstmt.executeUpdate(); } } catch (SQLException e) { diff --git a/src/main/java/ru/emotilt/antiplatka/event/OnMessageReceivedEvent.java b/src/main/java/ru/emotilt/antiplatka/event/OnMessageReceivedEvent.java index debfb8b..743bc31 100644 --- a/src/main/java/ru/emotilt/antiplatka/event/OnMessageReceivedEvent.java +++ b/src/main/java/ru/emotilt/antiplatka/event/OnMessageReceivedEvent.java @@ -123,7 +123,7 @@ public class OnMessageReceivedEvent extends ListenerAdapter { return text + " Никто не проголосовал."; } if (!isVictory) { - return text + String.format(" Голосование не преодолело порог в **%d%%.", Bot.config.threshold); + return text + String.format(" Голосование не преодолело порог в **%d%%**.", Bot.config.threshold); } return text; } @@ -157,7 +157,7 @@ public class OnMessageReceivedEvent extends ListenerAdapter { resultMessage.delete().queue(); resultMessage.getChannel().retrieveMessageById(pollMessageId) .queue(message -> message.delete().queue()); - Database.removePoll(resultMessage.getId()); + Database.removePoll(pollMessageId); } private static class PollResults { diff --git a/src/main/java/ru/emotilt/antiplatka/poll/BotPoll.java b/src/main/java/ru/emotilt/antiplatka/poll/BotPoll.java index 5d41e5d..90df7da 100644 --- a/src/main/java/ru/emotilt/antiplatka/poll/BotPoll.java +++ b/src/main/java/ru/emotilt/antiplatka/poll/BotPoll.java @@ -22,6 +22,7 @@ public abstract class BotPoll { public final Member targetUser; public final MessageChannel channel; public final Duration pollDuration; + public final long endTimestamp; @SuppressWarnings("method.invocation") protected BotPoll(Builder builder) { @@ -29,6 +30,7 @@ public abstract class BotPoll { this.targetUser = Objects.requireNonNull(builder.targetUser); this.channel = Objects.requireNonNull(builder.channel); this.pollDuration = Objects.requireNonNull(builder.pollDuration); + this.endTimestamp = builder.endTimestamp; schedulePollCompletion(message); }