From 462f23274e2c4e81e604a50d299ef5592554ce42 Mon Sep 17 00:00:00 2001 From: Matthew Cech Date: Tue, 25 Feb 2020 15:19:12 -0800 Subject: [PATCH 1/7] + Added nanoHTTPD library --- .classpath | 1 + lib/nanohttpd-2.3.1.jar | Bin 0 -> 51211 bytes 2 files changed, 1 insertion(+) create mode 100644 lib/nanohttpd-2.3.1.jar diff --git a/.classpath b/.classpath index 6cf8f5a..30f7b88 100644 --- a/.classpath +++ b/.classpath @@ -27,5 +27,6 @@ + diff --git a/lib/nanohttpd-2.3.1.jar b/lib/nanohttpd-2.3.1.jar new file mode 100644 index 0000000000000000000000000000000000000000..ade9bbe2bcdaa811a4110b38628ffd6681e29e20 GIT binary patch literal 51211 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 literal 0 HcmV?d00001 From 6be6bd4033b2ddfe8e7da21abcdc79f52faf7454 Mon Sep 17 00:00:00 2001 From: Alex Stewart Date: Tue, 25 Feb 2020 18:25:17 -0500 Subject: [PATCH 2/7] Auto stash before merge of "master" and "origin/master" --- assets/config.csv | 11 + assets/plugins/derpisource.lua | 42 +- assets/plugins/e6source.lua | 14 +- src/commands/general/CommandBetBeans.java | 2 +- src/commands/general/CommandDerpi.java | 142 +-- src/commands/general/CommandE6.java | 134 +-- src/commands/music/CommandMusicMain.java | 1 + src/commands/music/SubCommandAddTrack.java | 3 +- src/commands/music/SubCommandSkip.java | 46 +- src/commands/music/SubCommandVolume.java | 42 + src/core/CommandManager.java | 469 +++++----- src/core/ObjectBuilderFactory.java | 956 ++++++++++----------- src/dataStructures/KittyChannel.java | 28 +- src/dataStructures/KittyGuild.java | 360 ++++---- src/main/Main.java | 268 +++--- src/network/NetworkSauceNAO.java | 96 +-- src/utils/audio/AudioUtils.java | 13 + 17 files changed, 1356 insertions(+), 1271 deletions(-) create mode 100644 src/commands/music/SubCommandVolume.java diff --git a/assets/config.csv b/assets/config.csv index 437a63e..20f1aa9 100644 --- a/assets/config.csv +++ b/assets/config.csv @@ -17,6 +17,8 @@ "Localized Commands","dbstats","" "Localized Commands","defaultdance","" "Localized Commands","derp","" +"Localized Commands","derpi","" +"Localized Commands","e6","" "Localized Commands","e621","" "Localized Commands","eightball, 8ball","" "Localized Commands","fetch","" @@ -48,6 +50,7 @@ "Localized Commands","stats","" "Localized Commands","teey","" "Localized Commands","tony, stark, dontfeelgood, dontfeelsogood","tony, stark, dontfeelgood, dontfeelsogood, snap" +"Localized Commands","tradebeans","" "Localized Commands","tweet","" "Localized Commands","vote","" "Localized Commands","wolfram","" @@ -110,8 +113,10 @@ "Localized Strings","DBFlushInfo","Takes all objects queued for the database and writes them to the database, then says how many were written." "Localized Strings","DBStatsInfo","Shows current statistics for the database" "Localized Strings","DefaultDanceInfo","y'all know forknife, get ready to dance, or make a friend dance with @!" +"Localized Strings","DerpiError","" "Localized Strings","DoWorkFinished","I finished with my work! :D" "Localized Strings","DoWorkInfo","Occupies a core for a few seconds" +"Localized Strings","E6Blacklisted","I can't show that image ;3; (it may be blacklisted)" "Localized Strings","EightBallError","Hmm? You'll need to ask a question!" "Localized Strings","EightBallInfo","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." "Localized Strings","EightBallMaybe1","Reply hazy, try again." @@ -182,7 +187,10 @@ "Localized Strings","MapVersion","Using mapgen v0.1" "Localized Strings","MapWidth","" "Localized Strings","ModInfo","Mod is a super command for admin or mod use only!\n\t`mod ban @user` will ban a user from the server\n\t`mod kick @user` will kick the user from the server" +"Localized Strings","MusicAddTrack","" "Localized Strings","MusicInfo","" +"Localized Strings","MusicVolChanged","Volume set to %s!" +"Localized Strings","MusicVolCurrent","Volume is at %s!" "Localized Strings","PerishInfo","Adds a red, 'a n g e r y' overlay to your icon or the icon of a friend you mentioned" "Localized Strings","PingInfo","Will respond with Pong!" "Localized Strings","PingResponse","Pong!" @@ -271,6 +279,8 @@ "Command Enabler","dbstats","1" "Command Enabler","defaultdance","1" "Command Enabler","derp","1" +"Command Enabler","derpi","1" +"Command Enabler","e6","1" "Command Enabler","e621","1" "Command Enabler","eightball, 8ball","1" "Command Enabler","fetch","1" @@ -313,6 +323,7 @@ "Command Enabler","stats","1" "Command Enabler","teey","1" "Command Enabler","tony, stark, dontfeelgood, dontfeelsogood","1" +"Command Enabler","tradebeans","1" "Command Enabler","tweet","1" "Command Enabler","vote","1" "Command Enabler","wolfram","1" diff --git a/assets/plugins/derpisource.lua b/assets/plugins/derpisource.lua index 01bf91c..455eaeb 100644 --- a/assets/plugins/derpisource.lua +++ b/assets/plugins/derpisource.lua @@ -1,22 +1,22 @@ -function plugin(message, user) - local index; - local concat; - if(string.find(message, "https://derpicdn.net/img"))then - if(string.find(message, "view/"))then - index = string.find(message, "/[^/]*$"); - return "!derpi ID:" .. string.sub(message, index + 1, string.find(message, ".[^.]*$")-1); - else - if(string.find(message, "download/"))then - index = string.find(message, "_"); - concat = string.sub(message, 0, index-1); - return "!derpi ID:" .. string.sub(concat, string.find(message, "/[^/]*$") + 1); - else - index = string.find(message, "/[^/]*$"); - concat = string.sub(message, 0, index - 1); - index = string.find(concat, "/[^/]*$"); - - return "!derpi ID:" .. string.sub(concat, index + 1); - end - end - end +function plugin(message, user) + local index; + local concat; + if(string.find(message, "https://derpicdn.net/img"))then + if(string.find(message, "view/"))then + index = string.find(message, "/[^/]*$"); + return "!derpi ID:" .. string.sub(message, index + 1, string.find(message, ".[^.]*$")-1); + else + if(string.find(message, "download/"))then + index = string.find(message, "_"); + concat = string.sub(message, 0, index-1); + return "!derpi ID:" .. string.sub(concat, string.find(message, "/[^/]*$") + 1); + else + index = string.find(message, "/[^/]*$"); + concat = string.sub(message, 0, index - 1); + index = string.find(concat, "/[^/]*$"); + + return "!derpi ID:" .. string.sub(concat, index + 1); + end + end + end end \ No newline at end of file diff --git a/assets/plugins/e6source.lua b/assets/plugins/e6source.lua index 00f3aea..e215906 100644 --- a/assets/plugins/e6source.lua +++ b/assets/plugins/e6source.lua @@ -1,8 +1,8 @@ -function plugin(message, user) - if(string.find(message, "https://static1.e621.net/data") or string.find(message, "https://static1.e926.net/data"))then - if(string.find(message, " "))then - message = string.sub(message, 0, string.find(message, " ")); - end - return "!e6 md5:" .. string.sub(message, string.find(message, "/[^/]*$") + 1 ,string.find(message, ".[^.]*$") - 1); - end +function plugin(message, user) + if(string.find(message, "https://static1.e621.net/data") or string.find(message, "https://static1.e926.net/data"))then + if(string.find(message, " "))then + message = string.sub(message, 0, string.find(message, " ")); + end + return "!e6 md5:" .. string.sub(message, string.find(message, "/[^/]*$") + 1 ,string.find(message, ".[^.]*$") - 1); + end end \ No newline at end of file diff --git a/src/commands/general/CommandBetBeans.java b/src/commands/general/CommandBetBeans.java index bcb14b0..29b65ad 100644 --- a/src/commands/general/CommandBetBeans.java +++ b/src/commands/general/CommandBetBeans.java @@ -20,7 +20,7 @@ public class CommandBetBeans extends Command { String call = ""; - int min = 50; + int min = 20; int bet = 0; int win = 0; diff --git a/src/commands/general/CommandDerpi.java b/src/commands/general/CommandDerpi.java index 7a27173..c082ccf 100644 --- a/src/commands/general/CommandDerpi.java +++ b/src/commands/general/CommandDerpi.java @@ -1,72 +1,72 @@ -package commands.general; - -import core.Command; -import core.LocStrings; -import dataStructures.KittyChannel; -import dataStructures.KittyEmbed; -import dataStructures.KittyGuild; -import dataStructures.KittyRating; -import dataStructures.KittyRole; -import dataStructures.KittyUser; -import dataStructures.Response; -import dataStructures.UserInput; -import network.NetworkDerpi; - -public class CommandDerpi extends Command -{ - NetworkDerpi searcher = new NetworkDerpi(); - KittyEmbed response; - - // Required constructor - public CommandDerpi(KittyRole level, KittyRating rating) { super(level, rating); } - - @Override - public String getHelpText() { return "Will search derpibooru for the tags entered, if KittyBot's content filter allows it"; } - - @Override - public void onRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res) - { - if(guild.contentRating == KittyRating.Filtered) - { - try - { - response = searcher.getDerpi(input.args.replace(',', ' ') + " safe").output(); - res.send(response); - } - catch(Exception e) - { - res.send(LocStrings.stub("DerpiError")); - } - } - else - { - if(input.args == null || input.args.length() == 0) - res.send("DerpiNoSearchError"); - else - { - response = searcher.getDerpi(input.args).output(); - try - { - res.send(response); - } - catch(Exception e) - { - res.send(LocStrings.stub("DerpiError")); - } - } - } - - if(input.args.startsWith("ID:")) - { - response = searcher.getDerpiByID(input.args.substring(input.args.indexOf(':'))).output(); - try - { - res.send(response); - } - catch(Exception e) - { - res.send(LocStrings.stub("DerpiError")); - } - } - } +package commands.general; + +import core.Command; +import core.LocStrings; +import dataStructures.KittyChannel; +import dataStructures.KittyEmbed; +import dataStructures.KittyGuild; +import dataStructures.KittyRating; +import dataStructures.KittyRole; +import dataStructures.KittyUser; +import dataStructures.Response; +import dataStructures.UserInput; +import network.NetworkDerpi; + +public class CommandDerpi extends Command +{ + NetworkDerpi searcher = new NetworkDerpi(); + KittyEmbed response; + + // Required constructor + public CommandDerpi(KittyRole level, KittyRating rating) { super(level, rating); } + + @Override + public String getHelpText() { return "Will search derpibooru for the tags entered, if KittyBot's content filter allows it"; } + + @Override + public void onRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res) + { + if(guild.contentRating == KittyRating.Filtered) + { + try + { + response = searcher.getDerpi(input.args.replace(',', ' ') + " safe").output(); + res.send(response); + } + catch(Exception e) + { + res.send(LocStrings.stub("DerpiError")); + } + } + else + { + if(input.args == null || input.args.length() == 0) + res.send("DerpiNoSearchError"); + else + { + response = searcher.getDerpi(input.args).output(); + try + { + res.send(response); + } + catch(Exception e) + { + res.send(LocStrings.stub("DerpiError")); + } + } + } + + if(input.args.startsWith("ID:")) + { + response = searcher.getDerpiByID(input.args.substring(input.args.indexOf(':'))).output(); + try + { + res.send(response); + } + catch(Exception e) + { + res.send(LocStrings.stub("DerpiError")); + } + } + } } \ No newline at end of file diff --git a/src/commands/general/CommandE6.java b/src/commands/general/CommandE6.java index a5d5bb0..cf31858 100644 --- a/src/commands/general/CommandE6.java +++ b/src/commands/general/CommandE6.java @@ -1,60 +1,76 @@ -package commands.general; - -import core.Command; -import core.LocStrings; -import dataStructures.*; -import network.NetworkE6; - -public class CommandE6 extends Command -{ - NetworkE6 searcher = new NetworkE6(); - KittyEmbed response; - - public CommandE6(KittyRole level, KittyRating rating) { super(level, rating); } - - @Override - public String getHelpText() - { - String toRet = "Will search e6"; - toRet += "21 for the tags entered, if KittyBot's content filter allows it"; - return toRet; - } - - @Override - public void onRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res) - { - if(guild.contentRating == KittyRating.Filtered || !guild.channels.get(Long.getLong(channel.uniqueID)).mature) - { - if(!guild.channels.get(Long.getLong(channel.uniqueID)).mature) - { - res.send("This channel is SFW only! Have some (probably) wholesome content ^^~"); - } - response = searcher.getE6(input.args + " rating:safe").output(); - try - { - res.send(response); - } - catch(Exception e) - { - res.send(LocStrings.stub("E6Blacklisted")); - } - } - else - { - if(input.args == null || input.args.length() == 0) - res.send("E6NoSearchError"); - else - { - try - { - response = searcher.getE6(input.args).output(); - res.send(response); - } - catch(Exception e) - { - res.send(LocStrings.stub("E6Blacklisted")); - } - } - } - } +package commands.general; + +import core.Command; +import core.LocStrings; +import dataStructures.*; +import network.NetworkE6; + +public class CommandE6 extends Command +{ + NetworkE6 searcher = new NetworkE6(); + KittyEmbed response; + GenericImage image; + + public CommandE6(KittyRole level, KittyRating rating) { super(level, rating); } + + @Override + public String getHelpText() + { + String toRet = "Will search e6"; + toRet += "21 for the tags entered, if KittyBot's content filter allows it"; + return toRet; + } + + @Override + public void onRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res) + { + if(guild.contentRating == KittyRating.Filtered || !guild.channels.get(Long.getLong(channel.uniqueID)).mature) + { + if(!guild.channels.get(Long.getLong(channel.uniqueID)).mature) + { + res.send("This channel is SFW only! Have some (probably) wholesome content ^^~"); + } + + image = searcher.getE6(input.args + " rating:safe"); + try + { + response = image.output(); + } + catch(Exception e) + { + res.send(LocStrings.stub("E6Blacklisted")); + return; + } + try + { + if(response.authorText == null) + { + Exception e = new Exception(); + throw e; + } + res.send(response); + } + catch(Exception e) + { + res.send(LocStrings.stub("E6Blacklisted")); + } + } + else + { + if(input.args == null || input.args.length() == 0) + res.send("E6NoSearchError"); + else + { + try + { + response = searcher.getE6(input.args).output(); + res.send(response); + } + catch(Exception e) + { + res.send(LocStrings.stub("E6Blacklisted")); + } + } + } + } } \ No newline at end of file diff --git a/src/commands/music/CommandMusicMain.java b/src/commands/music/CommandMusicMain.java index 7e71fc6..a3534a8 100644 --- a/src/commands/music/CommandMusicMain.java +++ b/src/commands/music/CommandMusicMain.java @@ -18,6 +18,7 @@ public class CommandMusicMain extends Command framework.addCommand("skip", new SubCommandSkip(KittyRole.General, KittyRating.Safe)); framework.addCommand("stop", new SubCommandStop(KittyRole.General, KittyRating.Safe)); framework.addCommand("playlist", new SubCommandPlaylist(KittyRole.General, KittyRating.Safe)); + framework.addCommand("volume", new SubCommandVolume(KittyRole.General, KittyRating.Safe)); } @Override diff --git a/src/commands/music/SubCommandAddTrack.java b/src/commands/music/SubCommandAddTrack.java index 39febae..3dbe47e 100644 --- a/src/commands/music/SubCommandAddTrack.java +++ b/src/commands/music/SubCommandAddTrack.java @@ -1,5 +1,6 @@ package commands.music; +import core.LocStrings; import core.SubCommand; import core.SubCommandFormattable; import dataStructures.KittyChannel; @@ -27,6 +28,6 @@ public class SubCommandAddTrack extends SubCommand video = YT.getYT(video); } guild.audio.playVideo(video); - return new SubCommandFormattable(video); + return new SubCommandFormattable(String.format(LocStrings.stub("MusicAddTrack"), video)); } } \ No newline at end of file diff --git a/src/commands/music/SubCommandSkip.java b/src/commands/music/SubCommandSkip.java index b57ee52..78d0bf6 100644 --- a/src/commands/music/SubCommandSkip.java +++ b/src/commands/music/SubCommandSkip.java @@ -1,23 +1,23 @@ -package commands.music; - -import core.SubCommand; -import core.SubCommandFormattable; -import dataStructures.KittyChannel; -import dataStructures.KittyGuild; -import dataStructures.KittyRating; -import dataStructures.KittyRole; -import dataStructures.KittyUser; -import dataStructures.UserInput; - -public class SubCommandSkip extends SubCommand -{ - public SubCommandSkip(KittyRole level, KittyRating rating) { super(level, rating); } - { - - } - @Override - public SubCommandFormattable OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input) - { - return new SubCommandFormattable(guild.audio.skipVideo(guild.audio.player)); - } -} +package commands.music; + +import core.SubCommand; +import core.SubCommandFormattable; +import dataStructures.KittyChannel; +import dataStructures.KittyGuild; +import dataStructures.KittyRating; +import dataStructures.KittyRole; +import dataStructures.KittyUser; +import dataStructures.UserInput; + +public class SubCommandSkip extends SubCommand +{ + public SubCommandSkip(KittyRole level, KittyRating rating) { super(level, rating); } + { + + } + @Override + public SubCommandFormattable OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input) + { + return new SubCommandFormattable(guild.audio.skipVideo(guild.audio.player)); + } +} diff --git a/src/commands/music/SubCommandVolume.java b/src/commands/music/SubCommandVolume.java new file mode 100644 index 0000000..ab45d59 --- /dev/null +++ b/src/commands/music/SubCommandVolume.java @@ -0,0 +1,42 @@ +package commands.music; + +import core.LocStrings; +import core.SubCommand; +import core.SubCommandFormattable; +import dataStructures.KittyChannel; +import dataStructures.KittyGuild; +import dataStructures.KittyRating; +import dataStructures.KittyRole; +import dataStructures.KittyUser; +import dataStructures.UserInput; + +public class SubCommandVolume extends SubCommand +{ + public SubCommandVolume(KittyRole level, KittyRating rating) { super(level, rating); } + { + + } + @Override + public SubCommandFormattable OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input) + { + int newVol = guild.audio.getVolume(guild.audio.player); + if(input.args != null) + { + try + { + newVol = Integer.parseInt(input.args); + if(newVol > 100 || newVol <1) + { + return new SubCommandFormattable(String.format(LocStrings.stub("MusicVolOOB"))); + } + guild.audio.changeVolume(guild.audio.player, newVol); + } + catch(Exception e) + { + return new SubCommandFormattable(String.format(LocStrings.stub("MusicVolCurrent"), newVol)); + } + + } + return new SubCommandFormattable(String.format(LocStrings.stub("MusicVolChanged"), newVol)); + } +} \ No newline at end of file diff --git a/src/core/CommandManager.java b/src/core/CommandManager.java index e532e79..d356519 100644 --- a/src/core/CommandManager.java +++ b/src/core/CommandManager.java @@ -1,234 +1,235 @@ -package core; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map.Entry; - -import commands.characters.CommandCharacterMain; -import commands.general.*; -import commands.guildrole.CommandGuildRoleMain; -import commands.mod.CommandModMain; -import commands.music.CommandMusicMain; -import commands.poll.CommandPollMain; -import commands.raffle.CommandRaffleMain; -import dataStructures.*; -import utils.GlobalLog; -import utils.LogFilter; - -public class CommandManager -{ - // Variables - private HashMap commands; - private ArrayList threadAccumulator; - private CommandEnabler commandEnabler; - private long invokeCount; - - // Singleton - public static CommandManager instance; - - // Default Constructor - public CommandManager(CommandEnabler commandEnabler) - { - GlobalLog.log(LogFilter.Core, "Initializing " + this.getClass().getSimpleName()); - - if(instance == null) - { - this.commands = new HashMap(); - this.threadAccumulator = new ArrayList(); - this.invokeCount = 0; - this.commandEnabler = commandEnabler; - - registerAllCommands(); - - instance = this; - } - else - { - GlobalLog.error(LogFilter.Core, "You can't have two of the following: " + this.getClass().getSimpleName()); - } - } - - // Registers all the commands for the instance - public void registerAllCommands() - { - this.commands.clear(); - - // Dev - this.register(LocCommands.stub("work"), new CommandDoWork(KittyRole.Dev, KittyRating.Safe)); - this.register(LocCommands.stub("shutdown"), new CommandShutdown(KittyRole.Dev, KittyRating.Safe)); - this.register(LocCommands.stub("stats"), new CommandStats(KittyRole.Dev, KittyRating.Safe)); - this.register(LocCommands.stub("invite"), new CommandInvite(KittyRole.Dev, KittyRating.Safe)); - this.register(LocCommands.stub("buildHelp"), new CommandHelpBuilder(KittyRole.Dev, KittyRating.Safe)); - this.register(LocCommands.stub("tweet"), new CommandTweet(KittyRole.Dev, KittyRating.Safe)); - this.register(LocCommands.stub("dbflush"), new CommandDBFlush(KittyRole.Dev, KittyRating.Safe)); - this.register(LocCommands.stub("dbstats"), new CommandDBStats(KittyRole.Dev, KittyRating.Safe)); - - // Admin - this.register(LocCommands.stub("rating"), new CommandRating(KittyRole.Admin, KittyRating.Safe)); - this.register(LocCommands.stub("indicator"), new CommandChangeIndicator(KittyRole.Admin, KittyRating.Safe)); - - // Mod - this.register(LocCommands.stub("givebeans"), new CommandGiveBeans(KittyRole.Mod, KittyRating.Safe)); - this.register(LocCommands.stub("mod"), new CommandModMain(KittyRole.Mod, KittyRating.Safe)); - - // General - this.register(LocCommands.stub("fetch"), new CommandFetch(KittyRole.General, KittyRating.Safe)); - this.register(LocCommands.stub("teey"), new CommandTeey(KittyRole.General, KittyRating.Safe)); - this.register(LocCommands.stub("perish, thenperish"), new CommandPerish(KittyRole.General, KittyRating.Safe)); - this.register(LocCommands.stub("yeet"), new CommandYeet(KittyRole.General, KittyRating.Safe)); - this.register(LocCommands.stub("ping"), new CommandPing(KittyRole.General, KittyRating.Safe)); - this.register(LocCommands.stub("boop"), new CommandBoop(KittyRole.General, KittyRating.Safe)); - this.register(LocCommands.stub("roll"), new CommandRoll(KittyRole.General, KittyRating.Safe)); - this.register(LocCommands.stub("choose"), new CommandChoose(KittyRole.General, KittyRating.Safe)); - this.register(LocCommands.stub("help"), new CommandHelp(KittyRole.General, KittyRating.Safe)); - this.register(LocCommands.stub("info, about"), new CommandInfo(KittyRole.General, KittyRating.Safe)); - this.register(LocCommands.stub("wolfram"), new CommandWolfram(KittyRole.General, KittyRating.Safe)); - this.register(LocCommands.stub("c++, g++, cplus, cpp"), new CommandColiru(KittyRole.General, KittyRating.Safe)); - this.register(LocCommands.stub("java, jdoodle"), new CommandJDoodle(KittyRole.General, KittyRating.Safe)); - this.register(LocCommands.stub("beans"), new CommandBeansShow(KittyRole.General, KittyRating.Safe)); - this.register(LocCommands.stub("kittyrole"), new CommandRole(KittyRole.General, KittyRating.Safe)); - this.register(LocCommands.stub("bet"), new CommandBetBeans(KittyRole.General, KittyRating.Safe)); - this.register(LocCommands.stub("map"), new CommandMap(KittyRole.General, KittyRating.Safe)); - this.register(LocCommands.stub("rpstart"), new CommandRPStart(KittyRole.General, KittyRating.Safe)); - this.register(LocCommands.stub("rpend"), new CommandRPEnd(KittyRole.General, KittyRating.Safe)); - this.register(LocCommands.stub("tony, stark, dontfeelgood, dontfeelsogood"), new CommandStark(KittyRole.General, KittyRating.Safe)); - this.register(LocCommands.stub("blur"), new CommandBlurry(KittyRole.General, KittyRating.Safe)); - this.register(LocCommands.stub("eightball, 8ball"), new CommandEightBall(KittyRole.General, KittyRating.Safe)); - this.register(LocCommands.stub("catch"), new CommandCatch(KittyRole.General, KittyRating.Safe)); - this.register(LocCommands.stub("bethistory"), new CommandBetHistory(KittyRole.General, KittyRating.Safe)); - this.register(LocCommands.stub("crouton"), new CommandCrouton(KittyRole.General, KittyRating.Safe)); - this.register(LocCommands.stub("benchmark, bench"), new CommandBenchmark(KittyRole.General, KittyRating.Safe)); - this.register(LocCommands.stub("leaderboard"), new CommandLeaderboard(KittyRole.General, KittyRating.Safe)); - this.register(LocCommands.stub("color, colour"), new CommandColor(KittyRole.General, KittyRating.Safe)); - this.register(LocCommands.stub("remind"), new CommandRemind(KittyRole.General, KittyRating.Safe)); - this.register(LocCommands.stub("role"), new CommandGuildRoleMain(KittyRole.General, KittyRating.Safe)); - this.register(LocCommands.stub("character"), new CommandCharacterMain(KittyRole.General, KittyRating.Safe)); - this.register(LocCommands.stub("raffle"), new CommandRaffleMain(KittyRole.General, KittyRating.Safe)); - this.register(LocCommands.stub("poll"), new CommandPollMain(KittyRole.General, KittyRating.Safe)); - this.register(LocCommands.stub("music"), new CommandMusicMain(KittyRole.General, KittyRating.Safe)); - this.register(LocCommands.stub("defaultdance"), new CommandDefaultDance(KittyRole.General, KittyRating.Safe)); - this.register(LocCommands.stub("getsauce"), new CommandGetSauce(KittyRole.General, KittyRating.Safe)); - - this.register(LocCommands.stub("e6"), new CommandE6(KittyRole.General, KittyRating.Filtered)); - this.register(LocCommands.stub("derpi"), new CommandDerpi(KittyRole.General, KittyRating.Filtered)); - } - - // Allows the command manager to keep track of a command. Takes a pair (the un-localized and localzied commands) - // and the command associated with the localized commands. - public void register(Pair pair, Command command) - { - if(pair == null || pair.Second == null) - return; - - String[] keys = pair.Second.split(","); - - for(int i = 0; i < keys.length; ++i) - { - String key = keys[i].trim().toLowerCase(); - - command.registeredNames.add(key); - Command old = commands.put(key, command); - - if(old != null) - { - GlobalLog.warn(LogFilter.Core, "Writing over a command with the key " + key); - return; - } - - GlobalLog.log(LogFilter.Core, "Command registered under key " + key); - } - } - - // Calls the command but on a whole new thread! - public boolean invokeOnNewThread(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response responseContext) - { - // This is here to prevent spinning up a thread if this wasn't even a command. - if(input == null || !input.isValid()) - return false; - - // At this point, verify that the command is enabled. If we don't have any info - // on if it's enabled or not, we assume it's enabled to prevent broken functionality due - // to formatting or casing issues. - if(input.key != null && !commandEnabler.isEnabled(input.key)) - return false; - - Command command = commands.get(input.key); - if(command != null) - { - // Spin up a thread and begin it. The thread carries the info needed to invoke the command. - CommandThread newThread = new CommandThread(this, input, guild, channel, user, responseContext); - threadAccumulator.add(newThread); - newThread.start(); - return true; - } - else - { - GlobalLog.warn(LogFilter.Command, "User " + user.name + " tried to invoke command that doesn't exist: " + input.key); - return false; - } - } - - // Calls the command specified with the key, providing user information arguments, etc. - void invoke(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response responseContext) - { - if(input == null || !input.isValid()) - return; - - Command command = commands.get(input.key); - if(command != null) - { - ++invokeCount; - command.invoke(guild, channel, user, input, responseContext); - } - } - - // Looks up command by name. If it exists, dumps help text, otherwise returns null. - public String getCommandHelpText(String key) - { - Command command = commands.get(key); - - if(command != null) - return "`" + key + "`: " + command.getHelpText(); - - return null; - } - - // Returns the number of commands sent so far during this program run - public long getInvokeCount() - { - return invokeCount; - } - - // Returns all commands by name - public ArrayList getAllRegisteredCommands() - { - ArrayList cmds = new ArrayList(); - for(Entry entry : commands.entrySet()) - cmds.add(entry.getValue()); - - return cmds; - } - - // Info about threads running packaged into an object - public class ThreadData - { - public HashMap states = new HashMap(); - } - public ThreadData dumpThreadData() - { - ThreadData data = new ThreadData(); - - for(int i = 0; i < threadAccumulator.size(); ++i) - { - Thread.State state = threadAccumulator.get(i).getState(); - Integer num = data.states.get(state); - - if(num == null) - num = 0; - - data.states.put(state, num + 1); - } - - return data; - } -} +package core; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map.Entry; + +import commands.characters.CommandCharacterMain; +import commands.general.*; +import commands.guildrole.CommandGuildRoleMain; +import commands.mod.CommandModMain; +import commands.music.CommandMusicMain; +import commands.poll.CommandPollMain; +import commands.raffle.CommandRaffleMain; +import dataStructures.*; +import utils.GlobalLog; +import utils.LogFilter; + +public class CommandManager +{ + // Variables + private HashMap commands; + private ArrayList threadAccumulator; + private CommandEnabler commandEnabler; + private long invokeCount; + + // Singleton + public static CommandManager instance; + + // Default Constructor + public CommandManager(CommandEnabler commandEnabler) + { + GlobalLog.log(LogFilter.Core, "Initializing " + this.getClass().getSimpleName()); + + if(instance == null) + { + this.commands = new HashMap(); + this.threadAccumulator = new ArrayList(); + this.invokeCount = 0; + this.commandEnabler = commandEnabler; + + registerAllCommands(); + + instance = this; + } + else + { + GlobalLog.error(LogFilter.Core, "You can't have two of the following: " + this.getClass().getSimpleName()); + } + } + + // Registers all the commands for the instance + public void registerAllCommands() + { + this.commands.clear(); + + // Dev + this.register(LocCommands.stub("work"), new CommandDoWork(KittyRole.Dev, KittyRating.Safe)); + this.register(LocCommands.stub("shutdown"), new CommandShutdown(KittyRole.Dev, KittyRating.Safe)); + this.register(LocCommands.stub("stats"), new CommandStats(KittyRole.Dev, KittyRating.Safe)); + this.register(LocCommands.stub("invite"), new CommandInvite(KittyRole.Dev, KittyRating.Safe)); + this.register(LocCommands.stub("buildHelp"), new CommandHelpBuilder(KittyRole.Dev, KittyRating.Safe)); + this.register(LocCommands.stub("tweet"), new CommandTweet(KittyRole.Dev, KittyRating.Safe)); + this.register(LocCommands.stub("dbflush"), new CommandDBFlush(KittyRole.Dev, KittyRating.Safe)); + this.register(LocCommands.stub("dbstats"), new CommandDBStats(KittyRole.Dev, KittyRating.Safe)); + + // Admin + this.register(LocCommands.stub("rating"), new CommandRating(KittyRole.Admin, KittyRating.Safe)); + this.register(LocCommands.stub("indicator"), new CommandChangeIndicator(KittyRole.Admin, KittyRating.Safe)); + + // Mod + this.register(LocCommands.stub("givebeans"), new CommandGiveBeans(KittyRole.Mod, KittyRating.Safe)); + this.register(LocCommands.stub("mod"), new CommandModMain(KittyRole.Mod, KittyRating.Safe)); + + // General + this.register(LocCommands.stub("fetch"), new CommandFetch(KittyRole.General, KittyRating.Safe)); + this.register(LocCommands.stub("teey"), new CommandTeey(KittyRole.General, KittyRating.Safe)); + this.register(LocCommands.stub("perish, thenperish"), new CommandPerish(KittyRole.General, KittyRating.Safe)); + this.register(LocCommands.stub("yeet"), new CommandYeet(KittyRole.General, KittyRating.Safe)); + this.register(LocCommands.stub("ping"), new CommandPing(KittyRole.General, KittyRating.Safe)); + this.register(LocCommands.stub("boop"), new CommandBoop(KittyRole.General, KittyRating.Safe)); + this.register(LocCommands.stub("roll"), new CommandRoll(KittyRole.General, KittyRating.Safe)); + this.register(LocCommands.stub("choose"), new CommandChoose(KittyRole.General, KittyRating.Safe)); + this.register(LocCommands.stub("help"), new CommandHelp(KittyRole.General, KittyRating.Safe)); + this.register(LocCommands.stub("info, about"), new CommandInfo(KittyRole.General, KittyRating.Safe)); + this.register(LocCommands.stub("wolfram"), new CommandWolfram(KittyRole.General, KittyRating.Safe)); + this.register(LocCommands.stub("c++, g++, cplus, cpp"), new CommandColiru(KittyRole.General, KittyRating.Safe)); + this.register(LocCommands.stub("java, jdoodle"), new CommandJDoodle(KittyRole.General, KittyRating.Safe)); + this.register(LocCommands.stub("beans"), new CommandBeansShow(KittyRole.General, KittyRating.Safe)); + this.register(LocCommands.stub("kittyrole"), new CommandRole(KittyRole.General, KittyRating.Safe)); + this.register(LocCommands.stub("bet"), new CommandBetBeans(KittyRole.General, KittyRating.Safe)); + this.register(LocCommands.stub("map"), new CommandMap(KittyRole.General, KittyRating.Safe)); + this.register(LocCommands.stub("rpstart"), new CommandRPStart(KittyRole.General, KittyRating.Safe)); + this.register(LocCommands.stub("rpend"), new CommandRPEnd(KittyRole.General, KittyRating.Safe)); + this.register(LocCommands.stub("tony, stark, dontfeelgood, dontfeelsogood"), new CommandStark(KittyRole.General, KittyRating.Safe)); + this.register(LocCommands.stub("blur"), new CommandBlurry(KittyRole.General, KittyRating.Safe)); + this.register(LocCommands.stub("eightball, 8ball"), new CommandEightBall(KittyRole.General, KittyRating.Safe)); + this.register(LocCommands.stub("catch"), new CommandCatch(KittyRole.General, KittyRating.Safe)); + this.register(LocCommands.stub("bethistory"), new CommandBetHistory(KittyRole.General, KittyRating.Safe)); + this.register(LocCommands.stub("crouton"), new CommandCrouton(KittyRole.General, KittyRating.Safe)); + this.register(LocCommands.stub("benchmark, bench"), new CommandBenchmark(KittyRole.General, KittyRating.Safe)); + this.register(LocCommands.stub("leaderboard"), new CommandLeaderboard(KittyRole.General, KittyRating.Safe)); + this.register(LocCommands.stub("color, colour"), new CommandColor(KittyRole.General, KittyRating.Safe)); + this.register(LocCommands.stub("remind"), new CommandRemind(KittyRole.General, KittyRating.Safe)); + this.register(LocCommands.stub("role"), new CommandGuildRoleMain(KittyRole.General, KittyRating.Safe)); + this.register(LocCommands.stub("character"), new CommandCharacterMain(KittyRole.General, KittyRating.Safe)); + this.register(LocCommands.stub("raffle"), new CommandRaffleMain(KittyRole.General, KittyRating.Safe)); + this.register(LocCommands.stub("poll"), new CommandPollMain(KittyRole.General, KittyRating.Safe)); + this.register(LocCommands.stub("music"), new CommandMusicMain(KittyRole.General, KittyRating.Safe)); + this.register(LocCommands.stub("defaultdance"), new CommandDefaultDance(KittyRole.General, KittyRating.Safe)); + this.register(LocCommands.stub("getsauce"), new CommandGetSauce(KittyRole.General, KittyRating.Safe)); + this.register(LocCommands.stub("tradebeans"), new CommandTradeBeans(KittyRole.General, KittyRating.Safe)); + + this.register(LocCommands.stub("e6"), new CommandE6(KittyRole.General, KittyRating.Filtered)); + this.register(LocCommands.stub("derpi"), new CommandDerpi(KittyRole.General, KittyRating.Filtered)); + } + + // Allows the command manager to keep track of a command. Takes a pair (the un-localized and localzied commands) + // and the command associated with the localized commands. + public void register(Pair pair, Command command) + { + if(pair == null || pair.Second == null) + return; + + String[] keys = pair.Second.split(","); + + for(int i = 0; i < keys.length; ++i) + { + String key = keys[i].trim().toLowerCase(); + + command.registeredNames.add(key); + Command old = commands.put(key, command); + + if(old != null) + { + GlobalLog.warn(LogFilter.Core, "Writing over a command with the key " + key); + return; + } + + GlobalLog.log(LogFilter.Core, "Command registered under key " + key); + } + } + + // Calls the command but on a whole new thread! + public boolean invokeOnNewThread(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response responseContext) + { + // This is here to prevent spinning up a thread if this wasn't even a command. + if(input == null || !input.isValid()) + return false; + + // At this point, verify that the command is enabled. If we don't have any info + // on if it's enabled or not, we assume it's enabled to prevent broken functionality due + // to formatting or casing issues. + if(input.key != null && !commandEnabler.isEnabled(input.key)) + return false; + + Command command = commands.get(input.key); + if(command != null) + { + // Spin up a thread and begin it. The thread carries the info needed to invoke the command. + CommandThread newThread = new CommandThread(this, input, guild, channel, user, responseContext); + threadAccumulator.add(newThread); + newThread.start(); + return true; + } + else + { + GlobalLog.warn(LogFilter.Command, "User " + user.name + " tried to invoke command that doesn't exist: " + input.key); + return false; + } + } + + // Calls the command specified with the key, providing user information arguments, etc. + void invoke(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response responseContext) + { + if(input == null || !input.isValid()) + return; + + Command command = commands.get(input.key); + if(command != null) + { + ++invokeCount; + command.invoke(guild, channel, user, input, responseContext); + } + } + + // Looks up command by name. If it exists, dumps help text, otherwise returns null. + public String getCommandHelpText(String key) + { + Command command = commands.get(key); + + if(command != null) + return "`" + key + "`: " + command.getHelpText(); + + return null; + } + + // Returns the number of commands sent so far during this program run + public long getInvokeCount() + { + return invokeCount; + } + + // Returns all commands by name + public ArrayList getAllRegisteredCommands() + { + ArrayList cmds = new ArrayList(); + for(Entry entry : commands.entrySet()) + cmds.add(entry.getValue()); + + return cmds; + } + + // Info about threads running packaged into an object + public class ThreadData + { + public HashMap states = new HashMap(); + } + public ThreadData dumpThreadData() + { + ThreadData data = new ThreadData(); + + for(int i = 0; i < threadAccumulator.size(); ++i) + { + Thread.State state = threadAccumulator.get(i).getState(); + Integer num = data.states.get(state); + + if(num == null) + num = 0; + + data.states.put(state, num + 1); + } + + return data; + } +} diff --git a/src/core/ObjectBuilderFactory.java b/src/core/ObjectBuilderFactory.java index ccd7b04..f01912d 100644 --- a/src/core/ObjectBuilderFactory.java +++ b/src/core/ObjectBuilderFactory.java @@ -1,479 +1,479 @@ -package core; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.concurrent.Semaphore; - -import javax.security.auth.login.LoginException; - -import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager; -import com.sedmelluq.discord.lavaplayer.player.DefaultAudioPlayerManager; -import com.sedmelluq.discord.lavaplayer.source.AudioSourceManagers; - -//import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager; -//import com.sedmelluq.discord.lavaplayer.player.DefaultAudioPlayerManager; - -import core.lua.PluginManager; -import dataStructures.KittyChannel; -import dataStructures.KittyCore; -import dataStructures.KittyGuild; -import dataStructures.KittyRating; -import dataStructures.KittyRole; -import dataStructures.KittyStartupMode; -import dataStructures.KittyUser; -import main.Main; -import net.dv8tion.jda.core.AccountType; -import net.dv8tion.jda.core.JDA; -import net.dv8tion.jda.core.JDABuilder; -import net.dv8tion.jda.core.entities.Emote; -import net.dv8tion.jda.core.entities.Game; -import net.dv8tion.jda.core.entities.Guild; -import net.dv8tion.jda.core.entities.Member; -import net.dv8tion.jda.core.entities.User; -import net.dv8tion.jda.core.events.message.guild.GuildMessageReceivedEvent; -import offline.Ref; -import utils.AdminControl; -//import utils.AudioUtils; -import utils.GlobalLog; -import utils.LogFilter; -import utils.audio.AudioUtils; - -// NOTE(wisp): Isolated factory to assist with storage and caching if needed. -// This also minimizes the number of places JDA interacts with our codebase. -// As it stands, if the object name begins with Kitty, it's constructed here. -// TODO: Make all methods ID based instead of event based -public class ObjectBuilderFactory -{ - // Key: guild string id, Value: guild information - private static HashMap guildCache; - - // Key: channel string id, Value: channel information - private static HashMap channelCache; - - // Key: guild string id + user string id, Value: user information - private static HashMap userCache; - - // For tracking and managing object sync - private static DatabaseManager database; - - // Stats tracking and whatnot... for setting stats too internally potentially - private static Stats stats; - - // RPManger for tracking RP system - private static RPManager rpManager; - - // Plugin manager - private static PluginManager pluginManager; - - // Command manager - private static CommandManager commandManager; - - //Audio track manager - private static AudioPlayerManager playerManager = new DefaultAudioPlayerManager(); - - // Localization classes - these are singletons, but should be initialized before almost all other - // things so their inclusion in the factory is to ensure they're started at the correct time. - @SuppressWarnings("unused") private static LocStrings locStrings; - @SuppressWarnings("unused") private static LocCommands locCommands; - - // Config - @SuppressWarnings("unused") private static Config config; - - // Lazy initialization multithreaded mutex stuff to prevent explosions. - // TODO: Investigate using 'synchronized' instead potentially - private static boolean hasInitialized; - private static Semaphore initMutex = new Semaphore(1); - private static JDA kitty; - - // This is it, this is how the lazy init starts! - private static void lazyInit() - { - if(hasInitialized) - return; - - try - { - initMutex.acquire(); - try - { - // structure initialization - // Construct necessary data structures. - guildCache = new HashMap(); - userCache = new HashMap(); - channelCache = new HashMap(); - database = null; - stats = null; - - AudioSourceManagers.registerRemoteSources(playerManager); - AudioSourceManagers.registerLocalSource(playerManager); - - // Start by reading from things that are external. Because - // we require these things to be resolved before the rest of the application, - // we place them here. - config = new Config(); - } - finally - { - initMutex.release(); - hasInitialized = true; - } - } - catch(InterruptedException ie) - { - GlobalLog.error(LogFilter.Core, "Issue during object builder lazy initialization." - + " The factory was not initialized, and kitty will not be able to continue functionally."); - } - } - - //////////////////////// - // Extraction Methods // - //////////////////////// - - // Explicitly locks: guildCache - public static KittyGuild extractGuild(GuildMessageReceivedEvent event) - { - lazyInit(); - - // Look up the guild. This process can only happen in a single-threaded way - // because of the nature of the cache. We wait until the last second to - // look up the guild. - String uid = event.getGuild().getId(); - - List emotes = event.getGuild().getEmotes(); - ArrayList emotesString = new ArrayList(); - HashMap channels = new HashMap(); - String emote; - String emoteFix; - channels.put(Long.getLong(uid), extractChannel(event)); - for(int i = 0; i < emotes.size(); i++) - { - emote = emotes.get(i).toString(); - emoteFix = "<:" + emote.substring(2, emote.indexOf("(")); - emoteFix += ":" + emote.substring(emote.indexOf("(")+1, emote.length()-1) + ">"; - emotesString.add(emoteFix); - } - - // once we're lazily initialized, we can synchronize w/ the - // guildCache object now instead of having to use a mutex. - KittyGuild guild = null; - synchronized (guildCache) - { - KittyGuild cachedGuild = guildCache.get(uid); - if(cachedGuild != null) - { - guild = cachedGuild; - } - else - { - // Construct a new guild with defaults - guild = new KittyGuild(uid, new AdminControl(event.getGuild()), emotesString, new AudioUtils(event.getGuild(), playerManager), channels); - DatabaseManager.instance.globalRegister(guild); - guildCache.put(uid, guild); - } - } - - return guild; - } - - // Explicitly locks: guildCache - public static KittyRole extractRole(GuildMessageReceivedEvent event) - { - lazyInit(); - - // Looks up the user role. If none is found we check to see if they own - // the guild if not, they're assumed to be - // allowed to use the bot at a general level. - KittyRole role = KittyRole.General; - - if(event.getAuthor().getId() == event.getGuild().getOwner().getUser().getId()) - { - role = KittyRole.Admin; - } - - String uid = event.getGuild().getId() + event.getAuthor().getId(); - synchronized(userCache) - { - KittyUser cachedUser = userCache.get(uid); - if(cachedUser != null) - role = cachedUser.getRole(); - } - - return role; - } - - // Explicitly locks: guildCache - // Extracts the content rating information it can from the provided event. - public static KittyRating extractContentRating(GuildMessageReceivedEvent event) - { - lazyInit(); - - // Look up content rating of the guild, returns a safe content rating. - KittyRating contentRating = KittyRating.Safe; - String uid = event.getGuild().getId(); - synchronized(guildCache) - { - KittyGuild cachedGuild = guildCache.get(uid); - if(cachedGuild != null) - contentRating = cachedGuild.contentRating; - } - - return contentRating; - } - - // Implicitly locks guild cache by calling ExtractGuild - public static KittyChannel extractChannel(GuildMessageReceivedEvent event) - { - lazyInit(); - String channelID = event.getChannel().getId(); - KittyChannel channel = null; - - synchronized(channelCache) - { - KittyChannel cachedChannel = channelCache.get(channelID); - boolean mature; - - if(cachedChannel != null) - { - channel = cachedChannel; - } - else - { - mature = event.getChannel().isNSFW(); - channel = new KittyChannel(channelID, mature); - channelCache.put(channelID, channel); - } - } - - return channel; - } - - // Implicitly locks guild cache by calling ExtractRole and ExtractGuild - public static KittyUser extractUser(GuildMessageReceivedEvent event) - { - lazyInit(); - - String uid = event.getGuild().getId() + event.getAuthor().getId(); - KittyUser user = null; - synchronized(userCache) - { - KittyUser cachedUser = userCache.get(uid); - if(cachedUser != null) - { - updateUser(cachedUser, event.getMember()); - user = cachedUser; - } - else - { - KittyRole role = extractRole(event); - KittyGuild guild = extractGuild(event); - - String name; - if(event.getMember().getNickname() == null) - name = event.getAuthor().getName(); - else - name = event.getMember().getNickname(); - - String discordID = event.getMember().getUser().getId(); - String avatarID = event.getAuthor().getAvatarUrl(); - user = new KittyUser(name, guild, role, uid, avatarID, discordID); - DatabaseManager.instance.globalRegister(user); - userCache.put(uid, user); - } - } - - if(event.getMessage().getMentionedMembers().isEmpty()) - return user; - - Member mentioned; - for(int i = 0; i < event.getMessage().getMentionedMembers().size(); i++) - { - mentioned = event.getMessage().getMentionedMembers().get(i); - if(mentioned.getNickname() != null) - extractUserByJDAUser(event.getGuild().getId(), mentioned.getNickname(), - mentioned.getUser().getId(), mentioned.getUser().getAvatarUrl(), mentioned.getUser().getId()); - else - extractUserByJDAUser(event.getGuild().getId(), mentioned.getUser().getName(), - mentioned.getUser().getId(), mentioned.getUser().getAvatarUrl(), mentioned.getUser().getId()); - } - - return user; - } - - // TODO: Clean up - public static KittyUser extractUserByJDAUser(String guildID, String name, String userID, String avatarID, String discordID) - { - lazyInit(); - - String uid = guildID + userID; - KittyUser user = null; - synchronized(userCache) - { - KittyUser cachedUser = userCache.get(uid); - if(cachedUser != null) - { - if(name != null) - cachedUser.name = name; - - cachedUser.avatarID = avatarID; - user = cachedUser; - } - else - { - KittyRole role = KittyRole.General; - KittyGuild guild = guildCache.get(guildID); - user = new KittyUser(name, guild, role, uid, avatarID, discordID); - DatabaseManager.instance.globalRegister(user); - userCache.put(uid, user); - } - } - - return user; - } - - // There is some redundant lookup occurring. If the user isn't cached yet, then we construct them and cache them. - // The assumption is made that the user does, in fact, exist. - public static KittyUser getKittyUser(String guildID, String userID) - { - String uid = guildID + userID; - KittyUser user = null; - synchronized(userCache) - { - user = userCache.get(uid); - } - - if(user == null) - { - Guild jdaGuild = kitty.getGuildById(guildID); - if(jdaGuild == null) return null; - - Member jdaMember = jdaGuild.getMemberById(userID); - if(jdaMember == null) return null; - - User jdaUser = jdaMember.getUser(); - if(jdaUser == null) return null; - - user = extractUserByJDAUser(guildID, jdaMember.getNickname(), jdaUser.getId(), jdaUser.getAvatarUrl(), jdaUser.getId()); - updateUser(user, jdaMember); - } - - return user; - } - - // Updates a user's name appropriately based on nickname if available - public static void updateUser(KittyUser user, Member member) - { - if(member.getNickname() == null) - { - user.name = member.getUser().getName(); - } - else - { - user.name = member.getNickname(); - } - - user.avatarID = member.getUser().getAvatarUrl(); - } - - - ////////////////////////// - // Construction Methods // - ////////////////////////// - // Builds the core of the bot - public static KittyCore constructKittyCore() throws LoginException, InterruptedException - { - lazyInit(); - - // Determine token based on config. Default to test token. - String tokenToUse = Ref.TestToken; - if(ConfigGlobals.getStartupMode() == KittyStartupMode.Release) - tokenToUse = Ref.Token; - - // Construct bot based on token - kitty = new JDABuilder(AccountType.BOT) - .setToken(tokenToUse).buildBlocking(); - kitty.getPresence().setGame(Game.playing("with a laser pointer")); - kitty.addEventListener(new Main()); - - return new KittyCore(kitty); - } - - // Default construction of the command manager. In order to remotely resolve command enabling - // and disabling, what we do is construct the commands with a localized pair that is checked against - // the CommandEnabler object passed in. In theory, we could have multiple CommandManagers, tho we can - // only have one CommandEnabler. - public static CommandManager constructCommandManager(CommandEnabler commandEnabler) - { - lazyInit(); - - if(commandManager == null) - commandManager = new CommandManager(commandEnabler); - - return commandManager; - } - - // Default database manager construction. It can be constructed - // in different ways, and so we construct it outside of the constructor for - // the factory since it doesn't have to be present / can be elsewhere. - // Effectively we cache the database here. - public static DatabaseManager constructDatabaseManager() - { - lazyInit(); - - if(database == null) - database = new DatabaseManager(); - - return database; - } - - public static Stats constructStats(CommandManager manager) - { - lazyInit(); - - if(stats == null) - stats = new Stats(manager); - - return stats; - } - - public static RPManager constructRPManager() - { - lazyInit(); - - if(rpManager == null) - rpManager = new RPManager(); - - return rpManager; - } - - public static PluginManager constructPluginManager() - { - lazyInit(); - - if(pluginManager == null) - pluginManager = new PluginManager(Constants.AssetDirectory + "plugins/"); - - return pluginManager; - } - - - ///////////////////// - // Utility Methods // - ///////////////////// - - // Returns number of cached guilds (does not equal total users in the database, only what's in memory) - public static Integer getGuildCount() - { synchronized(guildCache) - { - return guildCache.size(); - } - } - - // Returns number of cached users (does not equal total users in the database, only what's in memory) - public static Integer getUserCount() - { synchronized(userCache) - { - return userCache.size(); - } - } +package core; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.concurrent.Semaphore; + +import javax.security.auth.login.LoginException; + +import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager; +import com.sedmelluq.discord.lavaplayer.player.DefaultAudioPlayerManager; +import com.sedmelluq.discord.lavaplayer.source.AudioSourceManagers; + +//import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager; +//import com.sedmelluq.discord.lavaplayer.player.DefaultAudioPlayerManager; + +import core.lua.PluginManager; +import dataStructures.KittyChannel; +import dataStructures.KittyCore; +import dataStructures.KittyGuild; +import dataStructures.KittyRating; +import dataStructures.KittyRole; +import dataStructures.KittyStartupMode; +import dataStructures.KittyUser; +import main.Main; +import net.dv8tion.jda.core.AccountType; +import net.dv8tion.jda.core.JDA; +import net.dv8tion.jda.core.JDABuilder; +import net.dv8tion.jda.core.entities.Emote; +import net.dv8tion.jda.core.entities.Game; +import net.dv8tion.jda.core.entities.Guild; +import net.dv8tion.jda.core.entities.Member; +import net.dv8tion.jda.core.entities.User; +import net.dv8tion.jda.core.events.message.guild.GuildMessageReceivedEvent; +import offline.Ref; +import utils.AdminControl; +//import utils.AudioUtils; +import utils.GlobalLog; +import utils.LogFilter; +import utils.audio.AudioUtils; + +// NOTE(wisp): Isolated factory to assist with storage and caching if needed. +// This also minimizes the number of places JDA interacts with our codebase. +// As it stands, if the object name begins with Kitty, it's constructed here. +// TODO: Make all methods ID based instead of event based +public class ObjectBuilderFactory +{ + // Key: guild string id, Value: guild information + private static HashMap guildCache; + + // Key: channel string id, Value: channel information + private static HashMap channelCache; + + // Key: guild string id + user string id, Value: user information + private static HashMap userCache; + + // For tracking and managing object sync + private static DatabaseManager database; + + // Stats tracking and whatnot... for setting stats too internally potentially + private static Stats stats; + + // RPManger for tracking RP system + private static RPManager rpManager; + + // Plugin manager + private static PluginManager pluginManager; + + // Command manager + private static CommandManager commandManager; + + //Audio track manager + private static AudioPlayerManager playerManager = new DefaultAudioPlayerManager(); + + // Localization classes - these are singletons, but should be initialized before almost all other + // things so their inclusion in the factory is to ensure they're started at the correct time. + @SuppressWarnings("unused") private static LocStrings locStrings; + @SuppressWarnings("unused") private static LocCommands locCommands; + + // Config + @SuppressWarnings("unused") private static Config config; + + // Lazy initialization multithreaded mutex stuff to prevent explosions. + // TODO: Investigate using 'synchronized' instead potentially + private static boolean hasInitialized; + private static Semaphore initMutex = new Semaphore(1); + private static JDA kitty; + + // This is it, this is how the lazy init starts! + private static void lazyInit() + { + if(hasInitialized) + return; + + try + { + initMutex.acquire(); + try + { + // structure initialization + // Construct necessary data structures. + guildCache = new HashMap(); + userCache = new HashMap(); + channelCache = new HashMap(); + database = null; + stats = null; + + AudioSourceManagers.registerRemoteSources(playerManager); + AudioSourceManagers.registerLocalSource(playerManager); + + // Start by reading from things that are external. Because + // we require these things to be resolved before the rest of the application, + // we place them here. + config = new Config(); + } + finally + { + initMutex.release(); + hasInitialized = true; + } + } + catch(InterruptedException ie) + { + GlobalLog.error(LogFilter.Core, "Issue during object builder lazy initialization." + + " The factory was not initialized, and kitty will not be able to continue functionally."); + } + } + + //////////////////////// + // Extraction Methods // + //////////////////////// + + // Explicitly locks: guildCache + public static KittyGuild extractGuild(GuildMessageReceivedEvent event) + { + lazyInit(); + + // Look up the guild. This process can only happen in a single-threaded way + // because of the nature of the cache. We wait until the last second to + // look up the guild. + String uid = event.getGuild().getId(); + + List emotes = event.getGuild().getEmotes(); + ArrayList emotesString = new ArrayList(); + HashMap channels = new HashMap(); + String emote; + String emoteFix; + channels.put(Long.getLong(uid), extractChannel(event)); + for(int i = 0; i < emotes.size(); i++) + { + emote = emotes.get(i).toString(); + emoteFix = "<:" + emote.substring(2, emote.indexOf("(")); + emoteFix += ":" + emote.substring(emote.indexOf("(")+1, emote.length()-1) + ">"; + emotesString.add(emoteFix); + } + + // once we're lazily initialized, we can synchronize w/ the + // guildCache object now instead of having to use a mutex. + KittyGuild guild = null; + synchronized (guildCache) + { + KittyGuild cachedGuild = guildCache.get(uid); + if(cachedGuild != null) + { + guild = cachedGuild; + } + else + { + // Construct a new guild with defaults + guild = new KittyGuild(uid, new AdminControl(event.getGuild()), emotesString, new AudioUtils(event.getGuild(), playerManager), channels); + DatabaseManager.instance.globalRegister(guild); + guildCache.put(uid, guild); + } + } + + return guild; + } + + // Explicitly locks: guildCache + public static KittyRole extractRole(GuildMessageReceivedEvent event) + { + lazyInit(); + + // Looks up the user role. If none is found we check to see if they own + // the guild if not, they're assumed to be + // allowed to use the bot at a general level. + KittyRole role = KittyRole.General; + + if(event.getAuthor().getId() == event.getGuild().getOwner().getUser().getId()) + { + role = KittyRole.Admin; + } + + String uid = event.getGuild().getId() + event.getAuthor().getId(); + synchronized(userCache) + { + KittyUser cachedUser = userCache.get(uid); + if(cachedUser != null) + role = cachedUser.getRole(); + } + + return role; + } + + // Explicitly locks: guildCache + // Extracts the content rating information it can from the provided event. + public static KittyRating extractContentRating(GuildMessageReceivedEvent event) + { + lazyInit(); + + // Look up content rating of the guild, returns a safe content rating. + KittyRating contentRating = KittyRating.Safe; + String uid = event.getGuild().getId(); + synchronized(guildCache) + { + KittyGuild cachedGuild = guildCache.get(uid); + if(cachedGuild != null) + contentRating = cachedGuild.contentRating; + } + + return contentRating; + } + + // Implicitly locks guild cache by calling ExtractGuild + public static KittyChannel extractChannel(GuildMessageReceivedEvent event) + { + lazyInit(); + String channelID = event.getChannel().getId(); + KittyChannel channel = null; + + synchronized(channelCache) + { + KittyChannel cachedChannel = channelCache.get(channelID); + boolean mature; + + if(cachedChannel != null) + { + channel = cachedChannel; + } + else + { + mature = event.getChannel().isNSFW(); + channel = new KittyChannel(channelID, mature); + channelCache.put(channelID, channel); + } + } + + return channel; + } + + // Implicitly locks guild cache by calling ExtractRole and ExtractGuild + public static KittyUser extractUser(GuildMessageReceivedEvent event) + { + lazyInit(); + + String uid = event.getGuild().getId() + event.getAuthor().getId(); + KittyUser user = null; + synchronized(userCache) + { + KittyUser cachedUser = userCache.get(uid); + if(cachedUser != null) + { + updateUser(cachedUser, event.getMember()); + user = cachedUser; + } + else + { + KittyRole role = extractRole(event); + KittyGuild guild = extractGuild(event); + + String name; + if(event.getMember().getNickname() == null) + name = event.getAuthor().getName(); + else + name = event.getMember().getNickname(); + + String discordID = event.getMember().getUser().getId(); + String avatarID = event.getAuthor().getAvatarUrl(); + user = new KittyUser(name, guild, role, uid, avatarID, discordID); + DatabaseManager.instance.globalRegister(user); + userCache.put(uid, user); + } + } + + if(event.getMessage().getMentionedMembers().isEmpty()) + return user; + + Member mentioned; + for(int i = 0; i < event.getMessage().getMentionedMembers().size(); i++) + { + mentioned = event.getMessage().getMentionedMembers().get(i); + if(mentioned.getNickname() != null) + extractUserByJDAUser(event.getGuild().getId(), mentioned.getNickname(), + mentioned.getUser().getId(), mentioned.getUser().getAvatarUrl(), mentioned.getUser().getId()); + else + extractUserByJDAUser(event.getGuild().getId(), mentioned.getUser().getName(), + mentioned.getUser().getId(), mentioned.getUser().getAvatarUrl(), mentioned.getUser().getId()); + } + + return user; + } + + // TODO: Clean up + public static KittyUser extractUserByJDAUser(String guildID, String name, String userID, String avatarID, String discordID) + { + lazyInit(); + + String uid = guildID + userID; + KittyUser user = null; + synchronized(userCache) + { + KittyUser cachedUser = userCache.get(uid); + if(cachedUser != null) + { + if(name != null) + cachedUser.name = name; + + cachedUser.avatarID = avatarID; + user = cachedUser; + } + else + { + KittyRole role = KittyRole.General; + KittyGuild guild = guildCache.get(guildID); + user = new KittyUser(name, guild, role, uid, avatarID, discordID); + DatabaseManager.instance.globalRegister(user); + userCache.put(uid, user); + } + } + + return user; + } + + // There is some redundant lookup occurring. If the user isn't cached yet, then we construct them and cache them. + // The assumption is made that the user does, in fact, exist. + public static KittyUser getKittyUser(String guildID, String userID) + { + String uid = guildID + userID; + KittyUser user = null; + synchronized(userCache) + { + user = userCache.get(uid); + } + + if(user == null) + { + Guild jdaGuild = kitty.getGuildById(guildID); + if(jdaGuild == null) return null; + + Member jdaMember = jdaGuild.getMemberById(userID); + if(jdaMember == null) return null; + + User jdaUser = jdaMember.getUser(); + if(jdaUser == null) return null; + + user = extractUserByJDAUser(guildID, jdaMember.getNickname(), jdaUser.getId(), jdaUser.getAvatarUrl(), jdaUser.getId()); + updateUser(user, jdaMember); + } + + return user; + } + + // Updates a user's name appropriately based on nickname if available + public static void updateUser(KittyUser user, Member member) + { + if(member.getNickname() == null) + { + user.name = member.getUser().getName(); + } + else + { + user.name = member.getNickname(); + } + + user.avatarID = member.getUser().getAvatarUrl(); + } + + + ////////////////////////// + // Construction Methods // + ////////////////////////// + // Builds the core of the bot + public static KittyCore constructKittyCore() throws LoginException, InterruptedException + { + lazyInit(); + + // Determine token based on config. Default to test token. + String tokenToUse = Ref.TestToken; + if(ConfigGlobals.getStartupMode() == KittyStartupMode.Release) + tokenToUse = Ref.PoguToken; + + // Construct bot based on token + kitty = new JDABuilder(AccountType.BOT) + .setToken(tokenToUse).buildBlocking(); + kitty.getPresence().setGame(Game.playing("with a laser pointer")); + kitty.addEventListener(new Main()); + + return new KittyCore(kitty); + } + + // Default construction of the command manager. In order to remotely resolve command enabling + // and disabling, what we do is construct the commands with a localized pair that is checked against + // the CommandEnabler object passed in. In theory, we could have multiple CommandManagers, tho we can + // only have one CommandEnabler. + public static CommandManager constructCommandManager(CommandEnabler commandEnabler) + { + lazyInit(); + + if(commandManager == null) + commandManager = new CommandManager(commandEnabler); + + return commandManager; + } + + // Default database manager construction. It can be constructed + // in different ways, and so we construct it outside of the constructor for + // the factory since it doesn't have to be present / can be elsewhere. + // Effectively we cache the database here. + public static DatabaseManager constructDatabaseManager() + { + lazyInit(); + + if(database == null) + database = new DatabaseManager(); + + return database; + } + + public static Stats constructStats(CommandManager manager) + { + lazyInit(); + + if(stats == null) + stats = new Stats(manager); + + return stats; + } + + public static RPManager constructRPManager() + { + lazyInit(); + + if(rpManager == null) + rpManager = new RPManager(); + + return rpManager; + } + + public static PluginManager constructPluginManager() + { + lazyInit(); + + if(pluginManager == null) + pluginManager = new PluginManager(Constants.AssetDirectory + "plugins/"); + + return pluginManager; + } + + + ///////////////////// + // Utility Methods // + ///////////////////// + + // Returns number of cached guilds (does not equal total users in the database, only what's in memory) + public static Integer getGuildCount() + { synchronized(guildCache) + { + return guildCache.size(); + } + } + + // Returns number of cached users (does not equal total users in the database, only what's in memory) + public static Integer getUserCount() + { synchronized(userCache) + { + return userCache.size(); + } + } } \ No newline at end of file diff --git a/src/dataStructures/KittyChannel.java b/src/dataStructures/KittyChannel.java index 770bc49..71fc794 100644 --- a/src/dataStructures/KittyChannel.java +++ b/src/dataStructures/KittyChannel.java @@ -1,15 +1,15 @@ -package dataStructures; - - -public class KittyChannel -{ - public String uniqueID; - public boolean mature; - - public KittyChannel(String uniqueID, boolean mature) - { - //super(uniqueID); - this.uniqueID = uniqueID; - this.mature = false; - } +package dataStructures; + + +public class KittyChannel +{ + public String uniqueID; + public boolean mature; + + public KittyChannel(String uniqueID, boolean mature) + { + //super(uniqueID); + this.uniqueID = uniqueID; + this.mature = false; + } } \ No newline at end of file diff --git a/src/dataStructures/KittyGuild.java b/src/dataStructures/KittyGuild.java index 71445b9..6e18606 100644 --- a/src/dataStructures/KittyGuild.java +++ b/src/dataStructures/KittyGuild.java @@ -1,180 +1,180 @@ -package dataStructures; - -import java.util.ArrayList; -import java.util.HashMap; - -import core.DatabaseManager; -import core.DatabaseTrackedObject; -import utils.AdminControl; -import utils.audio.AudioUtils; - -// Context for a given guild for kittybot. Primarily designed to hold guild-specific settings. -public class KittyGuild extends DatabaseTrackedObject -{ - // Variables - public final String uniqueID; - public KittyRating contentRating; - public KittyUser guildOwner; - public boolean polling; - public String poll; - public boolean raffling; - public int raffleCost; - public ArrayList hasVoted = new ArrayList(); - public ArrayList emoji = new ArrayList(); - public ArrayList choices = new ArrayList(); - public HashMap channels; - public AdminControl control; - public AudioUtils audio; - public ArrayList raffleUsersUnchosen = new ArrayList(); - public ArrayList raffleUsersChosen = new ArrayList(); - - // Database synced info - private final String roleListName = "guildRoles"; - public final KittyTrackedVector roleList; - - private final String beansName = "guildBeans"; - public final KittyTrackedLong beans; - - private String commandIndicator; - - private void registerTrackedObjects() - { - DatabaseManager.instance.globalRegister(roleList); - DatabaseManager.instance.globalRegister(beans); - } - - // Default content for a guild - public KittyGuild(String uniqueID, AdminControl adminControl, ArrayList emoji, AudioUtils audio, HashMap channels) - { - - super(uniqueID); - this.uniqueID = uniqueID; - roleList = new KittyTrackedVector(roleListName, uniqueID); - beans = new KittyTrackedLong(beansName, uniqueID); - registerTrackedObjects(); - - control = adminControl; - this.contentRating = KittyRating.Safe; - this.polling = false; - this.emoji = emoji; - this.audio = audio; - this.channels = channels; - setCommandIndicator("!"); - } - - // Explicit constructor - public KittyGuild(String commandIndicator, KittyRating contentRating, KittyUser guildOwner, String uniqueID, AudioUtils audio, HashMap channels) - { - super(uniqueID); - this.uniqueID = uniqueID; - roleList = new KittyTrackedVector(roleListName, uniqueID); - beans = new KittyTrackedLong(beansName, uniqueID); - registerTrackedObjects(); - - setCommandIndicator(commandIndicator); - this.contentRating = contentRating; - this.polling = false; - this.guildOwner = guildOwner; - this.audio = audio; - this.channels = channels; - } - - public String startPoll(String poll) - { - polling = true; - this.poll = poll; - return "Poll `" + poll + "` started! Don't forget to add choices with `!poll choice`~"; - } - - public String addChoiceToPoll(String choice) - { - choices.add(new KittyPoll(choice)); - return "Added `" + choice + "` to poll!"; - } - - public String endPoll() - { - choices.clear(); - hasVoted.clear(); - this.polling = false; - poll = null; - return "Poll ended!"; - } - - //Raffle methods - public boolean startRaffle(int beanCost) - { - if(raffling) - { - return false; - } - raffleCost = beanCost; - raffling = true; - return true; - } - - public boolean endRaffle() - { - if(raffling) - { - raffleCost = 0; - raffling = false; - raffleUsersChosen.removeAll(raffleUsersChosen); - raffleUsersUnchosen.removeAll(raffleUsersUnchosen); - return true; - } - return false; - } - - public boolean joinRaffle(KittyUser user) - { - if(!raffleUsersChosen.contains(user) && !raffleUsersUnchosen.contains(user) && user.getBeans() > raffleCost && raffling) - { - user.changeBeans(raffleCost); - raffleUsersUnchosen.add(user); - return true; - } - return false; - } - - public KittyUser chooseRaffleWinner() - { - if(!raffleUsersUnchosen.isEmpty()) - { - KittyUser chosen = raffleUsersUnchosen.get((int) (Math.random() * raffleUsersUnchosen.size())); - raffleUsersUnchosen.remove(chosen); - raffleUsersChosen.add(chosen); - return chosen; - } - return null; - } - - @Override - public String serialize() - { - return commandIndicator; - } - - @Override - public void deSerialzie(String string) - { - if(string == null || string.length() == 0) - setCommandIndicator("!"); - else - setCommandIndicator(string); - } - - public String getCommandIndicator() - { - return commandIndicator; - } - - public void setCommandIndicator(String newIndicator) - { - if(newIndicator != commandIndicator) - { - commandIndicator = newIndicator; - markDirty(); - } - } -} +package dataStructures; + +import java.util.ArrayList; +import java.util.HashMap; + +import core.DatabaseManager; +import core.DatabaseTrackedObject; +import utils.AdminControl; +import utils.audio.AudioUtils; + +// Context for a given guild for kittybot. Primarily designed to hold guild-specific settings. +public class KittyGuild extends DatabaseTrackedObject +{ + // Variables + public final String uniqueID; + public KittyRating contentRating; + public KittyUser guildOwner; + public boolean polling; + public String poll; + public boolean raffling; + public int raffleCost; + public ArrayList hasVoted = new ArrayList(); + public ArrayList emoji = new ArrayList(); + public ArrayList choices = new ArrayList(); + public HashMap channels; + public AdminControl control; + public AudioUtils audio; + public ArrayList raffleUsersUnchosen = new ArrayList(); + public ArrayList raffleUsersChosen = new ArrayList(); + + // Database synced info + private final String roleListName = "guildRoles"; + public final KittyTrackedVector roleList; + + private final String beansName = "guildBeans"; + public final KittyTrackedLong beans; + + private String commandIndicator; + + private void registerTrackedObjects() + { + DatabaseManager.instance.globalRegister(roleList); + DatabaseManager.instance.globalRegister(beans); + } + + // Default content for a guild + public KittyGuild(String uniqueID, AdminControl adminControl, ArrayList emoji, AudioUtils audio, HashMap channels) + { + + super(uniqueID); + this.uniqueID = uniqueID; + roleList = new KittyTrackedVector(roleListName, uniqueID); + beans = new KittyTrackedLong(beansName, uniqueID); + registerTrackedObjects(); + + control = adminControl; + this.contentRating = KittyRating.Safe; + this.polling = false; + this.emoji = emoji; + this.audio = audio; + this.channels = channels; + setCommandIndicator("!"); + } + + // Explicit constructor + public KittyGuild(String commandIndicator, KittyRating contentRating, KittyUser guildOwner, String uniqueID, AudioUtils audio, HashMap channels) + { + super(uniqueID); + this.uniqueID = uniqueID; + roleList = new KittyTrackedVector(roleListName, uniqueID); + beans = new KittyTrackedLong(beansName, uniqueID); + registerTrackedObjects(); + + setCommandIndicator(commandIndicator); + this.contentRating = contentRating; + this.polling = false; + this.guildOwner = guildOwner; + this.audio = audio; + this.channels = channels; + } + + public String startPoll(String poll) + { + polling = true; + this.poll = poll; + return "Poll `" + poll + "` started! Don't forget to add choices with `!poll choice`~"; + } + + public String addChoiceToPoll(String choice) + { + choices.add(new KittyPoll(choice)); + return "Added `" + choice + "` to poll!"; + } + + public String endPoll() + { + choices.clear(); + hasVoted.clear(); + this.polling = false; + poll = null; + return "Poll ended!"; + } + + //Raffle methods + public boolean startRaffle(int beanCost) + { + if(raffling) + { + return false; + } + raffleCost = beanCost; + raffling = true; + return true; + } + + public boolean endRaffle() + { + if(raffling) + { + raffleCost = 0; + raffling = false; + raffleUsersChosen.removeAll(raffleUsersChosen); + raffleUsersUnchosen.removeAll(raffleUsersUnchosen); + return true; + } + return false; + } + + public boolean joinRaffle(KittyUser user) + { + if(!raffleUsersChosen.contains(user) && !raffleUsersUnchosen.contains(user) && user.getBeans() > raffleCost && raffling) + { + user.changeBeans(-raffleCost); + raffleUsersUnchosen.add(user); + return true; + } + return false; + } + + public KittyUser chooseRaffleWinner() + { + if(!raffleUsersUnchosen.isEmpty()) + { + KittyUser chosen = raffleUsersUnchosen.get((int) (Math.random() * raffleUsersUnchosen.size())); + raffleUsersUnchosen.remove(chosen); + raffleUsersChosen.add(chosen); + return chosen; + } + return null; + } + + @Override + public String serialize() + { + return commandIndicator; + } + + @Override + public void deSerialzie(String string) + { + if(string == null || string.length() == 0) + setCommandIndicator("!"); + else + setCommandIndicator(string); + } + + public String getCommandIndicator() + { + return commandIndicator; + } + + public void setCommandIndicator(String newIndicator) + { + if(newIndicator != commandIndicator) + { + commandIndicator = newIndicator; + markDirty(); + } + } +} diff --git a/src/main/Main.java b/src/main/Main.java index 23e3b7d..3c937b8 100644 --- a/src/main/Main.java +++ b/src/main/Main.java @@ -1,135 +1,135 @@ -package main; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.security.auth.login.LoginException; - -import com.sedmelluq.discord.lavaplayer.player.AudioLoadResultHandler; -import com.sedmelluq.discord.lavaplayer.player.AudioPlayer; -import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager; -import com.sedmelluq.discord.lavaplayer.player.DefaultAudioPlayerManager; -import com.sedmelluq.discord.lavaplayer.source.AudioSourceManagers; -import com.sedmelluq.discord.lavaplayer.tools.FriendlyException; -import com.sedmelluq.discord.lavaplayer.track.AudioPlaylist; -import com.sedmelluq.discord.lavaplayer.track.AudioTrack; -import com.sedmelluq.discord.lavaplayer.track.playback.AudioFrame; - -import core.CharacterManager; -import core.CommandEnabler; -import core.CommandManager; -import core.DatabaseManager; -import core.ObjectBuilderFactory; -import core.RPManager; -import core.Stats; -import core.lua.PluginManager; -import dataStructures.KittyChannel; -import dataStructures.KittyCore; -import dataStructures.KittyGuild; -import dataStructures.KittyUser; -import dataStructures.Response; -import dataStructures.UserInput; -import net.dv8tion.jda.core.AccountType; -import net.dv8tion.jda.core.JDA; -import net.dv8tion.jda.core.JDABuilder; -import net.dv8tion.jda.core.audio.AudioSendHandler; -import net.dv8tion.jda.core.entities.Guild; -import net.dv8tion.jda.core.entities.TextChannel; -import net.dv8tion.jda.core.entities.VoiceChannel; -import net.dv8tion.jda.core.events.message.guild.GuildMessageReceivedEvent; -import net.dv8tion.jda.core.hooks.ListenerAdapter; -import net.dv8tion.jda.core.managers.AudioManager; -import offline.Ref; -import utils.GlobalLog; - -// http://www.slf4j.org/ - this JDA logging tool has been disabled by specifying NOP implementation. -// This is the application entry point, and bot startup location! - -@SuppressWarnings("unused") -public class Main extends ListenerAdapter -{ - // Variables and bot specific objects - private static KittyCore kittyCore; - private static DatabaseManager databaseManager; - private static CommandManager commandManager; - private static Stats stats; - private static RPManager rpManager; - private static PluginManager pluginManager; - private static CharacterManager charManager; - - - // Initialization and setup - public static void main(String[] args) throws InterruptedException, LoginException, Exception - { - // Factory startup. The ordering is intentional. - GlobalLog.initialize(); - databaseManager = ObjectBuilderFactory.constructDatabaseManager(); - commandManager = ObjectBuilderFactory.constructCommandManager(CommandEnabler.instance); // TODO: Untangle this singleton - stats = ObjectBuilderFactory.constructStats(commandManager); - charManager = new CharacterManager(); - rpManager = ObjectBuilderFactory.constructRPManager(); - pluginManager = ObjectBuilderFactory.constructPluginManager(); - - // Bot startup - kittyCore = ObjectBuilderFactory.constructKittyCore(); - } - - // When a message is sent in a server that kitty is in, this is what's called. - @Override - public void onGuildMessageReceived(GuildMessageReceivedEvent event) - { - // Tweak the event as necessary - if(!Superintendent.preProcessSetup(event, stats)) - return; - - // Factory objects - KittyUser user = ObjectBuilderFactory.extractUser(event); - KittyGuild guild = ObjectBuilderFactory.extractGuild(event); - KittyChannel channel = ObjectBuilderFactory.extractChannel(event); - - // Specialized uncached objects - Response response = new Response(event, kittyCore); - UserInput input = new UserInput(event, guild); - - // Tweak object construction as necessary - if(!Superintendent.postProcessSetup(event, user, guild, channel, response, input)) - return; - - // Track beans! - user.changeBeans(1); - - // RP logging system - RPManager.instance.addLine(channel, user, input); - - // Run any pre-emptive upkeep we need to - if(!Superintendent.perCommandUpkeepPre(pluginManager)) - return; - - // Attempt to spin up a command. If the command doesn't exist. - // Run plugins right before invoking the commands but after all other setup. - if(commandManager.invokeOnNewThread(guild, channel, user, input, response) == false) - { - List pluginOutput = pluginManager.runAll(input.message, user); - - if(pluginOutput != null && pluginOutput.size() > 0) - { - for(int i = 0; i < pluginOutput.size(); ++i) - { - if(pluginOutput.get(i).startsWith("!")) - { - commandManager.invokeOnNewThread(guild, channel, user, new UserInput(pluginOutput.get(i).substring(1), guild), response); - } - else - { - response.send(pluginOutput.get(i)); - } - } - } - } - - // Run any upkeep in post we need to - if(!Superintendent.perCommandUpkeepPost(kittyCore, databaseManager)) - return; - } +package main; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.security.auth.login.LoginException; + +import com.sedmelluq.discord.lavaplayer.player.AudioLoadResultHandler; +import com.sedmelluq.discord.lavaplayer.player.AudioPlayer; +import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager; +import com.sedmelluq.discord.lavaplayer.player.DefaultAudioPlayerManager; +import com.sedmelluq.discord.lavaplayer.source.AudioSourceManagers; +import com.sedmelluq.discord.lavaplayer.tools.FriendlyException; +import com.sedmelluq.discord.lavaplayer.track.AudioPlaylist; +import com.sedmelluq.discord.lavaplayer.track.AudioTrack; +import com.sedmelluq.discord.lavaplayer.track.playback.AudioFrame; + +import core.CharacterManager; +import core.CommandEnabler; +import core.CommandManager; +import core.DatabaseManager; +import core.ObjectBuilderFactory; +import core.RPManager; +import core.Stats; +import core.lua.PluginManager; +import dataStructures.KittyChannel; +import dataStructures.KittyCore; +import dataStructures.KittyGuild; +import dataStructures.KittyUser; +import dataStructures.Response; +import dataStructures.UserInput; +import net.dv8tion.jda.core.AccountType; +import net.dv8tion.jda.core.JDA; +import net.dv8tion.jda.core.JDABuilder; +import net.dv8tion.jda.core.audio.AudioSendHandler; +import net.dv8tion.jda.core.entities.Guild; +import net.dv8tion.jda.core.entities.TextChannel; +import net.dv8tion.jda.core.entities.VoiceChannel; +import net.dv8tion.jda.core.events.message.guild.GuildMessageReceivedEvent; +import net.dv8tion.jda.core.hooks.ListenerAdapter; +import net.dv8tion.jda.core.managers.AudioManager; +import offline.Ref; +import utils.GlobalLog; + +// http://www.slf4j.org/ - this JDA logging tool has been disabled by specifying NOP implementation. +// This is the application entry point, and bot startup location! + +@SuppressWarnings("unused") +public class Main extends ListenerAdapter +{ + // Variables and bot specific objects + private static KittyCore kittyCore; + private static DatabaseManager databaseManager; + private static CommandManager commandManager; + private static Stats stats; + private static RPManager rpManager; + private static PluginManager pluginManager; + private static CharacterManager charManager; + + + // Initialization and setup + public static void main(String[] args) throws InterruptedException, LoginException, Exception + { + // Factory startup. The ordering is intentional. + GlobalLog.initialize(); + databaseManager = ObjectBuilderFactory.constructDatabaseManager(); + commandManager = ObjectBuilderFactory.constructCommandManager(CommandEnabler.instance); // TODO: Untangle this singleton + stats = ObjectBuilderFactory.constructStats(commandManager); + charManager = new CharacterManager(); + rpManager = ObjectBuilderFactory.constructRPManager(); + pluginManager = ObjectBuilderFactory.constructPluginManager(); + + // Bot startup + kittyCore = ObjectBuilderFactory.constructKittyCore(); + } + + // When a message is sent in a server that kitty is in, this is what's called. + @Override + public void onGuildMessageReceived(GuildMessageReceivedEvent event) + { + // Tweak the event as necessary + if(!Superintendent.preProcessSetup(event, stats)) + return; + + // Factory objects + KittyUser user = ObjectBuilderFactory.extractUser(event); + KittyGuild guild = ObjectBuilderFactory.extractGuild(event); + KittyChannel channel = ObjectBuilderFactory.extractChannel(event); + + // Specialized uncached objects + Response response = new Response(event, kittyCore); + UserInput input = new UserInput(event, guild); + + // Tweak object construction as necessary + if(!Superintendent.postProcessSetup(event, user, guild, channel, response, input)) + return; + + // Track beans! + user.changeBeans(1); + + // RP logging system + RPManager.instance.addLine(channel, user, input); + + // Run any pre-emptive upkeep we need to + if(!Superintendent.perCommandUpkeepPre(pluginManager)) + return; + + // Attempt to spin up a command. If the command doesn't exist. + // Run plugins right before invoking the commands but after all other setup. + if(commandManager.invokeOnNewThread(guild, channel, user, input, response) == false) + { + List pluginOutput = pluginManager.runAll(input.message, user); + + if(pluginOutput != null && pluginOutput.size() > 0) + { + for(int i = 0; i < pluginOutput.size(); ++i) + { + if(pluginOutput.get(i).startsWith("!")) + { + commandManager.invokeOnNewThread(guild, channel, user, new UserInput(pluginOutput.get(i).substring(1), guild), response); + } + else + { + response.send(pluginOutput.get(i)); + } + } + } + } + + // Run any upkeep in post we need to + if(!Superintendent.perCommandUpkeepPost(kittyCore, databaseManager)) + return; + } } \ No newline at end of file diff --git a/src/network/NetworkSauceNAO.java b/src/network/NetworkSauceNAO.java index 080c25d..11504cc 100644 --- a/src/network/NetworkSauceNAO.java +++ b/src/network/NetworkSauceNAO.java @@ -1,48 +1,48 @@ -package network; - -import java.util.List; - -import com.google.gson.Gson; - -import offline.Ref; -import utils.HTTPUtils; - -public class NetworkSauceNAO -{ - private static final Gson jsonParser_ = new Gson(); - private static final String API_ROOT = "https://saucenao.com/search.php?db=999&output_type=2&numres=10&api_key=" + Ref.SauceNAOKey +"&url="; - NetworkE6 e6Sauce = new NetworkE6(); - private class SauceNAOResponseObject - { - List results; - } - - private class SauceNAOResult - { - SauceNAOData data; - } - - private class SauceNAOData - { - String [] ext_urls; - } - - public String getSauce(String input) - { - input = input.trim(); - input = input.replace("+", "%2B"); - input = input.replace(" ", "%20"); - - String res = HTTPUtils.sendGETRequest(API_ROOT + input); - - SauceNAOResponseObject sauce = jsonParser_.fromJson(res, SauceNAOResponseObject.class); - String sauceUrl = sauce.results.get(0).data.ext_urls[0]; - if(sauceUrl.startsWith("https://e621.net/post/show/")) - { - System.out.println("id:" + sauceUrl.substring(26)); - return e6Sauce.getE6("id:" + sauceUrl.substring(27)).toString(); - } - return sauce.results.get(0).data.ext_urls[0]; - } - -} +package network; + +import java.util.List; + +import com.google.gson.Gson; + +import offline.Ref; +import utils.HTTPUtils; + +public class NetworkSauceNAO +{ + private static final Gson jsonParser_ = new Gson(); + private static final String API_ROOT = "https://saucenao.com/search.php?db=999&output_type=2&numres=10&api_key=" + Ref.SauceNAOKey +"&url="; + NetworkE6 e6Sauce = new NetworkE6(); + private class SauceNAOResponseObject + { + List results; + } + + private class SauceNAOResult + { + SauceNAOData data; + } + + private class SauceNAOData + { + String [] ext_urls; + } + + public String getSauce(String input) + { + input = input.trim(); + input = input.replace("+", "%2B"); + input = input.replace(" ", "%20"); + + String res = HTTPUtils.sendGETRequest(API_ROOT + input); + + SauceNAOResponseObject sauce = jsonParser_.fromJson(res, SauceNAOResponseObject.class); + String sauceUrl = sauce.results.get(0).data.ext_urls[0]; + if(sauceUrl.startsWith("https://e621.net/post/show/")) + { + System.out.println("id:" + sauceUrl.substring(26)); + return e6Sauce.getE6("id:" + sauceUrl.substring(27)).toString(); + } + return sauce.results.get(0).data.ext_urls[0]; + } + +} diff --git a/src/utils/audio/AudioUtils.java b/src/utils/audio/AudioUtils.java index 7430926..18586f0 100644 --- a/src/utils/audio/AudioUtils.java +++ b/src/utils/audio/AudioUtils.java @@ -119,6 +119,16 @@ public class AudioUtils return null; } + public int getVolume(AudioPlayer player) + { + return player.getVolume(); + } + + public void changeVolume(AudioPlayer player, int newVol) + { + player.setVolume(newVol); + } + public String skipVideo(AudioPlayer player) { player.stopTrack(); @@ -152,6 +162,9 @@ class MusicController extends Thread @Override public void run() { + try { + Thread.sleep(5000); + } catch (InterruptedException e) {} AudioTrack nowPlaying = null; do { From 22f8e0b9dfee0fcf6140d3f17ce5e3cee853d43b Mon Sep 17 00:00:00 2001 From: Alex Stewart Date: Tue, 25 Feb 2020 21:07:51 -0500 Subject: [PATCH 3/7] =Fix for GetSauce Command Fixed issue #2 --- assets/config.csv | 1 + src/commands/general/CommandE6.java | 9 ++------- src/network/NetworkE6.java | 11 ++++++++--- src/network/NetworkSauceNAO.java | 3 ++- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/assets/config.csv b/assets/config.csv index 7007008..bdc348e 100644 --- a/assets/config.csv +++ b/assets/config.csv @@ -191,6 +191,7 @@ "Localized Strings","MusicInfo","" "Localized Strings","MusicVolChanged","Volume set to %s!" "Localized Strings","MusicVolCurrent","Volume is at %s!" +"Localized Strings","MusicVolOOB","" "Localized Strings","PerishInfo","Adds a red, 'a n g e r y' overlay to your icon or the icon of a friend you mentioned" "Localized Strings","PingInfo","Will respond with Pong!" "Localized Strings","PingResponse","Pong!" diff --git a/src/commands/general/CommandE6.java b/src/commands/general/CommandE6.java index cf31858..cfd5551 100644 --- a/src/commands/general/CommandE6.java +++ b/src/commands/general/CommandE6.java @@ -24,13 +24,8 @@ public class CommandE6 extends Command @Override public void onRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res) { - if(guild.contentRating == KittyRating.Filtered || !guild.channels.get(Long.getLong(channel.uniqueID)).mature) + if(guild.contentRating == KittyRating.Filtered) { - if(!guild.channels.get(Long.getLong(channel.uniqueID)).mature) - { - res.send("This channel is SFW only! Have some (probably) wholesome content ^^~"); - } - image = searcher.getE6(input.args + " rating:safe"); try { @@ -43,7 +38,7 @@ public class CommandE6 extends Command } try { - if(response.authorText == null) + if(response.bodyImageURL == null) { Exception e = new Exception(); throw e; diff --git a/src/network/NetworkE6.java b/src/network/NetworkE6.java index da8ebfa..1c65259 100644 --- a/src/network/NetworkE6.java +++ b/src/network/NetworkE6.java @@ -77,15 +77,20 @@ public class NetworkE6 } else { + for(int i = 0; i < imageObj.length; ++i) { + String [] TagsList = imageObj[i].tags.split(" "); blacklisted = false; for(int j = 0; j < blacklist.length; j++) { - if(imageObj[i].tags.contains(blacklist[j])) + for(int k = 0; k < TagsList.length; k ++) { - System.out.println("BLACKLISTED " + blacklist[j]); - blacklisted = true; + if(TagsList[k].equals(blacklist[j])) + { + System.out.println("BLACKLISTED " + blacklist[j]); + blacklisted = true; + } } } diff --git a/src/network/NetworkSauceNAO.java b/src/network/NetworkSauceNAO.java index 11504cc..38e6408 100644 --- a/src/network/NetworkSauceNAO.java +++ b/src/network/NetworkSauceNAO.java @@ -10,7 +10,7 @@ import utils.HTTPUtils; public class NetworkSauceNAO { private static final Gson jsonParser_ = new Gson(); - private static final String API_ROOT = "https://saucenao.com/search.php?db=999&output_type=2&numres=10&api_key=" + Ref.SauceNAOKey +"&url="; + private static final String API_ROOT = "https://saucenao.com/search.php?dbmask=268435456&output_type=2&numres=10&api_key=" + Ref.SauceNAOKey +"&url="; NetworkE6 e6Sauce = new NetworkE6(); private class SauceNAOResponseObject { @@ -40,6 +40,7 @@ public class NetworkSauceNAO if(sauceUrl.startsWith("https://e621.net/post/show/")) { System.out.println("id:" + sauceUrl.substring(26)); + System.out.println("HERE"); return e6Sauce.getE6("id:" + sauceUrl.substring(27)).toString(); } return sauce.results.get(0).data.ext_urls[0]; From dc56532ed0c87a143ed073b6a3e0a11c98087108 Mon Sep 17 00:00:00 2001 From: Matthew Cech Date: Tue, 25 Feb 2020 21:11:56 -0800 Subject: [PATCH 4/7] + Added additional checks for colors --- assets/config.csv | 1 + src/commands/general/CommandColor.java | 2 +- src/network/NetworkTheColorAPI.java | 15 ++++++++++++++- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/assets/config.csv b/assets/config.csv index 7007008..bdc348e 100644 --- a/assets/config.csv +++ b/assets/config.csv @@ -191,6 +191,7 @@ "Localized Strings","MusicInfo","" "Localized Strings","MusicVolChanged","Volume set to %s!" "Localized Strings","MusicVolCurrent","Volume is at %s!" +"Localized Strings","MusicVolOOB","" "Localized Strings","PerishInfo","Adds a red, 'a n g e r y' overlay to your icon or the icon of a friend you mentioned" "Localized Strings","PingInfo","Will respond with Pong!" "Localized Strings","PingResponse","Pong!" diff --git a/src/commands/general/CommandColor.java b/src/commands/general/CommandColor.java index d159bc0..6d2293b 100644 --- a/src/commands/general/CommandColor.java +++ b/src/commands/general/CommandColor.java @@ -32,7 +32,7 @@ public class CommandColor extends Command public void onRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res) { // First, try and parse out the color to make sure we can even get it. - ColorData colorData = theColorAPI.lookupHex(input.args.trim()); + ColorData colorData = theColorAPI.lookupHex(input.args); // Verify the color was even found if(colorData == null) diff --git a/src/network/NetworkTheColorAPI.java b/src/network/NetworkTheColorAPI.java index 07e9b35..76725b6 100644 --- a/src/network/NetworkTheColorAPI.java +++ b/src/network/NetworkTheColorAPI.java @@ -73,9 +73,22 @@ public class NetworkTheColorAPI public ColorData lookupHex(String hex) { + if(hex == null) + return null; + + hex = hex.replace("#", "").trim(); + int len = hex.length(); + + if(len == 0) + return null; + + // Verify we're either a full or half length color. Intermediate colors not supported. + // Alpha is also not supported. + if(len != 6 && len != 3) + return null; + try { - hex = hex.replace("#", "").trim(); String hexUpper = hex.toUpperCase(); // Verify the number is hex. From 02f9b09199cb185e48b4284fe64164f7be17d490 Mon Sep 17 00:00:00 2001 From: Alex Stewart Date: Wed, 26 Feb 2020 02:59:44 -0500 Subject: [PATCH 5/7] =Edited Bean Command to incorporate image --- assets/beans/BeansBG.png | Bin 0 -> 1117 bytes assets/beans/hunBean.png | Bin 0 -> 4352 bytes assets/beans/oneBean.png | Bin 0 -> 2636 bytes assets/beans/tenBean.png | Bin 0 -> 2265 bytes assets/beans/thouBean.png | Bin 0 -> 2341 bytes assets/fonts/B612Mono-Regular.ttf | Bin 0 -> 136716 bytes beanImage.png | Bin 0 -> 36160 bytes src/commands/general/CommandBeansShow.java | 96 ++++++++++++++++++++- 8 files changed, 94 insertions(+), 2 deletions(-) create mode 100644 assets/beans/BeansBG.png create mode 100644 assets/beans/hunBean.png create mode 100644 assets/beans/oneBean.png create mode 100644 assets/beans/tenBean.png create mode 100644 assets/beans/thouBean.png create mode 100644 assets/fonts/B612Mono-Regular.ttf create mode 100644 beanImage.png diff --git a/assets/beans/BeansBG.png b/assets/beans/BeansBG.png new file mode 100644 index 0000000000000000000000000000000000000000..ae1bd6daeef888b1d4616b7cc1fde0166825320d GIT binary patch literal 1117 zcmeAS@N?(olHy`uVBq!ia0y~yU;;9k7&zE~)R&4Yzkn2Hfk$L90|U1Z2s2)~Tla^7 zfra1G#WAE}&f9~Aj6fxa7JT*3WzSy#WR8N-5Eu=C5f%au%$YtgFy2i6*a7mmr>mdK II;Vst0E~YdA^-pY literal 0 HcmV?d00001 diff --git a/assets/beans/hunBean.png b/assets/beans/hunBean.png new file mode 100644 index 0000000000000000000000000000000000000000..824db9636775744d867de14f50dc5d422e325fe2 GIT binary patch literal 4352 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 LNkvXXu0mjfrfh+I literal 0 HcmV?d00001 diff --git a/assets/fonts/B612Mono-Regular.ttf b/assets/fonts/B612Mono-Regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..ec09c98060c0d771b1ba11f4703cf90da22f1c75 GIT binary patch literal 136716 zcmeEv349yXwfEeak>uT$C0Sl&%d#vl@+#Z%zQ#+uW^ zCv;~73BLrB-DvmX=$G5io#>Z#oWE9g=4@KO4lftk=FdMBSMV#XLd!`ZHm^<+ek?G7 z^_>*tGbaVC zDnOiI1AwvcaR@XH;HrA2+7LwzQEEffNg)Wxh{E64GZ-HYDv~)|xl$FgkNzQs%Z4D? z(i5W#(o5{js2{pB{ighq(u8f>5=u+*P5l@CqB;Bg_wp}wp9zUV3I-L{ezoxJBoR7_Et0{@|1qG*9Op)xF z_1?S~_KqRBbQ%^nu=pt`{}YVLD&z=tLXRNW9n8Z(fz*ACB2DPOBQ-)yq5*gctHt6g zxMJ^7@qwcwrA-T}6XUBEOl+E8otRL$z^RXMr#rJOdVNezdK&(+_b+#a?###p@4THI z?c3*+l+4-Q-m!C@mmPN0<|oCwE9?u?>Iw)*Id|_BT%=OYF^sud=nx7{3P!Ax1RRxl z8gZu(EvJkk?l5Wyqg4xHrg`>Q9j*vQ>y%HjGS`GGt07k+L|M#Mo6cG-726{~{R+;! zOujQRyRCBe#-FvfeQWOGqw8usljgWhu4J=o`tG^)OQ+UYCq?Gg^?38^GK?XzHG9H> zojtKhM*YY;H4}>_FD%TiFLXuu2F16!zCO6S^uBq8?zS5q?z`&tp$L?+B$7sMbi4YEh}0aAx3M2SOUTohUILwA6z3; zC_jatV19y}jRlQ$t3R#$4aQ%F-{EI~9Uahg(elqPFnKIyy}^O8{^EFZQ$=v7%&>Ud z9-UD*V{&`Cz}TOBv!!GDS|L+#;dVSClO6+JV-|w`gkOLxfYj%wvWF_ zv6wKcA&=oDH7t*LlbH*=#Q=;%GO1?Yf+;oBZ>HKh($UjIaMi$$xZ7zkH$h zM=dQcG`yB0Pu$*7H05^@=O-1mZ0?l!>ixlF76lESmXvO$x!a|G0qAU{cDBfXkm3XTe_~M<` z%o1Btab{e2W_xv!H99gbEZBkN`GO8~#3;ADExtV5uYUkNy9K=T zX7H5+!7I!=DU{-}EF7g+JqAd_EKcWoP`m+9qCk)Z=gLmwnS516P(LF^@f}slg6}*d zI0PMTh`_A{fbjOzTp7$q2EECUJu)~m;A*tx%2+b8xVQV(HQi;2u|<>D+};;}5Bk;x z#b!4ym{2vVJ}WL{G;FLJ7(Dh=Pw&Y`53Q;l4NF<&dvDpXxH@n0^369^m+#%Tb5V8P zq!pXD0XI+s zdPRWgq5;EZf&>JF0SW~KB7h3B10sy8DL>GFMHntfub(_X4{bw|}Cw{5yCb ze~yek@l*dwz?wQ8u_nQZL!=vC)>?lJ;Lp@biqzA*RRHw1_P~!d;IA4GO8`AXrgstW z8~##HvEAs!qGnbsz(25=<-6Zq!CoC?Gl!&?fA#Eho7e;9vo8%16+R72_kq6LLeEJd zC+`$QR1k1M*vAs|Ne#D!1$?uGT5T)*AqN4Zn(%!otcrX65b(NsgHJ(3a+w>mL5@>+`1$ z?cY4JuxiH9~z=^j<9%mnY z$2YH!ee><_Gq>+u<~}CJna^LlkKJMPZKfXo6_1;US;`Prl7v)NI?WWx?~_6__#6FA zJM#=K(f>)fmh`Gvyq}C7Cw0v^s;}wPkWLM!U{&bwA3ey3nTqCf<^<&86vb%n_uUdQkxfft@y{0pG!ZMqoc#? z*4#OL;jx>SG&_dGl+w<*1J$0nZMorQYl!&V5O8xBc=t}Mt!!a}u;--E2)M5nS_Ta%W7HV4sUdq*Lp(LaD-(o;C)DymXW&^9mf^GD zof$$rpYeFKm2f7{xcVa-uqahZCF4-#`!QB-PQch8gNF6<}_ni|*8 z+Me2T-*s&hcbpuUf5$*up1GiJ*ReO&N2Z00+{WY}LqtL2tg^1vO?KymtIA6j&1}@w ziY#Z!)i)oRx-KdyCOp6Yo|P-U_qAy?OLpC|r)R z>E4lC-I*J+Z+iH9uf2X%X3zA@R@=gXRj%c4e)rM6OKd>TAri;A#|{eQ!rJ6 zR6Y?2$O}w@pWX$4^*syJdWA?J5>1@<_koM=LhB$75$8j2E1iE9w5LG0axft&I-a{%fN=B7pn1|>KEO$3CiHUS_HfDWY6D&{a1=0>Ve zhGQa*nK+i>Fkq5WfhaRpFD|7A#NbHBQG%lh$8;Qva2SYe)&bawL&SYoz{JWW|%)nyVM>xOHE} z+7DiOaC3|9A^oC9esRO&ZMUp$aCfe%uN#<>ms-}2nYt5t_zMy=4)iP^m;rWdILPMX zwn7{L2M)i@@I{)rag+@~q73~)_P!Gw5 zku2z84)sv!nbuS2rqnZXo>5P^?8>D1%%n97wc(;3jqYK<%DK2(m$Z7sZ5Q>;mo&Z| zBn%6)V5t$w3(Ud{R{T>ew~tKj>=2(gf31A#xbJ}3>^pdzz48{uILu_}H{x@kGy@!a z@JV7U1{@OT3l;H`($vs2c|o;h=I*7F8!BsC^NQN@tua}Z&Q$^+hqYCGC*=vi_gVGanbGz$_pBCCPLc{b@RBB2}Wo|^cG0swx z(>*)eV6~eQO`$sG=sCEi=&Gp=`SC_)dH3pOTUma3SV76!3G)xHpH>{3R55e??I)OC z7i+Z@q?yCwoN?B)u!s=dkLou(^vcKAZv5cUg=S}wy+1B@=8m4;n`XMhf`UUG-Y!pE zM6|(hePmduF{k&YUSCLZc0v1`nXRT{EcX}N%NFfB`pn$LZ#+A+t|2luG2&28cGK45 z?|gQ{_WyY2u`LbfDNuhesEI+RNnH;E zX$FIv>hMbzLZK6dflPzJ95t&^BHEEgao2!_tgcs?u8 zm7CMKWWx^VJhuZ$wMkdhPACz#17*-ff`x|x0J&fYg76*=nIaqeAws#Pa#R5f zxWtT0%(%oXNOZ}a(2@Bik7~d%=)(wy1kM@YJ+KI`;P@#HewY8^NBG4~?(V~ai6(r< z1l+6Yf|9pnPMf``V(vE&ZJd@n{n2v|Uh_;#Z){0jNABitZ>+GDOzszYgBHaCaN(B=tc|=IS$-{GjOwRiJP`0nl{D$br$*ZKD| zw{Lvp>Zr7+bln*&Mb`PK@6V?W{Px7QsV-f}zVoS-3%2dqUEY1?4U1Y_q9}uoh|X6- ze~%Qloq{V$u}V*2)(xDZ$N_~l>bFA23`iRu@|gY+=?E$c@N1crmRh6xhRWArjcFY(bE z@QW}&Q3f(#!gy#;QG{aS^)|T-3MvC(U1yTs@6i;5oJ+_`0bN6Mm*lFs?1 z+io+D{1qYXx98nkQ&aD(XtJ*l$;nAQaIbju1@xNM@MeN5dm~Vqt?=+ z0S{@wVFl0$r1QLrgFoV|cDffs;LmE)fV~=UtpXT?e*tlQAICd5xJZ5w0Ke&G4LGa; zXEk7!2DEFywHy%YLWLth*kd@J!|^(fGdOfKvYFbzf2slRYZz!kkEd(hKcjR%6ds%~ z;V6!$aJ-D;$2fF-P{zDQgkoS9IhgSc+XrIm&qh9Z@K{Vm5*Ng9)&u=i>exk@C^SOTF zAsg}hZFs)Lka$vv$pbNRXQ%~h4;&7N;r^-=2!4*&8wh|W*n(w5a^hL=8?zuoUnR$F z1b5t$q6X9SwDQ-4zZ5&N`q!*#Ne4(;bv6YW#*nniOF2m!(JAtYDdc+tx}o-rQd=-p zCNK?7dxHc}%bzs>UJ9jUk8+JpSPozd4jvqdA|6as+n@n|B7hz-O>1##Er&FqNdxLJ zH~eCU2ABw-2X5DZ9ongBTFZkPFsPmSvj!~EPQ9!FRstv>vktNY zJ={WixP_pUDXT}l`?qv0J*JlcI`zKRvRhkNWg2jo20TIl-L+Y3Ii~@$H6VkQBVALb z0fz}7%!C0*!~x9cgxLUAC_g0OaR9s*BO1^_0A05Z3wbB4YI`fCTLnDaia?E3{LOYryB)sa=#pMYHjg2K<-+db?L^`B-Z)5I`?=X~1sn)KUWI zIge;9?`tjb1khbShk3`Z$v^~!14{@XoWBR)H#j)X`Dukt)$5jOH$0-;AOYz(r94!< zrV-1ZKlIxgfY^=F(nJ6a=_w6BOiHF;NB4B-gN*tMjDAasV7+k&}bVq8nf~l zv>Q#XQ053_1`}7#O;)c7+W8w5y2Fq6Kka8%QvN+>_3>#?wiFPU>`DH z#Q7~;tiOErte8$}I}_ltl&3@DMu{Q`Te3Hv#iRiP5Ne9d)I({fPY1ir|Be5iC}+90AV7I0KyHWpz@X_ z8f9+MfZu9Byat@pfQL1LJfzK!lK^@kaZ>(30|E5XYz=r(n;C}&{7M5X1klA~=WxKq z0dm%SroHu-8n9La7HPmf0%%|lYCU@}uvAoeov+dQ1P$0p@1VOvw6`W`fLjA{37~=f zK?B~@fHoK+{8X|A)NsJgkOs;riXj1%48Cvqj9=H+ov^*aK0B)KIw754_b^|}`6Wa~ z=c{~IG4`}{Cs7jRl`0vLl*O}D$>O1i56|KOZIB~95wxRtf5<4y;x;SK4-w&|vw4tk$+LJ=b6pnq^xm;$c1^OaYS!k%vq!;agA?*QR=2k-Yt4@j0o=K& zy?JR{enN=RyKvvJ?=M~Y{bTzUdPl?JhfN3eZkbh*KXvuBH&!(t+`DCVNkRAO>tMHw z&>RH$gpTBeLs+PUK`8BwomMncw4lr3-0G#(LV74!^-llDzaX#Y6rL)QVhiJ$Y)6|Q z!-gfFia)x|WJequ70ouVQ_nkWlY3{o9{tNu$K2Xf@9nAW*nF_rn3tau312B? z4p*(bbJk5yt%W2HB?$4aEsq0%o`mOIW^PoaM z126ghyMETbxrHgE zty6n4vl{H;qLIVonU5%5a`(ceLu;Ci86(HVsS!HS;=9q)b4^{@jM|*|FvT1HJ@Am_ z@Bo%jwu~3p2*u&WSk1r+)PM9Z6j;gOP^o|XaYSfwqbRSC8VZT>$jL!YVp@L5fS!ex z2?wG|VR|8%Q&8&aDfoW*vH=zjoDv-Z_KecAGi5uD`KverIiMAvg>+YFE)KY+oT*S~ z0c3BJ7C z-h6CDf$fa5slVp-ow_sU^LD?stD*bu_jibIK<1QRb!c(P@h7B@(BT2>WH^R#1PeXz z6fkmIN$_gP+^a=>48|{H`cX8MyU@pIB!P}SO9i7#lV-LcWk|W}DNSE%)_^h%@OxbRirZ79!O<%!G+>Jc+^iWgSsKu*0hF4>?@G7; zpi#6@3jxrp6rfQ9o+5zW^_~XAX}~KQuvr5tG+;X?eB7lYfS$ZTYx$uD_&$c_N`&x6b;`V z8u>^{7QbWm<-atU#(3*T zuMdRi`1(**1v2TBF|O4B$Rnj?uLeM2QCfbk0c1dO%<#2D_*|#8Jf;C3XuyEBgp3-{ zr~$_`-~$aXYoxYT0~!@Thnyk<+-fl9>3uV`)B7~waSa&INU}}?qBY>S29W*E2QZ)k zMh$pO13u6IGT8aWCJneo1Ijhv0}VLNfne}f=u$)m;=izz7knLW``TY;DP7V-V)6M$ zM>dN)r5^LhtN#ro-G>>U2iYGE+E@Adm>CV|b!1kMHUpzvb#s$tK)McJBWk|3(`tw8 z(%D^hWGy@84)ghGX0iCB?=QY}W~n@KwD(ginrL3bNI-(qdI0tD_Xp$sU{-j)&I+Z+ zg}_;{-5|XkGx8E!iv+KIVr9%3yjgyaUXPnLOZ(-!p=SmO3&^(tbaM@eyc%T5D>|_f zLL|+{fIcWWr!;0#9?>7lcw=-cWonNRR)MJlQXHHcFt2>~E546&+`j*KkG;B0+RvI- zuk<}5w!#G|^!v)>Cw%YX^|Vul!gV4gFaVEyJFV~Cy9qb{CO;v~25ux+Nz`fe?E%eD zk$XzU4it8;G<)zDuggy`w;3zzQRscsSDW0g=G~87UXr^R&&BU-0fLiHsyhBlV{!a%Bq?Ti@IWt=|h6# zjD}eYS9tn&PfM%vh`4NI^Q_p!2|Hihy62bo%?OS(A=8TS8JdC_ath5Sg>-Z{iEFTY zk00-QD)l{8F#2umz%C9YK^J+l7!d8<2v-zsp1nY34Bvi=M7j&+T>8|tXW6u!eFb@a zduA8S?evDVL{|1)Kkd5L_IGvc|IxP1->;EYIovfXZtI$I=<0@8yFKKV@a!zxf(L)R zcFFe#XO$5TzXLPVgPDm!zc(rUjz-_pF*6C6iv;dFq|EPVw2+ode<=$%8r@9ev*e;# zO2tiN2J?}|&`4uwmehto;*Vk)6aPby5RV7}gjL3OkE+9rW1w#TKGO<@4I5VRce4kV zmwTozDbAbLQf{7}wz0E!Xk$~~&`+;DdcrI{*0_FX*34bKIVt&NapLCl)9zmrn^m{- zjeQ&6IxS>svG?8q9hZ&gRfKT)kY+P-h4kbO2JxeZH+AcwSzX0c*3i0}9 znYOuM_Vot4Mgb-*Wi%2DDI~eIcVz>purkRzb>+^k72n)kFUuoA`BT@_*UqZRiZtYO zEG%tU*y0YUcxGEliOVwQ-q%+*@7=nhGpA|mx0WTh+B>#iRbom^iD37-%jPy`WH(Go zyE+B^JP3KVNk19A>^%kb2!a+kI)y~QU~*tVYS=JtvWOD!*GjoXl`G+kVPMl!A^(nQnhAeO`j z8?Zsu1{;muCPWhDlMJfolS`7Y9+RuAniAd?11yxFjlT=!2FMTndwMCUM&bPJ01`Fe z96v>fS12aG0B0@Wn(S()A`2+N7JMQmnH5_V3!Rc}k&l8@O{5WGw~SHEzNLI9g`-Hf z_5|DWYh6|Am-jX}+xNV<-r1ad)rs28PhQ=%AuBe^I6uN3ojfJKdd1}2cxUpAvdXy= zi|tXx(^r*wCe;?0Z(5~~2oKI^U3}eb9qUdXnWYcC^?viYUGpEizBMB@BE_^S)Epcc z>zT1(f;7*bXmzF6c3(9wr~9_W88_)i>hpZL6M;VC8?G#=h=WH#KsHxjih*(IU$laR+SJj7LcF1 zBgDXNf<&0b-GPNd&A%_ z*Fy_Tz`7B%q5*!cZS)!(E;~vyIK&@@+X|fpeXRw0m%eD)K>hqp6Ra8gUNN)JUwZXb zc5~5;+O#N3w0KyGjkC~hZBbX5F~s%{qvnNfBqV0zzT0;nt4>7qRAC@_OlI-VW02tW7@Pb;l-9Zu6bDW=4M2MM5O z{Y3+KWQ!i!qP4uI0XGvsr?Rw`*EC?3cFL(4`Ar(IO9M&?pm%N3fMD%Z7H=UFyIZmF zb^c5yZUIs%6Tfv4KYd|N(>vy2w(H+~JDz-!{rm5I(Yk#n%;)E@!@fl|l_Rf+IV10Y ze!hbh*RHR{iW3-LUWz-CZ#qy*CiwWm`Y&^8equ&Lu`8@GsIX&kb??QmZh=7c{fS#mPX^N(k{MO0(T)OQGDuhh|3ps{ zg>IEk-&jeAnP36$v339F$XUyp+}c9G_xgo4Qwi{c#7M)Hl!7uvounoR^0 zIkn;q8ZfEcpLTU1HISSdq{tJ;;Ap!9uE0}IR7Dpw&8_RYz9;X5qk2ki{>=6&GcfSI zbz$+A2zAhZDCzXX#yYbp2WvlOc@y+D+F>=DvcnZGZ3afE1Dhga&WsmhS0qMC%9V{n zkvN}8L%QT}sH;%Pa0hua9f}2tsFS9XP~bqT0HeuE@#fXf>}qS-aq8;TPi=2$+;;MX z)YkRWCarIGIy*K^>$+y5!`O4z>CKzoyraAOjyE@LK7Ch@m^}H&miGEp`&uU-+1ysY zaxcd7wl7THiaCpdCVCy|8;Tw4M1PGKj}bCY(X5Gwr=gW1j-*W_sj|-~Bw@lZG81l% z#leIBWXq~H2Ifa`GAQOmD5iwZ7p0Jp@Wj3d&LN%J<_$6t4Tu_BM%hW(%*b{UkvGC2r&u+d#3|N^YZN1qB1qUD4#mNONmq0J z5QiLXc32dnLsg@olo}nE+IA?{4qk-{-bCa^rR_kBza{^=UmV{RLTADk4LFavos3pkq4_lncnlu@ES>?|NZ0)H#`=qhl9 z1Hw8HD^Kyxc;Hr7?5-NMO_}Uw!a*S($`k5|#%oE(t{r7ZCs9L^Vs6&*Ij6XE5}*to zmyV>r{I!K>GxD|~P(}uCBjsP)c&<@|tnF?BLr_&6@+Qc@oW>ul(u=0z`mUU+wY}bw zo>c=&(%l{9_QLLg>$X*-E?hb%zCN~d`s9S#RB&Z6nd2bQ?X+H#^N?|x!#(Sn`{ zW@&q{)f66Z7aSeEk04!BnNHGdGc^t&cg?AzWblc;Q!@MPl02ogS4f8We+LKiv z32);!Jw^bYOqR5b;@7zRW3E7u-tb#Zl{lvWI)PHG_u&xNjMcE=IV{F*2ZLR#h)l{( z%$q%_+SnM}xO7KL@5=IM-v{tkvX9KZVz!ZleoRu5VN+11+fG7XOdNV^weN)?E>nTm z9==L%RuKk{41cN0ek9<}!` zb3-SVhuV_NZP(sEUA)&k(pk5p)n(5sQrGV94TTeEZvLBJ+e0q#PK23gM zC6bA8kOjf%Cg8^AeFVNp^W@Poh!$wLd_CtE1f#l(my+A$Zr?3G^4 zN1}ct={LU--{dq5{pAVt!zjE%*i?`v;oV9km}Gc3eubeYloyVTQ@{>+X_N>Ey%8H9 zd0Pn1lHyOXDrD+%D9YbvRIkIlM2(&o)i?|=QZ>*LXb4P{ih_Vwha%6|8Ny$MeJUyx zsX`!TYXb91j!+5i+yv1hO{faJ@&5O3-%(n!{q~>Szs2(4U2OkZ)+(;RWU<-o0OGax z6MAm&Jth7e&t3-Xd;{2t6xU&vzA#2h$`^d6M0Y_LpPyTfv6)5(k|@xs^xoiyDCA0Q z%2LFTl{I}>1OAT&N!{FF(;*GmfMBE=)p}oPrAMgt+&vnwmclOdbY5qP0AwvFTyQh!l%IME ziU0@xtO3|HuC#2?fV(vS`B};-e@xUL0X;!XiC*DP3}2+R9MyoIYQSL)$l(An-dlNJ z{h?5vrHWAKi@x9HeXzbdF0~} zVwn&4QskRKzwyEj%1cqiP&|AU0{EQb4^%uowDpVjGf{~M+7Cyu94&8(u80K>uqxb$ zI4V&%=SHdvJ+N3+HXCRN_@ap?c^P?E(>3>nmq+)8S@;Rx3R`2(%BIpeSrhdpYeGa? zg(utWTlzc;Dq<_d56$Opn|5@^WOv#+eN<$KXG(veyu~~c_8W}x+gPJ><#tTPZs6@> zKBHKKes@%WVJa#)E=ty>9Ys}?`TtY{-qe8O8gLr{G?Tmql9IeSN>0Xw0Yj3Uf?>>mYp%ipDW2oT#$WR9H;g5W?WgDVuwE{FO zs-jwpgHTO69aVITq2HLDXg*J*)8zufK#OpK&qW}|gEUa1kjvR(Ej0OP&Q46&9bTo? zIG`M@Y)l4@-HA<6C6&&{p#WLj!Wb#dV(4QXNd z6}F7{(6F?IlJK}XQ;j9lQ&bq$x zPnSGalF-~e*YjD$>^i3$6}lzF7;dOqaiIG%@66f^ut2KYI3Pa9qjXuPfEKN?8_9Hd z-4yY}M;q{Ef=w08CR$Eb4QJa=r zoMj7UAC+D+yF9^_=Sr~URoJ4cw=SyXzha#E@l^E~l&}KU4ONMSPG%ibt(fh7`&THw z5g+GHF=<6Od;@Zx<=n4zSF2Tul~TrbH`v=*RM4HG%fM9D33E;g^%z1t^vXCsRPTHlCm54?^tC$~HzhrCfnPoTukGbrjx1`n;t8t!~y7An$V;QoJOHA9sR z)Zn1lFiQ23MWa|TWDpihN3+1*KiH|H0{9hqf(F4T=mkJmbMTSj-E#!>Q1f0e`tp3c92~E!@4pd^BlYbSV}8p{b0-DJ0n7 z6ooD5269x9lL`rIXpM)VW3m^!V6cz`@*>p)!!l4=8n6<3Kiiw=`x;C2efxEm(q&^v zKKV9t`1U8Ty}osC`__r+S9u4;J(PU%Yq5A_{b0#llxb%BL1n*02F9zvVXH7#n1o&t zqu~V9Oa#jb+qqQwjnnGhP)HoIQ`}r6u`G$_i#QxbiyZFPYz&*IZ-H ziAzbV$xSF(bZE}hn;R-GJl|54m7lDfK6urXJq^A(XI4UPOl^;V`& zs4k1oF~%nMRyrH2OXG7Q;HhG6omtw!V=p8s5E60XVD8~zgl2{j>KI0T3aX}vb=XV) z3HMfZ;5xM)nU<|#8kOl!enpcXru9hGX-zzny!RR#z_F*EMPH(#onO z`#v=_7H2i&#>M6~=Emo{67^|8w%ppRYE-vKZ&_SdH7`Z?3Ee*b*!8Wg*B_ftk2(J+ zZtUvXx3rQTL=O~WqRdJ8bq;5PCpk1SQm)aPOc6P)bBl9lOvsFfvrZCj6rU4O;tWs$ zbYQA2LrFpo%4lC(i5CbXa_!Fxj<+R8q_WQc6FQCYKt*g7vXE6WqBI+?LQ_ zi!Cq3XwZpzsUbMn5Sm=tng97?l!?MZtm%m{&V zr@-L2D@K--{5|7v)cK84$~(T-9{KJN*w+QLS1WX00rgqbohUJU^F=b%tH)u1CZ=W2 zT$Tc**04}}T3Tf9ETf|+weX&%_wg^Kxw1cp<`e#OiB8ZW%>BZ8UG>2@L39N)8+GX`q}a(=9$XGC_A{km9l* zOK(X`U6B)L`iQra-#2~;;Y?+ia4XDTepi_AH3A||i7Af>vzB<{(`gpByuTuWMTbX3Un z>5aK%Qm`@nyS^v&wbAE&nQ-%(Y%a4jD|$q%oK|EF4kDbLf=1X0swJlzvN2T6izm4l z9pd`dW!Wv$^CG8hKhnb9dt}!m;!U#6;^`1RHFRhB&wi7Ze!AkA}Kef zle=sIRI0vPa<#*v#~LA>2pLqQtCN?FjK+sjfCjHdYh=7rm(PnpWReRywOLEwyg;T%)rhE2APk zI@(p4l>zTO#LroG`;w}v#qC*H?Tf3bmbANBR7PiYy4~C4%E|X|y-z~cJTXev zkk>+l?0|Fux=40V1t>)sqg-HRn;7K+LmB~@WPXR@dP?_Jl67eV6=|0tEH0OE5#cL{5`d5`Z@q4a717MJez_20zom6gnKop14|AJp$ReOH0& z^g$1YPHd$@g#?&g55EB&S zKN@ZT*1~~_ufaR|zgkm|(v(!v4iv6>7Fq%31+#K-$vqSNzn3Vx7mozrv8DIKAWHcK zU0gWE2mZIm2u>0Kp+OtS)a5*y)r?6ULc^G0Lxfyn*dZiT##9`Xib%{{IO-VT(Es+R zm6@f$`e^Zl!O@mW1TZf-yYz($hv`yN{OiGfn{DCX6T@Q%EGFJLqvtLbJ8G_bIX&n6 z<7-5!*)EhGpn2rD5q^o;^c|3s3#!vx6RIndEh#Y((p<^zX>_Gj*Va3tldMtlB}QJ8 z(O&LIOii>Tr$@`~DK+Vd_Qa_8WGFeZO7%hN%C`Iy;6k z+SAi(drEla&Vte2CzCzL(BrI|UQjT@o?tw?f*15OZ#Tx;XB5zbP)&jt_he7u16rDE zihocGTt5k)M)E>aF(KhspfZHTynj$M)l!6#(PfZyUh~L~DBn*H|CGJxmV$kAVpyZ^ zRLBoAi-%AR>MS-GnumwJ>-#GeCuC2vbHDo|(m){bdVNdfHIT-wcs5c^^oB2z_`nIm z?c-IyT!ZSD9+Slweo3Xk5|{4ixst+|`1Y11_LAyDVuB$w=?bc5o&dS7h75`X&W8TM zl_M2>i?b|MJ?1Pc8X`$e^|`39B<(O6Q(Tg5fJC~m!lZ79OCwRKlBtgNU;e?Pg=mU` zXu|h0NHmdCosT>qiq(d|2inF~)+GC8ECPZdn=V9v{&kW|qsJdBJn#=5zcSnYY+f}A z#%J7w8IR>c>f%zO%%O^@F{2jknv}Y5=(-c5B$Pt!R4B>>gYKWNQYvLulS6LI=o|`< zzHn&zCB&aa>`E2nMWAZ3uwPKnI$rHdvRhDJ28#JVsP?52_qa$2BU2zuO=%;aoK_l> z*7uJtD32*-kh-bW$iyx!(lRf^0CF(MZ2PCh0M>mN)_u6L?)@tGnC}k+LXpZoJU>#f z<}XAFdz^bX)WV@+zOvR8s@MUlFbglixA6ryA^*ld0af_(i~=PPsa!^wVCKBwLdsD2 zz=fC)|5IZE0U8;tp(;38!B>h&xK9aoj7KRH>iCCZ<-&Q#=lVErxNyYBG|#<%_7$E0 z=b1d+&&h!@6;kY&uiU^cSheB*SJwJ}t+Lj5#?i$U zw?=XB-^IneC0Wmu@CZ6ml58|2ybdbpy<}+(Z{{l4@oM_(RJ*Mx^8_-ixrdS~E3u?Xee zp~RsA70)OO|H>+!@vUu~3y&xF0&F?3savUdrfi(xH>=xlI4ep(09h$Fap{6+E^@Gp zDT?+Wx536MjMlH(WTQv@=s#xE5Mprw3#*{@@%%bjbr{EB?KB44RbQ4Ys+84tu-@f>U{Kw#C0+w(D{N_~g| zzAuz=k$Lz7X>3N9u}IrWN1wp*e+o-yd9X)vlRVAYYq1snQW-jEzcY$vL;!DEGX$ zJU$~nJR&hG(OOVipB4Bz)(yv3=JRi34c>TnQcXW14UYnUR1KOc1R?zVH`E9sRsCsD*?L(SY z#X8ebU>McQl(ZYlr`Dv9#o)EeA4qzG>`RHsnUIrSoomx?iz{xK+fdxwTo4|WT|K>` zZBuuSyK7BjS#_jQmaU#VdriD8z9p+5YoIQxKHnZ3oK-ucWW~QJIL~W}PYj-GE6%XmOWU%t+Dh%b7~IXX za`55IkW{4{Txi%Xb5w*iF1s{2ximYja{cj-Wm(eq4Nx_>jJPBx8_u1Ibb*@5St}DL zGW-Z4!;^tG6n72emutr96-0{FiVZPV=?|BxhgNHiGe%xAQf!Ku(!B5sOQl8XBy0R7 zL&Wj1A*qFdI%<+qTMW{dYKxT!C#eGV=;~rr2m7m47YkI%{yS6`qoQZ3rc^?DP>G_( z77HF;iwZ$fKY@O6@i87f{!#_Vm|A9%}GV!<8c&-*a$$xoU4ef!gvVa4k(y{e7cxT_HS2{?gG@OdjU1M#TZY z^WTk%OEnyi_D7chw^U)`%8?t0ihntBKBOs9Ujol!xu!fpsw%iXqjHRLsz_LI0k)|| z##h63rQgQ;J7D|DQR$Dse<@6MD>}-TK%+E8iPI_d)@a9;jpXfx9?fDS)hi<>%q7dM z^;5Mq4_MNr%B^{ALz*Y%3f@7>bNqKuLdiJqP@EiE-8dSDW4v+r9SP&V=uwRz$9dam zZ-Q2-jxd)x-aEDF9RHP}!^6G-Oy4Cc)&YgID+-o9>K!4TTBrLNJb0B<1Be{^6t1oU zeFtj%U2&DFY9j9c;VM(bS$q|4YE*n)lO>Q?NTajgk_(-s=#CP+T2dzDS! z)up<*w8fC>=3cJy6|bFp@s1Ym1{quVN~x*E-6Po~pRyITAPaSKvbA8#7Z%3i!M)2C z$9fpc?eYb(#NR7EfD1>DudMt}jUJ*q1EM=q5#6-cons=CFp)V*bZ1aQh9bHVefnaA z5Kp))LOus?xI9ASSXDZY#z?+!y^@(g^g#Itm!k)sf$*j1f!FFHkEiM~gU<3SNCP{V zuaG9R0NiEq5T~)O%OeAySXYy#we|5czCN0%GF*$gKB(I3B6I@(xIl?K;SmBHv}C!1gR zr&K5NeWR#>*Bf+hd^ak(L#a9F-1eT)+@{nWl-}Vr2Rqv<#Y3^a_Q^-8*vJyAT7OXW z6el7l{b41NpzIDDUEzu%3SU&=DwTHd{rxIjDM2pIcvFbarYIsP8OTiG>}K2oSkUmK z`!8Jt>oy1+h~9AvVM#mGc-z~fFmmdj1S1ejNf1jmMJ!QC7LFaY!gL_Qp;o`+7Ug(I zqU@3JkmUOdq|g^(Nq$0&#RahB6dqG*#gC<%^vlqV>wki7{8bK|L_1D}c2Yn)N=fzc z&|=ga>f_-?lS^NO9_h}2L{czx2AXaP>^fAB<8>)9ix*apqe`D&w6@a!zBr=2yqB&X zr}>!28~@023LE~S@ykyT14i{f)OtFA{UeG^u|ui%%HY4K{*!KoYU3n*{wa3Pe1g&A<2%p}>9dBkfyJtPRD}|=4fFwZUhY9uznbP1 zv#gZF3QvxJ!ysmAV;EbT`>Vvc9Jdzyxx z_x*+T*9-gbCi@@pp-wXW(a zvW0~t7Iv&`E3Qimlfq)s%QK4WT@g{4jqGC2!8hXTVQ<^;kc1 zVo7^`Zd-|sNrh8ZU3*h~>GjvGol$hYySo3nn)I1HldGMLOSgF2Zdp~&-kaoiD-#~R z4x95mLlE}PMhMaW|2s@d1+o9vzr*BTxqqdSINJA^d`~Is^y2R_$<2IiGU0mPWcd}W zO^-lj)XqUH@Oo;q2%w67k7z9%SVQISTD5aCHK0Yis1YKW-!@GH8d1=VcCj;foTLaH zMR@!L=1dN+$I5FN@y}dPM8_b>nHi5}9gK)e&Z_OLb$APMV)H^0Y__n%s`Qx9+y0pG zNZzEV($;QwTx~;Ld|Xa_QblLj6shuX>4>pp@vL@laxhW^ZVZYFGZeJV$`YSGT*e;n z-qh}p!{cIZONuM2^3B20XEpLm(g6GiLHJ@0vg#7$JEC>E&(dx2 zSy}P6^zewhvhqBeEw8LJKLQnd82f|HES}^wL(&ukh*UL!oJYL(f%+jB$r-#E_6hsL ztFNM#5ByeanY=@4MBJ0xPE`9qL0}weKT%01C8r3DWFMK)NVTbL^q9-UIK>&4iB#(6 zUqQ%`v71q$VHGA1J2&lAatA4WR6!5bzUY?{Xr!OwzNA>Qz1*2p5t|s_oSyCMD|CZ( z#z#e4Z7B&2_N;tUXn1sgyvdl5Qr7OyXhB&8!rpeBNBVDlJg8e3&%R~bFJryx#U7dGPq zHDZ^l`sEHDO@-*iSH#|xtp)DT*wE0hNyet?MH{N3eLE^o@W!~1u+T}y#wzJ?v-H%+ zn?-Y4vSd+`wgy}I7dIT=IRAWpjmtHTJ6D8 zIeOFA%4o)?*)ShZ_|CIO zgkJ*7DlhO?P@&;-eqbT%!9uxV`32rl{sJX9Uz{sFamns49k=(QfVq`Q`P_Oy<)jRc zgBsnJz!w4sUkZ&$<8@FJo{%1s%5(>S6^{_D@JM23@i@{hsvP6Tg7eBzGfq!+eDnDw zCj5(f>N_u$@%i)67uGJQfpdu&g!!xt0!Sz0Ia8ZtwUXlall-?2Z#;q+cXU)+X+Sy; zDi0OrD_;v$zK$qEq|lxohQGmN75XdR2EH4p60a)E0)>~kg&!(EUQTVIJ-)Q_bjUELVSE!m;jJ>b^(J(h3 z5&h9dHS+M_$opdYAb2ukx3crn`;aF1aMQ(}LUwE3q~(>B%O~aKb}g%{TroLca#b$x z%FF9Q>&hwl`BPSsh2exe`WeGMC|)P$>5C|mkN<+IOyqL4k@`Vp`1xtI(iJF?hal)P z2RQ9_yL*Wnq53mFt&qFoxTRF&3>^G&Qt9Z4{@VgC9rGHsA@JY}*&GSd(Zqkr-|;yW zsk~T}8-J^E;@Qc|w+voXT}pXCP9;4cAt9&g;@{wu__l!|2s*n7_H+&^ruGQSg>Brj zzN8sGwQ0#UZK}FEvQb6uUas%X?}HLLgfOdKE|Ey%(Ce9F*)gJ z_(<;R-H1ckdNkL~>QAmk#slR31CHqGFBIqt|Ga<1?%tuo;NPw^MMW<_BQ#eNV^=xp7i1(FaA(O7d3H}LX^m$ zGuZVY2egP$EVJuVW98JP)f4yDbtG2L+A(kXUDwY|df;}wwEw}_-mPDsv*qQMn&j%% zndPO+rj;7X*=wD?GLeZ%;@&$Z?dbCqrfnq&+p*_6Ywjqoa%B##{?4ARw#H2{X>s9Y zi*D(54w_7^m~87ziiQio$P=(h49Mk2Z4O7V9W@x?9fF6}1vaKwOh%Zre;Srj3UAD~ zv9N#N#*B=O`=lMBrJ-Tu-^KDreeW{&qa!biGtLeUo*j7@Sm=kp;~2Mb1sI&X&K$3w zVq?+d_(9!VkHubGjn9`TsqBE5+ib_xAIFRD^|SZ`}DzC58tvh@z%WSj^-8lx5J2K3S2|kK8{0$5pUSWmFU+!_L2$t-N1Kx#|=_+7(q) zH!-bkVRgJdG9k0fRo&N+n-u-Sn1YUhLsu<1G{;@D?3RxD#hqp5w5hx1)$FV*No?+% z>OvVNtGGGVZ8zt1Z|RD!sxEgYxLfD19C&&1x4(7&mWeGJ4o}_r)av|rSFUCEC*SNh zIi^OZ#76jT1qLU4{(Jc)$h|O_^(vzbd@A7-%q-=L#UM+V`7mu=^mPjcgZ9y3-^+j4 z+40Qkv^1vInFr11dd*_`u-TXO*=N#kASukkXZT(PeZQ(2Ub)pusDl#msBT^)ubbxq z^nclV6Zojga}RjlbIxS4CzF}UWSu25lgT!dbu!uajUp_4|GmC-cl%-hFxA zXZb%Zgq!y~Ae=cst5aB@U{H36ilK2MQAMD}fuax?b_wX?Ih_9#Di?1SL0$43tSMy* z#l@=V9d3NiVNi~SWs->>!bRe&B%fHN9-&yQKxCH|Q*;VzD{Rh9iZG@YG#6&(#i&Cq zMQm!+9lLthRv9&h)SAB9iWyB6)}V_nRnHt>!5q?y(P^Vz+*;DPz?I!I&XqQ9c0s{{ zwyc*{&R^5C{^%s{;#reQZP`;-SL;^IUDve!?uqi1+^&u6?XfRWSNuZk61HG$(GkJV zj>?eoRC;pLkl1NIDlr{`%b17jxClr-QqaelA~NEoi#OIz0=B#m9py-L#|b^7pw3x9 zXs~&C`}y5;O&!1OUh!s!;O2led zTlxvFOl*Vuv?MoDV9PN-Wyj2XuOXc0uW-5BR#xcA&5bjoRwli>sNR(~t+mNnI=@8v z@r8HU=dsBd$*~a$sd0S?IZmUe!c*vxDDmAZ-9c+(I`bc4EQ4FpSt&rbE|&+_MWMoZ zo6a`KVv2w}def493zf zNag?-1jG4R1xX0S!z|nerhpTnk z{MzrRw?>$ISKfa9DgGe}ReMZ|VJk#uW}rcsDhDg&@qiBaZw{vqQPh~!DaxQ80ZJu9 zH%ZLnH`e98V`*|t>H75tN{;oVo_J3=qZmlh_OJ-VJhWw%+JJ~}P_Hp1pcqoPT$JIK znR$VcF_D%fQ^bcFwl|0mQ(PpqAgI>`>Y_rcC>SF8Y`1EikSs*OQY@d4!JM>!z{Avu zI0JIoD@RmySGr1Q|dv?GPFdl)*FFn!A5Pa;kOSZ)-25b zb<@M#+pX-E%X_Amem~eZs}*y0K4$O#Nb=N3tZ(oG0k1v!O=d%c0jo!6otKm>>sq@PWreUw_^woH9pR)?8|lV2%hmf`F8aWz<{Aq6GDG3L zbI*-#P2rX=Gc+V_1Nt-dhvW>2ST2anN?Q}QM@b-$wU1$(fLR46hv5po0dA0kCi9f8 zY1VsK#H;-Uvv0fqg+B59L3a4e8U5|w+1BI;jB>ZEJ+Um(9+}KfWlw&e7kJk4p!nD4 z_x<*%8z(ur7l2my<0HObmCU|z$1O#Z4{n~K!=gEG21nKA)i7ijH4Kx%j5e+m=?=FZ4{ z%1&++Z$<35Td!viic_vm2p~J2^+ZW!5aVb`IqM%v@m= zJl3IkWFNZ1Yt46rb9!AT;90@qm`5< z7};E+pgcu}H8Qeb99E2Im5t)TN}lGD%?QO7p@8qfDh()-uf<^G=-(zGwS;^~FtwMF zfBTE(hXR8D2~Qyz1dB&9I#4l^tFsAL2r7^=!GI)@S}u_PO~8hbm}mrmwIS|}auTpT z_1>U+ZeLejYDDIghMXIEjtvgJIBsFBHEqJOTJ?LcMLEm6*S8dHT-j%fv53pmx&yvP za;L4UFPl|uLoMkvSfc&|8|a{k2aTfm6Uc>rGTh$WHS~JDT{PEan-|#w;k0b=LbB#BvUoA0 z`TwshULZz{$G}OD2gh)z&k@uL|G@Ca4w6j9E*}$3@@cq=eT*GL`ipI2{B~n^00Vy) zc(Z6(cL&zhf8GR}1MCr+Goz#u)XA(Tr);_sWO>E1o{GFdzG!T$W%Xyi^XUocN~Gm< zvs(<(EFQ`k8*mx@^lgm2B?!%xk8|1{88e2W(Gg}0%_ch<484b*aY@t&PRt0pg}>=? zXu9W+P?kj0JYJ)asAfb09iTExGfP_CFF}4Pqg2Xh(a6d!XTyhW1kNdg z=OZ0t{bo3D{|rYf;TW#y(!brMuWapfmt8-nykyp8JY5(s_sht-b1l(;9ZLW3LtiN@u=pFLzrJFC;D?p&lF|nY2In^-ahG26ln^QWA zWsvbIXQ%I*N^YoJ_5FLMPba92#S`4FmicQomp{97_K`&ec{8@R-M650O;2Iz%r%8c zA*Ti$YrM$PMYHE&N4NDcKdK!fs!mh1R z6^=v-RQNeRw>C1eMxsEDsJFnrVeKOWLAXk3`C8vLVbl37Xbp%PI65B+uSh3aoX@~i zSRF=)9W_kj<$`|9etCW|zh={9@pY3)e0|~uSW29WJeJojB;9}i`JZ*?p?pu_{beX$ z#J?d{?1jZCLJ(Y4S`uyCdQt)O6%8`m*2vu$K zbAed%!m#F1U^fAqErPgW6VTunng0Yy-|`L*&E>Ek=7?F8zcM3iqyNHa-wJ8d@GDQT z(~xQuv2t;IK%^9?3NU7%zJ&^xU*sD+llW7v;0*TzU%EQ@`+DCtZXQMg%^wLX4H8lc zH;OX}bR$;i#VEWz$$g2(6UJiZvH4tr-uEk(@MRJ6`059JQ@nF_4#RzornwL5_T9Fj zD_=qTx@|*uz8~L<$@t6Y=MX}aCB^ZT5M?Qv&%Y6(?8Qj3!-%=)B^z`)rby)&7?>UuHCv&uxJcLJv*g=oW9gvh4{i)#1LX=uIF@eZ6G3*9Qbv+zwnke?qfh6+JR;=K$^I)-m0R~K#9^6GV?YF{zJrgH#5v`5Ct62Jt4Sel zQ;3Z+p;0}FLG*2W-ob~beD4Dxy>zQW99D>P3elwy%?d#Q=1E!{qPhzW_7FZV;PVDP z@8P4Sgr_ML|FJ^+L}`IKlz56#{P*PIhoBKdRVVN{jnAw2{16{?54JR~7KcU%wjob> z!}LCv^fTWlCm-QbKkx61K{`?}pO z9(jh{Z~HO(6Z8>G5Qok`C2y*DXD!|#-p!y%pnyymU|Jer2Kbue9D>RU>8O%LvIhgP znTX}MkNHNUmFze;XyGtOAM?k5swA%UCL#%cb zX9Z~N$WR`Vn^6p@7dN9a5~0KHD2=B9BB(?Dst`_v*dafohS>n8+JFy712B@-Q6j1p z;&UP>3BRgj5JAsI4sLg)_;v;;d zHkWS8yYdM_-*V@43U(&*uCrnCWa4fkhbbq&z<9viS=eM0zmu#?6{E}q6bKU z87_(*Kzn8Y_RMRK9uPIWv;HS~fHG%(p%AMSVy;5$B!as5K4q%hH!@ZH+jN#P)@u}E z8x0kDE0_qH(eVnAp%88&XcT>_5Z_aXCLC3zTV{nQmk2B4{UeG&s7i;n$3^Wu0hLdg zUT2@32$=BH6@vhv%w*NojMEW$NQ98>1?(;Gk)prymZ1;&_>YESq|fR{d>=ldeh-Ha zjzz&2aXLb03! zt_aAU)PVtf>5_w8H=kaX$%TkplE!c9sh(GBXHb!X_r;2)62@Z`L}96f_y+^PONJ{X zIC2^pUnU;;G#bKj=Cu-bm?f zL3+E8o<>zkfv;u1D@Dq3C7W%j-^uNQNm6eDjtGFp2xAcjj8-j|E>0Cf#BO!Tv18|6 zrd%XFC|1GX|9D?28;*2PthGDCc%BknX1(z3HtAs$wUer2z$REQ{rcvK;1x0GJ* zR|u^_JfslsD+Fzi(!)B1Sg8<23h}-|JSq{Rl$sYSG{-74u|^p%u8yL|W3eAQVJQS) zdGdmWnVQFI0NN#t2MEv6VAH`E53ut#$z{#RKCiDn`Orfr>uO%Bt3CP1!zZi9z4qE2 zhY#NQ+8qZE9e5)MW+d$G?=dbnTJxsBm#qWHbH#S6KHpf}h8{Wl+b;*3Fm_VLHg zB6~*2$HF5hLj)g=lP+}c_{&KG6%1Go^PJ>%vhMv^v~vjLFZ3%ER|!=*f@CoMGwLPl zz$HSwOO(MQD}_Ie(OP?s*d*y39qgy%18xm|Njpak$}bT(fy+cW5ws`8Dm&Rag(y}C z9qnzjC)Fs#X(H&YdW9%dh~e|<@V0ka;r@yhVuM25s<44+3el+$Bx;qih`)%SVl>ee zBA}y|iCTp?t+10nQixcEcwHgZD@3tEY*pring~jHjdJBRg&00b<|`B9S%r|KPt+QX zG!5wWX_ABo#B&Oft`JQ`&@+h&aUG;2sHqxq=uo^FD$m;2<*Ss0bemEKL2srjR}z#f zdW9png9s|h>k6@6A?DJ_k#4=J5UC155#FR*jYLou$;z?roI+6eI_cI<=?d98LdP#( z`k~a2R?;2VWWyF+ZV=cy;= zkFgJY8AE@knU$kr!c5F83w~&!X@OA?nF)YdMo@E-WRXR=mV2ReQjX!xg2i|B4KBWW zUasl)v3YHUu)$j*#1!;2aNB*m)_komTO&5JCxgnbdu$zB2C4PImPNHT4Zo4{A)e>o z&5|A7D8kLK;LegzYW=>pM$+4ov#l*DlWF|6n0{MiGlQLimmj0n7WfwOG39uDqAe;q zI@D88zP&m-CqBk$u@#o0d{2C4wl2qVCfGfry|pVNIM_A4eL|Nzg#T61 zRM&xpi+9>=`3N-6t%|SR+i!Ln1E(I60f2&IQq9YDXwBiiZ;e%g!~Vi|UYHNA&;)N9 zAXGr_4kUY0H=BU>FsxGJ9K+gZ8PJ{#r!d>1HQ`4rdys`y5$G2OXo9g0R-lU@D)XdKMbge$r_pvshX~ChsEcdi6lO#2p zv1roD)>RL$DEx7-UK?zwT{@wuf1KlpI@}m#ncYA@_%XQ?ywZpeLxmfKnPljsLurj< zckh)eFu3SH3_jGs5&EJ^2?DUp~#Oh^j-*0X-%yOHhC_NUl`M-VVB`s+V zimnM)OKvA7d|~AP&rBmrZdA@o;Y#@-eaZGMYdiBJGTJKL-IE*gO{w)Wyq%W9wAj4% z#RYYX8tj#`S3+d|fOt@^e(&y_HQVXg-C7;HH8MHX72~QZ z@K{o2EZ^R`;>Rx?_1qqRH%c@phVma_G$oL2rq*kK0kAX&u#ox3xrS{&bEY(^ptd!2 z!jhWAGZBt5cT!z-IZSNzPcI6MGlb{PyruoTN%%#6OKyz8ngX+UoYkZ;MW?PboVy4E z<|17iv$}x{5iV#*(3HtR>rM%x+n>ucv#zLhl#navOP_HK%r(x1ggo$ExE6 zT~ba>hqrlIlPg$T**|dV^wf^i4-WKKf`0IH$JEmg-q~Nt*A`#DW^Q0r*Jzt4r9SvC1g2 zzkCiGH4bJHMan3m=v+a%5wBl20+_Brwqj5`e)up{gs%-aVfqZ zqGz|GEb9U?u=8Q8K{-N(W8_gJnGKMRh1-!Qe*QB1nm)U*%o>xS9hcUdTeG~U*~Iog zBL0~l{K#h!He}Cf&DDo4vZuD)bfW$I*SQZyjhQ&I*;WkjahA7vXxUG80()TaOi=2? z#*$^}XU?RwG&R^9jfwg*7%;xDjL9{r?reT3aL8`VEHnj&g?&vtjv}hC-3d3r2Nm_V zLJfpf4V>*je9?E=qF8Km-RgXmJ;Ij5rENDvoc9<#K&VFeS z|6wdDDRjkqnkK~mIyQIN;@-ye=&Z)P%<1h7c^6GdQ(Vj3O-z&S~ z>f-3sXm?$=@lV0>K-t1y*L@c%Td!mA@UULBhdefA@)f4|~agLA-`ynJscy9$5&3tPH? z`Ygsf?Z!uz^Q*7kmKLdF3YYb@my-1*txk_&-o{9N4`c%Xw?n59J|%twGw&FujlMWf z+p^tLxsJa37g$V1>tEcu^~Lo?52mzT-`;+GTZ;0{Ih*!uTG*VvGh%n`ofB8Tb)<9p z(YKb3KeWENdHtdBEr-`PkKaIO7;tmJy3q{o6x<_miZ<*|TKE!axW5HOC!5~MHjB6G z`F=hBh_5TTtfVr??#rIgZI?U8vGJz2?-@0#Gz<{`LQfWf9P zHr&*pC?L=B4$B#$IRIo?BSBy+LGMf@tMwsKDZ@deePuxLa!n~nc{lmwPKN6*T z`1scz0c*rm^T6TVh;~ZC`asM+<0bxxTFI#M64Q@@MH>w;CvZBnmyntn8ZK-JPa9wE`@`K_^3ZR5ucWzg zX?uvH0d0UjLL1Qd${k)Iql+0aD&r5w3|fe1P+8NzFu8 zgeE4_IcfE{By~*Aw3~ZN&Sv%AJS`_i&0F;1iw)c6mNNbg{g9<>?zV zVEY>>3s)?gnh*Bwm-$ndtyq|XvMhuAGZ^jAKz*SM7-H~-i$E5Yax4xY3(;6H4D(Uo z1+{!!Kti#nq|&60NzTf4MNB%-UlkDJYFRlkx49@KA|j=5e9pv`Ev}e=^2N7LGS*jT zsZEt7p5lZ6?gxLa-`rbRyl8(%_nw6fF5S}3gWv6+=Uu*_yEaAd$T6969Qu^no(28h zdHvr#*tyiT^y%9=_Ae?f?A=_?u$#&=^;PicF7kQt+lG3rva76Qxns=L*!(C{ExxtBvev3z^7^4JwDfY!>Z8(`0xeC)BFzX}E)P4S7vNXIQKM1s(u&_XD}E;` zLvJ)Xsw>NFXWGV{Nvf! z(y9h9!Zz?fP}#^bPAzk{UclH%Eaj+^45pk8O8^~F!OwBd!Piqt>P#~Y8Obrm{ApFr z((%ro-7~Y_eC_Ooct>@o*BIff;*Ed(b-FXH?p#b0%hSEShJjmWd)bTdGVj2erecul;`irbDA#cW zKk@&I!ejD1(mx1~oo|)ya6l4J@l$b{A}vLM?2te#Ah{d>(c^Q-BKCn`J>Ux8#*aI| z1*d#jiT?0GadFhj-KH@mY#u5 zOnyo|>RFa?(Hj?r-{k2{A;$lv_TqOhP2mdZjHJg@Ln!TE;)# z*3@NTYpfyFVb=cmbxziF`Rl&dE`MDZH`6uGZl7tL8_hW?ljBlXYc{3C+Do0BZ~v9< z7_M{!+Q+w9AK&b+vFeJ|(tX)#ng4mE#~6a8>uda6cmb1+R5jKvme-rG(<-iw;Q}`= zt-dfVF+4ObwV=_RUSE)&06L|x@f9J|V9QQ2yR3#VwGbMel#^s~TMeOV?lpwSn%tG) z>Ym)_wO9(8rgWu)Zt_~#9f`H|Rk>zks;9KloLE;!bV`0HgmM_!+-ux%_y)&Ip632# ziZ(ggQ#@KPkSB7T1XB2_CL%T}*6oPpb$nb}fi=4%DO6wA7kpvXoH_h~xC~2FU`P-f z&xMADSPI8yFy5qZ9V82sN8s~&96rCqhmY|}<&KQ+WjV$-z~4n{$+pI(T4FS1Y_0g2@H`h36acir z^qeU*d3J3pi%f846_{hQl8u_+5H*_)r6knyOX-r_H8~ypj-XKlHuAwm60#Jt z93!pjl1NtGV`-)5s(DSQy{05LIaWvwvpSNs8Lj0GdsTNqc5{IvCOFnzJ!NjOHb^bL z#yEl3#3s2DQoQgTPs&V;&vhlK`&o2qVQoulQD8(!Kuk`HH-F~1G)rD}U2S6V^1ewW zRwjDFjnUEJ37J-%DW}|G$udWVMJG~wy?~ZJfcAo%33_|*y&BqjY&f<f(42u*Jy=eZG4r7RxMjbbxM(l$zzi^gL2xLXP=T2o52qc|lxV_bK3W=Bn` zF~w^!rkbLhCG`oG9J?+i)stW;%!oB*mIS-K2D1al1B*_Vl%ak#HnTb{(d|eK)28KD zISX1nv5DSE`6-ooDUso3dunV}y(?PW9&Sm?vqG$(i%QC|B;}=9rW=Y@m5pgHL@(qb4j_k?h_N0o=f}HUM4r7qf zUDZCfII?76YYrd4baszDDL+{snUrgb%T6&1@y2LtNqb)Yv`U*fx2nD_v1r+>iKTYF zozHDwUNI%PuD}}Y^ja+isWIBbWa`5~K8)Let%z(day@X4G|-%}4L;ZM9R3&F-~WEg zJMT!(eZcJy+{8DLjm98cnac!s3u-pVPvknJJ7DhV9{n3+d&PeG2=2PpI=p|5oo7D) z7lYHI&VO_@YNYso;P2_Ui~){q!oLoj3o@1D1{rjbLXt)ZQb)&za9l`ibdXxmBngo^ zLr`vs3Cv=~_(BWEt9jT6GlM-d&UbHIrriJ-S6&d9rC_{^YWN%E{7pG$1+ftz064o5 zetMZ{wGgaitqzj2)(2D8+?%fP1r~;|f5@70=DOvaku^p;El9}u z4a|?5(6*Q#>`HRje0h>a0kQ>5MX`8e=k&&B1sxIk>ktAS_rDn^lu0-pba* zJ7YsbqoQFL&8d!wJa;$au5E2+_k7v4UF824Ydh)-PWmK3P$1*H2yNj*1sp*P9gT*7 z7CM7BZbv;b=nYH&`9wo=;D3))A%Of0 zymY@Bkhd$WEQ1#kxE&W3(tc%B_N##wS~~~D-CT!s2m2M>yJ)`}pzR9ppYs*5AFvGC zuN0izuex7#UVXd5ZiRfmDd+o7+pWaVYuT+Hgrv(08HY>N4iScAb4u146 z4p}Z3pa)azS6i!OSd=gX3zgztPM#B%xP)9Zi+WlEKFg?Lkd%Z zjP|@_b=|-~Y?Zaub!TMh_@&M6uoT~;+@x^zo%Zr6Id>Me#s!3iptJc4t06ZfX8=gFNN+m(>6SVZ}wNsf4%`Q6VX+dwVEIdLjA464+i;I#rg6@n+(FE>n(>H!cC z0g);IjsR#+YQVjUvHS^{AdF-^9?|0wz3f|Z5Q2Qz)X`>i&Bg6+vRWj?a(r zkvvj{A3iBP3}}R6$fUC2gI6ng-4&yd6F?!qeB6-ql^Nvzogw>!=i`0_Kw&7_-m^Hm z3!lreadF;|fE9%jg6}B(AX}qhZw9I)vr(o8&w6t-v3Y2dvlWKtrTjaX$fN3z23i6gbVp*(f}uGIFH>X@j3HNSRFo;oEpI>oG$ zZiJ^bmx)gpBZJfdK?{r3Yo9UJwobHX^e$MwZgch4Ta8I+`dQmMUvboU%)th0jH7qi z+BGY3;u_mK(~Jcstvy^DSu&|>3s!WN0qy@s=-*5@y{TC4h@_k}F$fs|jnIfefFx)r zWj2Rj{2>WU4O*7bXKvZrS1_~I$wxY><~8*NM`{x+NxEnuwo*6AkX6*+nt4OBxsOfH zNlcB8&@evAkz{Zs$8ZVkjs7z`#=HCO>2ErI*KG^SwBBhJtIi;BTx7_GU~QPDbn(8) z+MUUjQ~MU?j=OD9rM2aT>AsT~MFyXUgGCSQo>zeb_Rl6KRPHD>qrXOj!qUOCL>UaZ zP_xQP5m|yGRpGMdV@`M$e6H_D~_#T|0B* zg#5W}*){Vw7U+{(tJ6(+wJFYqvRs?qTr@Fv#?fsn^G%3z9$UU}VsT5R&g`jmMp)vs z>EmWBT$&>uwindd?6c?eSf=D}*|DRnxLmy?G_Paxw6vV{%bvQSreewMt+jPAt=-d` zv+T8f<-OY`*<0gEW;a?&T=6NjowMg>dSQQ4yJBB+#u5`Gg>pPPr~3n+ec zJsq}z5{e&Ae6-mN4_LpJg`3dYSXpOPM+Ak0)y*hNih#1o*-&5=;tM^x=ukl&8Wpz9 z^Ba4O#~K*>R#UzP#Jjg9MUwVa{BI*fEEvajBVg-exK-VWu`M0b(=3ICSVL@@ zx2)2{UWyynwXm>cd2gd$mz& zrwd`$kkO|4v`BNCrPv&nSS!a59`OD4#53$iMpKM6Ik{qLzUw6W#uM4G8IXTiGb9Lm zozoXkj0)Z|JQEd;pMO=}nhaj~;shGxHq3 z8YoOSiu)sql7vMhW^LHZG9v87uKb?y zC8^N}s+7^Txid?fF=1JCz$jKQj?R|a=oO} zc@1q<3k?=5N*I}lXlx`Vf*Oy;O91^6+PLVT1*r|QR%|LywCMtpi>iu}&El4nM-Ro>qs$rcrG*g@ z)4Ux^3!K?;L9WyUp}C+YD>T*5Hm2oxc6K;t6x+wumdBN?uC=#j6)l+2?&!7Ur8x|twklVyAGJ^oV=;^kkE#l` zHqhztIN)66JnOg!*iZs8{PCAS;2Ww{&hjYk7#jwu^jWG|a_Irt z`^C}#_0_BA$41P!Mo2`K`X%a4_=(pjX2|&xEdy?a5Gd8W)EXJ^p^*Dh*#uw%a)~th zGQGIy8syVMXGis3#8r>|m+LdRlv%JDmr8l{KKr6-eA(U_xQ04@iC+5kRa=1i=J=?- zK>#Xgo_%4Zu62}NQ;+@p%MH-0cPh|NzXY5r>c4SR{Y$Q){*EyU7`c8Zpl|^9P#H@ox0~= zxNM85r7@zD)>@JXw5gOi{S|ahmsyT2Ur7r!v}t6a_Qm~^V~J)khDRR=M4NLCtYOLh@~U$gE%}1KB`Mx}1JF>GDrcZ8X^CMdnu}=Ym&*I4 zGq&GU>QeQw5Pp@RCWc6>{O&90x%u&5s9xs&dM$&?7p#8IbVc>UQ25oA&p3yHrxe`M zIu|LAx{EQ*$6%O`-Eh#n|Gz^q<2YdSYJP_{A;&@$*#c6$FfaZxe7HvSPVq2XuRpg+ z&pO2uTn0sXP`|hHeCx4eWEdzs27Zv4;O}}^YS#!zB~%W)=@^p|Kb^&kzxJKg%$L&p z`#~u^MC`&Hx*18R$sS^hKP^>M!vmx=GQ zj-mNddhm#c(cnQ=Bt)P4(V$-4DwlI7dafT)Urxb-D@ZjJp2Cbgg?S*eK}`!eB_S>c z;aA`&ui#4%I08s$96*S$&mp}4RgmPrLXz*pl6UHGLA_khNb%~02xDN(X2pO z{I!#sN~)TT>gj)-zd?M!U$Ixk6R7A&N=jq(p^8WlBO56Ot(Q_X$}Kk1{BoL7Z%V~d zuN>)7C1K%X>Q|+p7bk!2F?2G2;eiVu2k-Xh5P#)7C?9qQRbMkD-{bojZ-llVR(KRo&c z`7KVR!XEYv-U@`Wb_#Z}0NTX@-+mUU5xxb*%oOm8_wQoRxDhO=r12bq(8Yd*eMbg9 zl29U65K1WXL+1uDY(TWYQo)61#9eQRN1pzJC+BxV-#`Usp5Lh_SI0y+TYvBTQ&bn& z?4VTbQmOv0%Otdql;`5IpzSaG2IZhO{a3XPzjLHC?DfmH4yd>kP9OBMMq={2e6 zMzs``jqSZ``Q(8GCJ3br+&x@M{lBc7S1Rilm3MeH;J~gynZa{%tFMLuqoBXQ3V@g`?!vk_t!aGufzt8~e#E*jX6Zt9+ z>kH{NuR5v_tCTJH2MPfmTShinj|ERE%4r2g<*y2XxViGJ4GM8YAu<$V7;|M9VdW`| z8Y#hH*v`4il@ki_V}&@Z5H5)z%$40z5r;P$S}?sq%t~u!viMt&gAq(jHFxf^qxidDv>5XY7&e+$WzIrn{Lgy) zpV9npGMXiBdB+t;GDKbi|~%T0&6uy;n9m2DZx4|N27wNS+mQ5_u!MH#`g zPNNlZ&4sF6zWb^}9?+j=2Tn|HyK@)UHKFG|cHp%BWN0PcTZ;E)%I`66CbN1qT3Dkp zC--{W^b_>h10mJE`*v}Esti4;KP@i4uV(^&qCr$kaYCNS|BQ0fA$Vaq5I~$(KnpEJ z7E*@dVr0m-A%Em3E>?1E#d}rqdk&46Sv6iQaPOFreTW?CG33Z~?fR>fAv=H!@k{EB zKH)L+hUMbkP%H@uID)JaZ5MUQEAg3jz22S~U$D46kFdbl-qBqX5$`YN5;<>1@tj$%&`n5O(hTZ%1D>6y$+;@RFelI zZHY)9{L{dzgs-*S17!M1R)j_yf#HO6a4z4gbVq9K`ptW~dhg#*&kbI8WBu}lORC%0 za*PM5d(s=Oo9xb8dg{8hTfI}42j&4HZ-PEPBBn!IXPkWcd4X4;~R3>-=JLlg^=2_i`tjU{wTFEJ`g}Cb&&G) z*TP9Hi@@w?ZK?-vph|hr>|dDJMTJ--H>AIS+;63_u<26C&~nqT%DgO0mBxtGXf>iU zc&AZKOB)a@oxkP+)`};}xa%kSKKa!{;VgvHPxNh>ur5SsUN^zFWg@3%A>j}G%J<1c z?)q}^zO`JyP8ut;c0Dhr$~0R1gMib4?T6%?&?gDchg|Y@nRo(k3sZOc&aGu#<-V;G zIURBo|Kj_2BDZM*`TewB_zO~PUr<>^8TF$!G`p%JtavIWnSxyt92LG_Ysx^?rq9ve{op$NFWvmnLhU}!4xv%_^ zmO+}zu1&tTxgH8(KeA~_PR{=5^DF}a)JLy4_=*46=f`&Xu&((xbl=WnJ0-XaO4+|d zODSV;lgBiDM)pT3JDZd;k{Z1n;-|2R%@+?MJtVK}-$))Ct+a>NVZ{tZ00#)wM{y~+ z1~0O3;4^y1m^X0l9NUY}#XJj@AEL8C)qtOGky9I0f143L-a33P^X6zihB6TQ&z(cr z-Wuj+5c*yo471gOHnVstV0X?_AjVP4i8VRTCl%w&Yg2|A6d7grl;Jd z6$GuVeEOc7c13m{T3VLVx$%zsr%t{9j*Xo;rOOU=M{M1dQs29LV_Erz<-PSO$oo;K1O}#=&D48BG@o zgc|H{26)<;A?LPvF|c$kjX8Tif3hz)=sUiYwTDm3KLUll z6K{QNdi|~I=R5c(!hJuhyLH1n$52y%rhUibG(O<1j<}g*?H>w{C%>M{FV7$GT=YlM zldLunQcF^E5fZ6Fh4?ABW?JDmf;bBVI;_bS4v5ZQKD%Ke^O{V|J9(1?QdN@Ieg0?n z-!CK~@Fseg5UgKD4`U5XWl46)WrEoyU`_#kDBy13as>cJ;brmWQ{pGzoIn4YOm~W{ z(~I}KD*mY?LBk&yTC7PZVd1Z`-nOrQe*F07UvE3SZFg1cKwH)BZKzovdgW!*(FBLO z3@I0<#-<~*{W4}RX3|K2w+o_$pckwRdFqk`&_66mjXJSNxNYt69(`5)sFPDpke#%PWpp-mz{hP99NzRJQ;)1k%u0n}9d z)2re=dbaKq(@|@PpPUkJK7vUbJA&Rqu1-z`%tQ`H${7h_ggp1K zq~x;q3%l#GBaDTO-G!O;nMRX$Ja4O6G_yNbh^w5ktgiRAjc#$xOY1|V zccP2%4r{EMwak^hq`So1v8TP!K zuk2mw%3j<>Ar<;AJSzM^_&U}O@EG8+)HG%TG)7GjlY>?O-Rf`a#m@=~@(cg8cqoQD z=gx4u;85McHFX{Bd2QaD*L!zP;qt`aO?Yrh=cyJE%RPKBv6LzZc`60z4ls8ByBm#k zN1l7at7?jLhe$8d0SF+Tq3pSP#m6cu#Yc~`ht(UswIqZ=$ z;EMFVAB@g{GwOX$__N?uo5U``1kcw>xNlEFmcz(8ZiH7Sw8})qFH#aW(5Up%u7v>g z0BeO)n}o3pw>F%mwc$)n+nTlvb{^*D8)mvIb5jlFy2{v?LQ_V3ao@Pq)Ny^qbjQ_D zlx3KNJ3@4nBhejK($|=p+SpgJ$Kdc-DkiXB860`$@)n_I^1j8TnlNqfhLFf0y?J^2 zpCihqE-WfuFtt45(^2<$PSBhCCx04IK4oEX@xrNP5#rOyHHEHl_Cn%yO^)g!SGZW0 z2>bzFJaFL;oKK+0c!ahw9RmS_Avlv%56Y3mF!GzfYs>@x@^%D3Xv(MrxhYg1ZpeKP{IWC{+AjK}@vaXWz&d;ux zH=W;(A@7fnw+3U~DdjGYa)!-LDFv?J7c3Z1CXK&L1ZZ-F#*oT&4Q1mxa6;u0u2?*j zN-7`rKPq43moJ}!mlJ*h{CVNUY1{loBbCstMT!du&I?tk5+(79pMI%uFMU3 z@~+4VBAqKRffYxOR*vQYiML=9_si4njduMp^@;ozoS=2+r47XB;BZpaf+r-ulYgepTyP#b^?PNwtvI&{va-|`Rdt(q9ied2s8aj#<0LISEq!TMRyi3b>M})~` zW;XGCv&$601@!Ex5Z@Kwu~av&@rMYEjZTyZWvger_`VH+WGBTH~3OkDoqRT>PD$514tuJZ9#0 zitp_xD%!#9kFy~0Z&(BE7yiJOsDJ;j;eizND}~1yg{~rjagP0MAIsic?e|#rhg&~p zm%ro!<^!}gD(F?tV&{p)N!g0CGUTO@_GxS$C>{(BNn-C%(`i)p=pkJRNrHu6VJ-p>cQ4v6~R8^GPY7}KQB#a)JTyw=8B#D1=0 z5Rg^p0F^cRZOL;emwnFm`W}EYGhQ0=KI-DJ@|Hp018grHs*t{Fko%NB?N49MeJ?Kg ze!_jqeMh(0@*825~z4{EHZ(<$vyffE#rmr$|cAVTAmc z?a^xS!K#BOLtc_6(2UUjqYC)mF>;`hiMv;YhlomRxq zVU51U@6ki-Fjuq|&oLInekefULMbpSe)61n1D@DHXWx-~)XF5RL>eE8Ifv;XZUNiV zPS5eGXILWtcS&MEXP04QTLsofJ?6AAHeLzWVa`vDiAl{jo4qM9F)3d0hRWp!r%XAx zyi)mImD#qmtZZpprt-~C8uh%H-X9qKJiRyial8h(_r>L$fRg$ppNcE|)k zMk$N(&Am7#1N8n#+ralvL9$g+aNzuG(_(A7G^sa~9=Rk@sRMiuP}5&6eQ88!(HWPd zKiqtmPoC?b^YU%H`9S znt&yKLHdmS`2rUhuP!9S5nw1oX5}Qo6~XyPe{E^dsAobJ3alr92}*x6Id2}Z%|L(3 zr$4}^CbFF6B7%((Fj3L;MEur}@s9-1unojOYwwKuADwdibQq zJ5AFJDcWCXpAXXq-lsW;fP5iu8Lh_+-`8gtGm;lKPfJctPArJO-c*p2ahqvMf?NAm z$Z55P{ecZ8a)drGM|mzthYrT(`_^dz4;~|68LWDXK}VJ(=Ka6O1!Nvz97+Sq4fuQjOOpccu0#0 zV+7$@8*N_<;p(YV!VPAW7OxM7IBHssz z^Gb3jVJh#ZuVTyR3-VlOrnC3^(YLsXAhF>&xuYf*CF=kGx42V)OPF0442schzniME94iJYBmQqL15xY$A z=F0*k08(>5F_so2yS;8>vO6<1Jff&5-CW$BpTBX_x|}ex)>>PVrskq;?o3ydAcSXR zriH1wKzo*#Tb(p@LTON_#cB;VR5p$S9%4na-Fx7~V%T3#K-A*>V2)QF^@ z);M`Dypgfc5$}tdS-A&-O)XP8+sDOibuC!fH_;pTvo{|Q|G{&y6N}D2#k~}fWHkqi zy$C!w`D?dtn%5Mq&Dr(fi?6=Yt>psszU6G&?C;DNY809yoaydp;$%jb5IT3IjL=j= zNyj7XM>*qlqf5-iYz;j6y!c2C&Om)`iJTmfJCgEgPB24;%AW$w?k;ydEQ#M#sA z`sOf~G!F4@F4eb&nJWcst zUBCX`o}PQx*DK%bTVyN8*~ay^v@CD1Gg#u?ml~U$leEo40=-AGL$aoA)JK z_(dBzws4Zk&=er)L;apSdiZ9t$p%NAm-NZep-uqB)h z9|(>N*cPyX1@8~KKhPMqMSC*Rrn8x+l-HR}W~0m47vs_=NA<_lxf4zV?NZduLZBpM99H(8WJ!rDGMBivg zGpdt3f!ZK%W@|!pbc*gk^!&(#up1-i#0K7XA0MbW75uH>nDBA2%k#^l6IzjRMx6LP zB;MFanatkS*n~{ce5wJ=l+8l0boTWJPLLRH!eLdaPD1c3h&MNzXKlEB!jiMQCr#RY zc1ih~d?7WhegD#milzJ8rynZ_6qu!^ztu%Im%OxlQewOzh;FqXSX$9i9RQC!!W9&j zLJ9(%H27Y@1878;kHCo42_hH9Fr?zrUXJnhvkH>Mv=ruzN#Jz09J4LcZjSQw;o^M-|XZd9sTM5}dqK0}O0(pcAUZXi?8TW;@n?ZZiF4t@M|B z(O1nqkH0l0wtMMPafQhwu3Wm5?V_GYfonOTI&=JCZor4r zDAmwPEp?ejry=8B`7-}e%%WOjW_Dg;dR=LuNvH3NVnR@o3o(c4$2HmuXQsrt^cI_? zcvVqSiPsZnLG;3`$xRgr6*E&T`QbRD|5swVIy}x`&QFfk_-5z@`|mkEG&nFM-fb&z zM}@BoDb6#c#fAjJjNRzSj4jNJCNt+zrN4UFuc?q%FN#WF;3ES|C3$!>B;sxq1S0nU zFz?_?@@asRSyB*>_T$GKvIFC6vpUYb*fCQZ#T_?~Pjj}KxlUiC&%oyogoYckLO#}c@SsS+hNtsV zFDJw3-;2;-PBSA#bTM=CF!}VKRn$yq=#KqC(@Lk?a;V%gVS=Unkj3p>+4O_h?%8Y_ z+Z$bwZM9|>M2r36{d)H8cY+||{*f?bkFpO5KMK?Y1i!<+t@o|_f0}y_z^IDte|+Zd zZZ^I5x`o~JkRC!pI-w+xgoF@64cQF|q>(}|ief=U>{uxxpdzB8VtI%@MQqrxf)YFW z)W>@deJW)4|Cw7hcQ*+{`F_9u-z0P9%$atk+_|%J&z$k1Zh@LW{JT-F{uOM83s22{ z{worbtP6zxTz=)E)-rK{ARo002e#OW0?3zT;bRC>$FlYOjr6iHWBU(lG&F{L((-la zw5e03hgiN*oX}`2A1SUhS>A6nQ>>J2p47g$e3Ip-ao5q=OD(^m<+f3^ zvVdQu*{{+1hFFyiy#`}zE?45Ja#g*@-}zEP{Dd#xp6uH-lZOZxjZb0HPajdr0Lvu1 zOTHwfPlh1ukh;cIEZOwnym=39T2c`w#~0}e=PtXUs&dn^IfXi1;hbfgDuK@})Y0&_ z_0!fBQos7Qxu549+bSp zo#UI7k~TWVBiON(Cj7Nl610=jAdHrbpn$YL-z18-*0q+qscy;dkTzP|`=={y*>T{& zLax`n|LdBwu0J@|YW`oUl|hhxz|w38Wx;>GiuCWwfT);|yagrt_%c)1^6bRfwPj;8 z{?TKjqf(;7T_)3)EzkVvisvX?-JGLKW~JvYoR$|KFrVT=y6h4|88| zFH20QXfMv0Rh$^^9xFFT}zT=9Ef(q7jHPz(#;(ab3AM;2z6mNtLdMh3z<#;=e8OhsGTqN5hzJ=Xu zaZm2T7Y+XTM&bf8=av|8bzE3tX>w@BjE=F{Emf)E$wkKSWJ5sG#9FN}H$EsLC0}P8 zpB|~tp5UHU7;H@R4}*wOP)x?3Z^_k>W2#d1W8z17`KJ|BjxL^`AE_&DEJ&W3pX}#j zj7y2ksmThpjP;IA&5s#1Ha;jIHa9vZKh@Y3T$&mgAMWlQ85E_%N9vVH-oL{hbYMfzQMQx3~^vb1;lj0R79_jo=@of~@RWi{Qw{p+n#ys;h~$FFQ`jy*DoMuOAA7OWsgd4_HmOf9VXR?e zUHqAgO$ds`L$nGfeevBtAhq_s&#u1uv-@f#SF!Bvddp9R>!#_kl)bwD<)uqs?!Q`e zEuYL+jB-CeX-Vfb{m)}PCNH~Sgk@{(m!?6sS2Dje9fF^=mf5~3+4)f+W7G8d!g;yr zHAN|2H69VM83s*ebYNJ*SWQ@dabehCZoirzkzZ13h$t$nPD+|t8XuZm7(L2AR^uON z#B~_?Ik}^vCRR>QF!S{=DnCXW29ZfpJ=~>n=Qr@Y@|Sb4pXxLVo5=yv$0S_u8eqF` z#);ign}tI?snL@bZP;3W^{01L8zwegd2c;yW^UswRa8<|&e&kzM8A~Ud_!c$=83MEhWi!4&^){p>NDj zHH3O{^L_Lgljn`itsff!*@@t^%=F+Ihd$Cvb-UpBz52Q=+i;@@F?L&rZx<-eoF_*Ox5F3yF!sjYE!unVy<&neF81?i`*tHqua%JzD2S z=Lf{+O82Xgu>jYlLN7N(F4vR@50PH817tK@g_Y&JG z!N8U9HLF-Tb z^vXPA>WrSk!nwH-&X77UO`TJXPkx-Gz)v6M<%eZaba~FGz?d;QZ!DMW`wRm6j$iYs z7RyX_`BfS_bcDswI7mcFm62RJl|H6TE67drR5@{U6{k=*B^OS}jqZPaa9_OPn^)7+ zwWc7bsCb-jLP&agaP}%Z5>=s7u`wZ=;c{?oTZ6Qgv5jIT$vf82&uIH=lOb!b*iPGm})(Z?@2e`<0; zW3etWe}3`k%7Qe1uTk-1^r=;2BC+x?V&xH?8ygT5KXw#W9?@MM5xV%W;MhoS_we}0 z)Kc3xWp9CufjP|9LPNC-uC!AJVI7O}9I`F(d`L)2&B5AXP$MXe%AAI^6MZMFY^ul# zcMnS}o}F9VIwdx~yeTJffjMGE18})rmiF<%F|n)R$P09lUGPgrU7sDP%kC$=qy7_ZfvNh zYEZQ-&l!vAo7ywe+ZN)0ksPPr8m3GxNRBX$tE{Qk8>UVwNC`LORZOqO4j3Vgkk%{X z^+%{6Kb6IVBB9hoOI7}s&vAj&ziH@^Py1^lx$8eYV)+*02?bo;Ny~TC<#x}bo;OoB z%lF6y+KH53IaM)N6bFsKSz$c{``Gzzen?BQ54in{oq&me$_~ifaa&wNMkQ;L(}I;x z>^pS(?E&N3>&n_vjn}p$mgQ#zOb?ixSUZdA{4M`Iq>Ax~2=X!%&&^KUcD_cjcU#tU zd;*D%DID*G?a-xOQ4QTUApqRy@b%><)%64qFT0o>Ti65lSNmwC2a-P!C`^lxVU}i3 zOp!dlI2r4crq(Oo_lk%Q4;$H*#@EK3 zJFW6`HmSus*JiW}Le%q~nIWuQB`l@lSkcT5NfbniVhVnRHA>?KnM`=%$Z} z)dk!@M<4R0|3KbP(omO9CpE9nMBMUbTjGW!Rdkjj$Pafvsm^d!S#7l$S<{=7Lz9Ef z?GI>NyK&VVZ^QlHeMK7|pfeR$uky;Nn3tAOo*bxB{qB=rUQv>yx`vwbEY=Dxc8=JK z^PSd+vayg|m$ug(%3`Y!c6J{Jt2JTOoqxOa=uw=)_ctl}FU-d8!9oYB zC`7%Tk0>-mhi^e~_^N>?nBBjK9R|Etaeg;CEsC86$zqQU1TpX*4=v|{#slU?!_v;9 zbJx$Cs5eX-TeQQ>Y0ln!uxII0H=phAnP*bRIQtFB&_|pq~h47;jH4 z?K#MJGw+bdbM1IzlEw;6T%vJ)N>WX};po=cb=!~HyaU`p2`T28T6_@-!?Tz})*K|c zSOnGN!0vHS_zF~H(@ObslZ4-G*4akiUIJ=u9TPvJ&b zheMUm;Cwf`?bZ`X6M-eC;9RTSFHVT`!4IjKEDU{|fWT`AAD?mDfUBFnY032L@Zj{S zCAZ8Oz;CU|n_Uzi;>s!2s>uHT>YK(2erLBxPOV?)Q`mX?!%xkqKlspX?FDjtpCGcO z8<$sL_~iVu?0n_6q{_t*;wo7-`M6?3c0Oh22irkGc&#wKHgfrRq zGap_mBtXHhkBrec}K7ex-@L_;74iR7$y* zB9;kzoU3F-<~8dSS4CyU1Tpr`uhuo^F~&?|=B=AJ{>l_ZO*&rqEZ+HjDOZkX{BeH| z%LrX!NZ03tzU+H9#2x;t{DE?c+gx|LdpUWir`$GS@@?0^qnHMc^Ht5UaT=X@520vF{*YYT_@BHwMQ0TiWhUh!=AHIG5`M%5YQR72nMvxCg=`ykc zAnfU55L`%~ctEuelRODfXBd10_mcXEt~5b({^-Hft4teGpQckyPp2NdD)nj0W3=Mw z)T<7rK5eo*{&eaFsFxem74Nd1=-=~~dV+S1rI#=5nK`|?i(cMZJM{zq(^F~}Th_jK z+<)Jq+C@`q7rpq>;@YW;YFqB~|L#T0+C{bH@B5$5#;P;jdXMsu(ge%}UqqpAgQgjH zc?ksuy|6^i%u*iOc|LR(-A@x-oT(*uJ$+DLl~{ybXdh3=(y#8%g5WCs)$)b~i+B70 zD>97N;a4TjF`VP&QfJ`=O(SM};bYxUvZi|B`OATvMznM&*={{&FUty5Mt+FNtW!_U z^sLZf#7fe8d2p!u9H@5wcwUI(?KpA+*c2#-r;NVy(9HO3HhIGJ<4GQip_qN7lLP6{r9BQE}zD12jQ#nkGEDMw^~Elvq8c zv%)ophM&S#S&pw+!z@h@TsAJO*Ew%dzKFB;*n+h?O_Ih$-bEQqZI&$vKl&vq`+cmJ zZ9_pGXdnz47|}dV1-Wh2$;SNZBx7-EgegTIGI~^?Hfv(cxk`Vhz@(~NeNx5Z+&_x^ zxqFLyXQZ)nLZhq3=}npSz4^Iq(^B$t*B+%?VoK8^affw?KE)J~T1+=%A(_k4M&Lkz z4oCPCLt-XmM47lIeQs4!?&69hQ%Y@55j#1g1HrX$Nli*}Rr|QsDG}^9G~I8euKh)pUq+c zY@bqD9vYW9CNnNHp?GR>!ui#_!vn>YmORec#ofi3OD|6jG9?sGDNf))|9COhl;T8l zQ1aw-&e_$?&6(4s<)rE8Yr53jRGn)1+^ZUj(h|}NlT#)aji0%^`smS`r8CDDO-{|7 zJg%sD+ZxmP)s(;Wng$02=|+{c*G`x?Ei6H^F&FCo8>w|)V zsWH1aJNlfVWZamH)R2(Wj4|UN*r}jjS^ug20>5)YNhZOhE?l_nCkVXx1qS)?N6+=T zXoC^zC+zmQ*tu|=0E~oU#x#6tVS;6N_|$skYyJ@~TF%Ga!-vzjaNlFM+ttn0@*US7 zkY&35p_dmedikO2O<8iBJHQ_azyE&zB)EUOKYtc{`*!|(xPLqMfOB+ckPpQP2X7C{ zAMQSu?_J%zT%4W%K_?B)jL(=mCZ_f0bKberF6SNCg=RH(eit>*Ae9(LG>vCI+OASq zrt-@%@z)pht^}m1_$$eWY$5e+mLoqY>u){WGN=mv^;?Te8cwg5v&$ciKXdN4VVdg? z&bacG8)taz*x^tWx6;h3CsxVZujP>C_pPgjZ6sFP=TO@RrP|W8bYG}5u*q~7nSL6F zZe%S1J$u8~mOgieo#x*vuhRO{4JE}}>jziAiuYgIMz z>daC%$FAGqG2_NpR^pK8!xyaYSpsEyICgMkDmOir&H(>)aRW`u8)(mtv;4b z|3B780nH^ud5YgP$YV0@n1?wm{3u)aNqvJ8LwNp%?iXrUM@p&=pLr2*i6Y76b z=^GU8wJLr_O@(flqe7PXyOlnVE02#}vGLZ)&l|@$oEJKOlnXW{hdq&6J0Zh+h!aD~ z2pl3OPE1Jy-o*Pc#;}t^f*~t!v>R(U4up+xJXnLpTse)cBh;-Uk$9DlqW%+#iwnSF zg(UIki7$-dB6ncPhba*i9tZrS<7IDg1e>u50bCcxD}|zSNa3Ef@p!pR0(X-jn@ith zlDPd5OhOl{oGUHc2gdpD1M;}s^Gs6LvR4qxrLKa+E;`@(3ww)W1Sp|RAeiYiWW_@R zErsG0um~=o)=nR-FlhPCp391}bgFTa ze5c|Eq=K?}QYn7ez&9;^i&FT^p$?KsK48#tV{GlEINkNpk;lqc6x_c1srmDt+H-rs zit@*gd}Nv0N`tp;rNON&bzfd~`ImLe@^{UfyQ`opc5z<*;@I~i(v5+E#`Fl@HKcQf zfhIkw(8f>eowOov!FYpV{DQm{lX|Dc_n&O)?rv(SnmxN}X>M_GZdYtlQfx+GG;)Bj zD-%VCNRJMLzLzr6=(H1c4&YBtj%Rhgl!_V#+Ka3EAF1gMThpmZ|7tz2m9-X8qs~NS z!uVo3ZW6Ewn*)7qGAOtu722f+amlMYws z&`Fkss~c8itt_FF)0#45Z4r_j%!L*0nALd?^<8xCnYzx}wECE3=@^lRXebU zGy~tRTgmmPA3M3A=C_e}%|$rAz;^KXuhBTD%Qlzz?_f}9#9n|>g~hGdNEJI2A{=tX z^u-RnLPP1m)4@k`VsZFSxlY&~bk_U0x?23)!aThq-2>b`snsvoGuT{U9zQBHZ1j}z zkNy4a#(B3b%nA+Hj4R!`XJ2j7{CvhPxO_s=qOP6}b8JYQ_o&FRHJSbY zv~;Ft2BxN^1fJhx8x`D6O7lCmJoeJdho`&xxw>g%;{z%VJoC(+n-+}=QQqVo;t}R* ziFI>va}S90(Yn#U`MFrO)jV+5#_Z(DA#p`3_O&j2_sC-tlFLFO;-{~f7F*I*9^>ih zlcE{7?a{}|Q%rLzb9EkG+T!^3wbxEKAIm*Eu{5%{s4$$qC>vDVPj3EhGhTb|y~Dd! zmQw2K<*LeWzx~m}FFjwAHXFV11-{|UM{l@d^S_X+=X>MAZKwJl?=1BeTbupSd7(CY z_kXL`>}IVCHd+1uTDP&c^Y_*<>MeNwUGQ#6M}L$-zJsX5F^#W^?8`(De(0(2qgfjA zSxjbw9cOpp9~!23i{Y3E@Jfg_uti6?ZFthPrZ*4mUOmy(P2)ecdF{2EC(vhoeWh`n zC_Dhhy#BNFVfI8gvj(5u|BtI^*1bs+Zn(TV(Xw{8@}9?!+6G%$(k)LNJO1`8ZC*rD z+3x+1KXgyAPGK9Banf+sJ8@@ekDrUP(0t7b>b2*#*rG*c@!Y20XA>7FlIp}6yOYqJ zmqEs0-eaeE&5+bxi`hYxMiJJ&PS|s1=bZ2%RH63akqn<`1zQYbCCt7q;l#UI5oA!{ z!UI7~DSjv*1+=PSsmA|ofX~2wB=8d@{~^lGC!0LDpN+W*L7{?*#n4&QOlf$aPpHcD zYy^ISKijAZ^~TpAniig~DbC(^&pnjhd%Q#sQ<9RBQl6hTZd_jeq$yMSli*D$(d%^j z!|+bx11u4?VXt^ABr#VnX)~HqckWH4lhRk?=R+sVx8$+ye)`gU%QHTHVS%nH#jjpo zkxl*QD=Rr=|6Xo?iM}o=sZL*#y0Wlv)xLtfyQ`}1&MTPo?81f5rl+hbEL@o?#(0sZ zO%h{RK9fxo7;&DKPP}hVVkQVD1(5D4B{gIL^cAokkj)7H*PWp}X=^1*-v3@_*v$ZR z&;NaQ;O+kwo&j(4fD`t~Mni8Kd-|EKRy@ZUkWL*m*0EI`lreC)56?uj%5IR47WMQB z4}dBY7bRdipt0J*`m7M{%VPN${$yg|J>9l}UKSNb|7IJ$M{Gmdaw0qB%X8nbIY1Gs zjc@JjNIv(mZqN|r-fH={awqruz=(D^W73>M_!p0I#$9z56P@d?NVm+kT*?|Brq2TUM_cfz1cHm~d@1r&<3z2Vjc4SAUlmzi?B`At71e8~GlU;=(OjL0WlrlY zrQMcSXij%2E%6QacMVJ~&omlb{KEZ|4FTs4u%gCoue9u~*vCETm6}@^nNU|z9B4AO zWrX6BEH1vlNkZ$7s%LE_XR-NwaOs$yuyThoQvMr)c&xz2je!@+Q`*7@bH{m(NpeY; zT^$)6&Qxa-Ol78V|LfA!m9{Y+9I$OITX0V+9l;VtSeC}HE526LBLKKkUJ|2kp$fEKJfwY#BV_o;P~yWr6)rcAlw(FOA# zy>cpC#plZ{ozMrinf@$~#bR$@(OC5I_4^tdAH8ylj3)(tPvShf3m0}#ZVu9$EFIpP zrSc`$fe)pV<+SBASZ}&G8-w|vP=Tg!_$lVtEZq0rmJWK;c8LMWbzp@1nX!StsTXHN zY3n1VF(i!X(1flwe948jxr=Z^H!ojKgO@L_l-Q752X>TB{qJze{qHE&UYwmF+6B*} z-^Dn&k!^3iCY3L_4tyw{vUDnv{uB@H_;sC*7EuR92N)nN2<3nfB8U_Y#1Aue6i87}YQtPMO-5@#8z40IKsIxG5OX)=+cX`ChIwA90eE@eue;-5wJBOD9G}R>>N% zhmk#I1MMa9gbgE=pF)*!(M~)K!O~{~18M2S`j9%bBBGYuBT z(}-pP`K%O+br012Vz~pYYrIA>N%|TZy78W5;Z6Nhrlrj+j@D@oNZd=VV=X?!TP7>GxUxQJGLmOEte>1bds=bOE!vvo zwECjx=%V_x)H*Hw+r=LjCDsA=K(2W|)*@ce!jg>|Lg)g=?D-3!^tcCVpz)2P`7aoG zoS*y?DEpbQZ-r&r3Md<8@`~qX-M?z$q*eFVXD>bnnX=MJtM8x15@{m#q%Fw?HtGB?Y4yv;7cWQj`sF1>%j+|+vpK*i zlRQlkIb~NE*&6&J9OCz;`^edYgwx1aW9vA6|CQ<2#U0Av3>(8)(B-OTlHGW7FrBJQ z8H2ySV(%G~iK$QR-@~;kz0aLtw@squEXVPczq5ajiC-03p2lwOa?JXAwq8-?qun9M z!M-bDcTI~uH0&fnXP`n&1JXj+QV}B9fYgU>-WWG}o>Ac+q4m~xj?L~FOVv}KZt{!I zsmgx*B`;lKUOZg}(bxWxqyCoDioH~M`{}%#o^0==w2a^}mzP!ETr&Ohn*x*bYqIBm z9+Y0zGTCX)QKnXwCj9XuHUKT>Efb-tkM#ww-^-1!FS}Vv&%Qz!^teX~?ChopQOlXKVdHzDEXw*6}o&wZP<2HMVXpAp{}&rj`NJrx(M1gEAdG^we$

&T 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 D#}%|+ literal 0 HcmV?d00001 diff --git a/beanImage.png b/beanImage.png new file mode 100644 index 0000000000000000000000000000000000000000..4de82bd700bd1a056dc12948dd286ff81a1b9ebe GIT binary patch literal 36160 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

DTS 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 z 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 z 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 literal 0 HcmV?d00001 diff --git a/src/commands/general/CommandBeansShow.java b/src/commands/general/CommandBeansShow.java index f87b862..6529904 100644 --- a/src/commands/general/CommandBeansShow.java +++ b/src/commands/general/CommandBeansShow.java @@ -1,8 +1,23 @@ package commands.general; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; + +import javax.imageio.ImageIO; + import core.Command; +import core.Constants; import core.LocStrings; -import dataStructures.*; +import dataStructures.KittyChannel; +import dataStructures.KittyGuild; +import dataStructures.KittyRating; +import dataStructures.KittyRole; +import dataStructures.KittyUser; +import dataStructures.Response; +import dataStructures.UserInput; public class CommandBeansShow extends Command { @@ -15,7 +30,15 @@ public class CommandBeansShow extends Command public void onRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res) { if(input.mentions == null) - res.send(String.format(LocStrings.stub("BeansShowDisplay"), user.getBeans())); + { + res.send("" + user.getBeans()); + try { + res.sendFile(combineImages(user.getBeans()), "png"); + } catch (IOException e) { + e.printStackTrace(); + } +// res.send(String.format(LocStrings.stub("BeansShowDisplay"), user.getBeans())); + } else { String mentionedBeans = ""; @@ -26,4 +49,73 @@ public class CommandBeansShow extends Command res.send(String.format(LocStrings.stub("BeansShowMentioned"), mentionedBeans)); } } + + private File combineImages(long beans) throws IOException + { + // Acquire images + BufferedImage imageBase = ImageIO.read(new File(Constants.AssetDirectory + "beans/BeansBG.png")); + BufferedImage thouBean = ImageIO.read(new File(Constants.AssetDirectory + "beans/thouBean.png")); + BufferedImage hunBean = ImageIO.read(new File(Constants.AssetDirectory + "beans/hunBean.png")); + BufferedImage tenBean = ImageIO.read(new File(Constants.AssetDirectory + "beans/tenBean.png")); + BufferedImage oneBean = ImageIO.read(new File(Constants.AssetDirectory + "beans/oneBean.png")); + + final int baseWidth = imageBase.getWidth(); + final int baseHeight = imageBase.getHeight(); + + long calcBean = beans; + + System.out.println("BEANS: " + beans); + + long thousands = beans / 1000; + calcBean = beans % 1000; + long hundreds = (calcBean / 100); + calcBean = calcBean % 100; + long tens = (calcBean / 10); + calcBean = calcBean % 10; + long ones = calcBean; + + BufferedImage beanImage = new BufferedImage(baseWidth, baseHeight, BufferedImage.TYPE_INT_ARGB); + Graphics beanGraphics = beanImage.getGraphics(); + + for(int i = 0; i < ones; i++) + { + int x = (int)(Math.random() * (baseWidth - oneBean.getWidth())) + 1; + int y = (int)(Math.random() * (baseHeight - oneBean.getHeight())) + 1; + beanGraphics.drawImage(oneBean, x, y, null); + } + + for(int i = 0; i < tens; i++) + { + int x = (int)(Math.random() * (baseWidth - tenBean.getWidth())) + 1; + int y = (int)(Math.random() * (baseHeight - tenBean.getHeight())) + 1; + beanGraphics.drawImage(tenBean, x, y, null); + } + + for(int i = 0; i < hundreds; i++) + { + int x = (int)(Math.random() * (baseWidth - hunBean.getWidth())) + 1; + int y = (int)(Math.random() * (baseHeight - hunBean.getHeight())) + 1; + beanGraphics.drawImage(hunBean, x, y, null); + } + + for(int i = 0; i < thousands; i++) + { + int x = (int)(Math.random() * (baseWidth - thouBean.getWidth())) + 1; + int y = (int)(Math.random() * (baseHeight - thouBean.getHeight())) + 1; + beanGraphics.drawImage(thouBean, x, y, null); + } + + Font font = null; + try { + font = Font.createFont(Font.TRUETYPE_FONT, new File(Constants.AssetDirectory +"fonts/B612Mono-Regular.ttf")); + } catch (Exception e) + { + } + Font beanFont = new Font("font", Font.BOLD, 45); + beanGraphics.setFont(beanFont); + beanGraphics.drawString("YOU GOT " + beans + " BEANS", 0, baseHeight / 2); + + ImageIO.write(beanImage, "PNG", new File("beanImage.png")); + return new File("beanImage.png"); + } } From 0728370bf2d9c536acc6f2c2ac55345ba51181a4 Mon Sep 17 00:00:00 2001 From: Alex Stewart Date: Thu, 5 Mar 2020 22:29:35 -0500 Subject: [PATCH 6/7] =Edited Font system --- src/commands/general/CommandBeansShow.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/commands/general/CommandBeansShow.java b/src/commands/general/CommandBeansShow.java index 6529904..3b0d6fc 100644 --- a/src/commands/general/CommandBeansShow.java +++ b/src/commands/general/CommandBeansShow.java @@ -105,8 +105,10 @@ public class CommandBeansShow extends Command beanGraphics.drawImage(thouBean, x, y, null); } - Font font = null; + try { + @SuppressWarnings("unused") + Font font = null; font = Font.createFont(Font.TRUETYPE_FONT, new File(Constants.AssetDirectory +"fonts/B612Mono-Regular.ttf")); } catch (Exception e) { From 99e3566188cc5f6b464b0c116470b562805eee6a Mon Sep 17 00:00:00 2001 From: Alex Stewart Date: Thu, 26 Mar 2020 02:53:20 -0400 Subject: [PATCH 7/7] =E6 bug fixes E6 changed Json request and response Edited to mirror those changes --- src/network/NetworkE6.java | 104 ++++++++++++++++++++++++------------- 1 file changed, 69 insertions(+), 35 deletions(-) diff --git a/src/network/NetworkE6.java b/src/network/NetworkE6.java index 1c65259..80db428 100644 --- a/src/network/NetworkE6.java +++ b/src/network/NetworkE6.java @@ -24,22 +24,54 @@ public class NetworkE6 // Internal JSON class and variables // //////////////////////////////////.//// private static final Gson jsonParser_ = new Gson(); - private static final String API_ROOT = "https://e621.net/post/index.json?"; + private static final String API_ROOT = "https://e621.net/posts.json?"; private static int maxSearchResults_ = 10; private static String[] blacklist = Ref.e621Blacklist; private class E6ResponseObject { - // public varaibles matching the case and the type we want for JSON. + // public variables matching the case and the type we want for JSON. // There are many more fields, but if we don't provide some it just // doesn't bother parsing them. - public String file_url; - public String id; - public String tags; - public String [] artist; - public String [] sources; - public String score; + public E6ResponseObjectPost [] posts; + } + + private class E6ResponseObjectPost + { + public String id; + public String [] sources; + public String[] pools; + public String rating; + public E6ResponseObjectFile file; + public E6ResponseObjectScore score; + public E6ResponseObjectTags tags; + public E6ResponseObjectRelationships relationships; + } + + private class E6ResponseObjectFile + { + public String url; + } + + private class E6ResponseObjectScore + { + public String total; + } + + private class E6ResponseObjectTags + { + public String[] general; + public String[] artist; + } + + private class E6ResponseObjectRelationships + { + public String has_children; + public String[] children; + } + + @@ -59,28 +91,26 @@ public class NetworkE6 // Configure and send request. Note: Random ordering added as first // tag by default. User-provided tags, therefore, will override it. // If order:score is provided, that will be honored over order:random. - String res = HTTPUtils.sendPOSTRequest(API_ROOT - , "tags=order:random%20" + input + "&limit=" + maxSearchResults_); - - + String res = HTTPUtils.sendGETRequest(API_ROOT + "tags=order:random%20" + input + "&limit=" + maxSearchResults_); if(res != null) { - // Use class evaluation on an array of the response imageObject to be able to hold multiple. - E6ResponseObject[] imageObj = jsonParser_.fromJson(res, E6ResponseObject[].class); + // Use class evaluation on an array of the response imageObject to be able to hold multiple. + System.out.println("Still"); + E6ResponseObject imageObj = jsonParser_.fromJson(res, E6ResponseObject.class); + System.out.println("Broken"); // For now, we really just wanna display images and their source. // Append them all separately to a response string w/ some flavor text. - if(imageObj.length < 1) + if(imageObj.posts.length < 1) { } else { - - for(int i = 0; i < imageObj.length; ++i) + for(int i = 0; i < imageObj.posts.length; ++i) { - String [] TagsList = imageObj[i].tags.split(" "); + String [] TagsList = imageObj.posts[i].tags.general; blacklisted = false; for(int j = 0; j < blacklist.length; j++) { @@ -99,10 +129,15 @@ public class NetworkE6 return null; } // We will always have a file URL. That's a given. - image.editImageURL(imageObj[i].file_url); - image.editPostURL("https://e621.net/post/show/" + imageObj[i].id); - if(imageObj[i].artist.length > 0) - image.editArtist(imageObj[i].artist[0]); + image.editImageURL(imageObj.posts[i].file.url); + image.editPostURL("https://e621.net/posts/" + imageObj.posts[i].id); + if(imageObj.posts[i].tags.artist.length > 0) + { + String artists = ""; + for(int j = 0; j < imageObj.posts[i].tags.artist.length; j++) + artists += imageObj.posts[i].tags.artist[j]; + image.editArtist(artists); + } else image.editArtist("Artist Not Found!"); @@ -110,13 +145,13 @@ public class NetworkE6 String sources = ""; - if(imageObj[i].sources != null) + if(imageObj.posts[i].sources != null) { - for(int k = 0; k < imageObj[i].sources.length; k ++) + for(int k = 0; k < imageObj.posts[i].sources.length; k ++) { - if(!imageObj[i].sources[k].endsWith(imageObj[i].file_url.substring(imageObj[i].file_url.lastIndexOf('.')))) + if(!imageObj.posts[i].sources[k].endsWith(imageObj.posts[i].file.url.substring(imageObj.posts[i].file.url.lastIndexOf('.')))) { - String source = imageObj[i].sources[k]; + String source = imageObj.posts[i].sources[k]; if(source.contains("//www.")) { source = source.substring(source.indexOf(".") + 1); @@ -127,31 +162,30 @@ public class NetworkE6 source = source.substring(source.indexOf("/") + 2); source = source.substring(0, source.indexOf('.')); } - sources += " [" + source + "](" + imageObj[i].sources[k] + ") "; + sources += " [" + source + "](" + imageObj.posts[i].sources[k] + ") "; } } - image.editDescriptionText("Score: " + imageObj[i].score + "\n**Source:**" + sources); + image.editDescriptionText("Score: " + imageObj.posts[i].score.total + "\n**Source:**" + sources); } else { - image.editDescriptionText("Score: " + imageObj[i].score); + image.editDescriptionText("Score: " + imageObj.posts[i].score.total); } - - if(imageObj[i].tags.split(" ").length > 15) + String descTags = ""; + if(imageObj.posts[i].tags.general.length > 15) { - String [] splitTags = imageObj[i].tags.split(" "); - String descTags = ""; for(int o = 0; o < 15; o++) { - descTags += splitTags[o] + ", "; + descTags += imageObj.posts[i].tags.general[o] + ", "; } image.editFooterText("[Tags] " + descTags + " etc."); } else { - image.editFooterText("[Tags] " + imageObj[i].tags.replace(" ", ", ")); + descTags = imageObj.posts[i].tags.general.toString(); + image.editFooterText("[Tags] " + descTags); } if(image.output().authorText != null)