mirror of
https://github.com/LuckPerms/LuckPerms.git
synced 2024-11-23 19:16:37 +01:00
Add option to use bytebin for exports/imports (#2432)
This commit is contained in:
parent
6c7c1b67b8
commit
0fd7f643a7
@ -27,6 +27,7 @@ package me.lucko.luckperms.common.backup;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import me.lucko.luckperms.common.command.CommandResult;
|
||||
import me.lucko.luckperms.common.locale.message.Message;
|
||||
import me.lucko.luckperms.common.model.Group;
|
||||
import me.lucko.luckperms.common.model.Track;
|
||||
@ -40,10 +41,14 @@ import me.lucko.luckperms.common.util.ProgressLogger;
|
||||
import me.lucko.luckperms.common.util.gson.GsonProvider;
|
||||
import me.lucko.luckperms.common.util.gson.JArray;
|
||||
import me.lucko.luckperms.common.util.gson.JObject;
|
||||
import me.lucko.luckperms.common.web.AbstractHttpClient;
|
||||
import me.lucko.luckperms.common.web.UnsuccessfulRequestException;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.Writer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
@ -78,13 +83,30 @@ public class Exporter implements Runnable {
|
||||
private final Sender executor;
|
||||
private final Path filePath;
|
||||
private final boolean includeUsers;
|
||||
private final boolean saveFile;
|
||||
private final String label;
|
||||
private final ProgressLogger log;
|
||||
|
||||
public Exporter(LuckPermsPlugin plugin, Sender executor, Path filePath, boolean includeUsers) {
|
||||
public Exporter(LuckPermsPlugin plugin, Sender executor, Path filePath, boolean includeUsers, boolean saveFile) {
|
||||
this.plugin = plugin;
|
||||
this.executor = executor;
|
||||
this.filePath = filePath;
|
||||
this.includeUsers = includeUsers;
|
||||
this.saveFile = saveFile;
|
||||
this.label = null;
|
||||
|
||||
this.log = new ProgressLogger(Message.EXPORT_LOG, Message.EXPORT_LOG_PROGRESS, null);
|
||||
this.log.addListener(plugin.getConsoleSender());
|
||||
this.log.addListener(executor);
|
||||
}
|
||||
|
||||
public Exporter(LuckPermsPlugin plugin, Sender executor, boolean includeUsers, boolean saveFile, String label) {
|
||||
this.plugin = plugin;
|
||||
this.executor = executor;
|
||||
this.filePath = null;
|
||||
this.includeUsers = includeUsers;
|
||||
this.saveFile = saveFile;
|
||||
this.label = label;
|
||||
|
||||
this.log = new ProgressLogger(Message.EXPORT_LOG, Message.EXPORT_LOG_PROGRESS, null);
|
||||
this.log.addListener(plugin.getConsoleSender());
|
||||
@ -93,32 +115,61 @@ public class Exporter implements Runnable {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
JsonObject file = new JsonObject();
|
||||
file.add("metadata", new JObject()
|
||||
JsonObject json = new JsonObject();
|
||||
json.add("metadata", new JObject()
|
||||
.add("generatedBy", this.executor.getNameWithLocation())
|
||||
.add("generatedAt", DATE_FORMAT.format(new Date(System.currentTimeMillis())))
|
||||
.toJson());
|
||||
|
||||
this.log.log("Gathering group data...");
|
||||
file.add("groups", exportGroups());
|
||||
json.add("groups", exportGroups());
|
||||
|
||||
this.log.log("Gathering track data...");
|
||||
file.add("tracks", exportTracks());
|
||||
json.add("tracks", exportTracks());
|
||||
|
||||
if (this.includeUsers) {
|
||||
this.log.log("Gathering user data...");
|
||||
file.add("users", exportUsers());
|
||||
json.add("users", exportUsers());
|
||||
}
|
||||
|
||||
this.log.log("Finished gathering data, writing file...");
|
||||
if (this.saveFile) {
|
||||
this.log.log("Finished gathering data, writing file...");
|
||||
|
||||
try (BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new GZIPOutputStream(Files.newOutputStream(this.filePath)), StandardCharsets.UTF_8))) {
|
||||
GsonProvider.prettyPrinting().toJson(file, out);
|
||||
try (BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new GZIPOutputStream(Files.newOutputStream(this.filePath)), StandardCharsets.UTF_8))) {
|
||||
GsonProvider.prettyPrinting().toJson(json, out);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
this.log.getListeners().forEach(l -> Message.LOG_EXPORT_SUCCESS.send(l, this.filePath.toFile().getAbsolutePath()));
|
||||
} else {
|
||||
post(json, this.executor, this.plugin, label);
|
||||
}
|
||||
}
|
||||
|
||||
public static CommandResult post(JsonObject payload, Sender sender, LuckPermsPlugin plugin, String label) {
|
||||
ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
|
||||
try (Writer writer = new OutputStreamWriter(new GZIPOutputStream(bytesOut), StandardCharsets.UTF_8)) {
|
||||
GsonProvider.prettyPrinting().toJson(payload, writer);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
this.log.getListeners().forEach(l -> Message.LOG_EXPORT_SUCCESS.send(l, this.filePath.toFile().getAbsolutePath()));
|
||||
String pasteId;
|
||||
try {
|
||||
pasteId = plugin.getBytebin().postContent(bytesOut.toByteArray(), AbstractHttpClient.JSON_TYPE, false).key();
|
||||
} catch (UnsuccessfulRequestException e) {
|
||||
Message.EXPORT_HTTP_REQUEST_FAILURE.send(sender, e.getResponse().code(), e.getResponse().message());
|
||||
return CommandResult.STATE_ERROR;
|
||||
} catch (IOException e) {
|
||||
new RuntimeException("Error uploading data to bytebin", e).printStackTrace();
|
||||
Message.EXPORT_HTTP_UNKNOWN_FAILURE.send(sender);
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
|
||||
Message.EXPORT_CODE.send(sender, pasteId, label, pasteId);
|
||||
|
||||
return CommandResult.SUCCESS;
|
||||
}
|
||||
|
||||
private JsonObject exportGroups() {
|
||||
|
@ -56,41 +56,52 @@ public class ExportCommand extends SingleCommand {
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
|
||||
Path dataDirectory = plugin.getBootstrap().getDataDirectory();
|
||||
Path path = dataDirectory.resolve(args.get(0) + ".json.gz");
|
||||
|
||||
if (!path.getParent().equals(dataDirectory)) {
|
||||
Message.FILE_NOT_WITHIN_DIRECTORY.send(sender, path.toString());
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
boolean includeUsers = !args.remove("--without-users");
|
||||
boolean saveFile = !args.remove("--upload");
|
||||
|
||||
if (Files.exists(path)) {
|
||||
Message.LOG_EXPORT_ALREADY_EXISTS.send(sender, path.toString());
|
||||
return CommandResult.INVALID_ARGS;
|
||||
Exporter exporter;
|
||||
if (saveFile) {
|
||||
Path dataDirectory = plugin.getBootstrap().getDataDirectory();
|
||||
Path path = dataDirectory.resolve(args.get(0) + ".json.gz");
|
||||
|
||||
if (!path.getParent().equals(dataDirectory)) {
|
||||
Message.FILE_NOT_WITHIN_DIRECTORY.send(sender, path.toString());
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (Files.exists(path)) {
|
||||
Message.LOG_EXPORT_ALREADY_EXISTS.send(sender, path.toString());
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
try {
|
||||
Files.createFile(path);
|
||||
} catch (IOException e) {
|
||||
Message.LOG_EXPORT_FAILURE.send(sender);
|
||||
e.printStackTrace();
|
||||
return CommandResult.FAILURE;
|
||||
}
|
||||
|
||||
if (!Files.isWritable(path)) {
|
||||
Message.LOG_EXPORT_NOT_WRITABLE.send(sender, path.toString());
|
||||
return CommandResult.FAILURE;
|
||||
}
|
||||
|
||||
if (!this.running.compareAndSet(false, true)) {
|
||||
Message.EXPORT_ALREADY_RUNNING.send(sender);
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
|
||||
exporter = new Exporter(plugin, sender, path, includeUsers, saveFile);
|
||||
} else {
|
||||
if (!this.running.compareAndSet(false, true)) {
|
||||
Message.EXPORT_ALREADY_RUNNING.send(sender);
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
|
||||
exporter = new Exporter(plugin, sender, includeUsers, saveFile, label);
|
||||
}
|
||||
|
||||
try {
|
||||
Files.createFile(path);
|
||||
} catch (IOException e) {
|
||||
Message.LOG_EXPORT_FAILURE.send(sender);
|
||||
e.printStackTrace();
|
||||
return CommandResult.FAILURE;
|
||||
}
|
||||
|
||||
if (!Files.isWritable(path)) {
|
||||
Message.LOG_EXPORT_NOT_WRITABLE.send(sender, path.toString());
|
||||
return CommandResult.FAILURE;
|
||||
}
|
||||
|
||||
if (!this.running.compareAndSet(false, true)) {
|
||||
Message.EXPORT_ALREADY_RUNNING.send(sender);
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
|
||||
Exporter exporter = new Exporter(plugin, sender, path, includeUsers);
|
||||
|
||||
// Run the exporter in its own thread.
|
||||
plugin.getBootstrap().getScheduler().executeAsync(() -> {
|
||||
try {
|
||||
|
@ -39,6 +39,8 @@ import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
import me.lucko.luckperms.common.util.Predicates;
|
||||
import me.lucko.luckperms.common.util.gson.GsonProvider;
|
||||
import me.lucko.luckperms.common.web.UnsuccessfulRequestException;
|
||||
import me.lucko.luckperms.common.web.WebEditor;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
@ -63,46 +65,73 @@ public class ImportCommand extends SingleCommand {
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
|
||||
String fileName = args.get(0);
|
||||
Path dataDirectory = plugin.getBootstrap().getDataDirectory();
|
||||
Path path = dataDirectory.resolve(fileName);
|
||||
|
||||
if (!path.getParent().equals(dataDirectory) || path.getFileName().toString().equals("config.yml")) {
|
||||
Message.FILE_NOT_WITHIN_DIRECTORY.send(sender, path.toString());
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
// try auto adding the '.json.gz' extension
|
||||
if (!Files.exists(path) && !fileName.contains(".")) {
|
||||
Path pathWithDefaultExtension = path.resolveSibling(fileName + ".json.gz");
|
||||
if (Files.exists(pathWithDefaultExtension)) {
|
||||
path = pathWithDefaultExtension;
|
||||
}
|
||||
}
|
||||
|
||||
if (!Files.exists(path)) {
|
||||
Message.IMPORT_FILE_DOESNT_EXIST.send(sender, path.toString());
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (!Files.isReadable(path)) {
|
||||
Message.IMPORT_FILE_NOT_READABLE.send(sender, path.toString());
|
||||
return CommandResult.FAILURE;
|
||||
}
|
||||
|
||||
if (!this.running.compareAndSet(false, true)) {
|
||||
Message.IMPORT_ALREADY_RUNNING.send(sender);
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
boolean fromFile = !args.remove("--upload");
|
||||
|
||||
JsonObject data;
|
||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new GZIPInputStream(Files.newInputStream(path)), StandardCharsets.UTF_8))) {
|
||||
data = GsonProvider.normal().fromJson(reader, JsonObject.class);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
Message.IMPORT_FILE_READ_FAILURE.send(sender);
|
||||
this.running.set(false);
|
||||
return CommandResult.FAILURE;
|
||||
if (fromFile) {
|
||||
String fileName = args.get(0);
|
||||
Path dataDirectory = plugin.getBootstrap().getDataDirectory();
|
||||
Path path = dataDirectory.resolve(fileName);
|
||||
|
||||
if (!path.getParent().equals(dataDirectory) || path.getFileName().toString().equals("config.yml")) {
|
||||
Message.FILE_NOT_WITHIN_DIRECTORY.send(sender, path.toString());
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
// try auto adding the '.json.gz' extension
|
||||
if (!Files.exists(path) && !fileName.contains(".")) {
|
||||
Path pathWithDefaultExtension = path.resolveSibling(fileName + ".json.gz");
|
||||
if (Files.exists(pathWithDefaultExtension)) {
|
||||
path = pathWithDefaultExtension;
|
||||
}
|
||||
}
|
||||
|
||||
if (!Files.exists(path)) {
|
||||
Message.IMPORT_FILE_DOESNT_EXIST.send(sender, path.toString());
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (!Files.isReadable(path)) {
|
||||
Message.IMPORT_FILE_NOT_READABLE.send(sender, path.toString());
|
||||
return CommandResult.FAILURE;
|
||||
}
|
||||
|
||||
if (!this.running.compareAndSet(false, true)) {
|
||||
Message.IMPORT_ALREADY_RUNNING.send(sender);
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
|
||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new GZIPInputStream(Files.newInputStream(path)), StandardCharsets.UTF_8))) {
|
||||
data = GsonProvider.normal().fromJson(reader, JsonObject.class);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
Message.IMPORT_FILE_READ_FAILURE.send(sender);
|
||||
this.running.set(false);
|
||||
return CommandResult.FAILURE;
|
||||
}
|
||||
} else {
|
||||
String code = args.get(0);
|
||||
|
||||
if (code.isEmpty()) {
|
||||
Message.IMPORT_INVALID_CODE.send(sender, code);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
try {
|
||||
data = WebEditor.readDataFromBytebin(plugin.getBytebin(), code);
|
||||
} catch (UnsuccessfulRequestException e) {
|
||||
Message.IMPORT_HTTP_REQUEST_FAILURE.send(sender, e.getResponse().code(), e.getResponse().message());
|
||||
return CommandResult.STATE_ERROR;
|
||||
} catch (IOException e) {
|
||||
new RuntimeException("Error reading data to bytebin", e).printStackTrace();
|
||||
Message.IMPORT_HTTP_UNKNOWN_FAILURE.send(sender);
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
|
||||
if (data == null) {
|
||||
Message.IMPORT_UNABLE_TO_READ.send(sender, code);
|
||||
return CommandResult.FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
Importer importer = new Importer(plugin, sender, data, args.contains("--merge"));
|
||||
|
@ -473,10 +473,26 @@ public enum Message {
|
||||
IMPORT_ALREADY_RUNNING("&cAnother import process is already running. Please wait for it to finish and try again.", true),
|
||||
EXPORT_ALREADY_RUNNING("&cAnother export process is already running. Please wait for it to finish and try again.", true),
|
||||
FILE_NOT_WITHIN_DIRECTORY("&cError: File &4{}&c must be a direct child of the data directory.", true),
|
||||
|
||||
EXPORT_CODE(
|
||||
"&aExport code: &7{}" + "\n" +
|
||||
"&7Use the following command to import:" + "\n" +
|
||||
"&a/{} import {} --upload",
|
||||
true
|
||||
),
|
||||
|
||||
EXPORT_HTTP_REQUEST_FAILURE("&cUnable to communicate with bytebin. (response code &4{}&c, message='{}')", true),
|
||||
EXPORT_HTTP_UNKNOWN_FAILURE("&cUnable to communicate with bytebin. Check the console for errors.", true),
|
||||
|
||||
IMPORT_FILE_DOESNT_EXIST("&cError: File &4{}&c does not exist.", true),
|
||||
IMPORT_FILE_NOT_READABLE("&cError: File &4{}&c is not readable.", true),
|
||||
IMPORT_FILE_READ_FAILURE("&cAn unexpected error occured whilst reading from the import file. (is it the correct format?)", true),
|
||||
|
||||
IMPORT_INVALID_CODE("&cInvalid code. &7({})", true),
|
||||
IMPORT_HTTP_REQUEST_FAILURE("&cUnable to communicate with bytebin. (response code &4{}&c, message='{}')", true),
|
||||
IMPORT_HTTP_UNKNOWN_FAILURE("&cUnable to communicate with bytebin. Check the console for errors.", true),
|
||||
IMPORT_UNABLE_TO_READ("&cUnable to read data using the given code. &7({})", true),
|
||||
|
||||
IMPORT_PROGRESS("&b(Import) &b-> &f{}&f% complete &7- &b{}&f/&b{} &foperations complete with &c{} &ferrors.", true),
|
||||
IMPORT_PROGRESS_SIN("&b(Import) &b-> &f{}&f% complete &7- &b{}&f/&b{} &foperations complete with &c{} &ferror.", true),
|
||||
IMPORT_START("&b(Import) &b-> &fStarting import process.", true),
|
||||
|
Loading…
Reference in New Issue
Block a user