package fr.Alphart.BAT.Modules.Comment; import java.io.File; import java.sql.Connection; import java.sql.Date; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.logging.Level; import lombok.Getter; import net.cubespace.Yamler.Config.InvalidConfigurationException; import net.md_5.bungee.config.Configuration; import net.md_5.bungee.config.ConfigurationProvider; import net.md_5.bungee.config.YamlConfiguration; import com.google.common.collect.Lists; import fr.Alphart.BAT.BAT; import fr.Alphart.BAT.I18n.I18n; import fr.Alphart.BAT.Modules.BATCommand; import fr.Alphart.BAT.Modules.IModule; import fr.Alphart.BAT.Modules.ModuleConfiguration; import fr.Alphart.BAT.Modules.Comment.CommentEntry.Type; import fr.Alphart.BAT.Modules.Core.Core; import fr.Alphart.BAT.Utils.Utils; import fr.Alphart.BAT.database.DataSourceHandler; import fr.Alphart.BAT.database.SQLQueries; public class Comment implements IModule{ private final String name = "comment"; private CommentCommand commandHandler; private final CommentConfig config; public Comment(){ config = new CommentConfig(); } @Override public List<BATCommand> getCommands() { return commandHandler.getCmds(); } @Override public String getName() { return name; } @Override public String getMainCommand() { return "comment"; } @Override public CommentConfig getConfig() { return config; } @Override public boolean load() { // Init table Statement statement = null; try (Connection conn = BAT.getConnection()) { statement = conn.createStatement(); if (DataSourceHandler.isSQLite()) { for(final String commentsQuery : SQLQueries.Comments.SQLite.createTable){ statement.executeUpdate(commentsQuery); } } else { statement.executeUpdate(SQLQueries.Comments.createTable); } statement.close(); } catch (final SQLException e) { DataSourceHandler.handleException(e); } finally { DataSourceHandler.close(statement); } // Register commands commandHandler = new CommentCommand(this); commandHandler.loadCmds(); return true; } @Override public boolean unload() { return true; } public class CommentConfig extends ModuleConfiguration { public CommentConfig() { try { initThrowingExceptions(name); } catch (InvalidConfigurationException e) { /* The structure of a trigger has changed from 1.3.3 to 1.3.4 * so if an class cast exception is thrown it's probably caused by an old trigger. * We're going to convert this old trigger to the new ones */ if(e.getCause() instanceof ClassCastException){ try { final Configuration config; final File configFile = new File(BAT.getInstance().getDataFolder(), "comment.yml"); config = ConfigurationProvider.getProvider(YamlConfiguration.class).load(configFile); final Configuration triggerSection = config.getSection("triggers"); triggers.clear(); for(final String triggerName : triggerSection.getKeys()){ final List<String> patterns = Arrays.asList(triggerSection.getString(triggerName + ".pattern")); final List<String> cmds = triggerSection.getStringList(triggerName + ".commands"); final int triggerNumber = triggerSection.getInt(triggerName + ".triggerNumber"); triggers.put(triggerName, new Trigger(triggerNumber, patterns, cmds)); } save(); } catch (final Exception migrationException) { BAT.getInstance().getLogger().log(Level.SEVERE, "BAT met an error while migrating old triggers", migrationException); } }else{ BAT.getInstance().getLogger().log(Level.SEVERE, "BAT met an error while loading comments config", e); } } } @net.cubespace.Yamler.Config.Comments({"Triggers list", "Trigger name:", " pattern: reason which must be provided to trigger this", " commands: list of commands that should be executed when it triggers, you can use {player} variable", " triggerNumber: the number at which this triggers"}) @Getter private Map<String, Trigger> triggers = new HashMap<String, Trigger>(){ private static final long serialVersionUID = 1L; { put("example", new Trigger()); }}; @Getter @net.cubespace.Yamler.Config.Comment("Interval in seconds between two comments on the same player") private int cooldown = 3; } /** * Get the notes relative to an entity * @param entity | can be an ip or a player name * @return */ public List<CommentEntry> getComments(final String entity){ List<CommentEntry> notes = Lists.newArrayList(); PreparedStatement statement = null; ResultSet resultSet = null; try (Connection conn = BAT.getConnection()) { statement = conn.prepareStatement(DataSourceHandler.isSQLite() ? SQLQueries.Comments.SQLite.getEntries : SQLQueries.Comments.getEntries); if(Utils.validIP(entity)){ statement.setString(1, entity); }else{ statement.setString(1, Core.getUUID(entity)); } resultSet = statement.executeQuery(); while(resultSet.next()){ final long date; if(DataSourceHandler.isSQLite()){ date = resultSet.getLong("strftime('%s',date)") * 1000; }else{ date = resultSet.getTimestamp("date").getTime(); } notes.add(new CommentEntry(resultSet.getInt("id"), entity, resultSet.getString("note"), resultSet.getString("staff"), CommentEntry.Type.valueOf(resultSet.getString("type")), date)); } } catch (final SQLException e) { DataSourceHandler.handleException(e); } finally { DataSourceHandler.close(statement, resultSet); } return notes; } public List<CommentEntry> getManagedComments(final String staff){ List<CommentEntry> notes = Lists.newArrayList(); PreparedStatement statement = null; ResultSet resultSet = null; try (Connection conn = BAT.getConnection()) { statement = conn.prepareStatement(DataSourceHandler.isSQLite() ? SQLQueries.Comments.SQLite.getManagedEntries : SQLQueries.Comments.getManagedEntries); statement.setString(1, staff); resultSet = statement.executeQuery(); while(resultSet.next()){ final long date; if(DataSourceHandler.isSQLite()){ date = resultSet.getLong("strftime('%s',date)") * 1000; }else{ date = resultSet.getTimestamp("date").getTime(); } String entity = Core.getPlayerName(resultSet.getString("entity")); if(entity == null){ entity = "UUID:" + resultSet.getString("entity"); } notes.add(new CommentEntry(resultSet.getInt("id"), entity, resultSet.getString("note"), staff, CommentEntry.Type.valueOf(resultSet.getString("type")), date)); } } catch (final SQLException e) { DataSourceHandler.handleException(e); } finally { DataSourceHandler.close(statement, resultSet); } return notes; } public void insertComment(final String entity, final String comment, final Type type, final String author){ PreparedStatement statement = null; try (Connection conn = BAT.getConnection()) { statement = conn.prepareStatement(SQLQueries.Comments.insertEntry); statement.setString(1, (Utils.validIP(entity)) ? entity : Core.getUUID(entity)); statement.setString(2, comment); statement.setString(3, type.name()); statement.setString(4, author); statement.executeUpdate(); statement.close(); // Handle the trigger system for(final Trigger trigger : config.getTriggers().values()){ for(final String pattern : trigger.getPattern()){ if(pattern.isEmpty() || comment.contains(pattern)){ statement = conn.prepareStatement((pattern.isEmpty()) ? SQLQueries.Comments.simpleTriggerCheck : SQLQueries.Comments.patternTriggerCheck); statement.setString(1, Core.getUUID(entity)); if(!pattern.isEmpty()){ statement.setString(2, '%' + pattern + '%'); } final ResultSet rs = statement.executeQuery(); try{ if(rs.next()){ int count = rs.getInt("COUNT(*)"); if(trigger.getTriggerNumber() == count){ trigger.onTrigger(entity, comment); break; } } }finally{ rs.close(); statement.close(); } } } } } catch (final SQLException e) { DataSourceHandler.handleException(e); } finally { DataSourceHandler.close(statement); } } /** * Clear all the comments and warning of an entity or the specified one * @param entity * @param commentID | use -1 to remove all the comments * @return */ public String clearComments(final String entity, final int commentID){ PreparedStatement statement = null; try (Connection conn = BAT.getConnection()) { if(commentID == -1){ statement = conn.prepareStatement(SQLQueries.Comments.clearEntries); statement.setString(1, (Utils.validIP(entity)) ? entity : Core.getUUID(entity)); }else{ statement = conn.prepareStatement(SQLQueries.Comments.clearByID); statement.setString(1, (Utils.validIP(entity)) ? entity : Core.getUUID(entity)); statement.setInt(2, commentID); } // Check if it was successfully deleted, will be used if tried to delete an specific id comment boolean deleted = statement.executeUpdate() > 0; if(commentID != -1){ if(!deleted){ throw new IllegalArgumentException(I18n._("noCommentIDFound", new String[] {entity})); } return I18n._("commentIDCleared", new String[] {String.valueOf(commentID), entity}); } return I18n._("commentsCleared", new String[] {entity}); } catch (final SQLException e) { return DataSourceHandler.handleException(e); } finally { DataSourceHandler.close(statement); } } boolean hasLastcommentCooledDown(final String entity) throws RuntimeException{ try(Connection conn = BAT.getConnection()){ PreparedStatement statement = conn.prepareStatement(SQLQueries.Comments.getMostRecentCommentDate); statement.setString(1, (Utils.validIP(entity)) ? entity : Core.getUUID(entity)); ResultSet result = statement.executeQuery(); if(result.next()){ return new Date(result.getTimestamp("date").getTime()).before(new Date(System.currentTimeMillis() - getConfig().getCooldown()*1000)); } return true; } catch (final SQLException e) { throw new RuntimeException(DataSourceHandler.handleException(e)); } } }