// Copyright (c) 2015, Christopher "BlayTheNinth" Baker package net.blay09.mods.eirairc.config; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.gson.Gson; import com.google.gson.JsonArray; import com.google.gson.JsonObject; import com.google.gson.JsonSyntaxException; import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonWriter; import net.blay09.mods.eirairc.ConnectionManager; import net.blay09.mods.eirairc.EiraIRC; import net.blay09.mods.eirairc.api.bot.IBotCommand; import net.blay09.mods.eirairc.api.irc.IRCConnection; import net.blay09.mods.eirairc.bot.BotCommandCustom; import net.blay09.mods.eirairc.bot.IRCBotImpl; import net.blay09.mods.eirairc.config.base.MessageFormatConfig; import net.blay09.mods.eirairc.config.base.ServiceConfig; import net.blay09.mods.eirairc.util.ConfigHelper; import net.blay09.mods.eirairc.util.Utils; import net.minecraft.client.resources.IResourceManager; import net.minecraft.command.ICommandSender; import net.minecraft.util.ResourceLocation; import net.minecraftforge.common.config.Configuration; import org.apache.commons.io.IOUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import java.io.*; import java.net.URL; import java.util.Collection; import java.util.List; import java.util.Map; public class ConfigurationHandler { private static final Logger logger = LogManager.getLogger(); private static final Map<String, ServerConfig> serverConfigs = Maps.newHashMap(); private static final Map<String, MessageFormatConfig> displayFormats = Maps.newHashMap(); private static final List<IBotCommand> customCommands = Lists.newArrayList(); private static final List<RemoteBotCommand> remoteCommands = Lists.newArrayList(); private static final List<SuggestedChannel> suggestedChannels = Lists.newArrayList(); private static final Map<String, TrustedServer> trustedServers = Maps.newHashMap(); public static final List<String> failedToLoad = Lists.newArrayList(); private static File baseConfigDir; private static MessageFormatConfig defaultDisplayFormat; private static void loadDisplayFormats(File formatDir) { displayFormats.clear(); if (!formatDir.exists()) { if (!formatDir.mkdirs()) { return; } } MessageFormatConfig.setupDefaultFormats(formatDir); File[] files = formatDir.listFiles((file, name) -> { return name.endsWith(".cfg"); }); for (File file : files) { MessageFormatConfig dfc = new MessageFormatConfig(file); dfc.loadFormats(); displayFormats.put(dfc.getName(), dfc); } defaultDisplayFormat = displayFormats.get(MessageFormatConfig.DEFAULT_FORMAT); } private static void loadTrustedServers(File configDir) { trustedServers.clear(); Gson gson = new Gson(); try { Reader reader = new FileReader(new File(configDir, "trusted_servers.json")); JsonReader jsonReader = new JsonReader(reader); jsonReader.setLenient(true); JsonArray serverArray = gson.fromJson(jsonReader, JsonArray.class); for (int i = 0; i < serverArray.size(); i++) { addTrustedServer(TrustedServer.loadFromJson(serverArray.get(i).getAsJsonObject())); } reader.close(); } catch (JsonSyntaxException e) { logger.error("Syntax error in trusted_servers.json: ", e); failedToLoad.add("trusted_servers.json"); } catch (FileNotFoundException ignored) { } catch (IOException e) { e.printStackTrace(); } } public static void saveTrustedServers() { Gson gson = new Gson(); try { JsonArray serverArray = new JsonArray(); for (TrustedServer trustedServer : trustedServers.values()) { serverArray.add(trustedServer.toJsonObject()); } JsonWriter writer = new JsonWriter(new FileWriter(new File(baseConfigDir, "eirairc/trusted_servers.json"))); writer.setIndent(" "); gson.toJson(serverArray, writer); writer.close(); } catch (IOException e) { e.printStackTrace(); } } private static void loadServices(File configDir) { if (!configDir.exists()) { if (!configDir.mkdirs()) { return; } } Configuration serviceConfig = new Configuration(new File(configDir, "services.cfg")); ServiceConfig.setupDefaultServices(serviceConfig); ServiceConfig.load(serviceConfig); } public static void loadSuggestedChannels(IResourceManager resourceManager) throws IOException { suggestedChannels.clear(); InputStream in; File overrideFile = new File(baseConfigDir, "eirairc/suggested-channels.json"); if (overrideFile.exists()) { in = new FileInputStream(overrideFile); } else { URL remoteURL = new URL("https://raw.githubusercontent.com/blay09/EiraIRC/master/src/main/resources/assets/eirairc/suggested-channels.json"); try { in = remoteURL.openStream(); } catch (IOException e) { in = resourceManager.getResource(new ResourceLocation("eirairc", "suggested-channels.json")).getInputStream(); } } Gson gson = new Gson(); Reader reader = new InputStreamReader(in); JsonReader jsonReader = new JsonReader(reader); jsonReader.setLenient(true); try { JsonArray channelArray = gson.fromJson(jsonReader, JsonArray.class); for (int i = 0; i < channelArray.size(); i++) { suggestedChannels.add(SuggestedChannel.loadFromJson(channelArray.get(i).getAsJsonObject())); } } catch (JsonSyntaxException e) { logger.error("Syntax error in suggested-channels.json: ", e); failedToLoad.add("suggested-channels.json"); } reader.close(); in.close(); } private static void loadCommands(File configDir) { customCommands.clear(); if (!configDir.exists()) { if (!configDir.mkdirs()) { return; } } copyExampleFile("commands.json.example.txt"); Gson gson = new Gson(); try { File file = new File(configDir, "commands.json"); if (!file.exists()) { JsonArray root = new JsonArray(); JsonObject players = new JsonObject(); players.addProperty("name", "players"); players.addProperty("override", "who"); players.addProperty("description", "Default alias players for the who command."); root.add(players); try { JsonWriter writer = new JsonWriter(new FileWriter(new File(baseConfigDir, "eirairc/commands.json"))); writer.setIndent(" "); gson.toJson(root, writer); writer.close(); } catch (IOException e) { e.printStackTrace(); } } Reader reader = new FileReader(file); JsonReader jsonReader = new JsonReader(reader); jsonReader.setLenient(true); JsonArray commandArray = gson.fromJson(jsonReader, JsonArray.class); for (int i = 0; i < commandArray.size(); i++) { JsonObject obj = commandArray.get(i).getAsJsonObject(); String type = "custom"; if (obj.has("type")) { type = obj.get("type").getAsString(); } if (type.equals("custom")) { customCommands.add(BotCommandCustom.loadFromJson(obj)); } else if (type.equals("remote")) { remoteCommands.add(RemoteBotCommand.loadFromJson(obj)); } } reader.close(); } catch (FileNotFoundException ignored) { } catch (IOException e) { e.printStackTrace(); } catch (JsonSyntaxException e) { logger.error("Syntax error in commands.json: ", e); failedToLoad.add("commands.json"); } } private static void loadServers(File configDir) { serverConfigs.clear(); if (!configDir.exists()) { if (!configDir.mkdirs()) { return; } } copyExampleFile("servers.json.example.txt"); Gson gson = new Gson(); try { Reader reader = new FileReader(new File(configDir, "servers.json")); JsonReader jsonReader = new JsonReader(reader); jsonReader.setLenient(true); JsonArray serverArray = gson.fromJson(jsonReader, JsonArray.class); for (int i = 0; i < serverArray.size(); i++) { addServerConfig(ServerConfig.loadFromJson(serverArray.get(i).getAsJsonObject())); } reader.close(); } catch (JsonSyntaxException e) { logger.error("Syntax error in servers.json: ", e); failedToLoad.add("servers.json"); } catch (FileNotFoundException ignored) { } catch (IOException e) { e.printStackTrace(); } } public static void saveServers() { Gson gson = new Gson(); try { JsonArray serverArray = new JsonArray(); for (ServerConfig serverConfig : serverConfigs.values()) { serverArray.add(serverConfig.toJsonObject()); } JsonWriter writer = new JsonWriter(new FileWriter(new File(baseConfigDir, "eirairc/servers.json"))); writer.setIndent(" "); gson.toJson(serverArray, writer); writer.close(); } catch (IOException e) { e.printStackTrace(); } } private static void copyExampleFile(String fileName) { String exampleFileInput = "/assets/eirairc/" + fileName; File exampleFileOutput = new File(baseConfigDir, "eirairc/" + fileName); try (InputStreamReader reader = new InputStreamReader(ConfigurationHandler.class.getResourceAsStream(exampleFileInput)); FileWriter writer = new FileWriter(exampleFileOutput)) { IOUtils.copy(reader, writer); } catch (IOException e) { e.printStackTrace(); } } public static void load(File baseConfigDir) { ConfigurationHandler.baseConfigDir = baseConfigDir; File configDir = new File(baseConfigDir, "eirairc"); loadServices(configDir); loadDisplayFormats(new File(configDir, "formats")); EiraIRC.proxy.loadConfig(configDir, true); loadCommands(configDir); loadServers(configDir); loadTrustedServers(configDir); AuthManager.load(new File(".")); IgnoreList.load(configDir); } public static void save() { EiraIRC.proxy.saveConfig(); saveServers(); saveTrustedServers(); } public static void reloadAll() { failedToLoad.clear(); load(baseConfigDir); for (IRCConnection connection : ConnectionManager.getConnections()) { ((IRCBotImpl) connection.getBot()).reloadCommands(); } } public static void lightReload() { File configDir = new File(baseConfigDir, "eirairc"); EiraIRC.proxy.loadConfig(configDir, false); } public static ServerConfig getOrCreateServerConfig(String host) { ServerConfig serverConfig = serverConfigs.get(host.toLowerCase()); if (serverConfig == null) { serverConfig = new ServerConfig(host); } return serverConfig; } public static Collection<ServerConfig> getServerConfigs() { return serverConfigs.values(); } public static ServerConfig getServerConfig(String address) { return serverConfigs.get(address.toLowerCase()); } public static void addServerConfig(ServerConfig serverConfig) { serverConfigs.put(serverConfig.getAddress().toLowerCase(), serverConfig); } public static ServerConfig removeServerConfig(String host) { return serverConfigs.remove(host.toLowerCase()); } public static boolean hasServerConfig(String host) { return serverConfigs.containsKey(host.toLowerCase()); } public static void addTrustedServer(TrustedServer server) { trustedServers.put(server.getAddress(), server); } public static TrustedServer getOrCreateTrustedServer(String address) { TrustedServer server = trustedServers.get(address.toLowerCase()); if (server == null) { server = new TrustedServer(address); } return server; } public static void handleConfigCommand(ICommandSender sender, String target, String key, String value) { if (target.equals("global")) { boolean result = EiraIRC.proxy.handleConfigCommand(sender, key, value); if (result) { Utils.sendLocalizedMessage(sender, "commands.config.change", "Global", key, value); ConfigurationHandler.save(); } else { Utils.sendLocalizedMessage(sender, "commands.config.invalidOption", "Global", key); } } else { ChannelConfig channelConfig = ConfigHelper.resolveChannelConfig(target); if (channelConfig != null) { channelConfig.handleConfigCommand(sender, key, value); } else { ServerConfig serverConfig = ConfigHelper.resolveServerConfig(target); if (serverConfig != null) { serverConfig.handleConfigCommand(sender, key, value); } else { Utils.sendLocalizedMessage(sender, "error.targetNotFound", target); } } } } public static void handleConfigCommand(ICommandSender sender, String target, String key) { if (target.equals("global")) { String result = EiraIRC.proxy.handleConfigCommand(sender, key); if (result != null) { Utils.sendLocalizedMessage(sender, "commands.config.lookup", "Global", key, result); } else { Utils.sendLocalizedMessage(sender, "commands.config.invalidOption", "Global", key); } } else { ChannelConfig channelConfig = ConfigHelper.resolveChannelConfig(target); if (channelConfig != null) { channelConfig.handleConfigCommand(sender, key); } else { ServerConfig serverConfig = ConfigHelper.resolveServerConfig(target); if (serverConfig != null) { serverConfig.handleConfigCommand(sender, key); } else { Utils.sendLocalizedMessage(sender, "error.targetNotFound", target); } } } save(); } public static void addOptionsToList(List<String> list, String option, boolean autoCompleteOption) { EiraIRC.proxy.addConfigOptionsToList(list, option, autoCompleteOption); } public static MessageFormatConfig getMessageFormat(String displayMode) { MessageFormatConfig displayFormat = displayFormats.get(displayMode); if (displayFormat == null) { return defaultDisplayFormat; } return displayFormat; } public static List<IBotCommand> getCustomCommands() { return customCommands; } public static List<SuggestedChannel> getSuggestedChannels() { return suggestedChannels; } public static String[] getAvailableMessageFormats() { return displayFormats.keySet().toArray(new String[displayFormats.size()]); } public static boolean passesRemoteCommand(ICommandSender sender, String message) { for (RemoteBotCommand command : remoteCommands) { if (message.startsWith(command.command) && (!command.requireOp || Utils.isOP(sender))) { return true; } } return false; } }