diff --git a/localization.config b/localization.config index b52e3e6..2adcf25 100644 --- a/localization.config +++ b/localization.config @@ -1,174 +1,170 @@ -[CommandEightBall] -Ask again later. = -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. = -Without a doubt. = -My reply is no. = -Signs point to yes. = -Reply hazy, try again. = -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. = -Yes. = -Yes - definitely. = -It is certain. = -Concentrate and ask again. = -It is decidedly so. = -As I see it, yes. = -Outlook good. = -Outlook not so good. = -Cannot predict now. = -Most likely. = -Very doubtful. = -Don't count on it. = -Better not tell you now. = - -[CommandColiru] -Will try to compile any c++ code you put in! Supports up to C++14 standard, uses g++. = - -[CommandPerish] -Adds a red, 'a n g e r y' overlay to your icon or the icon of a friend you mentioned = +[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='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! = - -[CommandPollResults] -%s people voted for %s `%s` with `%s%` !\n = -Will show current results of a poll and percentages of votes per choice = -%s people voted for %s `%s` with `%s%` !\n = - -[CommandShutdown] -Forced immediate shutdown, threads abandoned without sync. = -Stops kitty. `-s` or `safe` as an argument attempts to sync off the database before shutdown. = -Forced shutdown, database synced before abandoning threads. = - -[CommandBetBeans] -That's not a valid bet! = -You don't have enough beans! = -Please bet with at least 50 beans! = -You won %s beans! = -Sorry, you didn't win, try again! = -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 = - -[CommandRole] -You aren't allowed to do that! You must have the KittyRole '%' or higher! = -Please enter `general`, `mod`, or `admin`! = -Your role is = -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. = -Changed %s to role `%s`! = - -[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` = - -[CommandTweet] -FUCKED UP HARD = - -[CommandStats] -Displays the actively running KittyBot application information = - -[CommandMap] -Invalid arguments provided! = -Using mapgen v0.1 = -Width = -Seed = -Height = - -[CommandPollVote] -You already voted = -That's not a vaild number! = -%s That's not a vaild vote! = -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 = - -[CommandDoWork] -I finished with my work! = D = -I finished with my work! :D = -Occupies a core for a few seconds = +You have %s beans!=You have %s beans! +Displays how many beans you have=Displays how many beans you have [CommandHelp] -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` = -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` = -Lets you look up specific commands, or get a link to a list of all commands. = - -[CommandPing] -Will respond with Pong! = -Pong! = - -[CommandBoop] -Woah! %s booped me! That's %s total! = -%s booped several others - %s! = -%s booped %s! = -Kitty will react with a counter = - -[CommandInfo] -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/ = -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/ = -Provides author info and a link to Kitty's website = - -[CommandBlurry] -Blurs your icon or the icon of a friend you mentioned = - -[CommandHelpBuilder] -Emit help for all commands as formatted HTML = -commands = - -[CommandRating] -Warning = NSFW may slip through, images are only based on tags on their respective sites! = -Kittybot content set to = -Warning: NSFW may slip through, images are only based on tags on their respective sites! = -Invalid content rating = - -[CommandRPEnd] -Here's your file! = -You can't end this RP! = -Ends RP in channel = - -[CommandPollShow] -Will show the current poll running = -The current poll is `%s`\n = -And the choices are = \n = -There is no poll running! = -And the choices are:\n = - -[CommandGiveBeans] -That's not a valid number! = -Gives beans to the mentioned users! = -You didn't mention anyone! = -Gave %s %s beans! = - -[CommandWolfram] -Will query wolframalpha with your question and give a full image output of the answer = -Something went wrong! = -You need to provide some arguments! = - -[CommandRPG] -Admin+ command only right now - experimental text RPG! Format is !rpg = -Invalid RPG Command! = - -[CommandYeet] -Yeet yourself or yeet a friend with @! = - -[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 = - -[CommandRPStart] -Starts an rp, add people to it by mentioning them! = - -[CommandStark] -Snaps your icon or the icon of a friend you mentioned = - -[CommandJDoodle] -Will compile any java code you put in! Supports Java 1.8 = +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`=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` +Lets you look up specific commands, or get a link to a list of all commands.=Lets you look up specific commands, or get a link to a list of all commands. [CommandRoll] -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 = -Didn't work ;3; = +Didn't work ;3;=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=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 -[CommandInvite] -Provies a direct invite link for KittyBot = +[CommandStats] +Displays the actively running KittyBot application information=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=With an input of x,y,z where x y and z are all choices, kitty will choose one +FUCKED UP HARD=FUCKED UP HARD + +[CommandRole] +Please enter `general`, `mod`, or `admin`!=Please enter `general`, `mod`, or `admin`! +You aren't allowed to do that! You must have the KittyRole '%' or higher!=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.=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=Your role is +Changed %s to role `%s`!=Changed %s to role `%s`! + +[CommandColiru] +Will try to compile any c++ code you put in! Supports up to C++14 standard, uses g++.=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=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!=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`=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=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=Snaps your icon or the icon of a friend you mentioned + +[CommandYeet] +Yeet yourself or yeet a friend with @!=Yeet yourself or yeet a friend with @! + +[CommandPollVote] +There is no poll running!=There is no poll running! +You already voted=You already voted +%s That's not a vaild vote!=%s That's not a vaild vote! +That's not a vaild number!=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!=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=You successfully voted for + +[CommandShutdown] +Stops kitty. `-s` or `safe` as an argument attempts to sync off the database before shutdown.=Stops kitty. `-s` or `safe` as an argument attempts to sync off the database before shutdown. +Forced shutdown, database synced before abandoning threads.=Forced shutdown, database synced before abandoning threads. +Forced immediate shutdown, threads abandoned without sync.=Forced immediate shutdown, threads abandoned without sync. + +[CommandBetBeans] +That's not a valid bet!=That's not a valid bet! +Please bet with at least 50 beans!=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=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!=Sorry, you didn't win, try again! +You don't have enough beans!=You don't have enough beans! +You won %s beans!=You won %s beans! + +[CommandDoWork] +I finished with my work! :D=I finished with my work! :D +Occupies a core for a few seconds=Occupies a core for a few seconds + +[CommandRPStart] +Starts an rp, add people to it by mentioning them!=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=Will show current results of a poll and percentages of votes per choice +%s people voted for %s `%s` with `%s%` !\n =%s people voted for %s `%s` with `%s%` !\n + +[CommandRating] +Kittybot content set to=Kittybot content set to +Warning: NSFW may slip through, images are only based on tags on their respective sites!=Warning: NSFW may slip through, images are only based on tags on their respective sites! +Invalid content rating=Invalid content rating + +[CommandGiveBeans] +That's not a valid number!=That's not a valid number! +Gave %s %s beans!=Gave %s %s beans! +Gives beans to the mentioned users!=Gives beans to the mentioned users! +You didn't mention anyone!=You didn't mention anyone! + +[CommandPollShow] +There is no poll running!=There is no poll running! +And the choices are:\n=And the choices are:\n +Will show the current poll running=Will show the current poll running +The current poll is `%s`\n=The current poll is `%s`\n + +[CommandHelpBuilder] +Emit help for all commands as formatted HTML=Emit help for all commands as formatted HTML +commands=commands + +[CommandRPEnd] +Here's your file!=Here's your file! +You can't end this RP!=You can't end this RP! +Ends RP in channel=Ends RP in channel + +[CommandRPG] +Invalid RPG Command!=Invalid RPG Command! +Admin+ command only right now - experimental text RPG! Format is !rpg =Admin+ command only right now - experimental text RPG! Format is !rpg + +[CommandBoop] +%s booped %s!=%s booped %s! +Kitty will react with a counter=Kitty will react with a counter +Woah! %s booped me! That's %s total!=Woah! %s booped me! That's %s total! +%s booped several others - %s!=%s booped several others - %s! + +[CommandInfo] +Provides author info and a link to Kitty's website=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/=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!=Pong! +Will respond with 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! = +With an input of x,y,z where x y and z are all choices, kitty will choose one=With an input of x,y,z where x y and z are all choices, kitty will choose one +I chooooooose %s!=I chooooooose %s! + +[CommandEightBall] +It is certain.=It is certain. +Ask again later.=Ask again later. +Cannot predict now.=Cannot predict now. +My sources say no.=My sources say no. +You may rely on it.=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.=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.=Concentrate and ask again. +Signs point to yes.=Signs point to yes. +Don't count on it.=Don't count on it. +Yes.=Yes. +My reply is no.=My reply is no. +Most likely.=Most likely. +Reply hazy, try again.=Reply hazy, try again. +Without a doubt.=Without a doubt. +Yes - definitely.=Yes - definitely. +Very doubtful.=Very doubtful. +As I see it, yes.=As I see it, yes. +Better not tell you now.=Better not tell you now. +Outlook good.=Outlook good. +Outlook not so good.=Outlook not so good. +It is decidedly so.=It is decidedly so. + +[CommandInvite] +Provies a direct invite link for KittyBot=Provies a direct invite link for KittyBot + +[CommandWolfram] +Something went wrong!=Something went wrong! +Will query wolframalpha with your question and give a full image output of the answer=Will query wolframalpha with your question and give a full image output of the answer +You need to provide some arguments!=You need to provide some arguments! + +[CommandMap] +Seed=Seed +Invalid arguments provided!=Invalid arguments provided! +Height=Height +Using mapgen v0.1=Using mapgen v0.1 +Width=Width + diff --git a/src/core/Localizer.java b/src/core/Localizer.java index 8498f9a..4068454 100644 --- a/src/core/Localizer.java +++ b/src/core/Localizer.java @@ -3,13 +3,17 @@ 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 org.sqlite.SQLiteConfig.Encoding; +import dataStructures.SectionedKeyValueStore; import utils.FileUtils; import utils.GlobalLog; import utils.LogFilter; @@ -23,8 +27,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); } @@ -87,37 +91,45 @@ public class Localizer // the string in question if one can be found. 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; + return stringStore.GetKey(input); } + // 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) @@ -138,24 +150,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 +167,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/SectionedKeyValueStore.java b/src/dataStructures/SectionedKeyValueStore.java index 02d4420..744d546 100644 --- a/src/dataStructures/SectionedKeyValueStore.java +++ b/src/dataStructures/SectionedKeyValueStore.java @@ -3,6 +3,8 @@ 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 @@ -13,20 +15,27 @@ import java.util.Map; // Valid Ridiculous Key&\n\t_.:;foo =Some Value // Key= // -public class SectionedKeyValue +// 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. +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 SectionedKeyValue(String input) + public SectionedKeyValueStore(String input) { sectionKeyValue = new HashMap>(); - + keyValue = new HashMap(); Parse(input); } @@ -36,18 +45,59 @@ public class SectionedKeyValue { AddSection(sectionName); sectionKeyValue.get(sectionName).putIfAbsent(key, value); + keyValue.putIfAbsent(key, value); } // Returns a HashMap of Keys to Values for a given section + @SuppressWarnings("unchecked") public HashMap GetSection(String sectionName) { - return sectionKeyValue.get(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; + } + + // 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())); + } } // Stores the internal hashmap as a string then reutrns it. // Places 1 newline between the sections. @SuppressWarnings({"rawtypes", "unchecked"}) - public String ToString() + public String toString() { String out = ""; @@ -55,7 +105,7 @@ public class SectionedKeyValue while (it.hasNext()) { Map.Entry pair = (Map.Entry)it.next(); - out += ("" + SectionStart + pair.getKey() + SectionEnd); + out += ("" + SectionStart + pair.getKey() + SectionEnd + "\n"); Iterator internal = ((HashMap)pair.getValue()).entrySet().iterator(); @@ -115,6 +165,7 @@ public class SectionedKeyValue String key = line.substring(0, splitPos); String value = line.substring(splitPos + KeyValueSplit.length()); sectionKeyValue.get(sectionName).putIfAbsent(key, value); + keyValue.putIfAbsent(key, value); } } } 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();