Fix polls not surviving bot restarts

This commit is contained in:
pixtaded 2025-03-19 23:36:46 +03:00
parent b31828bff5
commit 1f4a607adb
5 changed files with 33 additions and 28 deletions

View File

@ -57,9 +57,16 @@ public class Bot {
logger.info("Database shutdown complete."); logger.info("Database shutdown complete.");
})); }));
jda.awaitReady(); jda.awaitReady();
initinalizeDatabaze();
registerCommands(); registerCommands();
} }
private static void initinalizeDatabaze() {
logger.info("Initializing the database...");
Database.initializeDatabase();
Database.loadPolls();
}
private static Config readConfig() { private static Config readConfig() {
File file = new File("./config.json"); File file = new File("./config.json");

View File

@ -1,6 +1,5 @@
package ru.emotilt.antiplatka.command; package ru.emotilt.antiplatka.command;
import java.time.Duration;
import java.util.Objects; import java.util.Objects;
import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Member;
@ -38,14 +37,14 @@ public class PollMute extends Command {
BotPollMute.Builder pollbuilder = new BotPollMute.Builder() BotPollMute.Builder pollbuilder = new BotPollMute.Builder()
.targetUser(member) .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 interaction
.reply(pollbuilder.buildMessage(String.format("Голосование за мут %s", member.getAsMention())).build()) .reply(pollbuilder.buildMessage(String.format("Голосование за мут %s", member.getAsMention())).build())
.queue(i -> i.retrieveOriginal().queue(message -> { .queue(i -> i.retrieveOriginal().queue(message -> {
pollbuilder.channel(interaction.getChannel()).message(message); pollbuilder.channel(interaction.getChannel()).message(message);
BotPoll poll = pollbuilder.build(); BotPoll poll = pollbuilder.build();
Database.addPoll(message.getId(), poll); Database.addPoll(message.getId(), poll, "mute");
})); }));
} }

View File

@ -4,8 +4,9 @@ import java.sql.*;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.concurrent.*; 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.Message;
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
import ru.emotilt.antiplatka.Bot; import ru.emotilt.antiplatka.Bot;
@ -17,19 +18,15 @@ public class Database {
private static final Map<String, BotPoll> currentPolls = new ConcurrentHashMap<>(); private static final Map<String, BotPoll> currentPolls = new ConcurrentHashMap<>();
private static final ExecutorService asyncWriter = Executors.newCachedThreadPool(); private static final ExecutorService asyncWriter = Executors.newCachedThreadPool();
static { public static void initializeDatabase() {
initializeDatabase();
loadPolls();
}
private static void initializeDatabase() {
try (Connection conn = DriverManager.getConnection(DB_URL)) { try (Connection conn = DriverManager.getConnection(DB_URL)) {
String table = """ String table = """
CREATE TABLE IF NOT EXISTS polls ( CREATE TABLE IF NOT EXISTS polls (
id TEXT PRIMARY KEY, id TEXT PRIMARY KEY,
channelId TEXT, channelId TEXT,
endTimestamp INTEGER, endTimestamp INTEGER,
type TEXT type TEXT,
userId TEXT
) )
"""; """;
conn.createStatement().execute(table); 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); currentPolls.put(id, poll);
asyncWriter.submit(() -> writePollToDatabase(id, poll)); asyncWriter.submit(() -> writePollToDatabase(id, poll, type));
} }
public static void removePoll(String id) { public static void removePoll(String id) {
@ -49,9 +46,9 @@ public class Database {
} }
@SuppressWarnings("SwitchStatementWithTooFewBranches") @SuppressWarnings("SwitchStatementWithTooFewBranches")
private static void loadPolls() { public static void loadPolls() {
try (Connection conn = DriverManager.getConnection(DB_URL)) { 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(); try (Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(selectSQL)) { ResultSet rs = stmt.executeQuery(selectSQL)) {
while (rs.next()) { while (rs.next()) {
@ -59,17 +56,16 @@ public class Database {
String channelId = rs.getString("channelId"); String channelId = rs.getString("channelId");
long endTimestamp = rs.getLong("endTimestamp"); long endTimestamp = rs.getLong("endTimestamp");
String type = rs.getString("type"); String type = rs.getString("type");
AtomicReference<Message> messageReference = new AtomicReference<>(); Guild guild = Objects.requireNonNull(Bot.getJda().getGuildById(Bot.config.guildId));
TextChannel channel = Objects.requireNonNull(Bot.getJda().getChannelById(TextChannel.class, channelId)); Member member = guild.getMemberById(rs.getString("userId"));
channel.retrieveMessageById(id).queue(messageReference::set); TextChannel channel = guild.getChannelById(TextChannel.class, channelId);
Message message = messageReference.get(); Message message = Objects.requireNonNull(channel).retrieveMessageById(id).complete();
BotPoll poll; BotPoll poll;
switch (type) { switch (type) {
case "PollMute" -> poll = new BotPollMute.Builder() case "mute" -> poll = new BotPollMute.Builder()
.message(message) .message(message)
.targetUser(message.getMentions().getMembers().get(0)) .targetUser(member)
.channel(channel) .channel(channel)
.endTimestamp(endTimestamp) .endTimestamp(endTimestamp)
.build(); .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)) { 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)) { try (PreparedStatement pstmt = conn.prepareStatement(insertSQL)) {
pstmt.setString(1, id); pstmt.setString(1, id);
pstmt.setString(2, Objects.requireNonNull(poll.channel).getId()); pstmt.setString(2, Objects.requireNonNull(poll.channel).getId());
pstmt.setString(3, Objects.requireNonNull(poll.message).getId()); pstmt.setLong(3, poll.endTimestamp);
pstmt.setString(4, poll.getClass().getName()); pstmt.setString(4, Objects.requireNonNull(type));
pstmt.setString(5, poll.targetUser.getId());
pstmt.executeUpdate(); pstmt.executeUpdate();
} }
} catch (SQLException e) { } catch (SQLException e) {

View File

@ -123,7 +123,7 @@ public class OnMessageReceivedEvent extends ListenerAdapter {
return text + " Никто не проголосовал."; return text + " Никто не проголосовал.";
} }
if (!isVictory) { if (!isVictory) {
return text + String.format(" Голосование не преодолело порог в **%d%%.", Bot.config.threshold); return text + String.format(" Голосование не преодолело порог в **%d%%**.", Bot.config.threshold);
} }
return text; return text;
} }
@ -157,7 +157,7 @@ public class OnMessageReceivedEvent extends ListenerAdapter {
resultMessage.delete().queue(); resultMessage.delete().queue();
resultMessage.getChannel().retrieveMessageById(pollMessageId) resultMessage.getChannel().retrieveMessageById(pollMessageId)
.queue(message -> message.delete().queue()); .queue(message -> message.delete().queue());
Database.removePoll(resultMessage.getId()); Database.removePoll(pollMessageId);
} }
private static class PollResults { private static class PollResults {

View File

@ -22,6 +22,7 @@ public abstract class BotPoll {
public final Member targetUser; public final Member targetUser;
public final MessageChannel channel; public final MessageChannel channel;
public final Duration pollDuration; public final Duration pollDuration;
public final long endTimestamp;
@SuppressWarnings("method.invocation") @SuppressWarnings("method.invocation")
protected BotPoll(Builder<?> builder) { protected BotPoll(Builder<?> builder) {
@ -29,6 +30,7 @@ public abstract class BotPoll {
this.targetUser = Objects.requireNonNull(builder.targetUser); this.targetUser = Objects.requireNonNull(builder.targetUser);
this.channel = Objects.requireNonNull(builder.channel); this.channel = Objects.requireNonNull(builder.channel);
this.pollDuration = Objects.requireNonNull(builder.pollDuration); this.pollDuration = Objects.requireNonNull(builder.pollDuration);
this.endTimestamp = builder.endTimestamp;
schedulePollCompletion(message); schedulePollCompletion(message);
} }