Merge branch 'master' into develop

This commit is contained in:
Matthew Cech
2020-03-26 17:47:28 -07:00
36 changed files with 1599 additions and 1025 deletions
+1
View File
@@ -27,5 +27,6 @@
<classpathentry kind="lib" path="lib/google-http-client-1.32.0.jar"/> <classpathentry kind="lib" path="lib/google-http-client-1.32.0.jar"/>
<classpathentry kind="lib" path="lib/google-api-services-youtube-v3-rev212-1.25.0.jar"/> <classpathentry kind="lib" path="lib/google-api-services-youtube-v3-rev212-1.25.0.jar"/>
<classpathentry kind="lib" path="lib/LavaPlayerJar-0.0.1-jar-with-dependencies.jar"/> <classpathentry kind="lib" path="lib/LavaPlayerJar-0.0.1-jar-with-dependencies.jar"/>
<classpathentry kind="lib" path="lib/nanohttpd-2.3.1.jar"/>
<classpathentry kind="output" path="bin"/> <classpathentry kind="output" path="bin"/>
</classpath> </classpath>
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

+12
View File
@@ -17,6 +17,8 @@
"Localized Commands","dbstats","" "Localized Commands","dbstats",""
"Localized Commands","defaultdance","" "Localized Commands","defaultdance",""
"Localized Commands","derp","" "Localized Commands","derp",""
"Localized Commands","derpi",""
"Localized Commands","e6",""
"Localized Commands","e621","" "Localized Commands","e621",""
"Localized Commands","eightball, 8ball","" "Localized Commands","eightball, 8ball",""
"Localized Commands","fetch","" "Localized Commands","fetch",""
@@ -48,6 +50,7 @@
"Localized Commands","stats","" "Localized Commands","stats",""
"Localized Commands","teey","" "Localized Commands","teey",""
"Localized Commands","tony, stark, dontfeelgood, dontfeelsogood","tony, stark, dontfeelgood, dontfeelsogood, snap" "Localized Commands","tony, stark, dontfeelgood, dontfeelsogood","tony, stark, dontfeelgood, dontfeelsogood, snap"
"Localized Commands","tradebeans, trade",""
"Localized Commands","tweet","" "Localized Commands","tweet",""
"Localized Commands","vote","" "Localized Commands","vote",""
"Localized Commands","wolfram","" "Localized Commands","wolfram",""
@@ -110,8 +113,10 @@
"Localized Strings","DBFlushInfo","Takes all objects queued for the database and writes them to the database, then says how many were written." "Localized Strings","DBFlushInfo","Takes all objects queued for the database and writes them to the database, then says how many were written."
"Localized Strings","DBStatsInfo","Shows current statistics for the database" "Localized Strings","DBStatsInfo","Shows current statistics for the database"
"Localized Strings","DefaultDanceInfo","y'all know forknife, get ready to dance, or make a friend dance with @!" "Localized Strings","DefaultDanceInfo","y'all know forknife, get ready to dance, or make a friend dance with @!"
"Localized Strings","DerpiError",""
"Localized Strings","DoWorkFinished","I finished with my work! :D" "Localized Strings","DoWorkFinished","I finished with my work! :D"
"Localized Strings","DoWorkInfo","Occupies a core for a few seconds" "Localized Strings","DoWorkInfo","Occupies a core for a few seconds"
"Localized Strings","E6Blacklisted","I can't show that image ;3; (it may be blacklisted)"
"Localized Strings","EightBallError","Hmm? You'll need to ask a question!" "Localized Strings","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","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." "Localized Strings","EightBallMaybe1","Reply hazy, try again."
@@ -182,7 +187,11 @@
"Localized Strings","MapVersion","Using mapgen v0.1" "Localized Strings","MapVersion","Using mapgen v0.1"
"Localized Strings","MapWidth","" "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","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","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","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","PingInfo","Will respond with Pong!"
"Localized Strings","PingResponse","Pong!" "Localized Strings","PingResponse","Pong!"
@@ -271,6 +280,8 @@
"Command Enabler","dbstats","1" "Command Enabler","dbstats","1"
"Command Enabler","defaultdance","1" "Command Enabler","defaultdance","1"
"Command Enabler","derp","1" "Command Enabler","derp","1"
"Command Enabler","derpi","1"
"Command Enabler","e6","1"
"Command Enabler","e621","1" "Command Enabler","e621","1"
"Command Enabler","eightball, 8ball","1" "Command Enabler","eightball, 8ball","1"
"Command Enabler","fetch","1" "Command Enabler","fetch","1"
@@ -313,6 +324,7 @@
"Command Enabler","stats","1" "Command Enabler","stats","1"
"Command Enabler","teey","1" "Command Enabler","teey","1"
"Command Enabler","tony, stark, dontfeelgood, dontfeelsogood","1" "Command Enabler","tony, stark, dontfeelgood, dontfeelsogood","1"
"Command Enabler","tradebeans, trade","1"
"Command Enabler","tweet","1" "Command Enabler","tweet","1"
"Command Enabler","vote","1" "Command Enabler","vote","1"
"Command Enabler","wolfram","1" "Command Enabler","wolfram","1"
1 Type Key Value
17 Localized Commands dbstats
18 Localized Commands defaultdance
19 Localized Commands derp
20 Localized Commands derpi
21 Localized Commands e6
22 Localized Commands e621
23 Localized Commands eightball, 8ball
24 Localized Commands fetch
50 Localized Commands stats
51 Localized Commands teey
52 Localized Commands tony, stark, dontfeelgood, dontfeelsogood tony, stark, dontfeelgood, dontfeelsogood, snap
53 Localized Commands tradebeans, trade
54 Localized Commands tweet
55 Localized Commands vote
56 Localized Commands wolfram
113 Localized Strings DBFlushInfo Takes all objects queued for the database and writes them to the database, then says how many were written.
114 Localized Strings DBStatsInfo Shows current statistics for the database
115 Localized Strings DefaultDanceInfo y'all know forknife, get ready to dance, or make a friend dance with @!
116 Localized Strings DerpiError
117 Localized Strings DoWorkFinished I finished with my work! :D
118 Localized Strings DoWorkInfo Occupies a core for a few seconds
119 Localized Strings E6Blacklisted I can't show that image ;3; (it may be blacklisted)
120 Localized Strings EightBallError Hmm? You'll need to ask a question!
121 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.
122 Localized Strings EightBallMaybe1 Reply hazy, try again.
187 Localized Strings MapVersion Using mapgen v0.1
188 Localized Strings MapWidth
189 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
190 Localized Strings MusicAddTrack
191 Localized Strings MusicInfo
192 Localized Strings MusicVolChanged Volume set to %s!
193 Localized Strings MusicVolCurrent Volume is at %s!
194 Localized Strings MusicVolOOB
195 Localized Strings PerishInfo Adds a red, 'a n g e r y' overlay to your icon or the icon of a friend you mentioned
196 Localized Strings PingInfo Will respond with Pong!
197 Localized Strings PingResponse Pong!
280 Command Enabler dbstats 1
281 Command Enabler defaultdance 1
282 Command Enabler derp 1
283 Command Enabler derpi 1
284 Command Enabler e6 1
285 Command Enabler e621 1
286 Command Enabler eightball, 8ball 1
287 Command Enabler fetch 1
324 Command Enabler stats 1
325 Command Enabler teey 1
326 Command Enabler tony, stark, dontfeelgood, dontfeelsogood 1
327 Command Enabler tradebeans, trade 1
328 Command Enabler tweet 1
329 Command Enabler vote 1
330 Command Enabler wolfram 1
Binary file not shown.
+22
View File
@@ -0,0 +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
end
+8
View File
@@ -0,0 +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
end
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.
+96 -2
View File
@@ -1,8 +1,23 @@
package commands.general; 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.Command;
import core.Constants;
import core.LocStrings; 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 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) public void onRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
{ {
if(input.mentions == null) 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 else
{ {
String mentionedBeans = ""; String mentionedBeans = "";
@@ -26,4 +49,75 @@ public class CommandBeansShow extends Command
res.send(String.format(LocStrings.stub("BeansShowMentioned"), mentionedBeans)); 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");
}
} }
+1 -1
View File
@@ -20,7 +20,7 @@ public class CommandBetBeans extends Command
{ {
String call = ""; String call = "";
int min = 50; int min = 20;
int bet = 0; int bet = 0;
int win = 0; int win = 0;
+3 -2
View File
@@ -68,22 +68,23 @@ public class CommandBoop extends Command
{ {
if(input.mentions == null) if(input.mentions == null)
{ {
// No one is booped, just the bot!
boopTracker.applyBoop(); boopTracker.applyBoop();
res.send(String.format(LocStrings.stub("BoopStandard"), user.name, boopTracker.howMany())); res.send(String.format(LocStrings.stub("BoopStandard"), user.name, boopTracker.howMany()));
} }
else else
{ {
// When someone boops one other person
if(input.mentions.length == 1) if(input.mentions.length == 1)
{ {
boopTracker.applyBoop();
res.send(String.format(LocStrings.stub("BoopPerson"), user.name, input.mentions[0].name)); res.send(String.format(LocStrings.stub("BoopPerson"), user.name, input.mentions[0].name));
return; return;
} }
// A number of people have been booped
String booped = ""; String booped = "";
for(int i = 0; i < input.mentions.length; i++) for(int i = 0; i < input.mentions.length; i++)
{ {
boopTracker.applyBoop();
if(i < input.mentions.length-1) if(i < input.mentions.length-1)
booped += input.mentions[i].name + ", "; booped += input.mentions[i].name + ", ";
else else
+1 -1
View File
@@ -32,7 +32,7 @@ public class CommandColor extends Command
public void onRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res) 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. // 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 // Verify the color was even found
if(colorData == null) if(colorData == null)
+72
View File
@@ -0,0 +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"));
}
}
}
}
+71
View File
@@ -0,0 +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;
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"));
}
}
}
}
}
+12 -3
View File
@@ -27,13 +27,22 @@ public class CommandTradeBeans extends Command
} }
int beans = 0; int beans = 0;
try {
try
{
beans = Integer.parseInt(input.args.split(" ")[0]); beans = Integer.parseInt(input.args.split(" ")[0]);
} }
catch (NumberFormatException e) catch (NumberFormatException e)
{ {
res.send(LocStrings.stub("TradeBeansIntParseError")); try
return; {
beans = Integer.parseInt(input.args.split(" ")[1]);
}
catch(Exception eInner)
{
res.send(LocStrings.stub("TradeBeansIntParseError"));
return;
}
} }
if(user.getBeans() < beans) if(user.getBeans() < beans)
+1
View File
@@ -18,6 +18,7 @@ public class CommandMusicMain extends Command
framework.addCommand("skip", new SubCommandSkip(KittyRole.General, KittyRating.Safe)); framework.addCommand("skip", new SubCommandSkip(KittyRole.General, KittyRating.Safe));
framework.addCommand("stop", new SubCommandStop(KittyRole.General, KittyRating.Safe)); framework.addCommand("stop", new SubCommandStop(KittyRole.General, KittyRating.Safe));
framework.addCommand("playlist", new SubCommandPlaylist(KittyRole.General, KittyRating.Safe)); framework.addCommand("playlist", new SubCommandPlaylist(KittyRole.General, KittyRating.Safe));
framework.addCommand("volume", new SubCommandVolume(KittyRole.General, KittyRating.Safe));
} }
@Override @Override
+2 -1
View File
@@ -1,5 +1,6 @@
package commands.music; package commands.music;
import core.LocStrings;
import core.SubCommand; import core.SubCommand;
import core.SubCommandFormattable; import core.SubCommandFormattable;
import dataStructures.KittyChannel; import dataStructures.KittyChannel;
@@ -27,6 +28,6 @@ public class SubCommandAddTrack extends SubCommand
video = YT.getYT(video); video = YT.getYT(video);
} }
guild.audio.playVideo(video); guild.audio.playVideo(video);
return new SubCommandFormattable(video); return new SubCommandFormattable(String.format(LocStrings.stub("MusicAddTrack"), video));
} }
} }
+23 -23
View File
@@ -1,23 +1,23 @@
package commands.music; package commands.music;
import core.SubCommand; import core.SubCommand;
import core.SubCommandFormattable; import core.SubCommandFormattable;
import dataStructures.KittyChannel; import dataStructures.KittyChannel;
import dataStructures.KittyGuild; import dataStructures.KittyGuild;
import dataStructures.KittyRating; import dataStructures.KittyRating;
import dataStructures.KittyRole; import dataStructures.KittyRole;
import dataStructures.KittyUser; import dataStructures.KittyUser;
import dataStructures.UserInput; import dataStructures.UserInput;
public class SubCommandSkip extends SubCommand public class SubCommandSkip extends SubCommand
{ {
public SubCommandSkip(KittyRole level, KittyRating rating) { super(level, rating); } public SubCommandSkip(KittyRole level, KittyRating rating) { super(level, rating); }
{ {
} }
@Override @Override
public SubCommandFormattable OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input) public SubCommandFormattable OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input)
{ {
return new SubCommandFormattable(guild.audio.skipVideo(guild.audio.player)); return new SubCommandFormattable(guild.audio.skipVideo(guild.audio.player));
} }
} }
+42
View File
@@ -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));
}
}
+4
View File
@@ -108,6 +108,10 @@ public class CommandManager
this.register(LocCommands.stub("music"), new CommandMusicMain(KittyRole.General, KittyRating.Safe)); this.register(LocCommands.stub("music"), new CommandMusicMain(KittyRole.General, KittyRating.Safe));
this.register(LocCommands.stub("defaultdance"), new CommandDefaultDance(KittyRole.General, KittyRating.Safe)); this.register(LocCommands.stub("defaultdance"), new CommandDefaultDance(KittyRole.General, KittyRating.Safe));
this.register(LocCommands.stub("getsauce"), new CommandGetSauce(KittyRole.General, KittyRating.Safe)); this.register(LocCommands.stub("getsauce"), new CommandGetSauce(KittyRole.General, KittyRating.Safe));
this.register(LocCommands.stub("tradebeans, trade"), new CommandTradeBeans(KittyRole.General, KittyRating.Safe));
this.register(LocCommands.stub("e6"), new CommandE6(KittyRole.General, KittyRating.Filtered));
this.register(LocCommands.stub("derpi"), new CommandDerpi(KittyRole.General, KittyRating.Filtered));
} }
// Allows the command manager to keep track of a command. Takes a pair (the un-localized and localzied commands) // Allows the command manager to keep track of a command. Takes a pair (the un-localized and localzied commands)
+478 -477
View File
@@ -1,478 +1,479 @@
package core; package core;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.concurrent.Semaphore; import java.util.concurrent.Semaphore;
import javax.security.auth.login.LoginException; import javax.security.auth.login.LoginException;
import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager; import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager;
import com.sedmelluq.discord.lavaplayer.player.DefaultAudioPlayerManager; import com.sedmelluq.discord.lavaplayer.player.DefaultAudioPlayerManager;
import com.sedmelluq.discord.lavaplayer.source.AudioSourceManagers; import com.sedmelluq.discord.lavaplayer.source.AudioSourceManagers;
//import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager; //import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager;
//import com.sedmelluq.discord.lavaplayer.player.DefaultAudioPlayerManager; //import com.sedmelluq.discord.lavaplayer.player.DefaultAudioPlayerManager;
import core.lua.PluginManager; import core.lua.PluginManager;
import dataStructures.KittyChannel; import dataStructures.KittyChannel;
import dataStructures.KittyCore; import dataStructures.KittyCore;
import dataStructures.KittyGuild; import dataStructures.KittyGuild;
import dataStructures.KittyRating; import dataStructures.KittyRating;
import dataStructures.KittyRole; import dataStructures.KittyRole;
import dataStructures.KittyStartupMode; import dataStructures.KittyStartupMode;
import dataStructures.KittyUser; import dataStructures.KittyUser;
import main.Main; import main.Main;
import net.dv8tion.jda.core.AccountType; import net.dv8tion.jda.core.AccountType;
import net.dv8tion.jda.core.JDA; import net.dv8tion.jda.core.JDA;
import net.dv8tion.jda.core.JDABuilder; import net.dv8tion.jda.core.JDABuilder;
import net.dv8tion.jda.core.entities.Emote; import net.dv8tion.jda.core.entities.Emote;
import net.dv8tion.jda.core.entities.Game; import net.dv8tion.jda.core.entities.Game;
import net.dv8tion.jda.core.entities.Guild; import net.dv8tion.jda.core.entities.Guild;
import net.dv8tion.jda.core.entities.Member; import net.dv8tion.jda.core.entities.Member;
import net.dv8tion.jda.core.entities.User; import net.dv8tion.jda.core.entities.User;
import net.dv8tion.jda.core.events.message.guild.GuildMessageReceivedEvent; import net.dv8tion.jda.core.events.message.guild.GuildMessageReceivedEvent;
import offline.Ref; import offline.Ref;
import utils.AdminControl; import utils.AdminControl;
//import utils.AudioUtils; //import utils.AudioUtils;
import utils.GlobalLog; import utils.GlobalLog;
import utils.LogFilter; import utils.LogFilter;
import utils.audio.AudioUtils; import utils.audio.AudioUtils;
// NOTE(wisp): Isolated factory to assist with storage and caching if needed. // NOTE(wisp): Isolated factory to assist with storage and caching if needed.
// This also minimizes the number of places JDA interacts with our codebase. // 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. // As it stands, if the object name begins with Kitty, it's constructed here.
// TODO: Make all methods ID based instead of event based // TODO: Make all methods ID based instead of event based
public class ObjectBuilderFactory public class ObjectBuilderFactory
{ {
// Key: guild string id, Value: guild information // Key: guild string id, Value: guild information
private static HashMap<String, KittyGuild> guildCache; private static HashMap<String, KittyGuild> guildCache;
// Key: channel string id, Value: channel information // Key: channel string id, Value: channel information
private static HashMap<String, KittyChannel> channelCache; private static HashMap<String, KittyChannel> channelCache;
// Key: guild string id + user string id, Value: user information // Key: guild string id + user string id, Value: user information
private static HashMap<String, KittyUser> userCache; private static HashMap<String, KittyUser> userCache;
// For tracking and managing object sync // For tracking and managing object sync
private static DatabaseManager database; private static DatabaseManager database;
// Stats tracking and whatnot... for setting stats too internally potentially // Stats tracking and whatnot... for setting stats too internally potentially
private static Stats stats; private static Stats stats;
// RPManger for tracking RP system // RPManger for tracking RP system
private static RPManager rpManager; private static RPManager rpManager;
// Plugin manager // Plugin manager
private static PluginManager pluginManager; private static PluginManager pluginManager;
// Command manager // Command manager
private static CommandManager commandManager; private static CommandManager commandManager;
//Audio track manager //Audio track manager
private static AudioPlayerManager playerManager = new DefaultAudioPlayerManager(); private static AudioPlayerManager playerManager = new DefaultAudioPlayerManager();
// Localization classes - these are singletons, but should be initialized before almost all other // 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. // 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 LocStrings locStrings;
@SuppressWarnings("unused") private static LocCommands locCommands; @SuppressWarnings("unused") private static LocCommands locCommands;
// Config // Config
@SuppressWarnings("unused") private static Config config; @SuppressWarnings("unused") private static Config config;
// Lazy initialization multithreaded mutex stuff to prevent explosions. // Lazy initialization multithreaded mutex stuff to prevent explosions.
// TODO: Investigate using 'synchronized' instead potentially // TODO: Investigate using 'synchronized' instead potentially
private static boolean hasInitialized; private static boolean hasInitialized;
private static Semaphore initMutex = new Semaphore(1); private static Semaphore initMutex = new Semaphore(1);
private static JDA kitty; private static JDA kitty;
// This is it, this is how the lazy init starts! // This is it, this is how the lazy init starts!
private static void lazyInit() private static void lazyInit()
{ {
if(hasInitialized) if(hasInitialized)
return; return;
try try
{ {
initMutex.acquire(); initMutex.acquire();
try try
{ {
// structure initialization // structure initialization
// Construct necessary data structures. // Construct necessary data structures.
guildCache = new HashMap<String, KittyGuild>(); guildCache = new HashMap<String, KittyGuild>();
userCache = new HashMap<String, KittyUser>(); userCache = new HashMap<String, KittyUser>();
channelCache = new HashMap<String, KittyChannel>(); channelCache = new HashMap<String, KittyChannel>();
database = null; database = null;
stats = null; stats = null;
AudioSourceManagers.registerRemoteSources(playerManager); AudioSourceManagers.registerRemoteSources(playerManager);
AudioSourceManagers.registerLocalSource(playerManager); AudioSourceManagers.registerLocalSource(playerManager);
// Start by reading from things that are external. Because // Start by reading from things that are external. Because
// we require these things to be resolved before the rest of the application, // we require these things to be resolved before the rest of the application,
// we place them here. // we place them here.
config = new Config(); config = new Config();
} }
finally finally
{ {
initMutex.release(); initMutex.release();
hasInitialized = true; hasInitialized = true;
} }
} }
catch(InterruptedException ie) catch(InterruptedException ie)
{ {
GlobalLog.error(LogFilter.Core, "Issue during object builder lazy initialization." GlobalLog.error(LogFilter.Core, "Issue during object builder lazy initialization."
+ " The factory was not initialized, and kitty will not be able to continue functionally."); + " The factory was not initialized, and kitty will not be able to continue functionally.");
} }
} }
//////////////////////// ////////////////////////
// Extraction Methods // // Extraction Methods //
//////////////////////// ////////////////////////
// Explicitly locks: guildCache // Explicitly locks: guildCache
public static KittyGuild extractGuild(GuildMessageReceivedEvent event) public static KittyGuild extractGuild(GuildMessageReceivedEvent event)
{ {
lazyInit(); lazyInit();
// Look up the guild. This process can only happen in a single-threaded way // 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 // because of the nature of the cache. We wait until the last second to
// look up the guild. // look up the guild.
String uid = event.getGuild().getId(); String uid = event.getGuild().getId();
List<Emote> emotes = event.getGuild().getEmotes(); List<Emote> emotes = event.getGuild().getEmotes();
ArrayList<String> emotesString = new ArrayList<String>(); ArrayList<String> emotesString = new ArrayList<String>();
String emote; HashMap<Long, KittyChannel> channels = new HashMap<Long, KittyChannel>();
String emoteFix; String emote;
for(int i = 0; i < emotes.size(); i++) String emoteFix;
{ channels.put(Long.getLong(uid), extractChannel(event));
emote = emotes.get(i).toString(); for(int i = 0; i < emotes.size(); i++)
emoteFix = "<:" + emote.substring(2, emote.indexOf("(")); {
emoteFix += ":" + emote.substring(emote.indexOf("(")+1, emote.length()-1) + ">"; emote = emotes.get(i).toString();
emotesString.add(emoteFix); 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; // once we're lazily initialized, we can synchronize w/ the
synchronized (guildCache) // guildCache object now instead of having to use a mutex.
{ KittyGuild guild = null;
KittyGuild cachedGuild = guildCache.get(uid); synchronized (guildCache)
if(cachedGuild != null) {
{ KittyGuild cachedGuild = guildCache.get(uid);
guild = cachedGuild; if(cachedGuild != null)
} {
else guild = cachedGuild;
{ }
// Construct a new guild with defaults else
guild = new KittyGuild(uid, new AdminControl(event.getGuild()), emotesString, new AudioUtils(event.getGuild(), playerManager)); {
DatabaseManager.instance.globalRegister(guild); // Construct a new guild with defaults
guildCache.put(uid, guild); 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; }
}
return guild;
// Explicitly locks: guildCache }
public static KittyRole extractRole(GuildMessageReceivedEvent event)
{ // Explicitly locks: guildCache
lazyInit(); public static KittyRole extractRole(GuildMessageReceivedEvent event)
{
// Looks up the user role. If none is found we check to see if they own lazyInit();
// the guild if not, they're assumed to be
// allowed to use the bot at a general level. // Looks up the user role. If none is found we check to see if they own
KittyRole role = KittyRole.General; // the guild if not, they're assumed to be
// allowed to use the bot at a general level.
if(event.getAuthor().getId() == event.getGuild().getOwner().getUser().getId()) KittyRole role = KittyRole.General;
{
role = KittyRole.Admin; if(event.getAuthor().getId() == event.getGuild().getOwner().getUser().getId())
} {
role = KittyRole.Admin;
String uid = event.getGuild().getId() + event.getAuthor().getId(); }
synchronized(userCache)
{ String uid = event.getGuild().getId() + event.getAuthor().getId();
KittyUser cachedUser = userCache.get(uid); synchronized(userCache)
if(cachedUser != null) {
role = cachedUser.getRole(); KittyUser cachedUser = userCache.get(uid);
} if(cachedUser != null)
role = cachedUser.getRole();
return role; }
}
return role;
// Explicitly locks: guildCache }
// Extracts the content rating information it can from the provided event.
public static KittyRating extractContentRating(GuildMessageReceivedEvent event) // Explicitly locks: guildCache
{ // Extracts the content rating information it can from the provided event.
lazyInit(); public static KittyRating extractContentRating(GuildMessageReceivedEvent event)
{
// Look up content rating of the guild, returns a safe content rating. lazyInit();
KittyRating contentRating = KittyRating.Safe;
String uid = event.getGuild().getId(); // Look up content rating of the guild, returns a safe content rating.
synchronized(guildCache) KittyRating contentRating = KittyRating.Safe;
{ String uid = event.getGuild().getId();
KittyGuild cachedGuild = guildCache.get(uid); synchronized(guildCache)
if(cachedGuild != null) {
contentRating = cachedGuild.contentRating; KittyGuild cachedGuild = guildCache.get(uid);
} if(cachedGuild != null)
contentRating = cachedGuild.contentRating;
return contentRating; }
}
return contentRating;
// Implicitly locks guild cache by calling ExtractGuild }
public static KittyChannel extractChannel(GuildMessageReceivedEvent event)
{ // Implicitly locks guild cache by calling ExtractGuild
lazyInit(); public static KittyChannel extractChannel(GuildMessageReceivedEvent event)
{
String channelID = event.getChannel().getId(); lazyInit();
String guildID = event.getGuild().getId(); String channelID = event.getChannel().getId();
KittyChannel channel = null; KittyChannel channel = null;
synchronized(channelCache) synchronized(channelCache)
{ {
KittyChannel cachedChannel = channelCache.get(channelID); KittyChannel cachedChannel = channelCache.get(channelID);
boolean mature;
if(cachedChannel != null)
{ if(cachedChannel != null)
channel = cachedChannel; {
} channel = cachedChannel;
else }
{ else
KittyGuild cachedGuild = guildCache.get(guildID); {
channel = new KittyChannel(channelID, cachedGuild); mature = event.getChannel().isNSFW();
channelCache.put(channelID, channel); channel = new KittyChannel(channelID, mature);
} channelCache.put(channelID, channel);
} }
}
return channel;
} return channel;
}
// Implicitly locks guild cache by calling ExtractRole and ExtractGuild
public static KittyUser extractUser(GuildMessageReceivedEvent event) // Implicitly locks guild cache by calling ExtractRole and ExtractGuild
{ public static KittyUser extractUser(GuildMessageReceivedEvent event)
lazyInit(); {
lazyInit();
String uid = event.getGuild().getId() + event.getAuthor().getId();
KittyUser user = null; String uid = event.getGuild().getId() + event.getAuthor().getId();
synchronized(userCache) KittyUser user = null;
{ synchronized(userCache)
KittyUser cachedUser = userCache.get(uid); {
if(cachedUser != null) KittyUser cachedUser = userCache.get(uid);
{ if(cachedUser != null)
updateUser(cachedUser, event.getMember()); {
user = cachedUser; updateUser(cachedUser, event.getMember());
} user = cachedUser;
else }
{ else
KittyRole role = extractRole(event); {
KittyGuild guild = extractGuild(event); KittyRole role = extractRole(event);
KittyGuild guild = extractGuild(event);
String name;
if(event.getMember().getNickname() == null) String name;
name = event.getAuthor().getName(); if(event.getMember().getNickname() == null)
else name = event.getAuthor().getName();
name = event.getMember().getNickname(); else
name = event.getMember().getNickname();
String discordID = event.getMember().getUser().getId();
String avatarID = event.getAuthor().getAvatarUrl(); String discordID = event.getMember().getUser().getId();
user = new KittyUser(name, guild, role, uid, avatarID, discordID); String avatarID = event.getAuthor().getAvatarUrl();
DatabaseManager.instance.globalRegister(user); user = new KittyUser(name, guild, role, uid, avatarID, discordID);
userCache.put(uid, user); DatabaseManager.instance.globalRegister(user);
} userCache.put(uid, user);
} }
}
if(event.getMessage().getMentionedMembers().isEmpty())
return user; if(event.getMessage().getMentionedMembers().isEmpty())
return user;
Member mentioned;
for(int i = 0; i < event.getMessage().getMentionedMembers().size(); i++) Member mentioned;
{ for(int i = 0; i < event.getMessage().getMentionedMembers().size(); i++)
mentioned = event.getMessage().getMentionedMembers().get(i); {
if(mentioned.getNickname() != null) mentioned = event.getMessage().getMentionedMembers().get(i);
extractUserByJDAUser(event.getGuild().getId(), mentioned.getNickname(), if(mentioned.getNickname() != null)
mentioned.getUser().getId(), mentioned.getUser().getAvatarUrl(), mentioned.getUser().getId()); extractUserByJDAUser(event.getGuild().getId(), mentioned.getNickname(),
else mentioned.getUser().getId(), mentioned.getUser().getAvatarUrl(), mentioned.getUser().getId());
extractUserByJDAUser(event.getGuild().getId(), mentioned.getUser().getName(), else
mentioned.getUser().getId(), mentioned.getUser().getAvatarUrl(), mentioned.getUser().getId()); extractUserByJDAUser(event.getGuild().getId(), mentioned.getUser().getName(),
} mentioned.getUser().getId(), mentioned.getUser().getAvatarUrl(), mentioned.getUser().getId());
}
return user;
} return user;
}
// TODO: Clean up
public static KittyUser extractUserByJDAUser(String guildID, String name, String userID, String avatarID, String discordID) // TODO: Clean up
{ public static KittyUser extractUserByJDAUser(String guildID, String name, String userID, String avatarID, String discordID)
lazyInit(); {
lazyInit();
String uid = guildID + userID;
KittyUser user = null; String uid = guildID + userID;
synchronized(userCache) KittyUser user = null;
{ synchronized(userCache)
KittyUser cachedUser = userCache.get(uid); {
if(cachedUser != null) KittyUser cachedUser = userCache.get(uid);
{ if(cachedUser != null)
if(name != null) {
cachedUser.name = name; if(name != null)
cachedUser.name = name;
cachedUser.avatarID = avatarID;
user = cachedUser; cachedUser.avatarID = avatarID;
} user = cachedUser;
else }
{ else
KittyRole role = KittyRole.General; {
KittyGuild guild = guildCache.get(guildID); KittyRole role = KittyRole.General;
user = new KittyUser(name, guild, role, uid, avatarID, discordID); KittyGuild guild = guildCache.get(guildID);
DatabaseManager.instance.globalRegister(user); user = new KittyUser(name, guild, role, uid, avatarID, discordID);
userCache.put(uid, user); DatabaseManager.instance.globalRegister(user);
} userCache.put(uid, user);
} }
}
return 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. // There is some redundant lookup occurring. If the user isn't cached yet, then we construct them and cache them.
public static KittyUser getKittyUser(String guildID, String userID) // 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; String uid = guildID + userID;
synchronized(userCache) KittyUser user = null;
{ synchronized(userCache)
user = userCache.get(uid); {
} user = userCache.get(uid);
}
if(user == null)
{ if(user == null)
Guild jdaGuild = kitty.getGuildById(guildID); {
if(jdaGuild == null) return null; Guild jdaGuild = kitty.getGuildById(guildID);
if(jdaGuild == null) return null;
Member jdaMember = jdaGuild.getMemberById(userID);
if(jdaMember == null) return null; Member jdaMember = jdaGuild.getMemberById(userID);
if(jdaMember == null) return null;
User jdaUser = jdaMember.getUser();
if(jdaUser == 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); user = extractUserByJDAUser(guildID, jdaMember.getNickname(), jdaUser.getId(), jdaUser.getAvatarUrl(), jdaUser.getId());
} updateUser(user, jdaMember);
}
return user;
} return user;
}
// Updates a user's name appropriately based on nickname if available
public static void updateUser(KittyUser user, Member member) // Updates a user's name appropriately based on nickname if available
{ public static void updateUser(KittyUser user, Member member)
if(member.getNickname() == null) {
{ if(member.getNickname() == null)
user.name = member.getUser().getName(); {
} user.name = member.getUser().getName();
else }
{ else
user.name = member.getNickname(); {
} user.name = member.getNickname();
}
user.avatarID = member.getUser().getAvatarUrl();
} user.avatarID = member.getUser().getAvatarUrl();
}
//////////////////////////
// Construction Methods // //////////////////////////
////////////////////////// // Construction Methods //
// Builds the core of the bot //////////////////////////
public static KittyCore constructKittyCore() throws LoginException, InterruptedException // Builds the core of the bot
{ public static KittyCore constructKittyCore() throws LoginException, InterruptedException
lazyInit(); {
lazyInit();
// Determine token based on config. Default to test token.
String tokenToUse = Ref.TestToken; // Determine token based on config. Default to test token.
if(ConfigGlobals.getStartupMode() == KittyStartupMode.Release) String tokenToUse = Ref.TestToken;
tokenToUse = Ref.Token; if(ConfigGlobals.getStartupMode() == KittyStartupMode.Release)
tokenToUse = Ref.PoguToken;
// Construct bot based on token
kitty = new JDABuilder(AccountType.BOT) // Construct bot based on token
.setToken(tokenToUse).buildBlocking(); kitty = new JDABuilder(AccountType.BOT)
kitty.getPresence().setGame(Game.playing("with a laser pointer")); .setToken(tokenToUse).buildBlocking();
kitty.addEventListener(new Main()); kitty.getPresence().setGame(Game.playing("with a laser pointer"));
kitty.addEventListener(new Main());
return new KittyCore(kitty);
} 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 // Default construction of the command manager. In order to remotely resolve command enabling
// the CommandEnabler object passed in. In theory, we could have multiple CommandManagers, tho we can // and disabling, what we do is construct the commands with a localized pair that is checked against
// only have one CommandEnabler. // the CommandEnabler object passed in. In theory, we could have multiple CommandManagers, tho we can
public static CommandManager constructCommandManager(CommandEnabler commandEnabler) // only have one CommandEnabler.
{ public static CommandManager constructCommandManager(CommandEnabler commandEnabler)
lazyInit(); {
lazyInit();
if(commandManager == null)
commandManager = new CommandManager(commandEnabler); if(commandManager == null)
commandManager = new CommandManager(commandEnabler);
return commandManager;
} return commandManager;
}
// Default database manager construction. It can be constructed
// in different ways, and so we construct it outside of the constructor for // Default database manager construction. It can be constructed
// the factory since it doesn't have to be present / can be elsewhere. // in different ways, and so we construct it outside of the constructor for
// Effectively we cache the database here. // the factory since it doesn't have to be present / can be elsewhere.
public static DatabaseManager constructDatabaseManager() // Effectively we cache the database here.
{ public static DatabaseManager constructDatabaseManager()
lazyInit(); {
lazyInit();
if(database == null)
database = new DatabaseManager(); if(database == null)
database = new DatabaseManager();
return database;
} return database;
}
public static Stats constructStats(CommandManager manager)
{ public static Stats constructStats(CommandManager manager)
lazyInit(); {
lazyInit();
if(stats == null)
stats = new Stats(manager); if(stats == null)
stats = new Stats(manager);
return stats;
} return stats;
}
public static RPManager constructRPManager()
{ public static RPManager constructRPManager()
lazyInit(); {
lazyInit();
if(rpManager == null)
rpManager = new RPManager(); if(rpManager == null)
rpManager = new RPManager();
return rpManager;
} return rpManager;
}
public static PluginManager constructPluginManager()
{ public static PluginManager constructPluginManager()
lazyInit(); {
lazyInit();
if(pluginManager == null)
pluginManager = new PluginManager(Constants.AssetDirectory + "plugins/"); if(pluginManager == null)
pluginManager = new PluginManager(Constants.AssetDirectory + "plugins/");
return pluginManager;
} return pluginManager;
}
/////////////////////
// Utility Methods // /////////////////////
///////////////////// // Utility Methods //
/////////////////////
// Returns number of cached guilds (does not equal total users in the database, only what's in memory)
public static Integer getGuildCount() // Returns number of cached guilds (does not equal total users in the database, only what's in memory)
{ synchronized(guildCache) public static Integer getGuildCount()
{ { synchronized(guildCache)
return guildCache.size(); {
} 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() // Returns number of cached users (does not equal total users in the database, only what's in memory)
{ synchronized(userCache) public static Integer getUserCount()
{ { synchronized(userCache)
return userCache.size(); {
} return userCache.size();
} }
}
} }
+33 -16
View File
@@ -1,40 +1,57 @@
package dataStructures; package dataStructures;
// This is a structure representing an image reponse for handing around. import java.awt.Color;
// This is a structure representing an image response for handing around.
public class GenericImage public class GenericImage
{ {
private String artist; private KittyEmbed response= new KittyEmbed();
private String postURL;
private String imageURL;
public GenericImage(String artist, String postURL, String imageURL) public GenericImage(String artist, String postURL, String imageURL)
{ {
this.artist = artist; response.authorText = null;
this.postURL = postURL; response.color = new Color(0,0,0);
this.imageURL = imageURL;
} }
public void editArtist(String artist) public void editArtist(String artist)
{ {
this.artist = artist; response.authorText = artist;
}
public void editAuthorImage(String URL)
{
response.authorImage = URL;
} }
public void editPostURL(String postURL) public void editPostURL(String postURL)
{ {
this.postURL = postURL; response.authorLink = postURL;
} }
public void editImageURL(String imageURL) public void editImageURL(String imageURL)
{ {
this.imageURL = imageURL; response.imageURL = imageURL;
} }
public String toString() public void editDescriptionText(String score)
{ {
if(imageURL.isEmpty()) response.descriptionText = score;
{ }
return "I couldn't find anything! Please try again!";
} public void editFooterText(String tags)
return "Artist: " + artist + "\n<" + postURL.trim() + ">\n" + imageURL; {
response.footerText = tags;
}
public KittyEmbed output()
{
return response;
}
public boolean isValid()
{
if(response.title != null)
return true;
return false;
} }
} }
+15 -31
View File
@@ -1,31 +1,15 @@
package dataStructures; package dataStructures;
//import core.DatabaseTrackedObject;
public class KittyChannel
public class KittyChannel //extends DatabaseTrackedObject {
{ public String uniqueID;
public String uniqueID; public boolean mature;
public KittyGuild guild;
public KittyChannel(String uniqueID, boolean mature)
//public KittyRating rating; {
//public bool isVoice; //super(uniqueID);
this.uniqueID = uniqueID;
public KittyChannel(String uniqueID, KittyGuild guild) this.mature = false;
{ }
//super(uniqueID); }
this.uniqueID = uniqueID;
this.guild = guild;
}
// @Override
// public String serialize()
// {
// return "";
// }
//
// @Override
// public void deSerialzie(String string)
// {
//
// }
}
+180 -176
View File
@@ -1,176 +1,180 @@
package dataStructures; package dataStructures;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import core.DatabaseManager;
import core.DatabaseTrackedObject; import core.DatabaseManager;
import utils.AdminControl; import core.DatabaseTrackedObject;
import utils.audio.AudioUtils; 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 // Context for a given guild for kittybot. Primarily designed to hold guild-specific settings.
{ public class KittyGuild extends DatabaseTrackedObject
// Variables {
public final String uniqueID; // Variables
public KittyRating contentRating; public final String uniqueID;
public KittyUser guildOwner; public KittyRating contentRating;
public boolean polling; public KittyUser guildOwner;
public String poll; public boolean polling;
public boolean raffling; public String poll;
public int raffleCost; public boolean raffling;
public ArrayList<String> hasVoted = new ArrayList<String>(); public int raffleCost;
public ArrayList<String> emoji = new ArrayList<String>(); public ArrayList<String> hasVoted = new ArrayList<String>();
public ArrayList <KittyPoll> choices = new ArrayList<KittyPoll>(); public ArrayList<String> emoji = new ArrayList<String>();
public AdminControl control; public ArrayList <KittyPoll> choices = new ArrayList<KittyPoll>();
public AudioUtils audio; public HashMap <Long, KittyChannel> channels;
public ArrayList <KittyUser> raffleUsersUnchosen = new ArrayList<KittyUser>(); public AdminControl control;
public ArrayList <KittyUser> raffleUsersChosen = new ArrayList<KittyUser>(); public AudioUtils audio;
public ArrayList <KittyUser> raffleUsersUnchosen = new ArrayList<KittyUser>();
// Database synced info public ArrayList <KittyUser> raffleUsersChosen = new ArrayList<KittyUser>();
private final String roleListName = "guildRoles";
public final KittyTrackedVector roleList; // Database synced info
private final String roleListName = "guildRoles";
private final String beansName = "guildBeans"; public final KittyTrackedVector roleList;
public final KittyTrackedLong beans;
private final String beansName = "guildBeans";
private String commandIndicator; public final KittyTrackedLong beans;
private void registerTrackedObjects() private String commandIndicator;
{
DatabaseManager.instance.globalRegister(roleList); private void registerTrackedObjects()
DatabaseManager.instance.globalRegister(beans); {
} DatabaseManager.instance.globalRegister(roleList);
DatabaseManager.instance.globalRegister(beans);
// Default content for a guild }
public KittyGuild(String uniqueID, AdminControl adminControl, ArrayList <String> emoji, AudioUtils audio)
{ // Default content for a guild
public KittyGuild(String uniqueID, AdminControl adminControl, ArrayList <String> emoji, AudioUtils audio, HashMap<Long, KittyChannel> channels)
super(uniqueID); {
this.uniqueID = uniqueID;
roleList = new KittyTrackedVector(roleListName, uniqueID); super(uniqueID);
beans = new KittyTrackedLong(beansName, uniqueID); this.uniqueID = uniqueID;
registerTrackedObjects(); roleList = new KittyTrackedVector(roleListName, uniqueID);
beans = new KittyTrackedLong(beansName, uniqueID);
control = adminControl; registerTrackedObjects();
this.contentRating = KittyRating.Safe;
this.polling = false; control = adminControl;
this.emoji = emoji; this.contentRating = KittyRating.Safe;
this.audio = audio; this.polling = false;
setCommandIndicator("!"); this.emoji = emoji;
} this.audio = audio;
this.channels = channels;
// Explicit constructor setCommandIndicator("!");
public KittyGuild(String commandIndicator, KittyRating contentRating, KittyUser guildOwner, String uniqueID, AudioUtils audio) }
{
super(uniqueID); // Explicit constructor
this.uniqueID = uniqueID; public KittyGuild(String commandIndicator, KittyRating contentRating, KittyUser guildOwner, String uniqueID, AudioUtils audio, HashMap<Long, KittyChannel> channels)
roleList = new KittyTrackedVector(roleListName, uniqueID); {
beans = new KittyTrackedLong(beansName, uniqueID); super(uniqueID);
registerTrackedObjects(); this.uniqueID = uniqueID;
roleList = new KittyTrackedVector(roleListName, uniqueID);
setCommandIndicator(commandIndicator); beans = new KittyTrackedLong(beansName, uniqueID);
this.contentRating = contentRating; registerTrackedObjects();
this.polling = false;
this.guildOwner = guildOwner; setCommandIndicator(commandIndicator);
this.audio = audio; this.contentRating = contentRating;
} this.polling = false;
this.guildOwner = guildOwner;
public String startPoll(String poll) this.audio = audio;
{ this.channels = channels;
polling = true; }
this.poll = poll;
return "Poll `" + poll + "` started! Don't forget to add choices with `!poll choice`~"; public String startPoll(String poll)
} {
polling = true;
public String addChoiceToPoll(String choice) this.poll = poll;
{ return "Poll `" + poll + "` started! Don't forget to add choices with `!poll choice`~";
choices.add(new KittyPoll(choice)); }
return "Added `" + choice + "` to poll!";
} public String addChoiceToPoll(String choice)
{
public String endPoll() choices.add(new KittyPoll(choice));
{ return "Added `" + choice + "` to poll!";
choices.clear(); }
hasVoted.clear();
this.polling = false; public String endPoll()
poll = null; {
return "Poll ended!"; choices.clear();
} hasVoted.clear();
this.polling = false;
//Raffle methods poll = null;
public boolean startRaffle(int beanCost) return "Poll ended!";
{ }
if(raffling)
{ //Raffle methods
return false; public boolean startRaffle(int beanCost)
} {
raffleCost = beanCost; if(raffling)
raffling = true; {
return true; return false;
} }
raffleCost = beanCost;
public boolean endRaffle() raffling = true;
{ return true;
if(raffling) }
{
raffleCost = 0; public boolean endRaffle()
raffling = false; {
raffleUsersChosen.removeAll(raffleUsersChosen); if(raffling)
raffleUsersUnchosen.removeAll(raffleUsersUnchosen); {
return true; raffleCost = 0;
} raffling = false;
return false; raffleUsersChosen.removeAll(raffleUsersChosen);
} raffleUsersUnchosen.removeAll(raffleUsersUnchosen);
return true;
public boolean joinRaffle(KittyUser user) }
{ return false;
if(!raffleUsersChosen.contains(user) && !raffleUsersUnchosen.contains(user) && user.getBeans() > raffleCost && raffling) }
{
user.changeBeans(raffleCost); public boolean joinRaffle(KittyUser user)
raffleUsersUnchosen.add(user); {
return true; if(!raffleUsersChosen.contains(user) && !raffleUsersUnchosen.contains(user) && user.getBeans() > raffleCost && raffling)
} {
return false; user.changeBeans(-raffleCost);
} raffleUsersUnchosen.add(user);
return true;
public KittyUser chooseRaffleWinner() }
{ return false;
if(!raffleUsersUnchosen.isEmpty()) }
{
KittyUser chosen = raffleUsersUnchosen.get((int) (Math.random() * raffleUsersUnchosen.size())); public KittyUser chooseRaffleWinner()
raffleUsersUnchosen.remove(chosen); {
raffleUsersChosen.add(chosen); if(!raffleUsersUnchosen.isEmpty())
return chosen; {
} KittyUser chosen = raffleUsersUnchosen.get((int) (Math.random() * raffleUsersUnchosen.size()));
return null; raffleUsersUnchosen.remove(chosen);
} raffleUsersChosen.add(chosen);
return chosen;
@Override }
public String serialize() return null;
{ }
return commandIndicator;
} @Override
public String serialize()
@Override {
public void deSerialzie(String string) return commandIndicator;
{ }
if(string == null || string.length() == 0)
setCommandIndicator("!"); @Override
else public void deSerialzie(String string)
setCommandIndicator(string); {
} if(string == null || string.length() == 0)
setCommandIndicator("!");
public String getCommandIndicator() else
{ setCommandIndicator(string);
return commandIndicator; }
}
public String getCommandIndicator()
public void setCommandIndicator(String newIndicator) {
{ return commandIndicator;
if(newIndicator != commandIndicator) }
{
commandIndicator = newIndicator; public void setCommandIndicator(String newIndicator)
markDirty(); {
} if(newIndicator != commandIndicator)
} {
} commandIndicator = newIndicator;
markDirty();
}
}
}
+134 -134
View File
@@ -1,135 +1,135 @@
package main; package main;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import javax.security.auth.login.LoginException; import javax.security.auth.login.LoginException;
import com.sedmelluq.discord.lavaplayer.player.AudioLoadResultHandler; import com.sedmelluq.discord.lavaplayer.player.AudioLoadResultHandler;
import com.sedmelluq.discord.lavaplayer.player.AudioPlayer; import com.sedmelluq.discord.lavaplayer.player.AudioPlayer;
import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager; import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager;
import com.sedmelluq.discord.lavaplayer.player.DefaultAudioPlayerManager; import com.sedmelluq.discord.lavaplayer.player.DefaultAudioPlayerManager;
import com.sedmelluq.discord.lavaplayer.source.AudioSourceManagers; import com.sedmelluq.discord.lavaplayer.source.AudioSourceManagers;
import com.sedmelluq.discord.lavaplayer.tools.FriendlyException; import com.sedmelluq.discord.lavaplayer.tools.FriendlyException;
import com.sedmelluq.discord.lavaplayer.track.AudioPlaylist; import com.sedmelluq.discord.lavaplayer.track.AudioPlaylist;
import com.sedmelluq.discord.lavaplayer.track.AudioTrack; import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
import com.sedmelluq.discord.lavaplayer.track.playback.AudioFrame; import com.sedmelluq.discord.lavaplayer.track.playback.AudioFrame;
import core.CharacterManager; import core.CharacterManager;
import core.CommandEnabler; import core.CommandEnabler;
import core.CommandManager; import core.CommandManager;
import core.DatabaseManager; import core.DatabaseManager;
import core.ObjectBuilderFactory; import core.ObjectBuilderFactory;
import core.RPManager; import core.RPManager;
import core.Stats; import core.Stats;
import core.lua.PluginManager; import core.lua.PluginManager;
import dataStructures.KittyChannel; import dataStructures.KittyChannel;
import dataStructures.KittyCore; import dataStructures.KittyCore;
import dataStructures.KittyGuild; import dataStructures.KittyGuild;
import dataStructures.KittyUser; import dataStructures.KittyUser;
import dataStructures.Response; import dataStructures.Response;
import dataStructures.UserInput; import dataStructures.UserInput;
import net.dv8tion.jda.core.AccountType; import net.dv8tion.jda.core.AccountType;
import net.dv8tion.jda.core.JDA; import net.dv8tion.jda.core.JDA;
import net.dv8tion.jda.core.JDABuilder; import net.dv8tion.jda.core.JDABuilder;
import net.dv8tion.jda.core.audio.AudioSendHandler; import net.dv8tion.jda.core.audio.AudioSendHandler;
import net.dv8tion.jda.core.entities.Guild; import net.dv8tion.jda.core.entities.Guild;
import net.dv8tion.jda.core.entities.TextChannel; import net.dv8tion.jda.core.entities.TextChannel;
import net.dv8tion.jda.core.entities.VoiceChannel; import net.dv8tion.jda.core.entities.VoiceChannel;
import net.dv8tion.jda.core.events.message.guild.GuildMessageReceivedEvent; import net.dv8tion.jda.core.events.message.guild.GuildMessageReceivedEvent;
import net.dv8tion.jda.core.hooks.ListenerAdapter; import net.dv8tion.jda.core.hooks.ListenerAdapter;
import net.dv8tion.jda.core.managers.AudioManager; import net.dv8tion.jda.core.managers.AudioManager;
import offline.Ref; import offline.Ref;
import utils.GlobalLog; import utils.GlobalLog;
// http://www.slf4j.org/ - this JDA logging tool has been disabled by specifying NOP implementation. // 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! // This is the application entry point, and bot startup location!
@SuppressWarnings("unused") @SuppressWarnings("unused")
public class Main extends ListenerAdapter public class Main extends ListenerAdapter
{ {
// Variables and bot specific objects // Variables and bot specific objects
private static KittyCore kittyCore; private static KittyCore kittyCore;
private static DatabaseManager databaseManager; private static DatabaseManager databaseManager;
private static CommandManager commandManager; private static CommandManager commandManager;
private static Stats stats; private static Stats stats;
private static RPManager rpManager; private static RPManager rpManager;
private static PluginManager pluginManager; private static PluginManager pluginManager;
private static CharacterManager charManager; private static CharacterManager charManager;
// Initialization and setup // Initialization and setup
public static void main(String[] args) throws InterruptedException, LoginException, Exception public static void main(String[] args) throws InterruptedException, LoginException, Exception
{ {
// Factory startup. The ordering is intentional. // Factory startup. The ordering is intentional.
GlobalLog.initialize(); GlobalLog.initialize();
databaseManager = ObjectBuilderFactory.constructDatabaseManager(); databaseManager = ObjectBuilderFactory.constructDatabaseManager();
commandManager = ObjectBuilderFactory.constructCommandManager(CommandEnabler.instance); // TODO: Untangle this singleton commandManager = ObjectBuilderFactory.constructCommandManager(CommandEnabler.instance); // TODO: Untangle this singleton
stats = ObjectBuilderFactory.constructStats(commandManager); stats = ObjectBuilderFactory.constructStats(commandManager);
charManager = new CharacterManager(); charManager = new CharacterManager();
rpManager = ObjectBuilderFactory.constructRPManager(); rpManager = ObjectBuilderFactory.constructRPManager();
pluginManager = ObjectBuilderFactory.constructPluginManager(); pluginManager = ObjectBuilderFactory.constructPluginManager();
// Bot startup // Bot startup
kittyCore = ObjectBuilderFactory.constructKittyCore(); kittyCore = ObjectBuilderFactory.constructKittyCore();
} }
// When a message is sent in a server that kitty is in, this is what's called. // When a message is sent in a server that kitty is in, this is what's called.
@Override @Override
public void onGuildMessageReceived(GuildMessageReceivedEvent event) public void onGuildMessageReceived(GuildMessageReceivedEvent event)
{ {
// Tweak the event as necessary // Tweak the event as necessary
if(!Superintendent.preProcessSetup(event, stats)) if(!Superintendent.preProcessSetup(event, stats))
return; return;
// Factory objects // Factory objects
KittyUser user = ObjectBuilderFactory.extractUser(event); KittyUser user = ObjectBuilderFactory.extractUser(event);
KittyGuild guild = ObjectBuilderFactory.extractGuild(event); KittyGuild guild = ObjectBuilderFactory.extractGuild(event);
KittyChannel channel = ObjectBuilderFactory.extractChannel(event); KittyChannel channel = ObjectBuilderFactory.extractChannel(event);
// Specialized uncached objects // Specialized uncached objects
Response response = new Response(event, kittyCore); Response response = new Response(event, kittyCore);
UserInput input = new UserInput(event, guild); UserInput input = new UserInput(event, guild);
// Tweak object construction as necessary // Tweak object construction as necessary
if(!Superintendent.postProcessSetup(event, user, guild, channel, response, input)) if(!Superintendent.postProcessSetup(event, user, guild, channel, response, input))
return; return;
// Track beans! // Track beans!
user.changeBeans(1); user.changeBeans(1);
// RP logging system // RP logging system
RPManager.instance.addLine(channel, user, input); RPManager.instance.addLine(channel, user, input);
// Run any pre-emptive upkeep we need to // Run any pre-emptive upkeep we need to
if(!Superintendent.perCommandUpkeepPre(pluginManager)) if(!Superintendent.perCommandUpkeepPre(pluginManager))
return; return;
// Attempt to spin up a command. If the command doesn't exist. // Attempt to spin up a command. If the command doesn't exist.
// Run plugins right before invoking the commands but after all other setup. // Run plugins right before invoking the commands but after all other setup.
if(commandManager.invokeOnNewThread(guild, channel, user, input, response) == false) if(commandManager.invokeOnNewThread(guild, channel, user, input, response) == false)
{ {
List<String> pluginOutput = pluginManager.runAll(input.message, user); List<String> pluginOutput = pluginManager.runAll(input.message, user);
if(pluginOutput != null && pluginOutput.size() > 0) if(pluginOutput != null && pluginOutput.size() > 0)
{ {
for(int i = 0; i < pluginOutput.size(); ++i) for(int i = 0; i < pluginOutput.size(); ++i)
{ {
if(pluginOutput.get(i).startsWith("!")) if(pluginOutput.get(i).startsWith("!"))
{ {
commandManager.invokeOnNewThread(guild, channel, user, new UserInput(pluginOutput.get(i).substring(1), guild), response); commandManager.invokeOnNewThread(guild, channel, user, new UserInput(pluginOutput.get(i).substring(1), guild), response);
} }
else else
{ {
response.send(pluginOutput.get(i)); response.send(pluginOutput.get(i));
} }
} }
} }
} }
// Run any upkeep in post we need to // Run any upkeep in post we need to
if(!Superintendent.perCommandUpkeepPost(kittyCore, databaseManager)) if(!Superintendent.perCommandUpkeepPost(kittyCore, databaseManager))
return; return;
} }
} }
+29 -2
View File
@@ -6,14 +6,41 @@ public class NetworkColiru
{ {
public String compileCPlusPlus(String query) public String compileCPlusPlus(String query)
{ {
// Escape characters that need escaping. // Escape characters that need escaping - mostly whitespace.
// Primarily types of whitespace.
query = query.replace("\\n", "\\\\n"); query = query.replace("\\n", "\\\\n");
query = query.replace("\\t", "\\\\t"); query = query.replace("\\t", "\\\\t");
query = query.replace("\n", "\\n"); query = query.replace("\n", "\\n");
query = query.replace("\"", "\\\""); query = query.replace("\"", "\\\"");
query = query.replace("\t", "\\t"); query = query.replace("\t", "\\t");
query = query.replace("`", "");
// // replace backticks on only the edges of the string.
// StringBuilder s = new StringBuilder(query);
//
// for(int i = 0; i < s.length(); ++i)
// {
// if(s.charAt(i) != '`')
// break;
//
// s.setCharAt(i, ' ');
// }
//
// for(int i = s.length() - 1; i >= 0; --i)
// {
// if(s.charAt(i) != '`')
// break;
//
// s.setCharAt(i, ' ');
// }
//
// query = s.toString().trim();
// Determine if the query is effectively empty or not. If it is, don't attempt to compile it.
if(query.trim().length() == 0)
{
return "I can't compile nothing!";
}
// Send the compilation request! // Send the compilation request!
String result = HTTPUtils.sendPOSTRequest("http://coliru.stacked-crooked.com/compile" String result = HTTPUtils.sendPOSTRequest("http://coliru.stacked-crooked.com/compile"
, "{ \"cmd\": \"g++ main.cpp && ./a.out\", \"src\": \"" + query + "\" }"); , "{ \"cmd\": \"g++ main.cpp && ./a.out\", \"src\": \"" + query + "\" }");
+68 -3
View File
@@ -14,6 +14,7 @@ public class NetworkDerpi
{ {
public String image; public String image;
public String tags; public String tags;
public String score;
} }
private class InitialRequest private class InitialRequest
@@ -29,16 +30,26 @@ public class NetworkDerpi
String res = HTTPUtils.sendGETRequest(mainURL + query + "&random_image=1&key=" + Ref.derpiKey); String res = HTTPUtils.sendGETRequest(mainURL + query + "&random_image=1&key=" + Ref.derpiKey);
if(res != null) if(res != null)
{ {
InitialRequest obj;
// Use class evaluation on an array of the response object to be able to hold multiple. // Use class evaluation on an array of the response object to be able to hold multiple.
InitialRequest obj = jsonParser_.fromJson(res, InitialRequest.class); try
{
obj = jsonParser_.fromJson(res, InitialRequest.class);
}
catch(Exception e)
{
return null;
}
if(res != null) if(res != null)
{ {
String res2 = HTTPUtils.sendGETRequest("https://derpibooru.org/" + obj.id + ".json"); String res2 = HTTPUtils.sendGETRequest("https://derpibooru.org/" + obj.id + ".json");
image.editPostURL("<https://derpibooru.org/" + obj.id +">"); image.editPostURL("https://derpibooru.org/" + obj.id);
DerpiResponseObject imageObj = jsonParser_.fromJson(res2, DerpiResponseObject.class); DerpiResponseObject imageObj = jsonParser_.fromJson(res2, DerpiResponseObject.class);
image.editImageURL("https:" + imageObj.image.substring(0, imageObj.image.indexOf('_')) + imageObj.image.substring(imageObj.image.lastIndexOf('.'))); image.editImageURL("https:" + imageObj.image.substring(0, imageObj.image.indexOf('_')) +
imageObj.image.substring(imageObj.image.lastIndexOf('.')));
if(imageObj.tags.contains("artist:")) if(imageObj.tags.contains("artist:"))
{ {
String [] sepTags = imageObj.tags.split(","); String [] sepTags = imageObj.tags.split(",");
@@ -54,8 +65,20 @@ public class NetworkDerpi
artists += sepTags[i].substring(sepTags[i].indexOf(":")+1); artists += sepTags[i].substring(sepTags[i].indexOf(":")+1);
} }
} }
image.editAuthorImage("https://derpicdn.net/favicon.ico");
image.editArtist(artists); image.editArtist(artists);
String tags = "";
for(int i = 0; i < sepTags.length && i < 15; i++)
{
if(!sepTags[i].contains("artist:"))
{
tags += sepTags[i];
}
}
image.editFooterText("[Tags]" + tags);
image.editDescriptionText("Score: " + imageObj.score);
} }
else else
{ {
@@ -66,4 +89,46 @@ public class NetworkDerpi
return image; return image;
} }
public GenericImage getDerpiByID(String id)
{
GenericImage image = new GenericImage(" ", " ", " ");
String artists = "";
image.editAuthorImage("https://derpicdn.net/favicon.ico");
String res;
try
{
res = HTTPUtils.sendGETRequest("https://derpibooru.org/" + id + ".json");
}
catch(Exception e)
{
return null;
}
DerpiResponseObject imageObj = jsonParser_.fromJson(res, DerpiResponseObject.class);
if(imageObj.tags.contains("artist:"))
{
String [] sepTags = imageObj.tags.split(",");
for(int i = 0; i < sepTags.length; i++)
{
if(sepTags[i].contains("artist:"))
{
if(!artists.equals(""))
{
artists += " and ";
}
artists += sepTags[i].substring(sepTags[i].indexOf(":")+1);
}
}
}
if(artists != "")
image.editArtist(artists);
else
image.editArtist("Artist Unknown!");
image.editFooterText("[Tags]" + imageObj.tags);
image.editDescriptionText("Score: " + imageObj.score);
image.editImageURL("https:" + imageObj.image.substring(0, imageObj.image.indexOf('_')) +
imageObj.image.substring(imageObj.image.lastIndexOf('.')));
return image;
}
} }
+201
View File
@@ -0,0 +1,201 @@
package network;
import com.google.gson.Gson;
import dataStructures.GenericImage;
import offline.Ref;
import utils.HTTPUtils;
/**
* This is the e621 request class, designed for form and parse requests that
* use the e621 API, and is entirely static.
*
* If you ever find this class randomly not working,
* it may be a good idea to make sure the user agent string is set in
* HTTPUtils to something other than a browser emulating string, or the default
* java one.
*
* @author Wisp
* Edited by Rin
*/
public class NetworkE6
{
///////////////////////////////////////
// Internal JSON class and variables //
//////////////////////////////////.////
private static final Gson jsonParser_ = new Gson();
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 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 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;
}
////////////////////
// Static methods //
////////////////////
// Requests a specific image, then returns a few.
public GenericImage getE6(String input)
{
GenericImage image = new GenericImage("","","");
boolean blacklisted;
// Clean up request and replace problematic characters for the query string.
input = input.trim();
input = input.replace("+", "%2B");
input = input.replace(" ", "%20");
// 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.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.
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.posts.length < 1)
{
}
else
{
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++)
{
for(int k = 0; k < TagsList.length; k ++)
{
if(TagsList[k].equals(blacklist[j]))
{
System.out.println("BLACKLISTED " + blacklist[j]);
blacklisted = true;
}
}
}
if(blacklisted)
{
return null;
}
// We will always have a file URL. That's a given.
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!");
image.editAuthorImage("https://e621.net/favicon.ico");
String sources = "";
if(imageObj.posts[i].sources != null)
{
for(int k = 0; k < imageObj.posts[i].sources.length; k ++)
{
if(!imageObj.posts[i].sources[k].endsWith(imageObj.posts[i].file.url.substring(imageObj.posts[i].file.url.lastIndexOf('.'))))
{
String source = imageObj.posts[i].sources[k];
if(source.contains("//www."))
{
source = source.substring(source.indexOf(".") + 1);
source = source.substring(0, source.indexOf('.'));
}
else
{
source = source.substring(source.indexOf("/") + 2);
source = source.substring(0, source.indexOf('.'));
}
sources += " [" + source + "](" + imageObj.posts[i].sources[k] + ") ";
}
}
image.editDescriptionText("Score: " + imageObj.posts[i].score.total + "\n**Source:**" + sources);
}
else
{
image.editDescriptionText("Score: " + imageObj.posts[i].score.total);
}
String descTags = "";
if(imageObj.posts[i].tags.general.length > 15)
{
for(int o = 0; o < 15; o++)
{
descTags += imageObj.posts[i].tags.general[o] + ", ";
}
image.editFooterText("[Tags] " + descTags + " etc.");
}
else
{
descTags = imageObj.posts[i].tags.general.toString();
image.editFooterText("[Tags] " + descTags);
}
if(image.output().authorText != null)
{
return image;
}
}
}
}
return image;
}
}
-104
View File
@@ -1,104 +0,0 @@
package network;
import com.google.gson.Gson;
import dataStructures.GenericImage;
import offline.Ref;
import utils.*;
/**
* This is the e621 request class, designed for form and parse requests that
* use the e621 API, and is entirely static.
*
* If you ever find this class randomly not working,
* it may be a good idea to make sure the user agent string is set in
* HTTPUtils to something other than a browser emulating string, or the default
* java one.
*
* @author Wisp
* Edited by Rin
*/
public class NetworkE621
{
///////////////////////////////////////
// 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 int maxSearchResults_ = 10;
private static String[] blacklist = Ref.e621Blacklist;
private class E621ResponseObject
{
// public varaibles 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;
}
////////////////////
// Static methods //
////////////////////
// Requests a specific image, then returns a few.
public GenericImage getE621(String input)
{
GenericImage image = new GenericImage("","","");
boolean blacklisted;
// Clean up request and replace problematic characters for the query string.
input = input.trim();
input = input.replace("+", "%2B");
input = input.replace(" ", "%20");
// 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_);
if(res != null)
{
// Use class evaluation on an array of the response imageObject to be able to hold multiple.
E621ResponseObject[] imageObj = jsonParser_.fromJson(res, E621ResponseObject[].class);
// 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)
{
}
else
{
for(int i = 0; i < imageObj.length; ++i)
{
blacklisted = false;
for(int j = 0; j < blacklist.length; j++)
{
if(imageObj[i].tags.contains(blacklist[j]))
{
blacklisted = true;
}
}
if(blacklisted)
{
continue;
}
// 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]);
else
image.editArtist("Artist Not Found!");
}
}
}
return image;
}
}
+49 -48
View File
@@ -1,48 +1,49 @@
package network; package network;
import java.util.List; import java.util.List;
import com.google.gson.Gson; import com.google.gson.Gson;
import offline.Ref; import offline.Ref;
import utils.HTTPUtils; import utils.HTTPUtils;
public class NetworkSauceNAO public class NetworkSauceNAO
{ {
private static final Gson jsonParser_ = new Gson(); private static final Gson jsonParser_ = new Gson();
private static final String API_ROOT = "https://saucenao.com/search.php?db=999&output_type=2&numres=10&api_key=" + Ref.SauceNAOKey +"&url="; private static final String API_ROOT = "https://saucenao.com/search.php?dbmask=268435456&output_type=2&numres=10&api_key=" + Ref.SauceNAOKey +"&url=";
NetworkE621 e621Sauce = new NetworkE621(); NetworkE6 e6Sauce = new NetworkE6();
private class SauceNAOResponseObject private class SauceNAOResponseObject
{ {
List<SauceNAOResult> results; List<SauceNAOResult> results;
} }
private class SauceNAOResult private class SauceNAOResult
{ {
SauceNAOData data; SauceNAOData data;
} }
private class SauceNAOData private class SauceNAOData
{ {
String [] ext_urls; String [] ext_urls;
} }
public String getSauce(String input) public String getSauce(String input)
{ {
input = input.trim(); input = input.trim();
input = input.replace("+", "%2B"); input = input.replace("+", "%2B");
input = input.replace(" ", "%20"); input = input.replace(" ", "%20");
String res = HTTPUtils.sendGETRequest(API_ROOT + input); String res = HTTPUtils.sendGETRequest(API_ROOT + input);
SauceNAOResponseObject sauce = jsonParser_.fromJson(res, SauceNAOResponseObject.class); SauceNAOResponseObject sauce = jsonParser_.fromJson(res, SauceNAOResponseObject.class);
String sauceUrl = sauce.results.get(0).data.ext_urls[0]; String sauceUrl = sauce.results.get(0).data.ext_urls[0];
if(sauceUrl.startsWith("https://e621.net/post/show/")) if(sauceUrl.startsWith("https://e621.net/post/show/"))
{ {
System.out.println("id:" + sauceUrl.substring(26)); System.out.println("id:" + sauceUrl.substring(26));
return e621Sauce.getE621("id:" + sauceUrl.substring(27)).toString(); System.out.println("HERE");
} return e6Sauce.getE6("id:" + sauceUrl.substring(27)).toString();
return sauce.results.get(0).data.ext_urls[0]; }
} return sauce.results.get(0).data.ext_urls[0];
}
}
}
+28 -1
View File
@@ -73,9 +73,36 @@ public class NetworkTheColorAPI
public ColorData lookupHex(String hex) 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 try
{ {
hex = hex.replace("#", ""); String hexUpper = hex.toUpperCase();
// Verify the number is hex.
for(int i = 0; i < hexUpper.length(); ++i)
{
char current = hexUpper.charAt(i);
Boolean isValidNum = current >= '0' && current <= '9';
Boolean isValidChar = current >= 'A' && current <= 'F';
// If it's not a valid character or a valid number, return null/
if(!isValidNum && !isValidChar)
return null;
}
String response = HTTPUtils.sendGETRequest("https://www.thecolorapi.com/id?hex=" + hex); String response = HTTPUtils.sendGETRequest("https://www.thecolorapi.com/id?hex=" + hex);
ColorData data = jsonParser.fromJson(response, ColorData.class); ColorData data = jsonParser.fromJson(response, ColorData.class);
+13
View File
@@ -119,6 +119,16 @@ public class AudioUtils
return null; 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) public String skipVideo(AudioPlayer player)
{ {
player.stopTrack(); player.stopTrack();
@@ -152,6 +162,9 @@ class MusicController extends Thread
@Override @Override
public void run() public void run()
{ {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {}
AudioTrack nowPlaying = null; AudioTrack nowPlaying = null;
do do
{ {