Added new command framework and rudimentary playlist functionality
This commit is contained in:
parent
cafdfd6988
commit
54deb2fb61
52
README.md
52
README.md
|
@ -1,11 +1,59 @@
|
||||||
# HandieBot
|
# HandieBot
|
||||||
|
|
||||||
|
![AvatarIcon](/src/main/resources/avatarIcon.png)
|
||||||
|
|
||||||
HandieBot is a bot for Discord, written using Java, the [Discord4J](https://github.com/austinv11/Discord4J) library, and the [Lavaplayer](https://github.com/sedmelluq/lavaplayer) library for sound processing. It is a fully-fledged bot with the ability to manage playlists, get music from URLs, and perform other necessary functions for a clean and enjoyable user experience.
|
HandieBot is a bot for Discord, written using Java, the [Discord4J](https://github.com/austinv11/Discord4J) library, and the [Lavaplayer](https://github.com/sedmelluq/lavaplayer) library for sound processing. It is a fully-fledged bot with the ability to manage playlists, get music from URLs, and perform other necessary functions for a clean and enjoyable user experience.
|
||||||
|
|
||||||
|
## Description
|
||||||
|
|
||||||
|
This Bot is designed to run as one executable Jar file, to represent one Discord bot. The bot itself keeps track of which servers (`guilds`) that it's connected to, and can independently handle requests from each one, provided it has enough bandwidth.
|
||||||
|
|
||||||
|
In each guild, the bot will use, or create both a voice and a text channel for it to use. These values are set in the source code as `HandieBotMusic` and `handiebotmusic`, respectively. From these channels, the bot will send messages about what song it's currently playing, responses to player requests, and any possible errors that occur. The voice channel is specifically only for playing music, and the bot will try to only connect when it is doing so.
|
||||||
|
|
||||||
## Commands
|
## Commands
|
||||||
|
|
||||||
### `play <URL>`
|
HandieBot contains some commands, most of which should be quite intuitive to the user. However, for completions' sake, the format for commands is as follows:
|
||||||
|
|
||||||
Issuing the `play` command attempts to load a song from a given URL, and append it to the active queue. The bot will tell the user quite obviously if their link does not work, or if there was an internal error. If there are already some songs in the queue, then this will also, if successful, tell the user approximately how long it will be until their song is played.
|
All commands begin with a prefix, which will not be shown with all the following commands, as it can be configured by users. This prefix is by default `!`.
|
||||||
|
|
||||||
|
`command [optional arguments] <required arguments>`
|
||||||
|
|
||||||
|
In particular, if the optional argument is shown as capital letters, this means that you must give a value, but if the optional argument is given in lowercase letters, simply write this argument. For example, the following commands are valid:
|
||||||
|
|
||||||
|
```text
|
||||||
|
play
|
||||||
|
play https://www.youtube.com/watch?v=9bZkp7q19f0
|
||||||
|
queue
|
||||||
|
queue all
|
||||||
|
```
|
||||||
|
|
||||||
|
Because the play command is defined as `play [URL]`, and the queue command is defined as `queue [all]`.
|
||||||
|
|
||||||
|
|
||||||
|
### Music
|
||||||
|
|
||||||
|
* `play [URL]` - Starts playback from the queue, or if a URL is defined, then it will attempt to play that song, or add it to the queue, depending on if a song is already playing. If a song is already playing, you should receive an estimate of when your song should begin playing.
|
||||||
|
|
||||||
|
* `skip` - If a song is playing, the bot will skip it and play the next song in the queue.
|
||||||
|
|
||||||
|
* `queue [all]` - Lists up to the first 10 items on the queue, if no argument is given. If you add `all`, the bot will upload a list to [PasteBin](http://pastebin.com) of the entire queue, and give you
|
||||||
|
|
||||||
|
* `repeat [true|false]` - Sets the bot to repeat the playlist, as in once a song is removed from the queue to be played, it is added back to the end of the playlist.
|
||||||
|
|
||||||
|
* `shuffle [true|false]` - Sets the bot to shuffle the playlist, as in pull a random song from the playlist, with some filters to prevent repeating songs.
|
||||||
|
|
||||||
|
* `playlist <create|show|play|delete|add|remove|rename>` - Various commands to manipulate playlists. The specific sub-commands are explained below.
|
||||||
|
* `create <NAME> [URL]...` - Creates a new playlist, optionally with some starting URLs.
|
||||||
|
|
||||||
|
* `delete <NAME>` - Deletes a playlist with the given name.
|
||||||
|
|
||||||
|
* `show [NAME]` - If a name is given, shows the songs in a given playlist; otherwise it lists the names of the playlists.
|
||||||
|
|
||||||
|
* `play <NAME>` - Loads and begins playing the specified playlist.
|
||||||
|
|
||||||
|
* `add <NAME> <URL> [URL]...` - Adds the specified URL, or multiple URLs to the playlist given by `NAME`.
|
||||||
|
|
||||||
|
* `remove <NAME> <SONGNAME>` - Removes the specified song name, or the one that most closely matches the song name given, from the playlist given by `NAME`.
|
||||||
|
|
||||||
|
* `rename <NAME> <NEWNAME>` - Renames the playlist to the new name.
|
||||||
|
|
||||||
|
|
15
pom.xml
15
pom.xml
|
@ -4,9 +4,9 @@
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
<groupId>net.agspace.handiebot</groupId>
|
<groupId>com.github.andrewlalis</groupId>
|
||||||
<artifactId>handiebot</artifactId>
|
<artifactId>HandieBot</artifactId>
|
||||||
<version>1.0-SNAPSHOT</version>
|
<version>1.1.0</version>
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
|
@ -21,10 +21,6 @@
|
||||||
</build>
|
</build>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<properties>
|
|
||||||
<pastebin4j.version>1.1.0</pastebin4j.version>
|
|
||||||
</properties>
|
|
||||||
|
|
||||||
<repositories>
|
<repositories>
|
||||||
<repository>
|
<repository>
|
||||||
<id>jcenter</id>
|
<id>jcenter</id>
|
||||||
|
@ -47,11 +43,6 @@
|
||||||
<artifactId>lavaplayer</artifactId>
|
<artifactId>lavaplayer</artifactId>
|
||||||
<version>1.2.39</version>
|
<version>1.2.39</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>com.github.kennedyoliveira</groupId>
|
|
||||||
<artifactId>pastebin4j</artifactId>
|
|
||||||
<version>${pastebin4j.version}</version>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
|
@ -16,13 +16,15 @@ import sx.blah.discord.util.RateLimitException;
|
||||||
/**
|
/**
|
||||||
* @author Andrew Lalis
|
* @author Andrew Lalis
|
||||||
* Main Class for the discord bot. Contains client loading information and general event processing.
|
* Main Class for the discord bot. Contains client loading information and general event processing.
|
||||||
|
* Most variables are static here because this is the main file for the Bot across many possible guilds it could
|
||||||
|
* be runnnig on, so it is no problem to have only one copy.
|
||||||
*/
|
*/
|
||||||
public class HandieBot {
|
public class HandieBot {
|
||||||
|
|
||||||
public static final String APPLICATION_NAME = "HandieBot";
|
public static final String APPLICATION_NAME = "HandieBot";
|
||||||
private static final String TOKEN = "MjgzNjUyOTg5MjEyNjg4Mzg0.C45A_Q.506b0G6my1FEFa7_YY39lxLBHUY";
|
private static final String TOKEN = "MjgzNjUyOTg5MjEyNjg4Mzg0.C45A_Q.506b0G6my1FEFa7_YY39lxLBHUY";
|
||||||
|
|
||||||
private static IDiscordClient client;
|
public static IDiscordClient client;
|
||||||
public static View view;
|
public static View view;
|
||||||
private static BotWindow window;
|
private static BotWindow window;
|
||||||
public static BotLog log;
|
public static BotLog log;
|
||||||
|
@ -38,6 +40,7 @@ public class HandieBot {
|
||||||
@EventSubscriber
|
@EventSubscriber
|
||||||
public void onReady(ReadyEvent event){
|
public void onReady(ReadyEvent event){
|
||||||
log.log(BotLog.TYPE.INFO, "HandieBot initialized.");
|
log.log(BotLog.TYPE.INFO, "HandieBot initialized.");
|
||||||
|
//client.changeAvatar(Image.forStream("png", getClass().getClassLoader().getResourceAsStream("avatarIcon.png")));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) throws DiscordException, RateLimitException {
|
public static void main(String[] args) throws DiscordException, RateLimitException {
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
package handiebot.command;
|
||||||
|
|
||||||
|
import sx.blah.discord.handle.obj.IChannel;
|
||||||
|
import sx.blah.discord.handle.obj.IGuild;
|
||||||
|
import sx.blah.discord.handle.obj.IUser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andrew Lalis
|
||||||
|
* Class to hold important data for a command, such as user, channel, and guild.
|
||||||
|
*/
|
||||||
|
public class CommandContext {
|
||||||
|
|
||||||
|
private IUser user;
|
||||||
|
private IChannel channel;
|
||||||
|
private IGuild guild;
|
||||||
|
private String[] args;
|
||||||
|
|
||||||
|
public CommandContext(IUser user, IChannel channel, IGuild guild, String[] args){
|
||||||
|
this.user = user;
|
||||||
|
this.channel = channel;
|
||||||
|
this.guild = guild;
|
||||||
|
this.args = args;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IUser getUser(){
|
||||||
|
return this.user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IChannel getChannel(){
|
||||||
|
return this.channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IGuild getGuild(){
|
||||||
|
return this.guild;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[] getArgs(){
|
||||||
|
return this.args;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
package handiebot.command;
|
package handiebot.command;
|
||||||
|
|
||||||
import com.sun.istack.internal.NotNull;
|
import com.sun.istack.internal.NotNull;
|
||||||
|
import handiebot.command.commands.music.PlaylistCommand;
|
||||||
import handiebot.utils.DisappearingMessage;
|
import handiebot.utils.DisappearingMessage;
|
||||||
import handiebot.view.BotLog;
|
import handiebot.view.BotLog;
|
||||||
import handiebot.view.actions.QuitAction;
|
import handiebot.view.actions.QuitAction;
|
||||||
|
@ -34,6 +35,7 @@ public class CommandHandler {
|
||||||
IGuild guild = event.getGuild();
|
IGuild guild = event.getGuild();
|
||||||
String command = extractCommand(message);
|
String command = extractCommand(message);
|
||||||
String[] args = extractArgs(message);
|
String[] args = extractArgs(message);
|
||||||
|
CommandContext context = new CommandContext(user, channel, guild, args);
|
||||||
if (guild != null && command != null){
|
if (guild != null && command != null){
|
||||||
DisappearingMessage.deleteMessageAfter(1000, message);
|
DisappearingMessage.deleteMessageAfter(1000, message);
|
||||||
if (command.equals("play")){
|
if (command.equals("play")){
|
||||||
|
@ -58,7 +60,7 @@ public class CommandHandler {
|
||||||
new QuitAction(guild).actionPerformed(null);
|
new QuitAction(guild).actionPerformed(null);
|
||||||
} else if (command.equals("playlist")){
|
} else if (command.equals("playlist")){
|
||||||
//Do playlist actions.
|
//Do playlist actions.
|
||||||
//TODO perform actions!
|
new PlaylistCommand().execute(context);
|
||||||
} else if (command.equals("prefix") && args.length == 1){
|
} else if (command.equals("prefix") && args.length == 1){
|
||||||
//Set the prefix to the first argument.
|
//Set the prefix to the first argument.
|
||||||
if (args[0].length() != 1){
|
if (args[0].length() != 1){
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
package handiebot.command;
|
||||||
|
|
||||||
|
import handiebot.command.commands.music.*;
|
||||||
|
import handiebot.command.types.Command;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andrew Lalis
|
||||||
|
* Class to hold a list of commands, as static definitions that can be called upon by {@code CommandHandler}.
|
||||||
|
*/
|
||||||
|
public class Commands {
|
||||||
|
|
||||||
|
public static List<Command> commands = new ArrayList<Command>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
//Music commands.
|
||||||
|
commands.add(new PlayCommand());
|
||||||
|
commands.add(new QueueCommand());
|
||||||
|
commands.add(new SkipCommand());
|
||||||
|
commands.add(new RepeatCommand());
|
||||||
|
commands.add(new ShuffleCommand());
|
||||||
|
commands.add(new PlaylistCommand());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
package handiebot.command.commands;
|
||||||
|
|
||||||
|
import handiebot.command.CommandContext;
|
||||||
|
import handiebot.command.types.ContextCommand;
|
||||||
|
import sx.blah.discord.handle.obj.IPrivateChannel;
|
||||||
|
import sx.blah.discord.util.EmbedBuilder;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andrew Lalis
|
||||||
|
* Class for sending help/command info to a user if they so desire it.
|
||||||
|
*/
|
||||||
|
public class HelpCommand extends ContextCommand {
|
||||||
|
|
||||||
|
public HelpCommand() {
|
||||||
|
super("help");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(CommandContext context) {
|
||||||
|
IPrivateChannel pm = context.getUser().getOrCreatePMChannel();
|
||||||
|
EmbedBuilder builder = new EmbedBuilder();
|
||||||
|
|
||||||
|
builder.withAuthorName("HandieBot");
|
||||||
|
builder.withAuthorUrl("https://github.com/andrewlalis/HandieBot");
|
||||||
|
builder.withAuthorIcon("https://github.com/andrewlalis/HandieBot/blob/master/src/main/resources/icon.png");
|
||||||
|
|
||||||
|
builder.withColor(new Color(255, 0, 0));
|
||||||
|
builder.withDescription("I'm a discord bot that can manage music, as well as some other important functions which will be implemented later on. Some commands are shown below.");
|
||||||
|
builder.appendField("Commands:", "play, skip, help", false);
|
||||||
|
|
||||||
|
pm.sendMessage(builder.build());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
package handiebot.command.commands.music;
|
||||||
|
|
||||||
|
import handiebot.HandieBot;
|
||||||
|
import handiebot.command.CommandContext;
|
||||||
|
import handiebot.command.types.ContextCommand;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andrew Lalis
|
||||||
|
* Command to play a song from the queue or load a new song.
|
||||||
|
*/
|
||||||
|
public class PlayCommand extends ContextCommand {
|
||||||
|
|
||||||
|
public PlayCommand() {
|
||||||
|
super("play");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(CommandContext context) {
|
||||||
|
if (context.getArgs() == null || context.getArgs().length == 0){
|
||||||
|
HandieBot.musicPlayer.playQueue(context.getGuild());
|
||||||
|
} else {
|
||||||
|
HandieBot.musicPlayer.loadToQueue(context.getGuild(), context.getArgs()[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,126 @@
|
||||||
|
package handiebot.command.commands.music;
|
||||||
|
|
||||||
|
import handiebot.command.CommandContext;
|
||||||
|
import handiebot.command.CommandHandler;
|
||||||
|
import handiebot.command.types.ContextCommand;
|
||||||
|
import handiebot.lavaplayer.Playlist;
|
||||||
|
import handiebot.utils.DisappearingMessage;
|
||||||
|
import handiebot.view.BotLog;
|
||||||
|
import sx.blah.discord.handle.obj.IChannel;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static handiebot.HandieBot.log;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andrew Lalis
|
||||||
|
* Command to manipulate playlists.
|
||||||
|
*/
|
||||||
|
public class PlaylistCommand extends ContextCommand {
|
||||||
|
|
||||||
|
public PlaylistCommand(){
|
||||||
|
super("playlist");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(CommandContext context) {
|
||||||
|
String[] args = context.getArgs();
|
||||||
|
if (args.length > 0){
|
||||||
|
switch (args[0]){
|
||||||
|
case ("create"):
|
||||||
|
create(context);
|
||||||
|
break;
|
||||||
|
case ("delete"):
|
||||||
|
delete(context);
|
||||||
|
break;
|
||||||
|
case ("show"):
|
||||||
|
show(context);
|
||||||
|
break;
|
||||||
|
case ("add"):
|
||||||
|
|
||||||
|
break;
|
||||||
|
case ("remove"):
|
||||||
|
|
||||||
|
break;
|
||||||
|
case ("rename"):
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
incorrectMainArg(context.getChannel());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
incorrectMainArg(context.getChannel());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Error message to show if the main argument is incorrect.
|
||||||
|
* @param channel The channel to show the error message in.
|
||||||
|
*/
|
||||||
|
private void incorrectMainArg(IChannel channel){
|
||||||
|
new DisappearingMessage(channel, "Please use one of the following actions: \n`<create|delete|show|play|add|remove|rename>`", 5000);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new playlist.
|
||||||
|
* @param context The important data such as user and arguments to be passed.
|
||||||
|
*/
|
||||||
|
private void create(CommandContext context){
|
||||||
|
if (context.getArgs().length >= 2) {
|
||||||
|
Playlist playlist = new Playlist(context.getArgs()[1], context.getUser().getLongID());
|
||||||
|
playlist.save();
|
||||||
|
for (int i = 2; i < context.getArgs().length; i++){
|
||||||
|
String url = context.getArgs()[i];
|
||||||
|
playlist.loadTrack(url);
|
||||||
|
playlist.save();
|
||||||
|
}
|
||||||
|
log.log(BotLog.TYPE.INFO, "Created playlist: "+playlist.getName()+" with "+playlist.getTracks().size()+" new tracks.");
|
||||||
|
new DisappearingMessage(context.getChannel(), "Your playlist *"+playlist.getName()+"* has been created.\nType `"+ CommandHandler.PREFIX+"playlist play "+playlist.getName()+"` to play it.", 5000);
|
||||||
|
} else {
|
||||||
|
new DisappearingMessage(context.getChannel(), "You must specify a name for the new playlist.", 3000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempts to delete a playlist.
|
||||||
|
* @param context The context of the command.
|
||||||
|
*/
|
||||||
|
private void delete(CommandContext context){
|
||||||
|
if (context.getArgs().length == 2){
|
||||||
|
if (Playlist.playlistExists(context.getArgs()[1])){
|
||||||
|
File f = new File(System.getProperty("user.home")+"/.handiebot/playlist/"+context.getArgs()[1].replace(" ", "_")+".txt");
|
||||||
|
boolean success = f.delete();
|
||||||
|
if (success){
|
||||||
|
new DisappearingMessage(context.getChannel(), "The playlist *"+context.getArgs()[1]+"* has been deleted.", 5000);
|
||||||
|
} else {
|
||||||
|
log.log(BotLog.TYPE.ERROR, "Unable to delete playlist: "+context.getArgs()[1]);
|
||||||
|
new DisappearingMessage(context.getChannel(), "The playlist was not able to be deleted.", 3000);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
new DisappearingMessage(context.getChannel(), "The name you entered is not a playlist.\nType `"+CommandHandler.PREFIX+"playlist show` to list the playlists available.", 5000);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
new DisappearingMessage(context.getChannel(), "You must specify the name of a playlist to delete.", 3000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays the list of playlists, or a specific playlist's songs.
|
||||||
|
* @param context The data to be passed, containing channel and arguments.
|
||||||
|
*/
|
||||||
|
private void show(CommandContext context){
|
||||||
|
if (context.getArgs().length > 1){
|
||||||
|
|
||||||
|
} else {
|
||||||
|
List<String> playlists = Playlist.getAvailablePlaylists();
|
||||||
|
StringBuilder sb = new StringBuilder("**Playlists:**\n");
|
||||||
|
for (String playlist : playlists) {
|
||||||
|
sb.append(playlist).append('\n');
|
||||||
|
}
|
||||||
|
context.getChannel().sendMessage(sb.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package handiebot.command.commands.music;
|
||||||
|
|
||||||
|
import handiebot.HandieBot;
|
||||||
|
import handiebot.command.CommandContext;
|
||||||
|
import handiebot.command.types.ContextCommand;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andrew Lalis
|
||||||
|
* Queue command to display the active queue.
|
||||||
|
*/
|
||||||
|
public class QueueCommand extends ContextCommand {
|
||||||
|
public QueueCommand() {
|
||||||
|
super("queue");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(CommandContext context) {
|
||||||
|
HandieBot.musicPlayer.showQueueList(context.getGuild(), (context.getArgs() != null && context.getArgs()[0].equals("all")));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
package handiebot.command.commands.music;
|
||||||
|
|
||||||
|
import handiebot.HandieBot;
|
||||||
|
import handiebot.command.CommandContext;
|
||||||
|
import handiebot.command.types.ContextCommand;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andrew Lalis
|
||||||
|
* Command to toggle repeating of the active playlist.
|
||||||
|
*/
|
||||||
|
public class RepeatCommand extends ContextCommand {
|
||||||
|
|
||||||
|
public RepeatCommand(){
|
||||||
|
super("repeat");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(CommandContext context) {
|
||||||
|
if (context.getArgs().length == 1){
|
||||||
|
boolean shouldRepeat = Boolean.getBoolean(context.getArgs()[0].toLowerCase());
|
||||||
|
HandieBot.musicPlayer.setRepeat(context.getGuild(), shouldRepeat);
|
||||||
|
} else {
|
||||||
|
HandieBot.musicPlayer.toggleRepeat(context.getGuild());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
package handiebot.command.commands.music;
|
||||||
|
|
||||||
|
import handiebot.HandieBot;
|
||||||
|
import handiebot.command.CommandContext;
|
||||||
|
import handiebot.command.types.ContextCommand;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andrew Lalis
|
||||||
|
* Command to set shuffling of the active playlist.
|
||||||
|
*/
|
||||||
|
public class ShuffleCommand extends ContextCommand {
|
||||||
|
|
||||||
|
public ShuffleCommand(){
|
||||||
|
super("shuffle");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(CommandContext context) {
|
||||||
|
if (context.getArgs().length == 1){
|
||||||
|
boolean shouldShuffle = Boolean.getBoolean(context.getArgs()[0].toLowerCase());
|
||||||
|
HandieBot.musicPlayer.setShuffle(context.getGuild(), shouldShuffle);
|
||||||
|
} else {
|
||||||
|
HandieBot.musicPlayer.toggleShuffle(context.getGuild());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
package handiebot.command.commands.music;
|
||||||
|
|
||||||
|
import handiebot.HandieBot;
|
||||||
|
import handiebot.command.CommandContext;
|
||||||
|
import handiebot.command.types.ContextCommand;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andrew Lalis
|
||||||
|
* Skips the current song, if there is one playing.
|
||||||
|
*/
|
||||||
|
public class SkipCommand extends ContextCommand {
|
||||||
|
|
||||||
|
public SkipCommand() {
|
||||||
|
super("skip");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(CommandContext context) {
|
||||||
|
HandieBot.musicPlayer.skipTrack(context.getGuild());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package handiebot.command.types;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andrew Lalis
|
||||||
|
* Basic type of command.
|
||||||
|
*/
|
||||||
|
public abstract class Command {
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public Command(String name){
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName(){
|
||||||
|
return this.name;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
package handiebot.command.types;
|
||||||
|
|
||||||
|
import handiebot.command.CommandContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andrew Lalis
|
||||||
|
* Type of command which requires a guild to function properly.
|
||||||
|
*/
|
||||||
|
public abstract class ContextCommand extends Command {
|
||||||
|
|
||||||
|
public ContextCommand(String s) {
|
||||||
|
super(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void execute(CommandContext context);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package handiebot.command.types;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andrew Lalis
|
||||||
|
* Class for commands which require no context, so execute on a global scale.
|
||||||
|
*/
|
||||||
|
public abstract class StaticCommand extends Command {
|
||||||
|
|
||||||
|
public StaticCommand(String s) {
|
||||||
|
super(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void execute();
|
||||||
|
|
||||||
|
}
|
|
@ -16,7 +16,7 @@ public class GuildMusicManager {
|
||||||
|
|
||||||
public GuildMusicManager(AudioPlayerManager manager, IGuild guild){
|
public GuildMusicManager(AudioPlayerManager manager, IGuild guild){
|
||||||
this.player = manager.createPlayer();
|
this.player = manager.createPlayer();
|
||||||
this.scheduler = new TrackScheduler(this.player, guild, manager);
|
this.scheduler = new TrackScheduler(this.player, guild);
|
||||||
this.player.addListener(this.scheduler);
|
this.player.addListener(this.scheduler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,12 +10,26 @@ import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
|
||||||
import handiebot.command.CommandHandler;
|
import handiebot.command.CommandHandler;
|
||||||
import handiebot.utils.DisappearingMessage;
|
import handiebot.utils.DisappearingMessage;
|
||||||
import handiebot.view.BotLog;
|
import handiebot.view.BotLog;
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
|
import org.apache.http.HttpEntity;
|
||||||
|
import org.apache.http.HttpResponse;
|
||||||
|
import org.apache.http.NameValuePair;
|
||||||
|
import org.apache.http.client.HttpClient;
|
||||||
|
import org.apache.http.client.entity.UrlEncodedFormEntity;
|
||||||
|
import org.apache.http.client.methods.HttpPost;
|
||||||
|
import org.apache.http.impl.client.HttpClients;
|
||||||
|
import org.apache.http.message.BasicNameValuePair;
|
||||||
import sx.blah.discord.handle.obj.IChannel;
|
import sx.blah.discord.handle.obj.IChannel;
|
||||||
import sx.blah.discord.handle.obj.IGuild;
|
import sx.blah.discord.handle.obj.IGuild;
|
||||||
import sx.blah.discord.handle.obj.IMessage;
|
import sx.blah.discord.handle.obj.IMessage;
|
||||||
import sx.blah.discord.handle.obj.IVoiceChannel;
|
import sx.blah.discord.handle.obj.IVoiceChannel;
|
||||||
import sx.blah.discord.util.EmbedBuilder;
|
import sx.blah.discord.util.EmbedBuilder;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -55,6 +69,10 @@ public class MusicPlayer {
|
||||||
this.voiceChannels = new HashMap<>();
|
this.voiceChannels = new HashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public AudioPlayerManager getPlayerManager(){
|
||||||
|
return this.playerManager;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the music manager specific to a particular guild.
|
* Gets the music manager specific to a particular guild.
|
||||||
* @param guild The guild to get the music manager for.
|
* @param guild The guild to get the music manager for.
|
||||||
|
@ -113,14 +131,40 @@ public class MusicPlayer {
|
||||||
*/
|
*/
|
||||||
public void toggleRepeat(IGuild guild){
|
public void toggleRepeat(IGuild guild){
|
||||||
GuildMusicManager musicManager = this.getMusicManager(guild);
|
GuildMusicManager musicManager = this.getMusicManager(guild);
|
||||||
|
|
||||||
musicManager.scheduler.setRepeat(!musicManager.scheduler.isRepeating());
|
musicManager.scheduler.setRepeat(!musicManager.scheduler.isRepeating());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the repeating of songs for a particular guild.
|
||||||
|
* @param guild The guild to set repeat for.
|
||||||
|
* @param value True to repeat, false otherwise.
|
||||||
|
*/
|
||||||
|
public void setRepeat(IGuild guild, boolean value){
|
||||||
|
getMusicManager(guild).scheduler.setRepeat(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggles shuffling for a specific guild.
|
||||||
|
* @param guild The guild to toggle shuffling for.
|
||||||
|
*/
|
||||||
|
public void toggleShuffle(IGuild guild){
|
||||||
|
GuildMusicManager musicManager = this.getMusicManager(guild);
|
||||||
|
musicManager.scheduler.setShuffle(!musicManager.scheduler.isShuffling());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets shuffling for a specific guild.
|
||||||
|
* @param guild The guild to set shuffling for.
|
||||||
|
* @param value The value to set. True for shuffling, false for linear play.
|
||||||
|
*/
|
||||||
|
public void setShuffle(IGuild guild, boolean value){
|
||||||
|
getMusicManager(guild).scheduler.setShuffle(value);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends a formatted message to the guild about the first few items in a queue.
|
* Sends a formatted message to the guild about the first few items in a queue.
|
||||||
*/
|
*/
|
||||||
public void showQueueList(IGuild guild, boolean showAll){
|
public void showQueueList(IGuild guild, boolean showAll) {
|
||||||
List<AudioTrack> tracks = getMusicManager(guild).scheduler.queueList();
|
List<AudioTrack> tracks = getMusicManager(guild).scheduler.queueList();
|
||||||
if (tracks.size() == 0) {
|
if (tracks.size() == 0) {
|
||||||
new DisappearingMessage(getChatChannel(guild), "The queue is empty. Use **"+ CommandHandler.PREFIX+"play** *URL* to add songs.", 3000);
|
new DisappearingMessage(getChatChannel(guild), "The queue is empty. Use **"+ CommandHandler.PREFIX+"play** *URL* to add songs.", 3000);
|
||||||
|
@ -157,18 +201,60 @@ public class MusicPlayer {
|
||||||
String time = String.format(" [%d:%02d]\n", minutes, seconds);
|
String time = String.format(" [%d:%02d]\n", minutes, seconds);
|
||||||
sb.append(time);
|
sb.append(time);
|
||||||
}
|
}
|
||||||
//TODO: get pastebin working.
|
|
||||||
/*
|
HttpClient httpclient = HttpClients.createDefault();
|
||||||
PasteBin pasteBin = new PasteBin(new AccountCredentials(PASTEBIN_KEY));
|
HttpPost httppost = new HttpPost("https://www.pastebin.com/api/api_post.php");
|
||||||
Paste paste = new Paste(PASTEBIN_KEY);
|
|
||||||
paste.setTitle("Music Queue for Discord Server: "+guild.getName());
|
// Request parameters and other properties.
|
||||||
paste.setContent(sb.toString());
|
List<NameValuePair> params = new ArrayList<NameValuePair>(2);
|
||||||
paste.setExpiration(PasteExpiration.ONE_HOUR);
|
params.add(new BasicNameValuePair("api_dev_key", PASTEBIN_KEY));
|
||||||
paste.setVisibility(PasteVisibility.PUBLIC);
|
params.add(new BasicNameValuePair("api_option", "paste"));
|
||||||
final String pasteURL = pasteBin.createPaste(paste);
|
params.add(new BasicNameValuePair("api_paste_code", sb.toString()));
|
||||||
log.log(BotLog.TYPE.INFO, guild, "Uploaded full queue to "+pasteURL);
|
params.add(new BasicNameValuePair("api_paste_private", "0"));
|
||||||
new DisappearingMessage(getChatChannel(guild), "You may view the full queue here. "+pasteURL, 60000);
|
params.add(new BasicNameValuePair("api_paste_name", "Music Queue for Discord Server: "+guild.getName()));
|
||||||
*/
|
params.add(new BasicNameValuePair("api_paste_expire_date", "10M"));
|
||||||
|
//params.add(new BasicNameValuePair("api_paste_format", "text"));
|
||||||
|
params.add(new BasicNameValuePair("api_user_key", ""));
|
||||||
|
|
||||||
|
try {
|
||||||
|
httppost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Execute and get the response.
|
||||||
|
HttpResponse response = null;
|
||||||
|
try {
|
||||||
|
response = httpclient.execute(httppost);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
HttpEntity entity = response.getEntity();
|
||||||
|
|
||||||
|
if (entity != null) {
|
||||||
|
InputStream instream = null;
|
||||||
|
try {
|
||||||
|
instream = entity.getContent();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
StringWriter writer = new StringWriter();
|
||||||
|
IOUtils.copy(instream, writer, "UTF-8");
|
||||||
|
String pasteURL = writer.toString();
|
||||||
|
log.log(BotLog.TYPE.INFO, guild, "Uploaded full queue to "+pasteURL);
|
||||||
|
new DisappearingMessage(getChatChannel(guild), "You may view the full queue here. "+pasteURL, 60000);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
instream.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,17 @@
|
||||||
package handiebot.lavaplayer;
|
package handiebot.lavaplayer;
|
||||||
|
|
||||||
import com.sedmelluq.discord.lavaplayer.player.AudioLoadResultHandler;
|
import com.sedmelluq.discord.lavaplayer.player.AudioLoadResultHandler;
|
||||||
import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager;
|
|
||||||
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 handiebot.HandieBot;
|
||||||
import handiebot.view.BotLog;
|
import handiebot.view.BotLog;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
|
@ -21,6 +22,8 @@ import static handiebot.HandieBot.log;
|
||||||
* @author Andrew Lalis
|
* @author Andrew Lalis
|
||||||
* A Playlist is a list of AudioTracks which a track scheduler can pull from to create a queue filled with songs. The
|
* A Playlist is a list of AudioTracks which a track scheduler can pull from to create a queue filled with songs. The
|
||||||
* playlist is persistent, i.e. it is saved into a file.
|
* playlist is persistent, i.e. it is saved into a file.
|
||||||
|
* Be careful, though, as the playlist is not saved in this class, but must be saved manually by whoever is operating
|
||||||
|
* on the playlist.
|
||||||
*/
|
*/
|
||||||
public class Playlist {
|
public class Playlist {
|
||||||
|
|
||||||
|
@ -44,9 +47,9 @@ public class Playlist {
|
||||||
* Creates a playlist from a file with the given name.
|
* Creates a playlist from a file with the given name.
|
||||||
* @param name The name of the file.
|
* @param name The name of the file.
|
||||||
*/
|
*/
|
||||||
public Playlist(String name, AudioPlayerManager playerManager){
|
public Playlist(String name){
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.load(playerManager);
|
this.load();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName(){
|
public String getName(){
|
||||||
|
@ -69,6 +72,44 @@ public class Playlist {
|
||||||
this.tracks.add(track);
|
this.tracks.add(track);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempts to load a track or playlist from a URL, and add it to the tracks list.
|
||||||
|
* @param url The URL to get the song/playlist from.
|
||||||
|
*/
|
||||||
|
public void loadTrack(String url){
|
||||||
|
try {
|
||||||
|
HandieBot.musicPlayer.getPlayerManager().loadItem(url, new AudioLoadResultHandler() {
|
||||||
|
@Override
|
||||||
|
public void trackLoaded(AudioTrack audioTrack) {
|
||||||
|
tracks.add(audioTrack);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void playlistLoaded(AudioPlaylist audioPlaylist) {
|
||||||
|
tracks.addAll(audioPlaylist.getTracks());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void noMatches() {
|
||||||
|
log.log(BotLog.TYPE.ERROR, "No matches found for: "+url+".");
|
||||||
|
//Do nothing. This should not happen.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadFailed(FriendlyException e) {
|
||||||
|
log.log(BotLog.TYPE.ERROR, "Unable to load song from URL: "+url+". "+e.getMessage());
|
||||||
|
//Do nothing. This should not happen.
|
||||||
|
}
|
||||||
|
}).get();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
log.log(BotLog.TYPE.ERROR, "Loading of playlist ["+this.name+"] interrupted. "+e.getMessage());
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (ExecutionException e) {
|
||||||
|
log.log(BotLog.TYPE.ERROR, "Execution exception while loading playlist ["+this.name+"]. "+e.getMessage());
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes a track from the playlist.
|
* Removes a track from the playlist.
|
||||||
* @param track The track to remove.
|
* @param track The track to remove.
|
||||||
|
@ -159,7 +200,7 @@ public class Playlist {
|
||||||
/**
|
/**
|
||||||
* Loads the playlist from a file with the playlist's name.
|
* Loads the playlist from a file with the playlist's name.
|
||||||
*/
|
*/
|
||||||
public void load(AudioPlayerManager playerManager){
|
public void load(){
|
||||||
String path = System.getProperty("user.home")+"/.handiebot/playlist/"+this.name.replace(" ", "_")+".txt";
|
String path = System.getProperty("user.home")+"/.handiebot/playlist/"+this.name.replace(" ", "_")+".txt";
|
||||||
log.log(BotLog.TYPE.INFO, "Loading playlist from: "+path);
|
log.log(BotLog.TYPE.INFO, "Loading playlist from: "+path);
|
||||||
File playlistFile = new File(path);
|
File playlistFile = new File(path);
|
||||||
|
@ -172,41 +213,41 @@ public class Playlist {
|
||||||
this.tracks = new ArrayList<>(trackCount);
|
this.tracks = new ArrayList<>(trackCount);
|
||||||
for (int i = 0; i < trackCount; i++){
|
for (int i = 0; i < trackCount; i++){
|
||||||
String url = lines.remove(0);
|
String url = lines.remove(0);
|
||||||
playerManager.loadItem(url, new AudioLoadResultHandler() {
|
loadTrack(url);
|
||||||
@Override
|
|
||||||
public void trackLoaded(AudioTrack audioTrack) {
|
|
||||||
tracks.add(audioTrack);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void playlistLoaded(AudioPlaylist audioPlaylist) {
|
|
||||||
//Do nothing. This should not happen.
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void noMatches() {
|
|
||||||
System.out.println("No matches for: "+url);
|
|
||||||
//Do nothing. This should not happen.
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void loadFailed(FriendlyException e) {
|
|
||||||
System.out.println("Load failed: "+e.getMessage());
|
|
||||||
//Do nothing. This should not happen.
|
|
||||||
}
|
|
||||||
}).get();
|
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
log.log(BotLog.TYPE.ERROR, "IOException while loading playlist ["+this.name+"]. "+e.getMessage());
|
log.log(BotLog.TYPE.ERROR, "IOException while loading playlist ["+this.name+"]. "+e.getMessage());
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
} catch (InterruptedException e) {
|
|
||||||
log.log(BotLog.TYPE.ERROR, "Loading of playlist ["+this.name+"] interrupted. "+e.getMessage());
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (ExecutionException e) {
|
|
||||||
log.log(BotLog.TYPE.ERROR, "Execution exception while loading playlist ["+this.name+"]. "+e.getMessage());
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
log.log(BotLog.TYPE.ERROR, "The playlist ["+this.name+"] does not exist.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of all playlists, or essentially all playlist files.
|
||||||
|
* @return A list of all playlists.
|
||||||
|
*/
|
||||||
|
public static List<String> getAvailablePlaylists(){
|
||||||
|
File playlistFolder = new File(System.getProperty("user.home")+"/.handiebot/playlist");
|
||||||
|
List<String> names = new ArrayList<String>(Arrays.asList(playlistFolder.list()));
|
||||||
|
names.forEach(name -> name = name.replace("_", " "));
|
||||||
|
return names;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if a playlist exists.
|
||||||
|
* @param name The name of the playlist.
|
||||||
|
* @return True if the playlist exists.
|
||||||
|
*/
|
||||||
|
public static boolean playlistExists(String name){
|
||||||
|
List<String> names = getAvailablePlaylists();
|
||||||
|
for (String n : names){
|
||||||
|
if (n.equals(name)){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package handiebot.lavaplayer;
|
package handiebot.lavaplayer;
|
||||||
|
|
||||||
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.event.AudioEventAdapter;
|
import com.sedmelluq.discord.lavaplayer.player.event.AudioEventAdapter;
|
||||||
import com.sedmelluq.discord.lavaplayer.tools.FriendlyException;
|
import com.sedmelluq.discord.lavaplayer.tools.FriendlyException;
|
||||||
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
|
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
|
||||||
|
@ -36,11 +35,11 @@ public class TrackScheduler extends AudioEventAdapter {
|
||||||
* Constructs a new track scheduler with the given player.
|
* Constructs a new track scheduler with the given player.
|
||||||
* @param player The audio player this scheduler uses.
|
* @param player The audio player this scheduler uses.
|
||||||
*/
|
*/
|
||||||
public TrackScheduler(AudioPlayer player, IGuild guild, AudioPlayerManager playerManager){
|
public TrackScheduler(AudioPlayer player, IGuild guild){
|
||||||
this.player = player;
|
this.player = player;
|
||||||
this.guild = guild;
|
this.guild = guild;
|
||||||
//this.activePlaylist = new Playlist("HandieBot Active Playlist", 283652989212688384L);
|
//this.activePlaylist = new Playlist("HandieBot Active Playlist", 283652989212688384L);
|
||||||
this.activePlaylist = new Playlist("HandieBot Active Playlist", playerManager);
|
this.activePlaylist = new Playlist("HandieBot Active Playlist");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 9.4 KiB |
Binary file not shown.
Before Width: | Height: | Size: 70 KiB |
|
@ -1,108 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
|
|
||||||
<svg
|
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
|
||||||
xmlns:cc="http://creativecommons.org/ns#"
|
|
||||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
width="256"
|
|
||||||
height="256"
|
|
||||||
viewBox="0 0 256 256"
|
|
||||||
id="svg4136"
|
|
||||||
version="1.1"
|
|
||||||
inkscape:version="0.91 r13725"
|
|
||||||
sodipodi:docname="icon.svg"
|
|
||||||
inkscape:export-filename="C:\Users\AndrewComputer\Documents\Programming\IntelliJ_Projects\handiebot\src\main\resources\icon.png"
|
|
||||||
inkscape:export-xdpi="360"
|
|
||||||
inkscape:export-ydpi="360">
|
|
||||||
<defs
|
|
||||||
id="defs4138">
|
|
||||||
<marker
|
|
||||||
inkscape:stockid="Arrow1Lstart"
|
|
||||||
orient="auto"
|
|
||||||
refY="0.0"
|
|
||||||
refX="0.0"
|
|
||||||
id="Arrow1Lstart"
|
|
||||||
style="overflow:visible"
|
|
||||||
inkscape:isstock="true">
|
|
||||||
<path
|
|
||||||
id="path4701"
|
|
||||||
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
|
|
||||||
style="fill-rule:evenodd;stroke:#ffffff;stroke-width:1pt;stroke-opacity:1;fill:#ffffff;fill-opacity:1"
|
|
||||||
transform="scale(0.8) translate(12.5,0)" />
|
|
||||||
</marker>
|
|
||||||
</defs>
|
|
||||||
<sodipodi:namedview
|
|
||||||
id="base"
|
|
||||||
pagecolor="#00024b"
|
|
||||||
bordercolor="#666666"
|
|
||||||
borderopacity="1.0"
|
|
||||||
inkscape:pageopacity="1"
|
|
||||||
inkscape:pageshadow="2"
|
|
||||||
inkscape:zoom="2.8"
|
|
||||||
inkscape:cx="140.27403"
|
|
||||||
inkscape:cy="113.84621"
|
|
||||||
inkscape:document-units="px"
|
|
||||||
inkscape:current-layer="layer1"
|
|
||||||
showgrid="false"
|
|
||||||
units="px"
|
|
||||||
inkscape:window-width="1920"
|
|
||||||
inkscape:window-height="1017"
|
|
||||||
inkscape:window-x="-8"
|
|
||||||
inkscape:window-y="-8"
|
|
||||||
inkscape:window-maximized="1" />
|
|
||||||
<metadata
|
|
||||||
id="metadata4141">
|
|
||||||
<rdf:RDF>
|
|
||||||
<cc:Work
|
|
||||||
rdf:about="">
|
|
||||||
<dc:format>image/svg+xml</dc:format>
|
|
||||||
<dc:type
|
|
||||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
|
||||||
<dc:title />
|
|
||||||
</cc:Work>
|
|
||||||
</rdf:RDF>
|
|
||||||
</metadata>
|
|
||||||
<g
|
|
||||||
inkscape:label="Layer 1"
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
id="layer1"
|
|
||||||
transform="translate(0,-796.36219)">
|
|
||||||
<path
|
|
||||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:12;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
|
||||||
d="M 26.071429,935.93362 C 83.571429,805.57648 182.26443,803.4602 238.57143,935.57647 226.96157,777.68558 38.855639,775.90407 26.071429,935.93362 Z"
|
|
||||||
id="path4689"
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
sodipodi:nodetypes="ccc" />
|
|
||||||
<ellipse
|
|
||||||
style="opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:12;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
|
||||||
id="path4979"
|
|
||||||
cx="223.82457"
|
|
||||||
cy="925.21936"
|
|
||||||
rx="19.245705"
|
|
||||||
ry="31.492556" />
|
|
||||||
<use
|
|
||||||
x="0"
|
|
||||||
y="0"
|
|
||||||
xlink:href="#path4979"
|
|
||||||
id="use4986"
|
|
||||||
transform="translate(-181.78571,-4.4666172e-7)"
|
|
||||||
width="100%"
|
|
||||||
height="100%"
|
|
||||||
style="stroke-width:12;stroke-miterlimit:4;stroke-dasharray:none" />
|
|
||||||
<g
|
|
||||||
id="g4981">
|
|
||||||
<ellipse
|
|
||||||
ry="73.582115"
|
|
||||||
rx="83.534172"
|
|
||||||
cy="936.95587"
|
|
||||||
cx="132.5"
|
|
||||||
id="path4691"
|
|
||||||
style="opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#ff6900;stroke-width:12;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 3.8 KiB |
Binary file not shown.
After Width: | Height: | Size: 39 KiB |
Loading…
Reference in New Issue