package chatty; import chatty.util.DateTime; import chatty.util.LogUtil; import chatty.util.MiscUtil; import chatty.util.SingleInstance; import java.io.File; import java.util.HashMap; import java.util.Map; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; /** * Main class that starts the client as well as parses the commandline * parameters and provides some app-specific global constants. * * @author tduva */ public class Chatty { /** * Enables debug commands as well as some other behaviour that allows * debugging. Should be disabled for a regular release. */ public static final boolean DEBUG = false; /** * Enables the hotkey feature for running commercials (windows only). */ public static final boolean HOTKEY = MiscUtil.OS_WINDOWS; /** * The Chatty website as it can be opened in the menu. */ public static final String WEBSITE = "http://chatty.github.io"; /** * The Twitch client id of this program. * * If you compile this program yourself, you should create your own client * id on http://www.twitch.tv/kraken/oauth2/clients/new */ public static final String CLIENT_ID = "spyiu9jqdnfjtwv6l1xjk5zgt8qb91l"; /** * The redirect URI for getting a token. */ public static final String REDIRECT_URI = "http://127.0.0.1:61324/token/"; /** * Version number of this version of Chatty, consisting of numbers seperated * by points. May contain a single "b" for beta versions, anything following * it will be ignored for version checking. */ public static final String VERSION = "0.8.6b2"; /** * Enable Version Checker (if you compile and distribute this yourself, you * may want to disable this) */ public static final boolean VERSION_CHECK_ENABLED = true; /** * The regular URL of the textfile where the most recent version is stored. */ public static final String VERSION_URL = "http://chatty.github.io/version.txt"; /** * For testing purposes. */ public static final String VERSION_TEST_URL = "http://127.0.0.1/twitch/version.txt"; public static final String COMPILE_INFO = "JDK8"; /** * For use with the -single commandline argument, if no port is specified. * Unregistered port from the User Ports range. */ private static final int DEFAULT_SINGLE_INSTANCE_PORT = 48724; // End of configuration /** * When this program was started */ public static final long STARTED_TIME = System.currentTimeMillis(); /** * If true, use the current working directory to save settings etc. */ private static boolean useCurrentDirectory = false; /** * Parse the commandline arguments and start the actual chat client. * * @param args The commandline arguments. */ public static void main(String[] args) { Map<String, String> parsedArgs = MiscUtil.parseArgs(args); /** * Continue only if single instance mode isn't enabled or registering * succeeded. */ if (parsedArgs.containsKey("single")) { int port = getInstancePort(parsedArgs); if (!SingleInstance.registerInstance(port)) { SingleInstance.notifyRunningInstance(port, encodeParametersToJSON(parsedArgs)); // Exit program return; } } if (parsedArgs.containsKey("cd")) { useCurrentDirectory = true; } final TwitchClient client = new TwitchClient(parsedArgs); // Adding listener just in case, will do nothing if not used SingleInstance.setNewInstanceListener(new SingleInstance.NewInstanceListener() { @Override public void newInstance(String message) { Map<String, String> args = decodeParametersFromJSON(message); if (args.containsKey("channel")) { String channel = args.get("channel"); client.joinChannels(Helper.parseChannelsFromString(channel, false)); } } }); LogUtil.startMemoryUsageLogging(); } /** * Encodes the given Map of parameters to a JSON String. * * @param parameters The Map of parsed parameters * @return The JSON String */ private static String encodeParametersToJSON(Map<String, String> parameters) { JSONObject object = new JSONObject(); object.putAll(parameters); return object.toJSONString(); } /** * Decodes the given JSON String into a Map of parameters. * * @param json The JSON String * @return The Map of parameters or an empty Map if any error occurs */ private static Map<String, String> decodeParametersFromJSON(String json) { try { JSONParser parser = new JSONParser(); JSONObject root = (JSONObject)parser.parse(json); Map<String, String> result = new HashMap<>(); for (Object key : root.keySet()) { result.put((String)key, (String)root.get(key)); } return result; } catch (Exception ex) { return new HashMap(); } } private static int getInstancePort(Map<String, String> args) { int port = DEFAULT_SINGLE_INSTANCE_PORT; String arg = args.get("single"); if (arg != null) { try { port = Integer.parseInt(arg); } catch (NumberFormatException ex) { // Use default } } return port; } /** * Gets the directory to save data in (settings, cache) and also creates it * if necessary. * * @return */ public static String getUserDataDirectory() { if (useCurrentDirectory) { return System.getProperty("user.dir") + File.separator; } String dir = System.getProperty("user.home") + File.separator + ".chatty" + File.separator; new File(dir).mkdirs(); return dir; } public static String getExportDirectory() { String dir = getUserDataDirectory()+"exported"+File.separator; new File(dir).mkdirs(); return dir; } public static String getCacheDirectory() { String dir = getUserDataDirectory()+"cache"+File.separator; new File(dir).mkdirs(); return dir; } public static String getWorkingDirectory() { return System.getProperty("user.dir")+File.separator; } public static String getSoundDirectory() { return getWorkingDirectory()+"sounds"+File.separator; } public static String getImageDirectory() { return getWorkingDirectory()+"img"+File.separator; } public static String getBackupDirectory() { return getUserDataDirectory()+"backup"+File.separator; } public static String getDebugLogDirectory() { return getUserDataDirectory()+"debuglogs"+File.separator; } public static String chattyVersion() { return String.format("Chatty Version %s%s%s / %s", Chatty.VERSION, (Chatty.HOTKEY ? " Hotkey": ""), (Chatty.DEBUG ? " (Debug)" : ""), COMPILE_INFO); } public static String uptime() { return DateTime.ago(STARTED_TIME); } }