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
{