Registered /plan db clear command

This commit is contained in:
Risto Lahtela 2020-06-20 20:54:39 +03:00
parent 42dce582c6
commit 58e10f5b5b
3 changed files with 74 additions and 136 deletions

View File

@ -251,6 +251,7 @@ public class PlanCommand {
.subcommand(backupCommand()) .subcommand(backupCommand())
.subcommand(restoreCommand()) .subcommand(restoreCommand())
.subcommand(moveCommand()) .subcommand(moveCommand())
.subcommand(clearCommand())
.inDepthDescription("Use different database subcommands to change the data in some way") .inDepthDescription("Use different database subcommands to change the data in some way")
.build(); .build();
} }
@ -289,4 +290,15 @@ public class PlanCommand {
.onCommand((sender, arguments) -> databaseCommands.onMove(commandName, sender, arguments)) .onCommand((sender, arguments) -> databaseCommands.onMove(commandName, sender, arguments))
.build(); .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();
}
} }

View File

@ -21,6 +21,7 @@ import com.djrapitops.plan.commands.use.CMDSender;
import com.djrapitops.plan.delivery.formatting.Formatter; import com.djrapitops.plan.delivery.formatting.Formatter;
import com.djrapitops.plan.delivery.formatting.Formatters; import com.djrapitops.plan.delivery.formatting.Formatters;
import com.djrapitops.plan.exceptions.database.DBOpException; 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.Locale;
import com.djrapitops.plan.settings.locale.lang.CommandLang; import com.djrapitops.plan.settings.locale.lang.CommandLang;
import com.djrapitops.plan.settings.locale.lang.ManageLang; 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.Database;
import com.djrapitops.plan.storage.database.SQLiteDB; import com.djrapitops.plan.storage.database.SQLiteDB;
import com.djrapitops.plan.storage.database.transactions.BackupCopyTransaction; 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.storage.file.PlanFiles;
import com.djrapitops.plan.utilities.logging.ErrorContext; import com.djrapitops.plan.utilities.logging.ErrorContext;
import com.djrapitops.plan.utilities.logging.ErrorLogger; import com.djrapitops.plan.utilities.logging.ErrorLogger;
@ -38,6 +40,7 @@ import com.djrapitops.plugin.logging.L;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import java.io.File; import java.io.File;
import java.util.Collections;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
@Singleton @Singleton
@ -49,6 +52,8 @@ public class DatabaseCommands {
private final PlanFiles files; private final PlanFiles files;
private final DBSystem dbSystem; private final DBSystem dbSystem;
private final SQLiteDB.Factory sqliteFactory; private final SQLiteDB.Factory sqliteFactory;
private final QuerySvc queryService;
private final PluginStatusCommands statusCommands;
private final ErrorLogger errorLogger; private final ErrorLogger errorLogger;
private final Formatter<Long> timestamp; private final Formatter<Long> timestamp;
@ -61,7 +66,9 @@ public class DatabaseCommands {
PlanFiles files, PlanFiles files,
DBSystem dbSystem, DBSystem dbSystem,
SQLiteDB.Factory sqliteFactory, SQLiteDB.Factory sqliteFactory,
QuerySvc queryService,
Formatters formatters, Formatters formatters,
PluginStatusCommands statusCommands,
ErrorLogger errorLogger ErrorLogger errorLogger
) { ) {
this.locale = locale; this.locale = locale;
@ -70,6 +77,8 @@ public class DatabaseCommands {
this.files = files; this.files = files;
this.dbSystem = dbSystem; this.dbSystem = dbSystem;
this.sqliteFactory = sqliteFactory; this.sqliteFactory = sqliteFactory;
this.queryService = queryService;
this.statusCommands = statusCommands;
this.errorLogger = errorLogger; this.errorLogger = errorLogger;
this.timestamp = formatters.iso8601NoClockLong(); this.timestamp = formatters.iso8601NoClockLong();
@ -240,4 +249,57 @@ public class DatabaseCommands {
sender.send(locale.getString(ManageLang.PROGRESS_FAIL, e.getMessage())); 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("<MySQL/SQLite/H2>"))));
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());
}
}
} }

View File

@ -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 <https://www.gnu.org/licenses/>.
*/
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("<DB>", "[-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));
}
}