diff --git a/Plan/common/src/main/java/com/djrapitops/plan/commands/PlanCommand.java b/Plan/common/src/main/java/com/djrapitops/plan/commands/PlanCommand.java index 8532434e6..2f799421c 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/commands/PlanCommand.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/commands/PlanCommand.java @@ -251,6 +251,7 @@ public class PlanCommand { .subcommand(backupCommand()) .subcommand(restoreCommand()) .subcommand(moveCommand()) + .subcommand(clearCommand()) .inDepthDescription("Use different database subcommands to change the data in some way") .build(); } @@ -289,4 +290,15 @@ public class PlanCommand { .onCommand((sender, arguments) -> databaseCommands.onMove(commandName, sender, arguments)) .build(); } + + private Subcommand clearCommand() { + return Subcommand.builder() + .aliases("clear") + .requirePermission("plan.data.clear") + .requiredArgument("MySQL/SQlite/H2", "Type of the database to remove data from.") + .description("Remove ALL Plan data from a database") + .inDepthDescription("Clears all Plan tables, removing all Plan-data in the process.") + .onCommand((sender, arguments) -> databaseCommands.onClear(commandName, sender, arguments)) + .build(); + } } diff --git a/Plan/common/src/main/java/com/djrapitops/plan/commands/subcommands/DatabaseCommands.java b/Plan/common/src/main/java/com/djrapitops/plan/commands/subcommands/DatabaseCommands.java index 248e7e1d1..c3c7b1064 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/commands/subcommands/DatabaseCommands.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/commands/subcommands/DatabaseCommands.java @@ -21,6 +21,7 @@ import com.djrapitops.plan.commands.use.CMDSender; import com.djrapitops.plan.delivery.formatting.Formatter; import com.djrapitops.plan.delivery.formatting.Formatters; import com.djrapitops.plan.exceptions.database.DBOpException; +import com.djrapitops.plan.query.QuerySvc; import com.djrapitops.plan.settings.locale.Locale; import com.djrapitops.plan.settings.locale.lang.CommandLang; import com.djrapitops.plan.settings.locale.lang.ManageLang; @@ -29,6 +30,7 @@ import com.djrapitops.plan.storage.database.DBType; import com.djrapitops.plan.storage.database.Database; import com.djrapitops.plan.storage.database.SQLiteDB; import com.djrapitops.plan.storage.database.transactions.BackupCopyTransaction; +import com.djrapitops.plan.storage.database.transactions.commands.RemoveEverythingTransaction; import com.djrapitops.plan.storage.file.PlanFiles; import com.djrapitops.plan.utilities.logging.ErrorContext; import com.djrapitops.plan.utilities.logging.ErrorLogger; @@ -38,6 +40,7 @@ import com.djrapitops.plugin.logging.L; import javax.inject.Inject; import javax.inject.Singleton; import java.io.File; +import java.util.Collections; import java.util.concurrent.ExecutionException; @Singleton @@ -49,6 +52,8 @@ public class DatabaseCommands { private final PlanFiles files; private final DBSystem dbSystem; private final SQLiteDB.Factory sqliteFactory; + private final QuerySvc queryService; + private final PluginStatusCommands statusCommands; private final ErrorLogger errorLogger; private final Formatter timestamp; @@ -61,7 +66,9 @@ public class DatabaseCommands { PlanFiles files, DBSystem dbSystem, SQLiteDB.Factory sqliteFactory, + QuerySvc queryService, Formatters formatters, + PluginStatusCommands statusCommands, ErrorLogger errorLogger ) { this.locale = locale; @@ -70,6 +77,8 @@ public class DatabaseCommands { this.files = files; this.dbSystem = dbSystem; this.sqliteFactory = sqliteFactory; + this.queryService = queryService; + this.statusCommands = statusCommands; this.errorLogger = errorLogger; this.timestamp = formatters.iso8601NoClockLong(); @@ -240,4 +249,57 @@ public class DatabaseCommands { sender.send(locale.getString(ManageLang.PROGRESS_FAIL, e.getMessage())); } } + + + public void onClear(String mainCommand, CMDSender sender, Arguments arguments) { + DBType fromDB = arguments.get(0).flatMap(DBType::getForName) + .orElseThrow(() -> new IllegalArgumentException(locale.getString(ManageLang.FAIL_INCORRECT_DB, arguments.get(0).orElse("")))); + + if (sender.isPlayer()) { + sender.buildMessage() + .addPart(colors.getMainColor() + "You are about to remove all Plan-data in " + fromDB.getName()).newLine() + .addPart("Confirm: ").addPart("§2§l[\u2714]").command("/" + mainCommand + " accept") + .addPart(" ") + .addPart("§4§l[\u2718]").command("/" + mainCommand + " cancel") + .send(); + } else { + sender.buildMessage() + .addPart(colors.getMainColor() + "You are about to remove all Plan-data in " + fromDB.getName()).newLine() + .addPart("Confirm: ").addPart("§a/" + mainCommand + " accept") + .addPart(" ") + .addPart("§c/" + mainCommand + " cancel") + .send(); + } + + confirmation.confirm(sender, choice -> { + if (choice) { + performClear(sender, fromDB); + } else { + sender.send(colors.getMainColor() + "Cancelled. No data was changed."); + } + }); + } + + private void performClear(CMDSender sender, DBType fromDB) { + try { + Database fromDatabase = dbSystem.getActiveDatabaseByType(fromDB); + fromDatabase.init(); + + sender.send("Removing Plan-data from " + fromDB.getName() + ".."); + + fromDatabase.executeTransaction(new RemoveEverythingTransaction()) + .get(); // Wait for completion + queryService.dataCleared(); + sender.send(locale.getString(ManageLang.PROGRESS_SUCCESS)); + + // Reload plugin to register the server into the database + // Otherwise errors will start. + statusCommands.onReload(sender, new Arguments(Collections.emptyList())); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } catch (DBOpException | ExecutionException e) { + sender.send(locale.getString(ManageLang.PROGRESS_FAIL, e.getMessage())); + errorLogger.log(L.ERROR, e, ErrorContext.builder().related(sender, fromDB.getName()).build()); + } + } } diff --git a/Plan/common/src/main/java/com/djrapitops/plan/commands/subcommands/manage/ManageClearCommand.java b/Plan/common/src/main/java/com/djrapitops/plan/commands/subcommands/manage/ManageClearCommand.java deleted file mode 100644 index b18fe71d9..000000000 --- a/Plan/common/src/main/java/com/djrapitops/plan/commands/subcommands/manage/ManageClearCommand.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * This file is part of Player Analytics (Plan). - * - * Plan is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License v3 as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Plan is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Plan. If not, see . - */ -package com.djrapitops.plan.commands.subcommands.manage; - -import com.djrapitops.plan.PlanPlugin; -import com.djrapitops.plan.exceptions.database.DBInitException; -import com.djrapitops.plan.exceptions.database.DBOpException; -import com.djrapitops.plan.processing.Processing; -import com.djrapitops.plan.query.QuerySvc; -import com.djrapitops.plan.settings.Permissions; -import com.djrapitops.plan.settings.locale.Locale; -import com.djrapitops.plan.settings.locale.lang.CmdHelpLang; -import com.djrapitops.plan.settings.locale.lang.CommandLang; -import com.djrapitops.plan.settings.locale.lang.DeepHelpLang; -import com.djrapitops.plan.settings.locale.lang.ManageLang; -import com.djrapitops.plan.storage.database.DBSystem; -import com.djrapitops.plan.storage.database.DBType; -import com.djrapitops.plan.storage.database.Database; -import com.djrapitops.plan.storage.database.transactions.commands.RemoveEverythingTransaction; -import com.djrapitops.plan.utilities.logging.ErrorLogger; -import com.djrapitops.plugin.command.CommandNode; -import com.djrapitops.plugin.command.CommandType; -import com.djrapitops.plugin.command.Sender; -import com.djrapitops.plugin.logging.L; -import com.djrapitops.plugin.utilities.Verify; - -import javax.inject.Inject; -import javax.inject.Singleton; -import java.util.Arrays; -import java.util.concurrent.ExecutionException; - -/** - * This manage SubCommand is used to clear a database of all data. - * - * @author Rsl1122 - */ -@Singleton -public class ManageClearCommand extends CommandNode { - - private final PlanPlugin plugin; - private final Locale locale; - private final Processing processing; - private final DBSystem dbSystem; - private final QuerySvc queryService; - private final ErrorLogger errorLogger; - - @Inject - public ManageClearCommand( - PlanPlugin plugin, - Locale locale, - Processing processing, - DBSystem dbSystem, - QuerySvc queryService, - ErrorLogger errorLogger - ) { - super("clear", Permissions.MANAGE.getPermission(), CommandType.PLAYER_OR_ARGS); - this.plugin = plugin; - - this.locale = locale; - this.processing = processing; - this.dbSystem = dbSystem; - this.queryService = queryService; - this.errorLogger = errorLogger; - - setArguments("", "[-a]"); - setShortHelp(locale.getString(CmdHelpLang.MANAGE_CLEAR)); - setInDepthHelp(locale.getArray(DeepHelpLang.MANAGE_CLEAR)); - } - - @Override - public void onCommand(Sender sender, String commandLabel, String[] args) { - Verify.isTrue(args.length >= 1, - () -> new IllegalArgumentException(locale.getString(CommandLang.FAIL_REQ_ONE_ARG, Arrays.toString(this.getArguments())))); - - String dbName = args[0].toLowerCase(); - - boolean isCorrectDB = DBType.exists(dbName); - Verify.isTrue(isCorrectDB, - () -> new IllegalArgumentException(locale.getString(ManageLang.FAIL_INCORRECT_DB, dbName))); - - if (!Verify.contains("-a", args)) { - sender.sendMessage(locale.getString(ManageLang.CONFIRMATION, locale.getString(ManageLang.CONFIRM_REMOVAL, dbName))); - return; - } - - try { - Database database = dbSystem.getActiveDatabaseByName(dbName); - database.init(); - runClearTask(sender, database); - } catch (DBInitException e) { - sender.sendMessage(locale.getString(ManageLang.PROGRESS_FAIL, e.getMessage())); - } - } - - private void runClearTask(Sender sender, Database database) { - processing.submitCritical(() -> { - try { - sender.sendMessage(locale.getString(ManageLang.PROGRESS_START)); - database.executeTransaction(new RemoveEverythingTransaction()) - .get(); // Wait for completion - queryService.dataCleared(); - sender.sendMessage(locale.getString(ManageLang.PROGRESS_SUCCESS)); - reloadPlugin(sender); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } catch (DBOpException | ExecutionException e) { - sender.sendMessage(locale.getString(ManageLang.PROGRESS_FAIL, e.getMessage())); - errorLogger.log(L.ERROR, this.getClass(), e); - } - }); - } - - private void reloadPlugin(Sender sender) { - try { - plugin.reloadPlugin(true); - } catch (Exception e) { - errorLogger.log(L.CRITICAL, this.getClass(), e); - sender.sendMessage(locale.getString(CommandLang.RELOAD_FAILED)); - } - sender.sendMessage(locale.getString(CommandLang.RELOAD_COMPLETE)); - } -}