From a1d7fa697b18c65e15c1f4a1b2c06088f78c3dd2 Mon Sep 17 00:00:00 2001 From: BuildTools Date: Fri, 20 Mar 2020 14:18:34 +1000 Subject: [PATCH] 1.0 update --- build.gradle | 13 ++- res/plugin.yml | 9 +- .../enderbot/core/ConfigManager.java | 13 +++ src/codedcosmos/enderbot/core/EnderBot.java | 7 +- src/codedcosmos/enderbot/discord/JDABot.java | 8 +- .../plugin/MinecraftChatListener.java | 16 +++ .../enderbot/plugin/MinecraftPlugin.java | 13 ++- .../plugin/commands/BackupCommand.java | 38 +++++++ src/codedcosmos/enderbot/utils/FileUtils.java | 4 + .../enderbot/utils/GoogleDrive.java | 103 +++++++++--------- 10 files changed, 162 insertions(+), 62 deletions(-) create mode 100644 src/codedcosmos/enderbot/plugin/commands/BackupCommand.java diff --git a/build.gradle b/build.gradle index 8e8306d..e38b019 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ plugins { } group 'codedcosmos' -version '0.1' +version '1.0' mainClassName = 'codedcosmos.enderbot.core.EnderBot' sourceCompatibility = 1.8 @@ -18,7 +18,14 @@ repositories { mavenCentral() jcenter() maven { - url "https://hub.spigotmc.org/nexus/content/repositories/snapshots" + url = 'https://hub.spigotmc.org/nexus/content/repositories/snapshots/' + + // As of Gradle 5.1, you can limit this to only those + // dependencies you expect from it + content { + includeGroup 'org.bukkit' + includeGroup 'org.spigotmc' + } } } @@ -36,7 +43,7 @@ dependencies { compile 'com.google.oauth-client:google-oauth-client-jetty:1.23.0' compile 'com.google.apis:google-api-services-drive:v3-rev110-1.23.0' - compileOnly "org.spigotmc:spigot-api:1.15.1-R0.1-SNAPSHOT" + compileOnly 'org.spigotmc:spigot:1.15.2-R0.1-SNAPSHOT' } jar { diff --git a/res/plugin.yml b/res/plugin.yml index 66f0875..f5684d7 100644 --- a/res/plugin.yml +++ b/res/plugin.yml @@ -1,5 +1,10 @@ name: EnderBot -version: 0.1 +version: 1.0 author: codedcosmos main: codedcosmos.enderbot.plugin.MinecraftPlugin -api-version: 1.15 \ No newline at end of file +api-version: 1.15 + +commands: + enderbackup: + description: Backs up the world and uploads zip + usage: /enderbackup \ No newline at end of file diff --git a/src/codedcosmos/enderbot/core/ConfigManager.java b/src/codedcosmos/enderbot/core/ConfigManager.java index 0114589..45f6fa3 100644 --- a/src/codedcosmos/enderbot/core/ConfigManager.java +++ b/src/codedcosmos/enderbot/core/ConfigManager.java @@ -34,6 +34,7 @@ public class ConfigManager { public static String minecraft_ingame_channel_name; public static String world_backups_channel_name; public static int world_backups_frequency_in_days; + public static boolean world_backups_enabled; // Censored Config values public static String discord_bot_token; @@ -49,6 +50,9 @@ public static HashMap getDefault() { // How often the world will be backed up (in days) defaults.put("world-backups-frequency-in-days", "30"); + + // Defines if the game will be backed up at all + defaults.put("world-backups-enabled", "False"); // Discord Developer API bot token @@ -122,6 +126,15 @@ public static void load() { world_backups_frequency_in_days = 30; } Log.print("Loaded 'world-backups-frequency-in-days' as " + world_backups_frequency_in_days); + + try { + world_backups_enabled = Boolean.parseBoolean(prop.getProperty("world-backups-enabled").toLowerCase()); + } catch (NumberFormatException e) { + Log.printErr("Failed to load config 'world-backups-frequency-in-days'"); + Log.printErr("Setting it as default!"); + world_backups_enabled = false; + } + Log.print("Loaded 'world-backups-enabled' as " + world_backups_enabled); diff --git a/src/codedcosmos/enderbot/core/EnderBot.java b/src/codedcosmos/enderbot/core/EnderBot.java index 9c6252c..0efa159 100644 --- a/src/codedcosmos/enderbot/core/EnderBot.java +++ b/src/codedcosmos/enderbot/core/EnderBot.java @@ -13,11 +13,12 @@ */ package codedcosmos.enderbot.core; +import codedcosmos.enderbot.utils.GoogleDrive; import codedcosmos.enderbot.utils.Log; public class EnderBot { - private static final String VERSION = "0.1"; + private static final String VERSION = "1.0"; private static boolean runningInSpigot = false; public static void load(boolean runningInSpigot) { @@ -35,4 +36,8 @@ public static void load(boolean runningInSpigot) { public static boolean isRunningInSpigot() { return runningInSpigot; } + + public static String getVersion() { + return VERSION; + } } diff --git a/src/codedcosmos/enderbot/discord/JDABot.java b/src/codedcosmos/enderbot/discord/JDABot.java index e088cef..39b6203 100644 --- a/src/codedcosmos/enderbot/discord/JDABot.java +++ b/src/codedcosmos/enderbot/discord/JDABot.java @@ -24,6 +24,8 @@ public class JDABot { + private static JDA jda; + public static void main(String[] args) { Log.print("Starting EnderBot Discord Subsystem"); EnderBot.load(false); @@ -40,11 +42,15 @@ public static void initBot() { builder.addEventListeners(new DiscordChatListener()); builder.addEventListeners(new DiscordEventHandler()); - JDA jda = builder.build(); + jda = builder.build(); jda.awaitReady(); } catch (LoginException | InterruptedException e) { Log.printErr(e); } } + + public static void stop() { + jda.shutdownNow(); + } } diff --git a/src/codedcosmos/enderbot/plugin/MinecraftChatListener.java b/src/codedcosmos/enderbot/plugin/MinecraftChatListener.java index 320ff89..04f45c0 100644 --- a/src/codedcosmos/enderbot/plugin/MinecraftChatListener.java +++ b/src/codedcosmos/enderbot/plugin/MinecraftChatListener.java @@ -20,6 +20,8 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.player.AsyncPlayerChatEvent; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerQuitEvent; public class MinecraftChatListener implements Listener { @EventHandler @@ -28,4 +30,18 @@ public void onAsyncPlayerChat(AsyncPlayerChatEvent event) { context.getInGameChannel().sendMessage("**"+event.getPlayer().getDisplayName()+"** : " + event.getMessage()); } } + + @EventHandler + public void onPlayerJoin(PlayerJoinEvent event) { + for (GuildContext context : Guilds.getContexts()) { + context.getInGameChannel().sendMessage("`"+event.getPlayer().getDisplayName()+" joined the game`"); + } + } + + @EventHandler + public void onPlayerQuit(PlayerQuitEvent event) { + for (GuildContext context : Guilds.getContexts()) { + context.getInGameChannel().sendMessage("`"+event.getPlayer().getDisplayName()+" left the game`"); + } + } } diff --git a/src/codedcosmos/enderbot/plugin/MinecraftPlugin.java b/src/codedcosmos/enderbot/plugin/MinecraftPlugin.java index 9c3a31c..571fdf4 100644 --- a/src/codedcosmos/enderbot/plugin/MinecraftPlugin.java +++ b/src/codedcosmos/enderbot/plugin/MinecraftPlugin.java @@ -13,8 +13,10 @@ */ package codedcosmos.enderbot.plugin; +import codedcosmos.enderbot.core.ConfigManager; import codedcosmos.enderbot.discord.JDABot; import codedcosmos.enderbot.core.EnderBot; +import codedcosmos.enderbot.plugin.commands.BackupCommand; import codedcosmos.enderbot.utils.GoogleDrive; import codedcosmos.enderbot.utils.Log; import org.bukkit.plugin.java.JavaPlugin; @@ -26,22 +28,24 @@ public class MinecraftPlugin extends JavaPlugin { @Override public void onEnable(){ //Fired when the server enables the plugin - Log.print("Enabling EnderBot"); + Log.print("Enabling EnderBot v" + EnderBot.getVersion()); EnderBot.load(true); JDABot.initBot(); mainPlugin = this; + + this.getCommand("enderbackup").setExecutor(new BackupCommand()); getServer().getPluginManager().registerEvents(new MinecraftChatListener(), this); - archiveLoop(); + + if (ConfigManager.world_backups_enabled) archiveLoop(); } public void archiveLoop() { JavaPlugin plugin = this; getServer().getScheduler().scheduleSyncDelayedTask(this, new Runnable() { public void run() { - int time = GoogleDrive.archiveIfNeeded(); - Log.print("Backup task completed in " + time + "ms"); + GoogleDrive.archiveIfNeeded(); archiveLoop(); } }, 20L*60*30); @@ -52,5 +56,6 @@ public void run() { public void onDisable(){ //Fired when the server stops and disables all plugins Log.print("Disabiling EnderBot"); + JDABot.stop(); } } diff --git a/src/codedcosmos/enderbot/plugin/commands/BackupCommand.java b/src/codedcosmos/enderbot/plugin/commands/BackupCommand.java new file mode 100644 index 0000000..2322e59 --- /dev/null +++ b/src/codedcosmos/enderbot/plugin/commands/BackupCommand.java @@ -0,0 +1,38 @@ +package codedcosmos.enderbot.plugin.commands; + +import codedcosmos.enderbot.core.ConfigManager; +import codedcosmos.enderbot.core.EnderBot; +import codedcosmos.enderbot.utils.GoogleDrive; +import net.minecraft.server.v1_15_R1.ItemMapEmpty; +import org.bukkit.Material; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.material.MaterialData; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; + +public class BackupCommand implements CommandExecutor { + public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) { + if (sender instanceof Player) { + Player player = (Player) sender; + if (player.isOp()) { + if (!ConfigManager.world_backups_enabled) { + player.sendMessage("Backups are disabled"); + return true; + } + + GoogleDrive.archive(); + return true; + } else { + player.sendMessage("You must be op to use this command"); + } + } + return false; + } +} diff --git a/src/codedcosmos/enderbot/utils/FileUtils.java b/src/codedcosmos/enderbot/utils/FileUtils.java index 0f65a86..0bc2805 100644 --- a/src/codedcosmos/enderbot/utils/FileUtils.java +++ b/src/codedcosmos/enderbot/utils/FileUtils.java @@ -14,14 +14,18 @@ package codedcosmos.enderbot.utils; import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.ArrayList; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; public class FileUtils { + public static void zip(String source, String zipname) throws IOException { // Helpful console message Log.print("Creating zip file '" + zipname + "' for folder '" + source + "'"); diff --git a/src/codedcosmos/enderbot/utils/GoogleDrive.java b/src/codedcosmos/enderbot/utils/GoogleDrive.java index 1715822..21846cc 100644 --- a/src/codedcosmos/enderbot/utils/GoogleDrive.java +++ b/src/codedcosmos/enderbot/utils/GoogleDrive.java @@ -16,6 +16,7 @@ import codedcosmos.enderbot.core.ConfigManager; import codedcosmos.enderbot.discord.GuildContext; import codedcosmos.enderbot.discord.Guilds; +import codedcosmos.enderbot.plugin.commands.BackupCommand; import com.google.api.client.googleapis.batch.BatchRequest; import com.google.api.client.googleapis.batch.json.JsonBatchCallback; import com.google.api.client.googleapis.json.GoogleJsonError; @@ -25,8 +26,8 @@ import com.google.api.client.json.jackson2.JacksonFactory; import com.google.api.services.drive.Drive; import com.google.api.services.drive.DriveScopes; +import com.google.api.services.drive.model.About; import com.google.api.services.drive.model.Permission; -import org.bukkit.plugin.java.JavaPlugin; import com.google.api.client.auth.oauth2.Credential; import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp; @@ -35,13 +36,8 @@ import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets; import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport; import com.google.api.client.http.javanet.NetHttpTransport; -import com.google.api.client.json.JsonFactory; -import com.google.api.client.json.jackson2.JacksonFactory; import com.google.api.client.util.store.FileDataStoreFactory; -import com.google.api.services.drive.Drive; -import com.google.api.services.drive.DriveScopes; import com.google.api.services.drive.model.File; -import com.google.api.services.drive.model.FileList; import java.io.FileNotFoundException; import java.io.IOException; @@ -54,33 +50,24 @@ import java.io.*; -import java.text.ParseException; import java.text.SimpleDateFormat; -import java.time.Duration; -import java.time.LocalDate; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; -import java.time.temporal.ChronoUnit; -import java.util.Calendar; -import java.util.Collections; import java.util.Date; -import java.util.List; import java.util.concurrent.TimeUnit; public class GoogleDrive { - public static final String EXPORT_LOG_PATH = "plugins/EnderBot/"; - public static final String EXPORT_LOG = EXPORT_LOG_PATH+"archive_log.txt"; + public static final String EXPORT_LOG_PATH = "plugins/EnderBot"; + public static final String EXPORT_LOG = EXPORT_LOG_PATH+"/archive_log.txt"; public static final String DATE_FORMAT = "yyyy-MM-dd--HH:mm:ss"; + + public static final String BACKUP_PATH = "plugins/EnderBot/backups"; - public static int archiveIfNeeded() { + public static void archiveIfNeeded() { if (shouldArchive()) { - Console.print("Running Server World Archive."); - Console.print("This will create lag for a short while"); - int time = archive(); - Console.print("Completed archival process in " + time + "ms"); + archive(); } - return -1; } public static boolean shouldArchive() { @@ -135,40 +122,52 @@ public static boolean shouldArchive() { return false; } - public static int archive() { - long start = System.currentTimeMillis(); - - DateTimeFormatter dtf = DateTimeFormatter.ofPattern(DATE_FORMAT); - LocalDateTime now = LocalDateTime.now(); - String filename = "world-"+dtf.format(now)+".zip"; - - try { - // Create zip - FileUtils.mkdirIfMissing("enderbotbackups"); - FileUtils.clearDirectory("enderbotbackups"); - FileUtils.zip("world", "enderbotbackups/"+filename); - - // Append to archive log - Writer output = new BufferedWriter(new FileWriter(EXPORT_LOG, true)); - output.append("\n"+dtf.format(now)); - output.close(); - } catch (IOException e) { - e.printStackTrace(); - } - - // Upload it - upload(); - - int timeMS = (int) (System.currentTimeMillis()-start); - return timeMS; + public static void archive() { + if (!ConfigManager.world_backups_enabled) return; + + Thread thread = new Thread() { + public void run() { + Console.print("Running Server World Archive."); + Console.print("This will create lag for a short while"); + + long start = System.currentTimeMillis(); + + DateTimeFormatter dtf = DateTimeFormatter.ofPattern(DATE_FORMAT); + LocalDateTime now = LocalDateTime.now(); + String filename = "world-"+dtf.format(now)+".zip"; + + try { + // Create zip + FileUtils.mkdirIfMissing(BACKUP_PATH); + FileUtils.clearDirectory(BACKUP_PATH); + FileUtils.zip("world", BACKUP_PATH+"/"+filename); + + // Append to archive log + Writer output = new BufferedWriter(new FileWriter(EXPORT_LOG, true)); + output.append("\n"+dtf.format(now)); + output.close(); + } catch (IOException e) { + e.printStackTrace(); + } + + // Upload it + upload(); + + int timeMS = (int) (System.currentTimeMillis()-start); + + Console.print("Completed archival process in " + timeMS + "ms"); + Log.print("Backup task completed in " + timeMS + "ms"); + } + }; + thread.start(); } private static final String APPLICATION_NAME = "Google Drive API Java Quickstart"; private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance(); private static final List SCOPES = Collections.singletonList(DriveScopes.DRIVE_FILE); - private static final String CREDENTIALS_FILE_PATH = EXPORT_LOG_PATH+"credentials.json"; - private static final String TOKENS_DIRECTORY_PATH = EXPORT_LOG_PATH+"tokens"; + private static final String CREDENTIALS_FILE_PATH = EXPORT_LOG_PATH+"/credentials.json"; + private static final String TOKENS_DIRECTORY_PATH = EXPORT_LOG_PATH+"/tokens"; public static void upload() { try { @@ -189,7 +188,9 @@ public static void upload() { .setDataStoreFactory(new FileDataStoreFactory(new java.io.File(TOKENS_DIRECTORY_PATH))) .setAccessType("offline") .build(); - LocalServerReceiver receiver = new LocalServerReceiver.Builder().setPort(8888).build(); + LocalServerReceiver receiver = new LocalServerReceiver.Builder() + .setPort(8888) + .build(); Credential credentials = new AuthorizationCodeInstalledApp(flow, receiver).authorize("user"); @@ -199,7 +200,7 @@ public static void upload() { .build(); // Upload - String filenameFull = FileUtils.getFirstZip("enderbotbackups"); + String filenameFull = FileUtils.getFirstZip(BACKUP_PATH); String filename = Paths.get(filenameFull).getFileName().toString(); java.io.File filePath = new java.io.File(filenameFull);