diff --git a/src/main/java/wtf/beatrice/hidekobot/Cache.java b/src/main/java/wtf/beatrice/hidekobot/Cache.java index 8d66843..deb170d 100644 --- a/src/main/java/wtf/beatrice/hidekobot/Cache.java +++ b/src/main/java/wtf/beatrice/hidekobot/Cache.java @@ -33,6 +33,7 @@ public class Cache private static final String heartbeatLink = "https://status.beatrice.wtf/api/push/%apikey%?status=up&msg=OK&ping="; private static String heartbeatApiKey = ""; + private final static String execPath = System.getProperty("user.dir"); private static final String botVersion = "0.1.5-slash"; // we should probably find a way to make this consistent with Maven private static final String botName = "HidekoBot"; @@ -232,5 +233,6 @@ public class Cache public static String getHeartBeatApiKey() { return heartbeatApiKey; } + public static String getExecPath() { return execPath; } } diff --git a/src/main/java/wtf/beatrice/hidekobot/HidekoBot.java b/src/main/java/wtf/beatrice/hidekobot/HidekoBot.java index f9c6fe0..5e66c4d 100644 --- a/src/main/java/wtf/beatrice/hidekobot/HidekoBot.java +++ b/src/main/java/wtf/beatrice/hidekobot/HidekoBot.java @@ -14,6 +14,7 @@ import wtf.beatrice.hidekobot.listeners.SlashCommandListener; import wtf.beatrice.hidekobot.runnables.CommandsUpdateTask; import wtf.beatrice.hidekobot.runnables.ExpiredMessageTask; import wtf.beatrice.hidekobot.runnables.HeartBeatTask; +import wtf.beatrice.hidekobot.utils.ConfigurationUtil; import wtf.beatrice.hidekobot.utils.Logger; import wtf.beatrice.hidekobot.utils.SlashCommandUtil; @@ -110,9 +111,16 @@ public class HidekoBot jda.getPresence().setStatus(OnlineStatus.ONLINE); jda.getPresence().setActivity(Activity.playing("Hatsune Miku: Project DIVA")); + + // load configuration + String configFilePath = Cache.getExecPath() + File.separator + "config.yml"; + ConfigurationUtil configurationUtil = new ConfigurationUtil(configFilePath); + configurationUtil.initConfig(); + + // connect to database logger.log("Connecting to database..."); - String dbFilePath = System.getProperty("user.dir") + File.separator + "db.sqlite"; // in current directory + String dbFilePath = Cache.getExecPath() + File.separator + "db.sqlite"; // in current directory DatabaseManager dbManager = new DatabaseManager(dbFilePath); if(dbManager.connect() && dbManager.initDb()) { diff --git a/src/main/java/wtf/beatrice/hidekobot/utils/ConfigurationUtil.java b/src/main/java/wtf/beatrice/hidekobot/utils/ConfigurationUtil.java index 5103f7b..4439132 100644 --- a/src/main/java/wtf/beatrice/hidekobot/utils/ConfigurationUtil.java +++ b/src/main/java/wtf/beatrice/hidekobot/utils/ConfigurationUtil.java @@ -1,40 +1,120 @@ package wtf.beatrice.hidekobot.utils; +import org.yaml.snakeyaml.DumperOptions; import org.yaml.snakeyaml.Yaml; +import wtf.beatrice.hidekobot.HidekoBot; -import java.io.IOException; -import java.io.InputStream; -import java.util.Map; +import java.io.*; +import java.util.LinkedHashMap; public class ConfigurationUtil { + + private final Logger logger; private final String configFilePath; public ConfigurationUtil(String configFilePath) { this.configFilePath = configFilePath; + logger = new Logger(getClass()); } public void initConfig() { + // load the YAML file from the archive's resources folder Yaml internalConfigYaml = new Yaml(); - Map internalConfigContents = null; - + LinkedHashMap internalConfigContents = null; // map holding all file entries try (InputStream internalConfigStream = getClass() .getClassLoader() .getResourceAsStream("config.yml")) - { - internalConfigContents = internalConfigYaml.load(internalConfigStream); - } catch (IOException e) { - e.printStackTrace(); - } + { internalConfigContents = internalConfigYaml.load(internalConfigStream); } + catch (IOException e) { logger.log(e.getMessage()); } - if(internalConfigContents == null) // todo error handling + if(internalConfigContents == null) { - + logger.log("Error reading internal configuration!"); + HidekoBot.shutdown(); return; } + // check if config files exists in filesystem + File fsConfigFile = new File(configFilePath); + if(!fsConfigFile.exists()) + { + // try to create config file + try { fsConfigFile.createNewFile(); } + catch (IOException e) { + logger.log("Error creating configuration file!"); + logger.log(e.getMessage()); + HidekoBot.shutdown(); + return; + } + } + // load the YAML file from the filesystem + Yaml fsConfigYaml = new Yaml(); + LinkedHashMap fsConfigContents = null; // map holding all file entries + try (InputStream fsConfigStream = new FileInputStream(fsConfigFile)) + { fsConfigContents = fsConfigYaml.load(fsConfigStream); } + catch (IOException e) { logger.log(e.getMessage()); } + + + if(fsConfigContents == null) // if file contents are empty or corrupted... + { + // "clean" them (this effectively forces a config file reset) + fsConfigContents = new LinkedHashMap<>(); + } + + // check for missing keys + boolean missingKeys = false; + for(String key : internalConfigContents.keySet()) + { + // if key is missing + if(!fsConfigContents.containsKey(key)) + { + // quit and flag it, as we need to complete the file with the missing ones + missingKeys = true; + break; + } + } + + // if keys are missing + if(missingKeys) + { + // create a new mixed map that will take existing values from the non-missing keys + // and fill everything else with the default values + LinkedHashMap filledEntries = new LinkedHashMap<>(); + for(String key : internalConfigContents.keySet()) + { + if(fsConfigContents.containsKey(key)) + { + // if the key already exists, copy the original value + filledEntries.put(key, fsConfigContents.get(key)); + } else { + // else, copy the value from the example config file + filledEntries.put(key, internalConfigContents.get(key)); + } + } + + try { + // new writer to actually write the contents to the file + PrintWriter missingKeysWriter = new PrintWriter(fsConfigFile); + + // set yaml options to make the output prettier + DumperOptions dumperOptions = new DumperOptions(); + dumperOptions.setIndent(2); + dumperOptions.setPrettyFlow(true); + dumperOptions.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); + + // create the yaml object and dump the values to filesystem + Yaml yaml = new Yaml(dumperOptions); + yaml.dump(filledEntries, missingKeysWriter); + } catch (FileNotFoundException e) { + logger.log(e.getMessage()); + HidekoBot.shutdown(); + return; + } + + } } }