package com.craftaro.ultimatemoderation.database; import com.craftaro.core.database.DataManager; import com.craftaro.core.database.DatabaseConnector; import com.craftaro.core.utils.TextUtils; import com.craftaro.core.utils.TimeUtils; import com.craftaro.ultimatemoderation.UltimateModeration; import com.craftaro.ultimatemoderation.punish.AppliedPunishment; import com.craftaro.ultimatemoderation.punish.Punishment; import com.craftaro.ultimatemoderation.punish.PunishmentNote; import com.craftaro.ultimatemoderation.punish.PunishmentType; import com.craftaro.ultimatemoderation.punish.player.PlayerPunishData; import com.craftaro.ultimatemoderation.punish.player.PunishmentManager; import com.craftaro.ultimatemoderation.punish.template.Template; import com.craftaro.ultimatemoderation.punish.template.TemplateManager; import com.craftaro.ultimatemoderation.tickets.Ticket; import com.craftaro.ultimatemoderation.tickets.TicketResponse; import com.craftaro.ultimatemoderation.tickets.TicketStatus; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.OfflinePlayer; import org.bukkit.entity.Player; import org.bukkit.plugin.Plugin; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.Statement; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.TreeMap; import java.util.UUID; import java.util.function.Consumer; public class DataHelper { private final DatabaseConnector databaseConnector; private final DataManager dataManager; private final UltimateModeration plugin; //Store highest punishment id for each type, we query for new punishment ids regular to keep data up to date //Table, id private final HashMap punishmentIds = new HashMap<>(); public final List TABLES = Arrays.asList("punishments", "templates", "notes", "tickets"); //TODO: Add ticket_responses? public DataHelper(DataManager dataManager, UltimateModeration plugin) { this.dataManager = dataManager; this.databaseConnector = dataManager.getDatabaseConnector(); this.plugin = plugin; } private void runAsync(Runnable runnable) { this.dataManager.getAsyncPool().execute(runnable); } private void sync(Runnable runnable) { Bukkit.getScheduler().runTask(this.plugin, runnable); } private String getTablePrefix() { return this.dataManager.getTablePrefix(); } private int getHighestPunishmentId(String table) { return this.punishmentIds.getOrDefault(table, 0); } private void setHighestPunishmentId(String table, int id) { this.punishmentIds.put(table, id); } //Method is called async, no need to make it async here public void updateData() { //We query all table ids to get the highest id for each punishment type for (String table : TABLES) { try (Connection connection = this.databaseConnector.getConnection()) { Statement statement = connection.createStatement(); String selectHighestId = "SELECT MAX(id) FROM " + this.getTablePrefix() + table; ResultSet result = statement.executeQuery(selectHighestId); if (result.next()) { int maxId = result.getInt(1); //Check if the id is higher than the current highest id we cached if (maxId > this.getHighestPunishmentId(table)) { int oldId = this.getHighestPunishmentId(table); this.setHighestPunishmentId(table, maxId); //Load all new data switch (table) { case "punishments": PreparedStatement punishmentStatement = connection.prepareStatement("SELECT * FROM " + this.getTablePrefix() + "punishments WHERE id > ?"); punishmentStatement.setInt(1, oldId); ResultSet punishmentResult = punishmentStatement.executeQuery(); while (punishmentResult.next()) { int id = punishmentResult.getInt("id"); PunishmentType punishmentType = PunishmentType.valueOf(punishmentResult.getString("type")); long duration = punishmentResult.getLong("duration"); String reason = punishmentResult.getString("reason"); UUID victim = UUID.fromString(punishmentResult.getString("victim")); UUID punisher = UUID.fromString(punishmentResult.getString("punisher")); long expiration = punishmentResult.getLong("expiration"); AppliedPunishment punishment = new AppliedPunishment(punishmentType, duration, reason, victim, punisher, expiration, id); plugin.getPunishmentManager().getPlayer(punishment.getVictim()).addPunishment(punishment); //If punishment is a BAN check if the player is online and kick them OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(punishment.getVictim()); switch (punishmentType) { case BAN: if (offlinePlayer.isOnline()) { Bukkit.getScheduler().runTask(plugin, () -> offlinePlayer.getPlayer().kickPlayer(plugin.getLocale() .getMessage("event.ban.message") .processPlaceholder("reason", reason == null ? "" : reason) .processPlaceholder("duration", TimeUtils.makeReadable(duration)).getMessage())); } break; case KICK: if (offlinePlayer.isOnline()) { Bukkit.getScheduler().runTask(plugin, () -> offlinePlayer.getPlayer().kickPlayer(plugin.getLocale() .getMessage("event.kick.message") .processPlaceholder("reason", reason == null ? "" : reason).getMessage())); } break; case MUTE: PlayerPunishData playerPunishData = plugin.getPunishmentManager().getPlayer(offlinePlayer); if (!playerPunishData.getActivePunishments(PunishmentType.MUTE).isEmpty()) { return; } sendMessage(offlinePlayer, punishment); break; case WARNING: sendMessage(offlinePlayer, punishment); } } break; case "templates": PreparedStatement templateStatement = connection.prepareStatement("SELECT * FROM " + this.getTablePrefix() + "templates WHERE id > ?"); templateStatement.setInt(1, oldId); ResultSet templateResult = templateStatement.executeQuery(); while (templateResult.next()) { int id = templateResult.getInt("id"); PunishmentType punishmentType = PunishmentType.valueOf(templateResult.getString("punishment_type")); long duration = templateResult.getLong("duration"); String reason = templateResult.getString("reason"); String name = templateResult.getString("name"); UUID creator = UUID.fromString(templateResult.getString("creator")); Template template = new Template(punishmentType, duration, reason, creator, name, id); plugin.getTemplateManager().addTemplate(template); } break; case "notes": PreparedStatement noteStatement = connection.prepareStatement("SELECT * FROM " + this.getTablePrefix() + "notes WHERE id > ?"); noteStatement.setInt(1, oldId); ResultSet noteResult = noteStatement.executeQuery(); while (noteResult.next()) { int id = noteResult.getInt("id"); String noteString = noteResult.getString("note"); UUID author = UUID.fromString(noteResult.getString("author")); UUID subject = UUID.fromString(noteResult.getString("subject")); long creation = noteResult.getLong("creation"); PunishmentNote note = new PunishmentNote(id, noteString, author, subject, creation); plugin.getPunishmentManager().getPlayer(note.getSubject()).addNotes(note); } break; case "tickets": PreparedStatement ticketStatement = connection.prepareStatement("SELECT * FROM " + this.getTablePrefix() + "tickets WHERE id > ?"); ticketStatement.setInt(1, oldId); ResultSet ticketResult = ticketStatement.executeQuery(); while (ticketResult.next()) { int id = ticketResult.getInt("id"); UUID victim = UUID.fromString(ticketResult.getString("victim")); String subject = ticketResult.getString("subject"); String type = ticketResult.getString("type"); TicketStatus status = TicketStatus.valueOf(ticketResult.getString("status")); String world = ticketResult.getString("world"); double x = ticketResult.getDouble("x"); double y = ticketResult.getDouble("y"); double z = ticketResult.getDouble("z"); float pitch = ticketResult.getFloat("pitch"); float yaw = ticketResult.getFloat("yaw"); Location location = Bukkit.getWorld(world) == null ? null : new Location(Bukkit.getWorld(world), x, y, z, yaw, pitch); Ticket ticket = new Ticket(id, victim, subject, type, status, location); ticket.setId(id); //Query ticket responses for the ticket and load them if they exist PreparedStatement responseStatement = connection.prepareStatement("SELECT * FROM " + this.getTablePrefix() + "ticket_responses WHERE ticket_id = ?"); responseStatement.setInt(1, id); ResultSet responseResult = responseStatement.executeQuery(); while (responseResult.next()) { UUID author = UUID.fromString(responseResult.getString("author")); String message = responseResult.getString("message"); long postedDate = responseResult.getLong("posted_date"); TicketResponse ticketResponse = new TicketResponse(author, message, postedDate); ticketResponse.setTicketId(id); ticket.addResponse(ticketResponse); } plugin.getTicketManager().addTicket(ticket); } break; } } } } catch (Exception ex) { ex.printStackTrace(); } } } private void sendMessage(OfflinePlayer offlineVictim, Punishment punishment) { if (!offlineVictim.isOnline()) { return; } Player victim = offlineVictim.getPlayer(); UltimateModeration plugin = UltimateModeration.getInstance(); String punishSuccess = plugin.getLocale() .getMessage("event." + punishment.getPunishmentType().name().toLowerCase() + ".message").getPrefixedMessage(); if (punishment.getReason() != null) { punishSuccess += plugin.getLocale().getMessage("event.punish.reason") .processPlaceholder("reason", punishment.getReason()).getMessage(); } if (punishment.getDuration() != -1) { punishSuccess += plugin.getLocale().getMessage("event.punish.yourduration") .processPlaceholder("duration", TimeUtils.makeReadable(punishment.getDuration())).getMessage(); } victim.sendMessage(punishSuccess + TextUtils.formatText("&7.")); } public void createTemplate(Template template) { this.runAsync(() -> { try (Connection connection = this.databaseConnector.getConnection()) { int nextId = this.dataManager.getNextId("templates"); String createTemplate = "INSERT INTO " + this.getTablePrefix() + "templates (punishment_type, duration, reason, name, creator) VALUES (?, ?, ?, ?, ?)"; PreparedStatement statement = connection.prepareStatement(createTemplate); statement.setString(1, template.getPunishmentType().name()); statement.setLong(2, template.getDuration()); statement.setString(3, template.getReason()); statement.setString(4, template.getName()); statement.setString(5, template.getCreator().toString()); statement.executeUpdate(); template.setId(nextId); } catch (Exception ex) { ex.printStackTrace(); } }); } public void deleteTemplate(Template template) { this.runAsync(() -> { try (Connection connection = this.databaseConnector.getConnection()) { String deleteTemplate = "DELETE FROM " + this.getTablePrefix() + "templates WHERE id = ?"; PreparedStatement statement = connection.prepareStatement(deleteTemplate); statement.setLong(1, template.getId()); statement.executeUpdate(); } catch (Exception ex) { ex.printStackTrace(); } }); } public void getTemplates(Consumer> callback) { List