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 super String, Pair super String, ? super String>> 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();