diff --git a/.classpath b/.classpath index c1a5172..b116255 100644 --- a/.classpath +++ b/.classpath @@ -13,6 +13,5 @@ - diff --git a/LICENSE b/LICENSE.md similarity index 95% rename from LICENSE rename to LICENSE.md index 9a6b930..9626f73 100644 --- a/LICENSE +++ b/LICENSE.md @@ -1,6 +1,6 @@ BSD 3-Clause License -Copyright (c) 2019, AlexStewartCode +Copyright (c) 2019, AlexStewartCode and individual contributors. All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/lib/ini4j-0.5.4.jar b/lib/ini4j-0.5.4.jar deleted file mode 100644 index 499f0af..0000000 Binary files a/lib/ini4j-0.5.4.jar and /dev/null differ diff --git a/localization.config b/localization.config index b810ae8..436b248 100644 --- a/localization.config +++ b/localization.config @@ -1,21 +1,170 @@ +[CommandPollManage] +'start' will start a new poll with the query of the line you put after, 'choice' will add a choice to the poll, 'stop' will end the poll= + [CommandBeansShow] -Displays how many beans you have = -You have %s beans! = +You have %s beans!= +Displays how many beans you have= + +[CommandHelp] +Lets you look up specific commands, or get a link to a list of all commands.= +You can get help with a specific command by typing `!help command`!\nGeneral Commands: `boop, roll, choose, help, info, vote, results, showpoll, wolfram, cplus, java, beans, role, bet, yeet`= + +[CommandRoll] +Didn't work ;3;= +Based on input of xdy where x is number of dice and y is faces kitty will roll that amount of dice, display the individual rolls and total= + +[CommandStats] +Displays the actively running KittyBot application information= + +[CommandTweet] +With an input of x,y,z where x y and z are all choices, kitty will choose one= +Tweet command failed!= + +[CommandRole] +Please enter `general`, `mod`, or `admin`!= +You aren't allowed to do that! You must have the KittyRole '%' or higher!= +Will show the current role you have, Admins can change others roles with input of 'role x @y' with x being blacklist, general, mod, or admin. Blacklist will not allow the user to interact with kitty anymore, general mod and admin will give the user access to those commands.= +Your role is= +Changed %s to role `%s`!= + +[CommandColiru] +Will try to compile any c++ code you put in! Supports up to C++14 standard, uses g++.= + +[CommandJDoodle] +Will compile any java code you put in! Supports Java 1.8= + +[CommandChangeIndicator] +Changes the command indicator to any single character. By default, it's '!'. If more than one character is provided, the first one is used!= +Indicator changed to `%s`= + +[CommandPerish] +Adds a red, 'a n g e r y' overlay to your icon or the icon of a friend you mentioned= + +[CommandStark] +Snaps your icon or the icon of a friend you mentioned= + +[CommandYeet] +Yeet yourself or yeet a friend with @!= + +[CommandPollVote] +There is no poll running!= +You already voted= +%s That's not a vaild vote!= +That's not a vaild number!= +Vote in a poll with the choice number, won't work if no poll is running, you can't change your vote once you have cast it! Be careful!= +You successfully voted for= + +[CommandShutdown] +Stops kitty. `-s` or `safe` as an argument attempts to sync off the database before shutdown.= +Forced shutdown, database synced before abandoning threads.= +Forced immediate shutdown, threads abandoned without sync.= [CommandBetBeans] -Please bet with at least 50 beans! = -Allows you to bet your beans, set your amount after the command! Warning! House always wins!\nSets of 3 will get 5x, 4 will get 10x, and 5 will get 1000x = -That's not a valid bet! = -Sorry, you didn't win, try again! = -You don't have enough beans! = -You won %s beans! = +That's not a valid bet!= +Please bet with at least 50 beans!= +Allows you to bet your beans, set your amount after the command! Warning! House always wins!\nSets of 3 will get 5x, 4 will get 10x, and 5 will get 1000x= +Sorry, you didn't win, try again!= +You don't have enough beans!= +You won %s beans!= -[CommandBoop] -%s booped %s! = -Kitty will react with a counter = -Woah! %s booped me! That's %s total! = -%s booped several others - %s! = +[CommandDoWork] +I finished with my work! :D= +Occupies a core for a few seconds= + +[CommandRPStart] +Starts an rp, add people to it by mentioning them!= [CommandBlurry] -Blurs your icon or the icon of a friend you mentioned = +Blurs your icon or the icon of a friend you mentioned= + +[CommandPollResults] +Will show current results of a poll and percentages of votes per choice= +%s people voted for %s `%s` with `%s%` !\n = + +[CommandRating] +Kittybot content set to= +Warning: NSFW may slip through, images are only based on tags on their respective sites!= +Invalid content rating= + +[CommandGiveBeans] +That's not a valid number!= +Gave %s %s beans!= +Gives beans to the mentioned users!= +You didn't mention anyone!= + +[CommandPollShow] +There is no poll running!= +And the choices are:\n= +Will show the current poll running= +The current poll is `%s`\n= + +[CommandHelpBuilder] +Emit help for all commands as formatted HTML= +commands= + +[CommandRPEnd] +Here's your file!= +You can't end this RP!= +Ends RP in channel= + +[CommandRPG] +Invalid RPG Command!= +Admin+ command only right now - experimental text RPG! Format is !rpg = + +[CommandBoop] +%s booped %s!= +Kitty will react with a counter= +Woah! %s booped me! That's %s total!= +%s booped several others - %s!= + +[CommandInfo] +Provides author info and a link to Kitty's website= +I'm made by `Rin#8904` and `Reverie Wisp#3703`!\nYou can find more info about me along with a Patreon link to support us and GitHub link for filing bugs https://www.rinsnowmew.com/bot/= + +[CommandPing] +Pong!= +Will respond with Pong!= + +[CommandChoose] +With an input of x,y,z where x y and z are all choices, kitty will choose one= +I chooooooose %s!= + +[CommandEightBall] +It is certain.= +Ask again later.= +Cannot predict now.= +My sources say no.= +You may rely on it.= +Answers a yes or no question! Warning: Kitty can not actually tell the future, she claims no responsibility for any lion mauling, lack of lottery wins, or felony charges.= +Concentrate and ask again.= +Signs point to yes.= +Don't count on it.= +Yes.= +My reply is no.= +Most likely.= +Reply hazy, try again.= +Without a doubt.= +Yes - definitely.= +Very doubtful.= +As I see it, yes.= +Better not tell you now.= +Outlook good.= +Outlook not so good.= +It is decidedly so.= + +[CommandInvite] +Provies a direct invite link for KittyBot= + +[CommandWolfram] +Something went wrong!= +Will query wolframalpha with your question and give a full image output of the answer= +You need to provide some arguments!= + +[CommandMap] +Seed= +Invalid arguments provided!= +Height= +Using mapgen v0.1= +Width= + diff --git a/src/commands/CommandChangeIndicator.java b/src/commands/CommandChangeIndicator.java index 0a7a725..da25d8d 100644 --- a/src/commands/CommandChangeIndicator.java +++ b/src/commands/CommandChangeIndicator.java @@ -1,6 +1,7 @@ package commands; import core.Command; +import core.Localizer; import dataStructures.*; public class CommandChangeIndicator extends Command @@ -8,7 +9,7 @@ public class CommandChangeIndicator extends Command public CommandChangeIndicator(KittyRole level, KittyRating rating) { super(level, rating); } @Override - public String HelpText() { return "Changes the command indicator to any single character. By default, it's '!'. If more than one character is provided, the first one is used!"; } + public String HelpText() { return Localizer.Stub("Changes the command indicator to any single character. By default, it's '!'. If more than one character is provided, the first one is used!"); } @Override public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res) @@ -21,6 +22,6 @@ public class CommandChangeIndicator extends Command } guild.SetCommandIndicator(arg.substring(0, 1)); - res.Call("Indicator changed to `" + guild.GetCommandIndicator() +"`!"); + res.Call(String.format(Localizer.Stub("Indicator changed to `%s`"), guild.GetCommandIndicator())); } } diff --git a/src/commands/CommandChoose.java b/src/commands/CommandChoose.java index d65672e..842e341 100644 --- a/src/commands/CommandChoose.java +++ b/src/commands/CommandChoose.java @@ -14,7 +14,7 @@ public class CommandChoose extends Command public CommandChoose(KittyRole level, KittyRating rating) { super(level, rating); } @Override - public String HelpText() { return "With an input of x,y,z where x y and z are all choices, kitty will choose one"; } + public String HelpText() { return Localizer.Stub("With an input of x,y,z where x y and z are all choices, kitty will choose one"); } @Override public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res) @@ -26,6 +26,6 @@ public class CommandChoose extends Command return; } - res.Call("I chooooooose" + choices[(int) (Math.random()*choices.length)] + "!"); + res.Call(String.format(Localizer.Stub("I chooooooose %s!"), (choices[(int) (Math.random()*choices.length)]).toString())); } } diff --git a/src/commands/CommandColiru.java b/src/commands/CommandColiru.java index 25145fa..d16e066 100644 --- a/src/commands/CommandColiru.java +++ b/src/commands/CommandColiru.java @@ -1,6 +1,7 @@ package commands; import core.Command; +import core.Localizer; import dataStructures.*; import network.NetworkColiru; @@ -11,7 +12,7 @@ public class CommandColiru extends Command public CommandColiru(KittyRole level, KittyRating rating) { super(level, rating);} @Override - public String HelpText() { return "Will try to compile any c++ code you put in! Supports up to C++14 standard, uses g++."; } + public String HelpText() { return Localizer.Stub("Will try to compile any c++ code you put in! Supports up to C++14 standard, uses g++."); } @Override public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res) diff --git a/src/commands/CommandDoWork.java b/src/commands/CommandDoWork.java index e219695..b1466e3 100644 --- a/src/commands/CommandDoWork.java +++ b/src/commands/CommandDoWork.java @@ -15,7 +15,7 @@ public class CommandDoWork extends Command public CommandDoWork(KittyRole level, KittyRating rating) { super(level, rating); } @Override - public String HelpText() { return "Occupies a core for a few seconds"; } + public String HelpText() { return Localizer.Stub("Occupies a core for a few seconds"); } // Called when the command is run! @Override @@ -28,6 +28,6 @@ public class CommandDoWork extends Command thispieceofshit += Math.log((double)i); } - res.Call("I finished with my work! :D"); + res.Call(Localizer.Stub("I finished with my work! :D")); } } \ No newline at end of file diff --git a/src/commands/CommandEightBall.java b/src/commands/CommandEightBall.java index 642e943..9ec450f 100644 --- a/src/commands/CommandEightBall.java +++ b/src/commands/CommandEightBall.java @@ -1,21 +1,41 @@ package commands; import core.Command; +import core.Localizer; import dataStructures.*; public class CommandEightBall extends Command { - String [] answers = {"It is certain.", "It is decidedly so.", "Without a doubt.", "Yes - definitely.", "You may rely on it.", "As I see it, yes.", "Most likely.", - "Outlook good.", "Yes.", "Signs point to yes.", "Reply hazy, try again.", "Ask again later.", "Better not tell you now.", "Cannot predict now.", - "Concentrate and ask again.", "Don't count on it.", "My reply is no.", "My sources say no.", "Outlook not so good.", "Very doubtful."}; - public CommandEightBall(KittyRole level, KittyRating rating) + String [] answers = { - super(level, rating); - } + Localizer.Stub("It is certain.") + , Localizer.Stub("It is decidedly so.") + , Localizer.Stub("Without a doubt.") + , Localizer.Stub("Yes - definitely.") + , Localizer.Stub("You may rely on it.") + , Localizer.Stub("As I see it, yes.") + , Localizer.Stub("Most likely.") + , Localizer.Stub("Outlook good.") + , Localizer.Stub("Yes.") + , Localizer.Stub("Signs point to yes.") + + , Localizer.Stub("Reply hazy, try again.") + , Localizer.Stub("Ask again later.") + , Localizer.Stub("Better not tell you now.") + , Localizer.Stub("Cannot predict now.") + , Localizer.Stub("Concentrate and ask again.") + + , Localizer.Stub("Don't count on it.") + , Localizer.Stub("My reply is no.") + , Localizer.Stub("My sources say no.") + , Localizer.Stub("Outlook not so good.") + , Localizer.Stub("Very doubtful.") + }; + + public CommandEightBall(KittyRole level, KittyRating rating) { super(level, rating); } @Override - public String HelpText() { return "Answers a yes or no question! Warning: Kitty can not actually tell the future," - + " she claims no responsibility for any lion mauling, lack of lottery wins, or felony charges."; } + public String HelpText() { return Localizer.Stub("Answers a yes or no question! Warning: Kitty can not actually tell the future, she claims no responsibility for any lion mauling, lack of lottery wins, or felony charges."); } @Override public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res) diff --git a/src/commands/CommandGiveBeans.java b/src/commands/CommandGiveBeans.java index 5f9a7a1..e22cc28 100644 --- a/src/commands/CommandGiveBeans.java +++ b/src/commands/CommandGiveBeans.java @@ -1,6 +1,7 @@ package commands; import core.Command; +import core.Localizer; import dataStructures.*; public class CommandGiveBeans extends Command @@ -8,7 +9,7 @@ public class CommandGiveBeans extends Command public CommandGiveBeans (KittyRole level, KittyRating rating) { super(level, rating); } @Override - public String HelpText() { return "Gives beans to the mentioned users!"; } + public String HelpText() { return Localizer.Stub("Gives beans to the mentioned users!"); } @Override public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res) @@ -19,20 +20,20 @@ public class CommandGiveBeans extends Command } catch (NumberFormatException e) { - res.Call("That's not a valid number!"); + res.Call(Localizer.Stub("That's not a valid number!")); return; } if(input.mentions == null) { - res.Call("You didn't mention anyone!"); + res.Call(Localizer.Stub("You didn't mention anyone!")); return; } for(int i = 0; i < input.mentions.length; i++) { input.mentions[i].ChangeBeans(beans); - res.Call("Gave " + input.mentions[i].name + " " + beans + " beans!"); + res.Call(String.format(Localizer.Stub("Gave %s %s beans!"), input.mentions[i].name, "" + beans)); } } } diff --git a/src/commands/CommandHelp.java b/src/commands/CommandHelp.java index 580554b..0621b26 100644 --- a/src/commands/CommandHelp.java +++ b/src/commands/CommandHelp.java @@ -9,14 +9,13 @@ import dataStructures.KittyUser; import dataStructures.Response; import dataStructures.UserInput; -// TODO: Convert this to a per-command help string! This lets us do all sorts of neat stuff, -// mostly tho it lets us construct this on the fly or by hand for a specific command! +// Either allows for specifically looking up commands or gets a list of general commands to try out! public class CommandHelp extends Command { public CommandHelp(KittyRole level, KittyRating rating) { super(level, rating); } @Override - public String HelpText() { return "Lets you look up specific commands, or get a link to a list of all commands."; } + public String HelpText() { return Localizer.Stub("Lets you look up specific commands, or get a link to a list of all commands."); } @Override public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res) @@ -25,11 +24,7 @@ public class CommandHelp extends Command if(help == null) { - help = "You can get help with a specific command by typing `!help command`!" - + "\nYou can also look at " - + "\nGeneral Commands: `boop, roll, choose, help, info, vote, " - + "results, showpoll, wolfram, cplus, java," - + "beans, role, bet, yeet`"; + help = Localizer.Stub("You can get help with a specific command by typing `!help command`!\nGeneral Commands: `boop, roll, choose, help, info, vote, results, showpoll, wolfram, cplus, java, beans, role, bet, yeet`"); } else { diff --git a/src/commands/CommandHelpBuilder.java b/src/commands/CommandHelpBuilder.java index 968b949..9b77b55 100644 --- a/src/commands/CommandHelpBuilder.java +++ b/src/commands/CommandHelpBuilder.java @@ -7,6 +7,7 @@ import java.util.ArrayList; import java.util.HashMap; import core.Command; +import core.Localizer; import core.Stats; import dataStructures.KittyChannel; import dataStructures.KittyGuild; @@ -25,7 +26,7 @@ public class CommandHelpBuilder extends Command { } @Override - public String HelpText() { return "Emit help for all commands as formatted HTML"; } + public String HelpText() { return Localizer.Stub("Emit help for all commands as formatted HTML"); } @Override public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res) @@ -95,7 +96,7 @@ public class CommandHelpBuilder extends Command { roleStr = roleStr.substring(0, 1).toUpperCase() + roleStr.toLowerCase().substring(1); // Section header - accumulated += headerStart + roleStr + " commands" + headerEnd; + accumulated += headerStart + roleStr + " " + Localizer.Stub("commands") + headerEnd; accumulated += sectionStart; // Section content diff --git a/src/commands/CommandInfo.java b/src/commands/CommandInfo.java index 99ae8b8..568ad14 100644 --- a/src/commands/CommandInfo.java +++ b/src/commands/CommandInfo.java @@ -1,6 +1,7 @@ package commands; import core.Command; +import core.Localizer; import dataStructures.KittyChannel; import dataStructures.KittyGuild; import dataStructures.KittyRating; @@ -14,13 +15,12 @@ public class CommandInfo extends Command public CommandInfo(KittyRole level, KittyRating rating) { super(level, rating); } @Override - public String HelpText() { return "Provides author info and a link to Kitty's website"; } + public String HelpText() { return Localizer.Stub("Provides author info and a link to Kitty's website"); } @Override public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res) { - String info = "I'm made by `Rin#8904` and `Reverie Wisp#3703`!\n" - + "You can find more info about me along with a Patreon link to support us and GitHub link for filing bugs https://www.rinsnowmew.com/bot/" ; + String info = Localizer.Stub("I'm made by `Rin#8904` and `Reverie Wisp#3703`!\nYou can find more info about me along with a Patreon link to support us and GitHub link for filing bugs https://www.rinsnowmew.com/bot/"); res.Call(info); } } \ No newline at end of file diff --git a/src/commands/CommandInvite.java b/src/commands/CommandInvite.java index 3bcb6a4..75080e4 100644 --- a/src/commands/CommandInvite.java +++ b/src/commands/CommandInvite.java @@ -1,6 +1,7 @@ package commands; import core.Command; +import core.Localizer; import dataStructures.*; import offline.Ref; @@ -9,7 +10,7 @@ public class CommandInvite extends Command public CommandInvite(KittyRole level, KittyRating rating) { super(level, rating); } @Override - public String HelpText() { return "Provies a direct invite link for KittyBot"; } + public String HelpText() { return Localizer.Stub("Provies a direct invite link for KittyBot"); } @Override public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res) diff --git a/src/commands/CommandJDoodle.java b/src/commands/CommandJDoodle.java index a2add42..9d7b146 100644 --- a/src/commands/CommandJDoodle.java +++ b/src/commands/CommandJDoodle.java @@ -1,6 +1,7 @@ package commands; import core.Command; +import core.Localizer; import dataStructures.*; import network.NetworkJDoodle; @@ -11,7 +12,7 @@ public class CommandJDoodle extends Command public CommandJDoodle(KittyRole level, KittyRating rating) { super(level, rating); } @Override - public String HelpText() { return "Will compile any java code you put in! Supports Java 1.8"; } + public String HelpText() { return Localizer.Stub("Will compile any java code you put in! Supports Java 1.8"); } @Override public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res) diff --git a/src/commands/CommandMap.java b/src/commands/CommandMap.java index d4fb4a9..02aca37 100644 --- a/src/commands/CommandMap.java +++ b/src/commands/CommandMap.java @@ -3,6 +3,7 @@ package commands; import java.util.Random; import core.Command; +import core.Localizer; import dataStructures.KittyChannel; import dataStructures.KittyGuild; import dataStructures.KittyRating; @@ -22,7 +23,7 @@ public class CommandMap extends Command public CommandMap(KittyRole roleLevel, KittyRating contentRating) { super(roleLevel, contentRating); } @Override - public String HelpText() { return "Generates a map! You can pass additional information if you want with the flags `-s -w -h`. If one of the fields isn't provided, its default will be used. Note that adjusting the width and height impacts the map outcomes.\n\nDefault seed: Random,\nDefault Width: 35(max "+ MaxWidth + "),\nDefault Height: 25(max " + MaxHeight + ")"; } + public String HelpText() { return String.format(Localizer.Stub("Generates a map! You can pass additional information if you want with the flags `-s -w -h`. If one of the fields isn't provided, its default will be used. Note that adjusting the width and height impacts the map outcomes.\n\nDefault seed: Random,\nDefault Width: 35(max %s),\nDefault Height: 25(max %s)"), "" + MaxWidth, "" + MaxHeight); } @Override public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res) @@ -59,7 +60,7 @@ public class CommandMap extends Command } catch(NumberFormatException e) { - res.Call("Invalid arguments provided!"); + res.Call(Localizer.Stub("Invalid arguments provided!")); return; } @@ -75,8 +76,10 @@ public class CommandMap extends Command } // Response header creation - header += "Using mapgen v0.1\n"; - header += "Seed: `" + seed + "`, Width: `"+ width +"`, Height: `"+ height + "`\n"; + header += Localizer.Stub("Using mapgen v0.1") + "\n"; + header += Localizer.Stub("Seed") + ": `" + seed + "`, "; + header += Localizer.Stub("Width") + "`"+ width +"`, "; + header += Localizer.Stub("Height") + ": `"+ height + "`\n"; // Response body creation body += "```\n"; diff --git a/src/commands/CommandPerish.java b/src/commands/CommandPerish.java index 475c099..b51080e 100644 --- a/src/commands/CommandPerish.java +++ b/src/commands/CommandPerish.java @@ -8,6 +8,7 @@ import java.io.IOException; import javax.imageio.ImageIO; import core.Command; +import core.Localizer; import dataStructures.KittyChannel; import dataStructures.KittyGuild; import dataStructures.KittyRating; @@ -22,7 +23,7 @@ public class CommandPerish extends Command public CommandPerish(KittyRole level, KittyRating rating) { super(level, rating); } @Override - public String HelpText() { return "Adds a red, 'a n g e r y' overlay to your icon or the icon of a friend you mentioned"; }; + public String HelpText() { return Localizer.Stub("Adds a red, 'a n g e r y' overlay to your icon or the icon of a friend you mentioned"); }; private static Long num = 0l; diff --git a/src/commands/CommandPing.java b/src/commands/CommandPing.java index 137d3a9..51b6212 100644 --- a/src/commands/CommandPing.java +++ b/src/commands/CommandPing.java @@ -15,12 +15,12 @@ public class CommandPing extends Command public CommandPing(KittyRole level, KittyRating rating) { super(level, rating); } @Override - public String HelpText() { return "Will respond with Pong!"; } + public String HelpText() { return Localizer.Stub("Will respond with Pong!"); } // Called when the command is run! @Override public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res) { - res.Call("Pong!"); + res.Call(Localizer.Stub("Pong!")); } } diff --git a/src/commands/CommandPollManage.java b/src/commands/CommandPollManage.java index 33230a0..a1d9976 100644 --- a/src/commands/CommandPollManage.java +++ b/src/commands/CommandPollManage.java @@ -14,7 +14,7 @@ public class CommandPollManage extends Command public CommandPollManage(KittyRole level, KittyRating rating) { super(level, rating); } @Override - public String HelpText() { return "'start' will start a new poll with the query of the line you put after, 'choice' will add a choice to the poll, 'stop' will end the poll"; } + public String HelpText() { return Localizer.Stub("'start' will start a new poll with the query of the line you put after, 'choice' will add a choice to the poll, 'stop' will end the poll"); } @Override public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res) diff --git a/src/commands/CommandPollResults.java b/src/commands/CommandPollResults.java index 8178955..3312009 100644 --- a/src/commands/CommandPollResults.java +++ b/src/commands/CommandPollResults.java @@ -10,7 +10,7 @@ public class CommandPollResults extends Command public CommandPollResults(KittyRole level, KittyRating rating) { super(level, rating); } @Override - public String HelpText() { return "Will show current results of a poll and percentages of votes per choice"; } + public String HelpText() { return Localizer.Stub("Will show current results of a poll and percentages of votes per choice"); } @Override public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res) @@ -26,8 +26,7 @@ public class CommandPollResults extends Command for(int i = 0; i < votes.size(); i++) { - - results += votes.get(i).votes + " people voted for `" + votes.get(i).choice + "` with `" + (int)(((double)votes.get(i).votes) / ((double)totalVotes) * 100) + "%`!\n"; + results += String.format(Localizer.Stub("%s people voted for %s `%s` with `%s%` !\n "), votes.get(i).votes, votes.get(i).choice, (int)(((double)votes.get(i).votes) / ((double)totalVotes) * 100)); } res.Call(results); diff --git a/src/commands/CommandPollShow.java b/src/commands/CommandPollShow.java index 46df883..06c3a1c 100644 --- a/src/commands/CommandPollShow.java +++ b/src/commands/CommandPollShow.java @@ -8,18 +8,18 @@ public class CommandPollShow extends Command public CommandPollShow(KittyRole level, KittyRating rating) { super(level, rating); } @Override - public String HelpText() { return "Will show the current poll running"; } + public String HelpText() { return Localizer.Stub("Will show the current poll running"); } @Override public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res) { if(!guild.polling) { - res.Call("There is no poll running!"); + res.Call(Localizer.Stub("There is no poll running!")); return; } - String poll = "The current poll is `" + guild.poll + "`\n"; - poll += "And the choices are:\n"; + String poll = String.format(Localizer.Stub("The current poll is `%s`\n"), guild.poll); + poll += Localizer.Stub("And the choices are:\n"); for(int i = 0; i < guild.choices.size(); i++) { poll += (i+1) + ": `" + guild.choices.get(i).choice + "`\n"; diff --git a/src/commands/CommandPollVote.java b/src/commands/CommandPollVote.java index 120b371..761ff67 100644 --- a/src/commands/CommandPollVote.java +++ b/src/commands/CommandPollVote.java @@ -8,7 +8,7 @@ public class CommandPollVote extends Command public CommandPollVote(KittyRole level, KittyRating rating) { super(level, rating); } @Override - public String HelpText() { return "Vote in a poll with the choice number, won't work if no poll is running, you can't change your vote once you have cast it! Be careful!"; } + public String HelpText() { return Localizer.Stub("Vote in a poll with the choice number, won't work if no poll is running, you can't change your vote once you have cast it! Be careful!"); } @Override public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res) @@ -17,7 +17,7 @@ public class CommandPollVote extends Command { if(guild.hasVoted.contains(user.uniqueID)) { - res.Call("You already voted"); + res.Call(Localizer.Stub("You already voted")); return; } try @@ -25,21 +25,22 @@ public class CommandPollVote extends Command int voteNum = Integer.parseInt(input.args)-1; if(voteNum >= guild.choices.size() || voteNum < 0) { - res.Call(voteNum + " That's not a vaild vote!"); + res.Call(String.format(Localizer.Stub("%s That's not a vaild vote!"), voteNum)); return; } + KittyPoll polled = guild.choices.get(voteNum); polled.votes++; guild.hasVoted.add(user.uniqueID); - res.Call("You successfully voted for `" + polled.choice + "`!"); + res.Call(Localizer.Stub("You successfully voted for") + " `" + polled.choice + "`!"); return; } catch (NumberFormatException e) { - res.Call("That's not a vaild number!"); + res.Call(Localizer.Stub("That's not a vaild number!")); return; } } - res.Call("There is no poll running!"); + res.Call(Localizer.Stub("There is no poll running!")); } } diff --git a/src/commands/CommandRPEnd.java b/src/commands/CommandRPEnd.java index 1f97c5f..5fa72b3 100644 --- a/src/commands/CommandRPEnd.java +++ b/src/commands/CommandRPEnd.java @@ -5,6 +5,7 @@ import java.io.FileNotFoundException; import java.io.UnsupportedEncodingException; import core.Command; +import core.Localizer; import core.RPManager; import dataStructures.*; @@ -13,24 +14,30 @@ public class CommandRPEnd extends Command public CommandRPEnd (KittyRole level, KittyRating rating) { super(level, rating); } @Override - public String HelpText() { return "Ends RP in channel"; } + public String HelpText() { return Localizer.Stub("Ends RP in channel"); } @Override public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res) { File sending = null; - try { + + try + { sending = RPManager.instance.endRP(channel, user); - } catch (FileNotFoundException | UnsupportedEncodingException e) + } + catch (FileNotFoundException | UnsupportedEncodingException e) { System.out.println("I don't know how you got here"); } + if(sending != null) { res.CallFile(sending, "txt"); - res.Call("Here's your file!"); + res.Call(Localizer.Stub("Here's your file!")); } else - res.Call("You can't end this RP!"); + { + res.Call(Localizer.Stub("You can't end this RP!")); + } } } diff --git a/src/commands/CommandRPG.java b/src/commands/CommandRPG.java index dd2273c..255d460 100644 --- a/src/commands/CommandRPG.java +++ b/src/commands/CommandRPG.java @@ -1,6 +1,7 @@ package commands; import core.Command; +import core.Localizer; import core.rpg.RPGFramework; import dataStructures.KittyChannel; import dataStructures.KittyGuild; @@ -22,7 +23,7 @@ public class CommandRPG extends Command } @Override - public String HelpText() { return "Admin+ command only right now - experimental text RPG! Format is !rpg "; }; + public String HelpText() { return Localizer.Stub("Admin+ command only right now - experimental text RPG! Format is !rpg "); }; @Override @@ -42,7 +43,7 @@ public class CommandRPG extends Command if(result == null) { - res.Call("Invalid RPG Command!"); + res.Call(Localizer.Stub("Invalid RPG Command!")); return; } diff --git a/src/commands/CommandRPStart.java b/src/commands/CommandRPStart.java index dce9b3b..4045a4f 100644 --- a/src/commands/CommandRPStart.java +++ b/src/commands/CommandRPStart.java @@ -3,6 +3,7 @@ package commands; import java.util.ArrayList; import core.Command; +import core.Localizer; import core.RPManager; import dataStructures.*; @@ -11,7 +12,7 @@ public class CommandRPStart extends Command public CommandRPStart (KittyRole level, KittyRating rating) { super(level, rating); } @Override - public String HelpText() { return "Starts an rp, add people to it by mentioning them!"; } + public String HelpText() { return Localizer.Stub("Starts an rp, add people to it by mentioning them!"); } @Override public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res) diff --git a/src/commands/CommandRating.java b/src/commands/CommandRating.java index c2a09c2..8ca7a6d 100644 --- a/src/commands/CommandRating.java +++ b/src/commands/CommandRating.java @@ -1,6 +1,7 @@ package commands; import core.Command; +import core.Localizer; import dataStructures.KittyChannel; import dataStructures.KittyGuild; import dataStructures.KittyRating; @@ -14,7 +15,7 @@ public class CommandRating extends Command public CommandRating(KittyRole level, KittyRating rating) { super(level, rating); } @Override - public String HelpText() { return "'0' is fully sfw (Derpi and e621 searches are disabled), '1' is filtered (kitty auto appends a sfw tag on any searches), '2' is nsfw (any search will go through). Some other words are supported for setting filter as well."; } + public String HelpText() { return Localizer.Stub("'0' is fully sfw (Derpi and e621 searches are disabled), '1' is filtered (kitty auto appends a sfw tag on any searches), '2' is nsfw (any search will go through). Some other words are supported for setting filter as well."); } // Called when the command is run! @Override @@ -54,11 +55,11 @@ public class CommandRating extends Command } if(newRating != null) - res.Call("Kittybot content set to " + newRating); + res.Call(Localizer.Stub("Kittybot content set to") + " " + newRating); else - res.Call("Invalid content rating `" + input.args + "`"); + res.Call(Localizer.Stub("Invalid content rating") + " `" + input.args + "`"); if(newRating.equals("Filtered")) - res.Call("Warning: NSFW may slip through, images are only based on tags on their respective sites!"); + res.Call(Localizer.Stub("Warning: NSFW may slip through, images are only based on tags on their respective sites!")); } } \ No newline at end of file diff --git a/src/commands/CommandRole.java b/src/commands/CommandRole.java index 196ddda..8497e27 100644 --- a/src/commands/CommandRole.java +++ b/src/commands/CommandRole.java @@ -1,6 +1,7 @@ package commands; import core.Command; +import core.Localizer; import dataStructures.*; public class CommandRole extends Command @@ -8,20 +9,20 @@ public class CommandRole extends Command public CommandRole (KittyRole level, KittyRating rating) { super(level, rating); } @Override - public String HelpText() { return "Will show the current role you have, Admins can change others roles with input of 'role x @y' with x being blacklist, general, mod, or admin. Blacklist will not allow the user to interact with kitty anymore, general mod and admin will give the user access to those commands."; } + public String HelpText() { return Localizer.Stub("Will show the current role you have, Admins can change others roles with input of 'role x @y' with x being blacklist, general, mod, or admin. Blacklist will not allow the user to interact with kitty anymore, general mod and admin will give the user access to those commands."); } @Override public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res) { if(input.args.isEmpty()) { - res.Call("Your role is " + user.GetRole().name() + "!"); + res.Call(Localizer.Stub("Your role is") + " " + user.GetRole().name() + "!"); return; } if(user.GetRole().getValue() < KittyRole.Admin.getValue()) { - res.Call("You aren't allowed to do that! You must have the KittyRole '" + KittyRole.Admin.toString() + "' or higher!"); + res.Call(String.format(Localizer.Stub("You aren't allowed to do that! You must have the KittyRole '%' or higher!"), KittyRole.Admin.toString())); return; } @@ -45,7 +46,7 @@ public class CommandRole extends Command break; default: - res.Call("Please enter `general`, `mod`, or `admin`!"); + res.Call(Localizer.Stub("Please enter `general`, `mod`, or `admin`!")); return; } String users = ""; @@ -55,6 +56,6 @@ public class CommandRole extends Command users += input.mentions[i].name + " "; } - res.Call("Changed " + users + " to role `" + newRole.name() + "`!"); + res.Call(String.format(Localizer.Stub("Changed %s to role `%s`!"), users, newRole.name())); } } diff --git a/src/commands/CommandRoll.java b/src/commands/CommandRoll.java index d2f11b2..fd7e7f6 100644 --- a/src/commands/CommandRoll.java +++ b/src/commands/CommandRoll.java @@ -16,7 +16,7 @@ public class CommandRoll extends Command public CommandRoll(KittyRole level, KittyRating rating) { super(level, rating); } @Override - public String HelpText() { return "Based on input of xdy where x is number of dice and y is faces kitty will roll that amount of dice, display the individual rolls and total"; } + public String HelpText() { return Localizer.Stub("Based on input of xdy where x is number of dice and y is faces kitty will roll that amount of dice, display the individual rolls and total"); } @Override public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res) @@ -27,7 +27,7 @@ public class CommandRoll extends Command } catch(Exception e) { - res.Call("Didn't work ;3;"); + res.Call(Localizer.Stub("Didn't work ;3;")); } } diff --git a/src/commands/CommandShutdown.java b/src/commands/CommandShutdown.java index 7339c51..0963d7a 100644 --- a/src/commands/CommandShutdown.java +++ b/src/commands/CommandShutdown.java @@ -2,6 +2,7 @@ package commands; import core.Command; import core.DatabaseManager; +import core.Localizer; import core.Stats; import dataStructures.KittyChannel; import dataStructures.KittyGuild; @@ -17,7 +18,7 @@ public class CommandShutdown extends Command public CommandShutdown(KittyRole level, KittyRating rating) { super(level, rating); } @Override - public String HelpText() { return "Stops kitty. `-s` or `safe` as an argument attempts to sync off the database before shutdown."; } + public String HelpText() { return Localizer.Stub("Stops kitty. `-s` or `safe` as an argument attempts to sync off the database before shutdown."); } // Called when the command is run! @Override @@ -41,12 +42,12 @@ public class CommandShutdown extends Command if(isSafe) { DatabaseManager.instance.Upkeep(); // Force upkeep, this works so long as on main thread. - res.CallImmediate("Forced shutdown, database synced before abandoning threads."); + res.CallImmediate(Localizer.Stub("Forced shutdown, database synced before abandoning threads.")); System.exit(0); } else { - res.CallImmediate("Forced immediate shutdown, threads abandoned without sync."); + res.CallImmediate(Localizer.Stub("Forced immediate shutdown, threads abandoned without sync.")); System.exit(0); } } diff --git a/src/commands/CommandStark.java b/src/commands/CommandStark.java index d27fa04..3507c3d 100644 --- a/src/commands/CommandStark.java +++ b/src/commands/CommandStark.java @@ -8,6 +8,7 @@ import java.io.IOException; import javax.imageio.ImageIO; import core.Command; +import core.Localizer; import dataStructures.*; import utils.ImageUtils; @@ -16,7 +17,7 @@ public class CommandStark extends Command public CommandStark(KittyRole level, KittyRating rating) { super(level, rating); } @Override - public String HelpText() { return "Snaps your icon or the icon of a friend you mentioned"; }; + public String HelpText() { return Localizer.Stub("Snaps your icon or the icon of a friend you mentioned"); }; private static Long num = 0l; diff --git a/src/commands/CommandStats.java b/src/commands/CommandStats.java index fe865a3..fad2086 100644 --- a/src/commands/CommandStats.java +++ b/src/commands/CommandStats.java @@ -1,6 +1,7 @@ package commands; import core.Command; +import core.Localizer; import core.CommandManager.ThreadData; import dataStructures.KittyChannel; import dataStructures.KittyGuild; @@ -16,7 +17,7 @@ public class CommandStats extends Command public CommandStats(KittyRole level, KittyRating rating) { super(level, rating); } @Override - public String HelpText() { return "Displays the actively running KittyBot application information"; } + public String HelpText() { return Localizer.Stub("Displays the actively running KittyBot application information"); } // Called when the command is run! @Override diff --git a/src/commands/CommandTweet.java b/src/commands/CommandTweet.java index 947a26d..8a0bb40 100644 --- a/src/commands/CommandTweet.java +++ b/src/commands/CommandTweet.java @@ -1,6 +1,7 @@ package commands; import core.Command; +import core.Localizer; import dataStructures.*; import network.NetworkTwitter; @@ -10,7 +11,7 @@ public class CommandTweet extends Command public CommandTweet(KittyRole level, KittyRating rating) { super(level, rating); } @Override - public String HelpText() { return "With an input of x,y,z where x y and z are all choices, kitty will choose one"; } + public String HelpText() { return Localizer.Stub("With an input of x,y,z where x y and z are all choices, kitty will choose one"); } @Override public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res) @@ -18,7 +19,7 @@ public class CommandTweet extends Command try { res.Call(tweet.tweet(input.args)); } catch (Exception e) { - res.Call("FUCKED UP HARD"); + res.Call(Localizer.Stub("Tweet command failed!")); } } } diff --git a/src/commands/CommandWolfram.java b/src/commands/CommandWolfram.java index 8f48c2e..80d6163 100644 --- a/src/commands/CommandWolfram.java +++ b/src/commands/CommandWolfram.java @@ -3,6 +3,7 @@ package commands; import java.io.File; import java.io.IOException; import core.Command; +import core.Localizer; import dataStructures.*; import network.*; import utils.ImageUtils; @@ -14,13 +15,13 @@ public class CommandWolfram extends Command public CommandWolfram(KittyRole level, KittyRating rating) { super(level, rating);} @Override - public String HelpText() { return "Will query wolframalpha with your question and give a full image output of the answer"; } + public String HelpText() { return Localizer.Stub("Will query wolframalpha with your question and give a full image output of the answer"); } @Override public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res) { if(input.args == null || input.args.trim().length() == 0) - res.Call("You need to provide some arguments!"); + res.Call(Localizer.Stub("You need to provide some arguments!")); try { @@ -30,7 +31,7 @@ public class CommandWolfram extends Command } catch (IOException e) { - res.Call("Something went wrong!"); + res.Call(Localizer.Stub("Something went wrong!")); } } } \ No newline at end of file diff --git a/src/commands/CommandYeet.java b/src/commands/CommandYeet.java index 646771e..7b29add 100644 --- a/src/commands/CommandYeet.java +++ b/src/commands/CommandYeet.java @@ -20,6 +20,7 @@ import javax.imageio.stream.FileImageOutputStream; import javax.imageio.stream.ImageOutputStream; import core.Command; +import core.Localizer; import dataStructures.KittyChannel; import dataStructures.KittyGuild; import dataStructures.KittyRating; @@ -38,7 +39,7 @@ public class CommandYeet extends Command private static Long num = 0l; @Override - public String HelpText() { return "Yeet yourself or yeet a friend with @!"; } + public String HelpText() { return Localizer.Stub("Yeet yourself or yeet a friend with @!"); } // Called when the command is run! @Override diff --git a/src/core/Localizer.java b/src/core/Localizer.java index 8498f9a..39a8526 100644 --- a/src/core/Localizer.java +++ b/src/core/Localizer.java @@ -3,13 +3,12 @@ package core; import java.io.File; import java.io.IOException; import java.io.PrintWriter; +import java.nio.charset.Charset; +import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; -import java.util.HashMap; -import org.ini4j.InvalidFileFormatException; -import org.ini4j.Profile.Section; -import org.ini4j.Wini; - +import dataStructures.SectionedKeyValueStore; import utils.FileUtils; import utils.GlobalLog; import utils.LogFilter; @@ -23,8 +22,8 @@ public class Localizer public final static String filename = "localization.config"; public final static String functionName = "Localizer.Stub"; - // Local translation - private static HashMap translated = new HashMap(); + // Local translation storage + private static SectionedKeyValueStore stringStore; // Logging private static void Log(String str) { GlobalLog.Log(LogFilter.Strings, str); } @@ -84,45 +83,54 @@ public class Localizer } // Nothing for now, but in the future will return a parsed and localized version of - // the string in question if one can be found. + // the string in question if one can be found. If the localized string is empty, + // returns a the key instead which is the default phrase. public static String Stub(String input) { - if(translated.containsKey(input)) - { - String value = translated.get(input).phrase; - if(value.trim().length() > 0) - return value; - } + if(stringStore == null) + return input; - return input; + String value = stringStore.GetKey(input); + if(value == null || value.length() < 1) + return input; + + return value; } + // Reads a file to string, adapted from https://stackoverflow.com/a/326440/5383198 + static String ReadFileAsString(String path, Charset encoding) + { + try + { + byte[] encoded = Files.readAllBytes(Paths.get(path)); + return new String(encoded, encoding); + } + catch (IOException e) + { + Warn("No file found to read from!"); + } + + return null; + } + // Update localization from the disk on file. Creates the file if it doesn't exist. // This file is internally formatted as an ini file. public static void UpdateLocFromDisk() { Log("Attempting to read localization file"); + try { - File file = new File(filename); - file.createNewFile(); - - Wini ini = new Wini(file); - - for(String str : ini.keySet()) + String fileContents = ReadFileAsString(filename, Charset.defaultCharset()); + if(fileContents == null) { - // Store everything in all .ini sections - Section sec = ini.get(str); - for(String s : sec.keySet()) - { - if(!translated.containsKey(s)) - translated.put(s, new LocInfo(sec.getName(), sec.get(s, String.class))); - } + File file = new File(filename); + file.createNewFile(); + } + else + { + stringStore = new SectionedKeyValueStore(fileContents); } - } - catch(InvalidFileFormatException e) - { - Error("File issue with format during localization file read"); } catch(IOException e) { @@ -138,24 +146,8 @@ public class Localizer try { PrintWriter pw = new PrintWriter(filename); + pw.println(stringStore.toString()); pw.close(); - - File file = new File(filename); - file.createNewFile(); - - Wini ini = new Wini(file); - - for(String s : translated.keySet()) - { - LocInfo toWrite = translated.get(s); - ini.put(toWrite.file, s, toWrite.phrase); - } - - ini.store(); - } - catch(InvalidFileFormatException e) - { - Error("File issue with format during localization file write"); } catch(IOException e) { @@ -171,12 +163,6 @@ public class Localizer FileUtils.AcquireAllFiles(".\\src").forEach((path) -> StripForContents(path, localizeList)); for(LocInfo toStub : localizeList) - { - if(!translated.containsKey(toStub.phrase)) - { - translated.put(toStub.phrase, new LocInfo(toStub.file, "")); - Log("Found new stubbed phrase '" + toStub.phrase + "' in " + toStub.file); - } - } + stringStore.AddKeyValue(toStub.file, toStub.phrase, toStub.phrase); } } \ No newline at end of file diff --git a/src/dataStructures/Pair.java b/src/dataStructures/Pair.java new file mode 100644 index 0000000..e4771db --- /dev/null +++ b/src/dataStructures/Pair.java @@ -0,0 +1,14 @@ +package dataStructures; + +// A generic class designed to hold two types, as a first and second variable. +public class Pair +{ + public T1 First; + public T2 Second; + + public Pair(T1 first, T2 second) + { + this.First = first; + this.Second = second; + } +} diff --git a/src/dataStructures/SectionedKeyValueStore.java b/src/dataStructures/SectionedKeyValueStore.java new file mode 100644 index 0000000..0f67458 --- /dev/null +++ b/src/dataStructures/SectionedKeyValueStore.java @@ -0,0 +1,190 @@ +package dataStructures; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.function.BiConsumer; +import java.util.function.Consumer; + +// This is a class designed to parse ini inspired key-value pairs that are sectioned off. +// The difference here is that this is more permissive than an ini file, and only accepts +// a single split character, not the traditional set an ini does. All of the following are valid: +// +// [ExampleSection] +// Key=Value +// Valid Ridiculous Key&\n\t_.:;foo = \tValid Ridiculous Value*&%$()^.[]{}@ +// EmptyValue= +// +// Note that the sections are NOT designed to allow for duplicate keys across them. +// This is a restriction of the structure, but can be changed later potentially. +// The only value not allowed in a key or value is the KeyValueSplit. +public class SectionedKeyValueStore +{ + // Variables + public final char SectionStart = '['; + public final char SectionEnd = ']'; + public final char KeyValueLineSeparator = '\n'; + public final String KeyValueSplit = "="; + + // [Key: SectionName, [Key: KeyString, Value: ValueString]] + private HashMap> sectionKeyValue; + + // [Key: KeyString, Value: ValueString]] + private HashMap keyValue; + + // String constructor that parses the input string into the object + public SectionedKeyValueStore(String input) + { + sectionKeyValue = new HashMap>(); + keyValue = new HashMap(); + Parse(input); + } + + // Calls back on each item in the entire structure. Provides section, then a pair of the keyString and valueString. + @SuppressWarnings({"rawtypes", "unchecked"}) + public void ForEach(BiConsumer> action) + { + Iterator it = sectionKeyValue.entrySet().iterator(); + while (it.hasNext()) + { + Map.Entry pair = (Map.Entry)it.next(); + Iterator internal = ((HashMap)pair.getValue()).entrySet().iterator(); + + while(internal.hasNext()) + { + Map.Entry internalPair = (Map.Entry)internal.next(); + action.accept((String)pair.getKey(), new Pair((String)internalPair.getKey(), (String)internalPair.getValue())); + } + } + } + + // Calls back each item in the structure but does not priv + @SuppressWarnings({"rawtypes"}) + public void ForEach(Consumer> action) + { + Iterator it = keyValue.entrySet().iterator(); + while (it.hasNext()) + { + Map.Entry pair = (Map.Entry)it.next(); + action.accept(new Pair((String)pair.getKey(), (String)pair.getValue())); + } + } + + // Parses the internal hashmap as a string then reutrns it, featuring sections. + // Iterates over all key/value pairs in the section and print them. Does not print + // the value of a given key if it is the same as the key. + @SuppressWarnings({"rawtypes", "unchecked"}) + public String toString() + { + String out = ""; + + // Iterates over the sections and + Iterator it = sectionKeyValue.entrySet().iterator(); + while (it.hasNext()) + { + Map.Entry pair = (Map.Entry)it.next(); + out += ("" + SectionStart + pair.getKey() + SectionEnd + KeyValueLineSeparator); + + Iterator internal = ((HashMap)pair.getValue()).entrySet().iterator(); + while(internal.hasNext()) + { + Map.Entry internalPair = (Map.Entry)internal.next(); + String key = (String)internalPair.getKey(); + String value = (String)internalPair.getValue(); + + if(key == value) + out += (key + KeyValueSplit) + KeyValueLineSeparator; + else + out += (key + KeyValueSplit + value) + KeyValueLineSeparator; + } + + out += KeyValueLineSeparator; + } + + return out; + } + + // Parses out the string passed in into the sectionkeyValue HashMap. + // Any character used in a split call is escaped just in case on + // account of some characters having specific regex meanings. + private void Parse(String input) + { + String[] sections = input.split("\\" + SectionStart); + + for(int sec = 0; sec < sections.length; ++sec) + { + // Gather information about the contents of the section, and the header. + String section = sections[sec]; + if(section.length() < 2) + continue; + + int pos = section.indexOf(SectionEnd); + if(pos == -1) + continue; + + // Parse section name. If it already exists, don't bother making it. + String sectionName = section.substring(0, pos); + AddSection(sectionName); + + // Parse out the pairs within the section, split them all out. + String unparsedPairs = section.substring(pos + 1); + String[] pairs = unparsedPairs.split("\\" + KeyValueLineSeparator); + + // Parse out valid key-value pairs, and store them in the specified section. + // At this point, we can be guarenteed that sectionName is in the Hashmap. + for(int pair = 0; pair < pairs.length; ++pair) + { + String line = pairs[pair]; + int splitPos = line.indexOf(KeyValueSplit); + if(splitPos < 0) + continue; + + String key = line.substring(0, splitPos); + String value = line.substring(splitPos + KeyValueSplit.length()); + sectionKeyValue.get(sectionName).putIfAbsent(key, value); + keyValue.putIfAbsent(key, value); + } + } + } + + // Dumps out a string array + @SuppressWarnings("unused") + private void Dump(String[] toPrint) + { + System.out.println("Length: " + toPrint.length); + + for(int i = 0; i < toPrint.length; ++i) + System.out.println(toPrint[i]); + } + + // Adds a KeyValue pair to the specified section if it's not already there. + // Also creates the section if it's not already present. + public void AddKeyValue(String sectionName, String key, String value) + { + AddSection(sectionName); + sectionKeyValue.get(sectionName).putIfAbsent(key, value); + keyValue.putIfAbsent(key, value); + } + + // Adds a given section to the hashmap if it's not already present + public void AddSection(String sectionName) + { + sectionKeyValue.putIfAbsent(sectionName, new HashMap()); + } + + // Returns a HashMap of Keys to Values for a given section + @SuppressWarnings("unchecked") + public HashMap GetSection(String sectionName) + { + return (HashMap) sectionKeyValue.get(sectionName).clone(); + } + + // Look up a global key + public String GetKey(String key) + { + if(keyValue.containsKey(key)) + return keyValue.get(key); + + return null; + } +} diff --git a/src/main/Main.java b/src/main/Main.java index 50ae429..72f4243 100644 --- a/src/main/Main.java +++ b/src/main/Main.java @@ -32,16 +32,17 @@ public class Main extends ListenerAdapter // Main test location public static void main(String[] args) throws InterruptedException, LoginException, Exception { + // Localizer startup - Potentially integrate with the factory. Needs to happen first tho. + Localizer.UpdateLocFromDisk(); + Localizer.ScrapeAll(); + Localizer.SaveLocToDisk(); + // Facotry startup. databaseManager = ObjectBuilderFactory.ConstructDatabaseManager(); commandManager = ObjectBuilderFactory.ConstructCommandManager(); rpManager = ObjectBuilderFactory.ConstructRPManager(); stats = ObjectBuilderFactory.ConstructStats(commandManager); - // Localizer startup - Potentially integrate with the factory. - Localizer.UpdateLocFromDisk(); - Localizer.ScrapeAll(); - Localizer.SaveLocToDisk(); // Bot startup kitty = new JDABuilder(AccountType.BOT).setToken(Ref.TestToken).buildBlocking();