Adds a migrate command for fixing book names and text -> yml
This commit is contained in:
@@ -15,6 +15,7 @@ import net.knarcraft.bookswithoutborders.command.CommandGivePublic;
|
||||
import net.knarcraft.bookswithoutborders.command.CommandGroupEncrypt;
|
||||
import net.knarcraft.bookswithoutborders.command.CommandLoad;
|
||||
import net.knarcraft.bookswithoutborders.command.CommandLoadPublic;
|
||||
import net.knarcraft.bookswithoutborders.command.CommandMigrate;
|
||||
import net.knarcraft.bookswithoutborders.command.CommandReload;
|
||||
import net.knarcraft.bookswithoutborders.command.CommandSave;
|
||||
import net.knarcraft.bookswithoutborders.command.CommandSavePublic;
|
||||
@@ -260,6 +261,7 @@ public class BooksWithoutBorders extends JavaPlugin {
|
||||
registerCommand(BwBCommand.SET_BOOKSHELF_DATA.toString(), new CommandSetBookshelfData());
|
||||
registerCommand(BwBCommand.ADD_TITLE_PAGE.toString(), new CommandAddTitlePage());
|
||||
registerCommand(BwBCommand.DELETE_PAGE.toString(), new CommandDeletePage());
|
||||
registerCommand(BwBCommand.MIGRATE.toString(), new CommandMigrate());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -0,0 +1,149 @@
|
||||
package net.knarcraft.bookswithoutborders.command;
|
||||
|
||||
import net.knarcraft.bookswithoutborders.BooksWithoutBorders;
|
||||
import net.knarcraft.bookswithoutborders.config.Translatable;
|
||||
import net.knarcraft.bookswithoutborders.utility.BookFileHelper;
|
||||
import net.knarcraft.bookswithoutborders.utility.BookHelper;
|
||||
import net.knarcraft.bookswithoutborders.utility.BookToFromTextHelper;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.TabExecutor;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.meta.BookMeta;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Level;
|
||||
|
||||
/**
|
||||
* Command executor for the migrate command
|
||||
*/
|
||||
public class CommandMigrate implements TabExecutor {
|
||||
|
||||
@Override
|
||||
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String s,
|
||||
@NotNull String[] arguments) {
|
||||
if (!(sender instanceof Player player)) {
|
||||
BooksWithoutBorders.getStringFormatter().displayErrorMessage(sender, Translatable.ERROR_PLAYER_ONLY);
|
||||
return false;
|
||||
}
|
||||
File bookDirectory = new File(BooksWithoutBorders.getConfiguration().getBookFolder());
|
||||
boolean success = migrateFiles(bookDirectory, player);
|
||||
if (success) {
|
||||
BooksWithoutBorders.sendSuccessMessage(player, "Successfully migrated all books!");
|
||||
} else {
|
||||
BooksWithoutBorders.sendErrorMessage(player, "Failed to migrate all books!");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public List<String> onTabComplete(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s,
|
||||
@NotNull String[] arguments) {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
/**
|
||||
* Migrates the given folder recursively
|
||||
*
|
||||
* @param folder <p>The folder to migrate files for</p>
|
||||
* @param player <p>The player causing this code to be executed</p>
|
||||
* @return <p>If all migrations were successful</p>
|
||||
*/
|
||||
private boolean migrateFiles(@NotNull File folder, @NotNull Player player) {
|
||||
File[] files = folder.listFiles();
|
||||
if (files == null) {
|
||||
BooksWithoutBorders.log(Level.WARNING, "Unable to access directory " + folder.getName() + " !");
|
||||
return false;
|
||||
}
|
||||
boolean success = true;
|
||||
for (File file : files) {
|
||||
if (file.isDirectory()) {
|
||||
success = success & migrateFiles(file, player);
|
||||
} else if (file.isFile()) {
|
||||
success = success & migrateFile(file, player);
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Migrates a single book file
|
||||
*
|
||||
* @param file <p>The file to migrate</p>
|
||||
* @param player <p>The player causing this code to be executed</p>
|
||||
* @return <p>True if the migration completed successfully</p>
|
||||
*/
|
||||
private boolean migrateFile(@NotNull File file, @NotNull Player player) {
|
||||
BookMeta bookMeta = (BookMeta) BooksWithoutBorders.getItemFactory().getItemMeta(Material.WRITTEN_BOOK);
|
||||
if (bookMeta == null) {
|
||||
return false;
|
||||
}
|
||||
BookMeta loadedBook;
|
||||
String extension = BookFileHelper.getExtensionFromPath(file.getName());
|
||||
if (extension.equalsIgnoreCase("yml")) {
|
||||
loadedBook = BookToFromTextHelper.encryptedBookFromYml(file, bookMeta, "", true);
|
||||
} else if (extension.equalsIgnoreCase("txt")) {
|
||||
loadedBook = BookToFromTextHelper.bookFromFile(file, bookMeta);
|
||||
} else {
|
||||
BooksWithoutBorders.log(Level.WARNING, "File with unexpected extension " + extension + " encountered!");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (loadedBook == null) {
|
||||
BooksWithoutBorders.log(Level.SEVERE, "Unable to load book: " + file.getName());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Attempt to retain UUID naming
|
||||
boolean isPublic = true;
|
||||
OfflinePlayer author = player;
|
||||
try {
|
||||
UUID authorId = UUID.fromString(file.getParentFile().getName());
|
||||
author = Bukkit.getOfflinePlayer(authorId);
|
||||
isPublic = false;
|
||||
} catch (IllegalArgumentException ignored) {
|
||||
}
|
||||
|
||||
try {
|
||||
String newName = BookHelper.getBookFile(loadedBook, author, isPublic);
|
||||
return saveBook(file.getParentFile(), newName, loadedBook, file);
|
||||
} catch (IllegalArgumentException exception) {
|
||||
BooksWithoutBorders.sendErrorMessage(player, "Failed to migrate book: " + file.getName() + " Cause:");
|
||||
BooksWithoutBorders.sendErrorMessage(player, exception.getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves a migrated book
|
||||
*
|
||||
* @param parent <p>The parent folder the file belongs to</p>
|
||||
* @param newName <p>The new name of the file</p>
|
||||
* @param bookMeta <p>The metadata of the book to migrate</p>
|
||||
* @param oldFile <p>The old file path, in case it should be deleted</p>
|
||||
* @return <p>True if successfully saved</p>
|
||||
*/
|
||||
private boolean saveBook(@NotNull File parent, @NotNull String newName, @NotNull BookMeta bookMeta,
|
||||
@NotNull File oldFile) {
|
||||
try {
|
||||
BookToFromTextHelper.bookToYml(parent.getAbsolutePath(), newName, bookMeta);
|
||||
if (!oldFile.getAbsolutePath().equalsIgnoreCase(new File(parent, newName + ".yml").getAbsolutePath())) {
|
||||
return oldFile.delete();
|
||||
}
|
||||
return true;
|
||||
} catch (IOException exception) {
|
||||
BooksWithoutBorders.log(Level.SEVERE, "Failed to save migrated book: " + newName);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -26,7 +26,7 @@ public class BooksWithoutBordersConfig {
|
||||
private final ChatColor commandColor = ChatColor.YELLOW;
|
||||
private final String SLASH = FileSystems.getDefault().getSeparator();
|
||||
private boolean isInitialized;
|
||||
public String bookFolder;
|
||||
private final String bookFolder;
|
||||
|
||||
private int bookDuplicateLimit;
|
||||
private String titleAuthorSeparator;
|
||||
|
@@ -138,6 +138,11 @@ public enum BwBCommand {
|
||||
* Deletes a page from the held book
|
||||
*/
|
||||
DELETE_PAGE("deleteBookPage", true),
|
||||
|
||||
/**
|
||||
* Migrates all books, fixing any problems with their names, and converts txt books to yml
|
||||
*/
|
||||
MIGRATE("migrateBooks", true),
|
||||
;
|
||||
|
||||
private final @NotNull String commandName;
|
||||
|
@@ -276,7 +276,7 @@ public class SignEventListener implements Listener {
|
||||
if (file == null) {
|
||||
file = BookFileHelper.findBookFile(encryptedFolder, oldBook);
|
||||
if (file == null) {
|
||||
file = BookFileHelper.findBookFile(config.bookFolder, oldBook);
|
||||
file = BookFileHelper.findBookFile(config.getBookFolder(), oldBook);
|
||||
if (file == null) {
|
||||
BooksWithoutBorders.sendErrorMessage(player, "Unable to find encrypted book");
|
||||
return;
|
||||
|
@@ -220,6 +220,24 @@ public final class BookFileHelper {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Strips the extension from the given path
|
||||
*
|
||||
* @param path <p>The path to strip the extension from</p>
|
||||
* @return <p>The input with the extension stripped</p>
|
||||
*/
|
||||
@NotNull
|
||||
public static String getExtensionFromPath(@NotNull String path) {
|
||||
int dotIndex = path.lastIndexOf(".");
|
||||
if (dotIndex > 0) {
|
||||
String separator = BooksWithoutBorders.getConfiguration().getTitleAuthorSeparator();
|
||||
if (path.lastIndexOf(separator) < dotIndex && (path.length() - dotIndex == 4)) {
|
||||
return path.substring(dotIndex + 1);
|
||||
}
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Strips the extension from the given path
|
||||
*
|
||||
|
@@ -6,6 +6,7 @@ import net.knarcraft.bookswithoutborders.config.Translatable;
|
||||
import net.knarcraft.bookswithoutborders.state.BookDirectory;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
@@ -159,8 +160,8 @@ public final class BookHelper {
|
||||
* @throws IllegalArgumentException <p>If the book title or author contains the title author separator</p>
|
||||
*/
|
||||
@NotNull
|
||||
public static String getBookFile(@NotNull BookMeta book, @NotNull Player player, boolean isPublic) throws IllegalArgumentException {
|
||||
String titleAuthorSeparator = BooksWithoutBorders.getConfiguration().getTitleAuthorSeparator();
|
||||
public static String getBookFile(@NotNull BookMeta book, @NotNull OfflinePlayer player, boolean isPublic) throws IllegalArgumentException {
|
||||
String separator = BooksWithoutBorders.getConfiguration().getTitleAuthorSeparator();
|
||||
String bookName;
|
||||
if (book.hasTitle()) {
|
||||
bookName = book.getTitle();
|
||||
@@ -171,8 +172,9 @@ public final class BookHelper {
|
||||
bookName = "Untitled";
|
||||
}
|
||||
|
||||
String playerName = player.getName() == null ? player.getUniqueId().toString() : player.getName();
|
||||
String authorName;
|
||||
if ((!book.hasAuthor() || isAuthor(player.getName(), book.getAuthor())) && !isPublic) {
|
||||
if ((!book.hasAuthor() || isAuthor(playerName, book.getAuthor())) && !isPublic) {
|
||||
//Store as unique id to account for name changes
|
||||
authorName = player.getUniqueId().toString();
|
||||
} else if (!book.hasAuthor()) {
|
||||
@@ -184,12 +186,14 @@ public final class BookHelper {
|
||||
}
|
||||
}
|
||||
|
||||
if (bookName.contains(titleAuthorSeparator) || authorName.contains(titleAuthorSeparator)) {
|
||||
throw new IllegalArgumentException("The author or title contains the title author separator. Saving this " +
|
||||
if (InputCleaningHelper.cleanString(bookName).contains(separator) ||
|
||||
InputCleaningHelper.cleanString(authorName).contains(separator)) {
|
||||
throw new IllegalArgumentException("The author; " + authorName + " or title; " + bookName +
|
||||
" contains the title author separator (" + separator + "). Saving this " +
|
||||
"book would lead to unexpected problems.");
|
||||
}
|
||||
|
||||
return InputCleaningHelper.cleanString(bookName + titleAuthorSeparator + authorName);
|
||||
return InputCleaningHelper.cleanString(bookName + separator + authorName);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -39,7 +39,7 @@ public final class BookToFromTextHelper {
|
||||
*/
|
||||
public static void bookToYml(@NotNull String path, @NotNull String fileName, @NotNull BookMeta bookMetadata) throws IOException {
|
||||
FileConfiguration bookYml = getBookConfiguration(bookMetadata);
|
||||
bookYml.save(path + fileName + ".yml");
|
||||
bookYml.save(new File(path, fileName + ".yml"));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -109,6 +109,10 @@ commands:
|
||||
description: Deletes one page from a book
|
||||
usage: /<command> <page>
|
||||
permission: bookswithoutborders.deletepage
|
||||
migrateBooks:
|
||||
description: Migrates all txt books to yml, and fixes any incorrect filenames
|
||||
usage: /<command>
|
||||
permission: bookswithoutborders.admin
|
||||
permissions:
|
||||
bookswithoutborders.*:
|
||||
description: Grants all permissions
|
||||
|
Reference in New Issue
Block a user