diff --git a/.classpath b/.classpath
index e5e8a9b..6cf8f5a 100644
--- a/.classpath
+++ b/.classpath
@@ -24,7 +24,8 @@
+
-
+
diff --git a/assets/config.csv b/assets/config.csv
index 2564dd9..437a63e 100644
--- a/assets/config.csv
+++ b/assets/config.csv
@@ -1,4 +1,5 @@
"Type","Key","Value"
+"Globals","mode (dev or release)","dev"
"Localized Commands","beans",""
"Localized Commands","benchmark, bench",""
"Localized Commands","bet",""
@@ -19,6 +20,7 @@
"Localized Commands","e621",""
"Localized Commands","eightball, 8ball",""
"Localized Commands","fetch",""
+"Localized Commands","getsauce",""
"Localized Commands","givebeans",""
"Localized Commands","help",""
"Localized Commands","indicator",""
@@ -60,6 +62,7 @@
"Localized Strings","BetBeansInfo","Allows you to bet your beans, set your amount after the command! Warning! House always wins!nSets of 3 will get 2x, 4 will get 10x, and 5 will get 1000x"
"Localized Strings","BetBeansLose","Sorry, you didn't win, try again!"
"Localized Strings","BetBeansLowBet","Please bet with at least 20 beans!"
+"Localized Strings","BetBeansMinThreshold",""
"Localized Strings","BetBeansNotEnough","You don't have enough beans!"
"Localized Strings","BetBeansNotValid","That's not a valid bet!"
"Localized Strings","BetBeansWin","You won %s beans!"
@@ -139,6 +142,7 @@
"Localized Strings","FetchInfo","Throw a custom emote and I'll try to bring it back.... maybe"
"Localized Strings","FetchRunAway","*Runs away and doesn't return for a long time*"
"Localized Strings","FetchStare","*Stares at %s*"
+"Localized Strings","GetSauceInfo",""
"Localized Strings","GiveBeansInfo","Gives beans to the mentioned users!"
"Localized Strings","GiveBeansInvalid","That's not a valid number!"
"Localized Strings","GiveBeansNoneMentioned","You didn't mention anyone!"
@@ -270,6 +274,7 @@
"Command Enabler","e621","1"
"Command Enabler","eightball, 8ball","1"
"Command Enabler","fetch","1"
+"Command Enabler","getsauce","1"
"Command Enabler","givebeans","1"
"Command Enabler","guildroleadd","1"
"Command Enabler","guildroleallowed","1"
diff --git a/lib/LavaPlayerJar-0.0.1-jar-with-dependencies.jar b/lib/LavaPlayerJar-0.0.1-jar-with-dependencies.jar
new file mode 100644
index 0000000..3a4e0ea
Binary files /dev/null and b/lib/LavaPlayerJar-0.0.1-jar-with-dependencies.jar differ
diff --git a/lib/google-http-client-1.32.0.jar b/lib/google-http-client-1.32.0.jar
new file mode 100644
index 0000000..b97d4d4
Binary files /dev/null and b/lib/google-http-client-1.32.0.jar differ
diff --git a/lib/lavaplayer-1.3.19.jar b/lib/lavaplayer-1.3.19.jar
deleted file mode 100644
index 472c468..0000000
Binary files a/lib/lavaplayer-1.3.19.jar and /dev/null differ
diff --git a/src/commands/general/CommandGetSauce.java b/src/commands/general/CommandGetSauce.java
new file mode 100644
index 0000000..be59ec8
--- /dev/null
+++ b/src/commands/general/CommandGetSauce.java
@@ -0,0 +1,29 @@
+package commands.general;
+
+import core.Command;
+import core.LocStrings;
+import dataStructures.KittyChannel;
+import dataStructures.KittyGuild;
+import dataStructures.KittyRating;
+import dataStructures.KittyRole;
+import dataStructures.KittyUser;
+import dataStructures.Response;
+import dataStructures.UserInput;
+import network.NetworkSauceNAO;
+
+public class CommandGetSauce extends Command
+{
+ NetworkSauceNAO sauce = new NetworkSauceNAO();
+
+ public CommandGetSauce(KittyRole level, KittyRating rating) { super(level, rating); }
+
+ @Override
+ public String getHelpText() { return LocStrings.stub("GetSauceInfo"); };
+
+ @Override
+ public void onRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
+ {
+ res.send(sauce.getSauce(input.args));
+
+ }
+}
\ No newline at end of file
diff --git a/src/commands/music/CommandMusicMain.java b/src/commands/music/CommandMusicMain.java
index 181fb21..6581271 100644
--- a/src/commands/music/CommandMusicMain.java
+++ b/src/commands/music/CommandMusicMain.java
@@ -2,6 +2,7 @@ package commands.music;
import core.Command;
import core.LocStrings;
+import core.SubCommandFormattable;
import core.SubCommandFramework;
import dataStructures.*;
@@ -9,18 +10,24 @@ public class CommandMusicMain extends Command
{
SubCommandFramework framework = new SubCommandFramework();
public CommandMusicMain(KittyRole level, KittyRating rating)
- {
+ {
super(level, rating);
framework.addCommand("join", new SubCommandJoin(KittyRole.General, KittyRating.Safe));
framework.addCommand("leave", new SubCommandLeave(KittyRole.General, KittyRating.Safe));
+ framework.addCommand("add", new SubCommandAddTrack(KittyRole.General, KittyRating.Safe));
+ 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));
}
@Override
- public String getHelpText() { return LocStrings.stub("MusicInfo"); }
+ public String getHelpText() {return LocStrings.stub("MusicInfo"); }
@Override
public void onRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
{
- framework.run(guild, channel, user, input).Call(res);
+ SubCommandFormattable scf = framework.run(guild, channel, user, input);
+ System.out.println("SCF: " + scf.resString);
+ scf.Call(res);
}
}
\ No newline at end of file
diff --git a/src/commands/music/SubCommandAddTrack.java b/src/commands/music/SubCommandAddTrack.java
index 1c19498..39febae 100644
--- a/src/commands/music/SubCommandAddTrack.java
+++ b/src/commands/music/SubCommandAddTrack.java
@@ -1,7 +1,5 @@
package commands.music;
-import com.google.api.services.youtube.YouTube;
-
import core.SubCommand;
import core.SubCommandFormattable;
import dataStructures.KittyChannel;
@@ -10,16 +8,25 @@ import dataStructures.KittyRating;
import dataStructures.KittyRole;
import dataStructures.KittyUser;
import dataStructures.UserInput;
+import network.NetworkYoutube;
public class SubCommandAddTrack extends SubCommand
{
public SubCommandAddTrack(KittyRole level, KittyRating rating) { super(level, rating); }
+ NetworkYoutube YT = new NetworkYoutube();
+
@Override
public SubCommandFormattable OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input)
{
-
- return null;
+ //Get track from Youtube
+ String video = input.args;
+ if(!(video.startsWith("https://www.youtube") || video.startsWith("https://www.youtu.be")))
+ {
+ video = YT.getYT(video);
+ }
+ guild.audio.playVideo(video);
+ return new SubCommandFormattable(video);
}
}
\ No newline at end of file
diff --git a/src/commands/music/SubCommandPlaylist.java b/src/commands/music/SubCommandPlaylist.java
new file mode 100644
index 0000000..4ab8c88
--- /dev/null
+++ b/src/commands/music/SubCommandPlaylist.java
@@ -0,0 +1,24 @@
+package commands.music;
+
+import java.util.ArrayList;
+
+import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
+
+import core.SubCommand;
+import core.SubCommandFormattable;
+import dataStructures.*;
+
+public class SubCommandPlaylist extends SubCommand
+{
+
+ public SubCommandPlaylist(KittyRole roleLevel, KittyRating contentRating) {super(roleLevel, contentRating); }
+
+ @Override
+ public SubCommandFormattable OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input)
+ {
+// ArrayList playlist = guild.audio.getPlaylist();
+ String stringPlaylist = guild.audio.getPlaylist(guild.audio.player);
+ return new SubCommandFormattable(stringPlaylist);
+ }
+
+}
diff --git a/src/commands/music/SubCommandSkip.java b/src/commands/music/SubCommandSkip.java
new file mode 100644
index 0000000..b57ee52
--- /dev/null
+++ b/src/commands/music/SubCommandSkip.java
@@ -0,0 +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));
+ }
+}
diff --git a/src/commands/music/SubCommandStop.java b/src/commands/music/SubCommandStop.java
new file mode 100644
index 0000000..2aacffd
--- /dev/null
+++ b/src/commands/music/SubCommandStop.java
@@ -0,0 +1,24 @@
+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 SubCommandStop extends SubCommand
+{
+
+ public SubCommandStop(KittyRole roleLevel, KittyRating contentRating) {super(roleLevel, contentRating);}
+
+ @Override
+ public SubCommandFormattable OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input)
+ {
+
+ return new SubCommandFormattable(guild.audio.stopPlayer(guild.audio.player));
+ }
+
+}
diff --git a/src/core/CommandManager.java b/src/core/CommandManager.java
index ec831ee..0dcc14d 100644
--- a/src/core/CommandManager.java
+++ b/src/core/CommandManager.java
@@ -106,7 +106,7 @@ public class CommandManager
this.register(LocCommands.stub("raffle"), new CommandRaffleMain(KittyRole.General, KittyRating.Safe));
this.register(LocCommands.stub("poll"), new CommandPollMain(KittyRole.General, KittyRating.Safe));
this.register(LocCommands.stub("music"), new CommandMusicMain(KittyRole.General, KittyRating.Safe));
- this.register(LocCommands.stub("defaultdance"), new CommandDefaultDance(KittyRole.General, KittyRating.Safe));
+ this.register(LocCommands.stub("getsauce"), new CommandGetSauce(KittyRole.General, KittyRating.Safe));
}
// Allows the command manager to keep track of a command. Takes a pair (the un-localized and localzied commands)
diff --git a/src/core/Config.java b/src/core/Config.java
index c76c9c2..96b29bc 100644
--- a/src/core/Config.java
+++ b/src/core/Config.java
@@ -28,6 +28,7 @@ public class Config
sections = new Vector();
// Add all sections
+ sections.add(new ConfigGlobals());
sections.add(new LocCommands());
sections.add(new LocStrings());
sections.add(new CommandEnabler());
diff --git a/src/core/ConfigGlobals.java b/src/core/ConfigGlobals.java
new file mode 100644
index 0000000..d6b5db9
--- /dev/null
+++ b/src/core/ConfigGlobals.java
@@ -0,0 +1,68 @@
+package core;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import dataStructures.KittyStartupMode;
+import utils.GlobalLog;
+
+// Want to add a single item to the config file? This is where that lives.
+public class ConfigGlobals implements IConfigSection
+{
+ // Defined const variables
+ public static final String header = "Globals";
+ public static ConfigGlobals instance;
+
+
+ // A pile of variables being manually tracked/serialized to the config file
+ private static final String startupStyleKey = "mode (dev or release)";
+ private KittyStartupMode startupStyleValue = KittyStartupMode.Dev;
+
+ // Constructor
+ public ConfigGlobals()
+ {
+ if(instance == null)
+ instance = this;
+ else
+ GlobalLog.error("Attempted to initialize a second config globals! Probably don't do this!");
+ }
+
+ @Override
+ public String getSectionTitle()
+ {
+ return header;
+ }
+
+ public static KittyStartupMode getStartupMode()
+ {
+ return instance.startupStyleValue;
+ }
+
+ @Override
+ public void consume(List pairs)
+ {
+ for(int i = 0; i < pairs.size(); ++i)
+ {
+ String key = pairs.get(i).key;
+ String value = pairs.get(i).value;
+
+ // Parse startup style
+ if(key.equalsIgnoreCase(startupStyleKey))
+ {
+ startupStyleValue = KittyStartupMode.Dev;
+
+ if(value.equalsIgnoreCase(KittyStartupMode.Release.name()))
+ startupStyleValue = KittyStartupMode.Release;
+ }
+ }
+ }
+
+ @Override
+ public List produce()
+ {
+ List items = new ArrayList();
+ items.add(new ConfigItem(getSectionTitle(), startupStyleKey, startupStyleValue.name().toLowerCase()));
+
+ return items;
+ }
+}
diff --git a/src/core/ConfigItem.java b/src/core/ConfigItem.java
index 7f556d2..75e8bad 100644
--- a/src/core/ConfigItem.java
+++ b/src/core/ConfigItem.java
@@ -6,9 +6,9 @@ import utils.StringUtils;
// perform any parsing past naming columns, and just holds the raw data.
public class ConfigItem
{
- public String type;
- public String key;
- public String value;
+ public String type; // The section this specific key/value pair belongs to. This almost certainly will appear in multiple places.
+ public String key; // A unique key for a given lookup value for the specified section. Keys, within sections, are unique.
+ public String value; // The value assocaited with the key.
public static final int items = 3;
public static final String[] header = {"Type","Key","Value"};
diff --git a/src/core/LocCommands.java b/src/core/LocCommands.java
index 30d071e..2d446e7 100644
--- a/src/core/LocCommands.java
+++ b/src/core/LocCommands.java
@@ -11,7 +11,7 @@ import dataStructures.Pair;
public class LocCommands extends BaseLocFile implements IConfigSection
{
// Defined const variables
- public static final String HeaderName = "Localized Commands";
+ public static final String header = "Localized Commands";
public static final String function = "LocCommands.stub";
// Instance
@@ -20,7 +20,7 @@ public class LocCommands extends BaseLocFile implements IConfigSection
// Constructor
public LocCommands()
{
- super(HeaderName, function);
+ super(header, function);
GlobalLog.log(LogFilter.Core, "Initializing " + this.getClass().getSimpleName());
diff --git a/src/core/ObjectBuilderFactory.java b/src/core/ObjectBuilderFactory.java
index fb93eff..a17d2ed 100644
--- a/src/core/ObjectBuilderFactory.java
+++ b/src/core/ObjectBuilderFactory.java
@@ -7,22 +7,37 @@ 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.*;
+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.*;
+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.
@@ -55,7 +70,7 @@ public class ObjectBuilderFactory
private static CommandManager commandManager;
//Audio track manager
-// private static AudioPlayerManager audioPlayer = new DefaultAudioPlayerManager();
+ 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.
@@ -90,6 +105,9 @@ public class ObjectBuilderFactory
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.
@@ -147,7 +165,7 @@ public class ObjectBuilderFactory
else
{
// Construct a new guild with defaults
- guild = new KittyGuild(uid, new AdminControl(event.getGuild()), emotesString);
+ guild = new KittyGuild(uid, new AdminControl(event.getGuild()), emotesString, new AudioUtils(event.getGuild(), playerManager));
DatabaseManager.instance.globalRegister(guild);
guildCache.put(uid, guild);
}
@@ -365,8 +383,15 @@ public class ObjectBuilderFactory
{
lazyInit();
- kitty = new JDABuilder(AccountType.BOT).setToken(Ref.TestToken).buildBlocking();
- kitty.getPresence().setGame(Game.playing("with digital yarn"));
+ // 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);
diff --git a/src/dataStructures/KittyGuild.java b/src/dataStructures/KittyGuild.java
index 7801f79..ceb056d 100644
--- a/src/dataStructures/KittyGuild.java
+++ b/src/dataStructures/KittyGuild.java
@@ -5,7 +5,7 @@ import java.util.ArrayList;
import core.DatabaseManager;
import core.DatabaseTrackedObject;
import utils.AdminControl;
-import utils.AudioUtils;
+import utils.audio.AudioUtils;
// Context for a given guild for kittybot. Primarily designed to hold guild-specific settings.
public class KittyGuild extends DatabaseTrackedObject
@@ -22,7 +22,7 @@ public class KittyGuild extends DatabaseTrackedObject
public ArrayList emoji = new ArrayList();
public ArrayList choices = new ArrayList();
public AdminControl control;
- public AudioUtils audio;
+ public AudioUtils audio;
public ArrayList raffleUsersUnchosen = new ArrayList();
public ArrayList raffleUsersChosen = new ArrayList();
@@ -42,8 +42,9 @@ public class KittyGuild extends DatabaseTrackedObject
}
// Default content for a guild
- public KittyGuild(String uniqueID, AdminControl adminControl, ArrayList emoji)
+ public KittyGuild(String uniqueID, AdminControl adminControl, ArrayList emoji, AudioUtils audio)
{
+
super(uniqueID);
this.uniqueID = uniqueID;
roleList = new KittyTrackedVector(roleListName, uniqueID);
@@ -54,11 +55,12 @@ public class KittyGuild extends DatabaseTrackedObject
this.contentRating = KittyRating.Safe;
this.polling = false;
this.emoji = emoji;
+ this.audio = audio;
setCommandIndicator("!");
}
// Explicit constructor
- public KittyGuild(String commandIndicator, KittyRating contentRating, KittyUser guildOwner, String uniqueID)
+ public KittyGuild(String commandIndicator, KittyRating contentRating, KittyUser guildOwner, String uniqueID, AudioUtils audio)
{
super(uniqueID);
this.uniqueID = uniqueID;
@@ -70,6 +72,7 @@ public class KittyGuild extends DatabaseTrackedObject
this.contentRating = contentRating;
this.polling = false;
this.guildOwner = guildOwner;
+ this.audio = audio;
}
public String startPoll(String poll)
diff --git a/src/dataStructures/KittyStartupMode.java b/src/dataStructures/KittyStartupMode.java
new file mode 100644
index 0000000..3f9f8a7
--- /dev/null
+++ b/src/dataStructures/KittyStartupMode.java
@@ -0,0 +1,18 @@
+package dataStructures;
+
+public enum KittyStartupMode
+{
+ Dev(1), Release(2);
+
+ private final int value;
+ private KittyStartupMode(int value)
+ {
+ this.value = value;
+ }
+
+ public int getValue()
+ {
+ return value;
+ }
+}
+
diff --git a/src/main/Main.java b/src/main/Main.java
index 06b562b..23e3b7d 100644
--- a/src/main/Main.java
+++ b/src/main/Main.java
@@ -1,9 +1,21 @@
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;
@@ -21,9 +33,13 @@ 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.entities.Game;
+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;
@@ -42,6 +58,7 @@ public class Main extends ListenerAdapter
private static PluginManager pluginManager;
private static CharacterManager charManager;
+
// Initialization and setup
public static void main(String[] args) throws InterruptedException, LoginException, Exception
{
diff --git a/src/network/NetworkSauceNAO.java b/src/network/NetworkSauceNAO.java
new file mode 100644
index 0000000..93c030f
--- /dev/null
+++ b/src/network/NetworkSauceNAO.java
@@ -0,0 +1,48 @@
+package network;
+
+import java.util.List;
+
+import com.google.gson.Gson;
+
+import offline.Ref;
+import utils.HTTPUtils;
+
+public class NetworkSauceNAO
+{
+ private static final Gson jsonParser_ = new Gson();
+ private static final String API_ROOT = "https://saucenao.com/search.php?db=999&output_type=2&numres=10&api_key=" + Ref.SauceNAOKey +"&url=";
+ NetworkE621 e621Sauce = new NetworkE621();
+ 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 e621Sauce.getE621("id:" + sauceUrl.substring(27)).toString();
+ }
+ return sauce.results.get(0).data.ext_urls[0];
+ }
+
+}
diff --git a/src/network/NetworkYoutube.java b/src/network/NetworkYoutube.java
index d2ee0b6..8bb0f76 100644
--- a/src/network/NetworkYoutube.java
+++ b/src/network/NetworkYoutube.java
@@ -1,14 +1,55 @@
package network;
-import com.google.api.services.youtube.YouTube;
+import java.util.List;
+
+import com.google.gson.Gson;
import offline.Ref;
+import utils.HTTPUtils;
public class NetworkYoutube
{
- private static YouTube youtube;
+ ///////////////////////////////////////
+ // Internal JSON class and variables //
+ //////////////////////////////////.////
- public NetworkYoutube()
+ //https://www.youtube.com/watch?v=
+
+ private static final Gson jsonParser_ = new Gson();
+ private static final String API_ROOT = "https://www.googleapis.com/youtube/v3/search?part=snippet&maxResults=10&q=";
+
+
+ // Use this as the base
+ public class YTOuter
{
+ List items;
}
-}
\ No newline at end of file
+
+ public class YTInner
+ {
+ TYID id;
+ YTSnippet snippet;
+ }
+
+ public class TYID
+ {
+ String videoId;
+ }
+
+ public class YTSnippet
+ {
+ String title;
+ String description;
+ }
+
+ public String getYT(String input)
+ {
+ input = input.trim();
+ input = input.replace("+", "%2B");
+ input = input.replace(" ", "%20");
+
+ String res = HTTPUtils.sendGETRequest(API_ROOT + input + "&order=viewCount&type=video&topicId=%2Fm%2F04rlf&videoDefinition=high&key=" + Ref.youtube);
+ YTOuter videoObj = jsonParser_.fromJson(res, YTOuter.class);
+ return "https://www.youtube.com/watch?v=" + videoObj.items.get(0).id.videoId;
+ }
+}
diff --git a/src/utils/AudioUtils.java b/src/utils/AudioUtils.java
deleted file mode 100644
index 79c1529..0000000
--- a/src/utils/AudioUtils.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package utils;
-/***
- * https://developers.google.com/youtube/v3/code_samples/code_snippets?apix_params=%7B%22part%22%3A%22snippet%22%2C%22maxResults%22%3A25%2C%22q%22%3A%22surfing%22%7D
- * https://github.com/sedmelluq/LavaPlayer#jda-integration
- * https://ci.dv8tion.net/job/JDA/javadoc/net/dv8tion/jda/core/entities/VoiceChannel.html
- * https://developers.google.com/youtube/registering_an_application#Create_API_Keys
- */
-import com.sedmelluq.discord.lavaplayer.player.AudioPlayer;
-
-import net.dv8tion.jda.core.entities.Guild;
-import net.dv8tion.jda.core.entities.VoiceChannel;
-import net.dv8tion.jda.core.managers.AudioManager;
-
-public class AudioUtils
-{
- private Guild guild;
- AudioManager audio;
- AudioPlayer player;
-
-
- public AudioUtils(Guild guild)
- {
- this.guild = guild;
- audio = guild.getAudioManager();
- }
-
- public boolean joinChannel(String channelName)
- {
- VoiceChannel channel = null;
- channel = guild.getVoiceChannelsByName(channelName, true).get(0);
- if(channel != null)
- {
- audio.openAudioConnection(channel);
- return true;
- }
- return false;
- }
-
- public boolean leaveChannel()
- {
- if(audio.isConnected())
- {
- audio.closeAudioConnection();
- return true;
- }
- return false;
- }
-}
diff --git a/src/utils/audio/AudioUtils.java b/src/utils/audio/AudioUtils.java
new file mode 100644
index 0000000..c320651
--- /dev/null
+++ b/src/utils/audio/AudioUtils.java
@@ -0,0 +1,144 @@
+package utils.audio;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.Queue;
+
+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.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 net.dv8tion.jda.core.audio.AudioSendHandler;
+import net.dv8tion.jda.core.entities.Guild;
+import net.dv8tion.jda.core.entities.VoiceChannel;
+import net.dv8tion.jda.core.managers.AudioManager;
+
+public class AudioUtils
+{
+ private Guild guild;
+ public AudioManager am;
+ public final AudioPlayer player;
+ public final AudioPlayerManager playerManager;
+ private Queue playlist = new LinkedList<>();
+
+
+ public AudioUtils(Guild guild, AudioPlayerManager playerManager)
+ {
+ player = playerManager.createPlayer();
+ this.playerManager = playerManager;
+ this.guild = guild;
+ am = guild.getAudioManager();
+
+ }
+
+ public boolean joinChannel(String channelName)
+ {
+ VoiceChannel channel = null;
+ channel = guild.getVoiceChannelsByName(channelName, true).get(0);
+ if(channel != null)
+ {
+ am.openAudioConnection(channel);
+ return true;
+ }
+ return false;
+ }
+
+ public boolean leaveChannel()
+ {
+ if(am.isConnected())
+ {
+ am.closeAudioConnection();
+ return true;
+ }
+ return false;
+ }
+
+
+ public class AudioPlayerSendHandler implements AudioSendHandler
+ {
+ private final AudioPlayer audioPlayer;
+ private AudioFrame lastFrame;
+
+ public AudioPlayerSendHandler(AudioPlayer audioPlayer)
+ {
+ this.audioPlayer = audioPlayer;
+ }
+
+ @Override
+ public boolean canProvide()
+ {
+ lastFrame = audioPlayer.provide();
+ return lastFrame != null;
+ }
+
+ @Override public byte[] provide20MsAudio()
+ {
+ return lastFrame.getData();
+ }
+
+ @Override public boolean isOpus()
+ {
+ return true;
+ }
+ }
+
+ public class SmallAudio implements AudioLoadResultHandler
+ {
+ private AudioPlayer player;
+
+ private SmallAudio(AudioPlayer player)
+ {
+ this.player = player;
+ }
+
+ @Override public void loadFailed(FriendlyException arg0) { }
+ @Override public void noMatches() { }
+ @Override public void playlistLoaded(AudioPlaylist arg0) { }
+
+ @Override
+ public void trackLoaded(AudioTrack track)
+ {
+ synchronized(playlist)
+ {
+ playlist.add(track);
+ }
+ do
+ {
+ if(player.getPlayingTrack() == null)
+ {
+ player.startTrack(playlist.poll(), false);
+ }
+ }
+ while(!playlist.isEmpty());
+ }
+ }
+
+
+ public String playVideo(String videoURL)
+ {
+ guild.getAudioManager().setSendingHandler(new AudioPlayerSendHandler(player));
+ playerManager.loadItemOrdered(player, videoURL, new SmallAudio(player));
+
+ return null;
+ }
+
+ public String skipVideo(AudioPlayer player)
+ {
+ return null;
+ }
+
+ public String stopPlayer(AudioPlayer player)
+ {
+ playlist.clear();
+ player.stopTrack();
+ return "Stopped";
+ }
+
+ public String getPlaylist(AudioPlayer player)
+ {
+ return player.getPlayingTrack().getInfo().title;
+ }
+}