diff --git a/.classpath b/.classpath index 6cf8f5a..30f7b88 100644 --- a/.classpath +++ b/.classpath @@ -27,5 +27,6 @@ + diff --git a/assets/beans/BeansBG.png b/assets/beans/BeansBG.png new file mode 100644 index 0000000..ae1bd6d Binary files /dev/null and b/assets/beans/BeansBG.png differ diff --git a/assets/beans/hunBean.png b/assets/beans/hunBean.png new file mode 100644 index 0000000..824db96 Binary files /dev/null and b/assets/beans/hunBean.png differ diff --git a/assets/beans/oneBean.png b/assets/beans/oneBean.png new file mode 100644 index 0000000..ec96286 Binary files /dev/null and b/assets/beans/oneBean.png differ diff --git a/assets/beans/tenBean.png b/assets/beans/tenBean.png new file mode 100644 index 0000000..36a3f92 Binary files /dev/null and b/assets/beans/tenBean.png differ diff --git a/assets/beans/thouBean.png b/assets/beans/thouBean.png new file mode 100644 index 0000000..3b4eeb8 Binary files /dev/null and b/assets/beans/thouBean.png differ diff --git a/assets/config.csv b/assets/config.csv index 685c3cd..bdc348e 100644 --- a/assets/config.csv +++ b/assets/config.csv @@ -116,7 +116,7 @@ "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","" +"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." @@ -187,7 +187,11 @@ "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","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/assets/fonts/B612Mono-Regular.ttf b/assets/fonts/B612Mono-Regular.ttf new file mode 100644 index 0000000..ec09c98 Binary files /dev/null and b/assets/fonts/B612Mono-Regular.ttf differ 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/beanImage.png b/beanImage.png new file mode 100644 index 0000000..4de82bd Binary files /dev/null and b/beanImage.png differ diff --git a/lib/nanohttpd-2.3.1.jar b/lib/nanohttpd-2.3.1.jar new file mode 100644 index 0000000..ade9bbe Binary files /dev/null and b/lib/nanohttpd-2.3.1.jar differ diff --git a/src/commands/general/CommandBeansShow.java b/src/commands/general/CommandBeansShow.java index f87b862..3b0d6fc 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,75 @@ 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); + } + + + try { + @SuppressWarnings("unused") + Font font = null; + 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"); + } } 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/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..cfd5551 100644 --- a/src/commands/general/CommandE6.java +++ b/src/commands/general/CommandE6.java @@ -1,60 +1,71 @@ -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) + { + image = searcher.getE6(input.args + " rating:safe"); + try + { + response = image.output(); + } + catch(Exception e) + { + res.send(LocStrings.stub("E6Blacklisted")); + return; + } + try + { + if(response.bodyImageURL == 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/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/NetworkE6.java b/src/network/NetworkE6.java index da8ebfa..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,33 +91,36 @@ 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.posts[i].tags.general; 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; + } } } @@ -94,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!"); @@ -105,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); @@ -122,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) diff --git a/src/network/NetworkSauceNAO.java b/src/network/NetworkSauceNAO.java index 080c25d..38e6408 100644 --- a/src/network/NetworkSauceNAO.java +++ b/src/network/NetworkSauceNAO.java @@ -1,48 +1,49 @@ -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?dbmask=268435456&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)); + System.out.println("HERE"); + return e6Sauce.getE6("id:" + sauceUrl.substring(27)).toString(); + } + return sauce.results.get(0).data.ext_urls[0]; + } + +} 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. 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 {