Many bug fixes, small features added. #3
17
README.md
17
README.md
|
@ -29,14 +29,29 @@ queue all
|
|||
|
||||
Because the play command is defined as `play [URL]`, and the queue command is defined as `queue [all]`.
|
||||
|
||||
### General
|
||||
|
||||
* `info` - Displays the most common commands, and some basic information about the bot.
|
||||
|
||||
* `help` - Sends a private message to whoever issues this command. The message contains an in-depth list of all commands and their proper usage.
|
||||
|
||||
* `setprefix <PREFIX>` - Sets the prefix for all commands. Be careful, as some values will cause irreversible damage, if for example, a prefix conflicts with another bot's prefix.
|
||||
|
||||
### 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.
|
||||
|
||||
* `stop` - If music is playing, this will stop it.
|
||||
|
||||
* `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
|
||||
* `queue [all|clear|save]` - Lists up to the first 10 items on the queue, if no argument is given.
|
||||
|
||||
* `all` - The bot will upload a list to [PasteBin](http://pastebin.com) of the entire queue, provided it is greater than 10 elements, and give you a link which expires in 10 minutes.
|
||||
|
||||
* `clear` - The queue will be cleared and the current song will be stopped.
|
||||
|
||||
* `save <PLAYLIST>` - The queue will be saved as a playlist with the given name.
|
||||
|
||||
* `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.
|
||||
|
||||
|
|
25
pom.xml
25
pom.xml
|
@ -17,6 +17,31 @@
|
|||
<target>1.8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
<descriptorRefs>
|
||||
<descriptorRef>jar-with-dependencies</descriptorRef>
|
||||
</descriptorRefs>
|
||||
<archive>
|
||||
<manifest>
|
||||
<mainClass>handiebot.HandieBot</mainClass>
|
||||
</manifest>
|
||||
</archive>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>single</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<packaging>jar</packaging>
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
Manifest-Version: 1.0
|
||||
Main-Class: handiebot.HandieBot
|
||||
|
|
@ -1,7 +1,9 @@
|
|||
package handiebot;
|
||||
|
||||
import handiebot.command.CommandHandler;
|
||||
import handiebot.command.types.ReactionHandler;
|
||||
import handiebot.lavaplayer.MusicPlayer;
|
||||
import handiebot.utils.DisappearingMessage;
|
||||
import handiebot.view.BotLog;
|
||||
import handiebot.view.BotWindow;
|
||||
import handiebot.view.View;
|
||||
|
@ -10,6 +12,8 @@ import sx.blah.discord.api.IDiscordClient;
|
|||
import sx.blah.discord.api.events.EventSubscriber;
|
||||
import sx.blah.discord.handle.impl.events.ReadyEvent;
|
||||
import sx.blah.discord.handle.impl.events.guild.channel.message.MessageReceivedEvent;
|
||||
import sx.blah.discord.handle.impl.events.guild.channel.message.reaction.ReactionEvent;
|
||||
import sx.blah.discord.handle.obj.IGuild;
|
||||
import sx.blah.discord.util.DiscordException;
|
||||
import sx.blah.discord.util.RateLimitException;
|
||||
|
||||
|
@ -29,17 +33,24 @@ public class HandieBot {
|
|||
private static BotWindow window;
|
||||
public static BotLog log;
|
||||
|
||||
private static CommandHandler commandHandler;
|
||||
public static MusicPlayer musicPlayer;
|
||||
|
||||
@EventSubscriber
|
||||
public void onMessageReceived(MessageReceivedEvent event) {
|
||||
commandHandler.handleCommand(event);
|
||||
CommandHandler.handleCommand(event);
|
||||
}
|
||||
|
||||
@EventSubscriber
|
||||
public void onReactionReceived(ReactionEvent event){
|
||||
ReactionHandler.handleReaction(event);
|
||||
}
|
||||
|
||||
@EventSubscriber
|
||||
public void onReady(ReadyEvent event){
|
||||
log.log(BotLog.TYPE.INFO, "HandieBot initialized.");
|
||||
for (IGuild guild : client.getGuilds()){
|
||||
DisappearingMessage.deleteMessageAfter(5000, musicPlayer.getChatChannel(guild).sendMessage("HandieBot initialized."));
|
||||
}
|
||||
//client.changeAvatar(Image.forStream("png", getClass().getClassLoader().getResourceAsStream("avatarIcon.png")));
|
||||
}
|
||||
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
package handiebot.command;
|
||||
|
||||
import com.sun.istack.internal.NotNull;
|
||||
import handiebot.command.commands.music.PlayCommand;
|
||||
import handiebot.command.commands.music.PlaylistCommand;
|
||||
import handiebot.command.commands.music.RepeatCommand;
|
||||
import handiebot.command.commands.music.ShuffleCommand;
|
||||
import handiebot.utils.DisappearingMessage;
|
||||
import handiebot.utils.FileUtil;
|
||||
import handiebot.view.BotLog;
|
||||
import handiebot.view.actions.QuitAction;
|
||||
import handiebot.view.actions.music.QueueListAction;
|
||||
import handiebot.view.actions.music.SkipAction;
|
||||
import sx.blah.discord.handle.impl.events.guild.channel.message.MessageReceivedEvent;
|
||||
import sx.blah.discord.handle.obj.*;
|
||||
import sx.blah.discord.util.EmbedBuilder;
|
||||
import sx.blah.discord.handle.obj.IChannel;
|
||||
import sx.blah.discord.handle.obj.IGuild;
|
||||
import sx.blah.discord.handle.obj.IMessage;
|
||||
import sx.blah.discord.handle.obj.IUser;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static handiebot.HandieBot.client;
|
||||
import static handiebot.HandieBot.log;
|
||||
|
||||
/**
|
||||
|
@ -24,7 +24,8 @@ import static handiebot.HandieBot.log;
|
|||
*/
|
||||
public class CommandHandler {
|
||||
|
||||
public static String PREFIX = "!";
|
||||
public static final String DEFAULT_PREFIX = "!";
|
||||
public static Map<IGuild, String> PREFIXES = loadGuildPrefixes();
|
||||
/**
|
||||
* Main method to handle user messages.
|
||||
* @param event The event generated by the message.
|
||||
|
@ -32,50 +33,23 @@ public class CommandHandler {
|
|||
public static void handleCommand(MessageReceivedEvent event){
|
||||
IMessage message = event.getMessage();
|
||||
IUser user = event.getAuthor();
|
||||
//Exit immediately if the user is a bot; avoids bot spam chat.
|
||||
if (user.isBot()){
|
||||
return;
|
||||
}
|
||||
IChannel channel = event.getChannel();
|
||||
IGuild guild = event.getGuild();
|
||||
//Check if the guild already has a prefix assigned, and if not, give it the default.
|
||||
if (!PREFIXES.containsKey(guild)){
|
||||
PREFIXES.put(guild, DEFAULT_PREFIX);
|
||||
}
|
||||
String command = extractCommand(message);
|
||||
String[] args = extractArgs(message);
|
||||
//Create a context to give to each command's execution, so it knows what channel to reply on, etc.
|
||||
CommandContext context = new CommandContext(user, channel, guild, args);
|
||||
if (guild != null && command != null){
|
||||
DisappearingMessage.deleteMessageAfter(1000, message);
|
||||
if (command.equals("play")){
|
||||
//Play or queue a song.
|
||||
new PlayCommand().execute(context);
|
||||
} else if (command.equals("skip") && args.length == 0){
|
||||
//Skip the current song.
|
||||
new SkipAction(guild).actionPerformed(null);
|
||||
} else if (command.equals("help")){
|
||||
//Send a PM to the user with help info.
|
||||
sendHelpInfo(user);//TODO finish the help command and fill in with new descriptions each time.
|
||||
} else if (command.equals("queue")){
|
||||
//Display the first few items of the queue.
|
||||
new QueueListAction(guild, (args.length == 1) && args[0].equals("all")).actionPerformed(null);
|
||||
} else if (command.equals("repeat")) {
|
||||
//Toggle repeat.
|
||||
new RepeatCommand().execute(context);
|
||||
} else if (command.equals("shuffle")){
|
||||
new ShuffleCommand().execute(context);
|
||||
} else if (command.equals("clear")){
|
||||
//TODO clear command.
|
||||
} else if (command.equals("quit")){
|
||||
//Quit the application.
|
||||
new QuitAction(guild).actionPerformed(null);
|
||||
} else if (command.equals("playlist")){
|
||||
//Do playlist actions.
|
||||
new PlaylistCommand().execute(context);
|
||||
} else if (command.equals("prefix") && args.length == 1){
|
||||
//Set the prefix to the first argument.
|
||||
if (args[0].length() != 1){
|
||||
new DisappearingMessage(channel, "You may only set the prefix to 1 character. To do otherwise is simply foolish.", 3000);
|
||||
} else {
|
||||
new DisappearingMessage(channel, "Command prefix set to "+PREFIX, 10000);
|
||||
log.log(BotLog.TYPE.INFO, guild, "Prefix set to "+PREFIX);
|
||||
setPrefix(args[0]);
|
||||
}
|
||||
} else {
|
||||
log.log(BotLog.TYPE.ERROR, guild, "Invalid command: "+command+" issued by "+user.getName());
|
||||
}
|
||||
Commands.executeCommand(command, context);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -86,8 +60,8 @@ public class CommandHandler {
|
|||
*/
|
||||
private static String extractCommand(IMessage message){
|
||||
String[] words = message.getContent().split(" ");
|
||||
if (words[0].startsWith(PREFIX)){
|
||||
return words[0].replaceFirst(PREFIX, "").toLowerCase();
|
||||
if (words[0].startsWith(PREFIXES.get(message.getGuild()))){
|
||||
return words[0].replaceFirst(PREFIXES.get(message.getGuild()), "").toLowerCase();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -97,10 +71,9 @@ public class CommandHandler {
|
|||
* @param message The message to parse.
|
||||
* @return A list of strings representing args.
|
||||
*/
|
||||
@NotNull
|
||||
private static String[] extractArgs(IMessage message){
|
||||
String[] words = message.getContent().split(" ");
|
||||
if (words[0].startsWith(PREFIX)){
|
||||
if (words[0].startsWith(PREFIXES.get(message.getGuild()))){
|
||||
String[] args = new String[words.length-1];
|
||||
for (int i = 0; i < words.length-1; i++){
|
||||
args[i] = words[i+1];
|
||||
|
@ -111,30 +84,34 @@ public class CommandHandler {
|
|||
}
|
||||
|
||||
/**
|
||||
* Method to send a useful list of commands to any user if they desire.
|
||||
* @param user The user to send the message to.
|
||||
* Loads a persistent list of prefixes for guilds from a file called guildPrefixes.txt
|
||||
* @return The mapping of guild to prefix.
|
||||
*/
|
||||
private static void sendHelpInfo(IUser user){
|
||||
IPrivateChannel pm = user.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());
|
||||
private static Map<IGuild, String> loadGuildPrefixes(){
|
||||
File prefixFile = new File(FileUtil.getDataDirectory()+"guildPrefixes.txt");
|
||||
Map<IGuild, String> prefixes = new HashMap<>();
|
||||
if (prefixFile.exists()){
|
||||
List<String> lines = FileUtil.getLinesFromFile(prefixFile);
|
||||
for (String line : lines){
|
||||
String[] words = line.split(" / ");
|
||||
prefixes.put(client.getGuildByID(Long.parseLong(words[0])), words[1]);
|
||||
}
|
||||
}
|
||||
log.log(BotLog.TYPE.INFO, "Loaded prefixes.");
|
||||
return prefixes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the prefix used to identify commands.
|
||||
* @param prefix The prefix appended to the beginning of commands.
|
||||
* Saves the list of prefixes to a file.
|
||||
*/
|
||||
public static void setPrefix(String prefix){
|
||||
PREFIX = prefix;
|
||||
public static void saveGuildPrefixes(){
|
||||
File prefixFile = new File(FileUtil.getDataDirectory()+"guildPrefixes.txt");
|
||||
List<String> lines = new ArrayList<>();
|
||||
for (Map.Entry<IGuild, String> entry : PREFIXES.entrySet()){
|
||||
lines.add(Long.toString(entry.getKey().getLongID())+" / "+entry.getValue());
|
||||
}
|
||||
FileUtil.writeLinesToFile(lines, prefixFile);
|
||||
log.log(BotLog.TYPE.INFO, "Saved prefixes.");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,11 +1,18 @@
|
|||
package handiebot.command;
|
||||
|
||||
import handiebot.command.commands.HelpCommand;
|
||||
import handiebot.command.commands.InfoCommand;
|
||||
import handiebot.command.commands.SetPrefixCommand;
|
||||
import handiebot.command.commands.music.*;
|
||||
import handiebot.command.types.Command;
|
||||
import handiebot.command.types.ContextCommand;
|
||||
import handiebot.view.BotLog;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static handiebot.HandieBot.log;
|
||||
|
||||
/**
|
||||
* @author Andrew Lalis
|
||||
* Class to hold a list of commands, as static definitions that can be called upon by {@code CommandHandler}.
|
||||
|
@ -17,11 +24,46 @@ public class Commands {
|
|||
static {
|
||||
//Music commands.
|
||||
commands.add(new PlayCommand());
|
||||
commands.add(new StopCommand());
|
||||
commands.add(new QueueCommand());
|
||||
commands.add(new SkipCommand());
|
||||
commands.add(new RepeatCommand());
|
||||
commands.add(new ShuffleCommand());
|
||||
commands.add(new PlaylistCommand());
|
||||
//Other commands.
|
||||
commands.add(new HelpCommand());
|
||||
commands.add(new InfoCommand());
|
||||
commands.add(new SetPrefixCommand());
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to execute a command from a given command string.
|
||||
* @param command The string representation of a main command, without prefix.
|
||||
*/
|
||||
public static void executeCommand(String command, CommandContext context){
|
||||
for (Command cmd : commands) {
|
||||
if (cmd.getName().equals(command)){
|
||||
if (cmd instanceof ContextCommand){
|
||||
((ContextCommand)cmd).execute(context);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
log.log(BotLog.TYPE.ERROR, context.getGuild(), "Invalid command: "+command+" issued by "+context.getUser().getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to get a command object, given the name of a command.
|
||||
* @param command The name of the command to get.
|
||||
* @return Either a command, or null.
|
||||
*/
|
||||
public Command get(String command){
|
||||
for (Command cmd : commands){
|
||||
if (cmd.getName().equals(command)){
|
||||
return cmd;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,35 +1,45 @@
|
|||
package handiebot.command.commands;
|
||||
|
||||
import handiebot.command.CommandContext;
|
||||
import handiebot.command.Commands;
|
||||
import handiebot.command.types.Command;
|
||||
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 {
|
||||
|
||||
//TODO: Finish the help class.
|
||||
public HelpCommand() {
|
||||
super("help");
|
||||
super("help",
|
||||
"",
|
||||
"Displays a list of commands and what they do.");
|
||||
}
|
||||
|
||||
@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());
|
||||
StringBuilder sb = new StringBuilder("HandieBot Commands:\n");
|
||||
for (Command cmd : Commands.commands){
|
||||
StringBuilder commandText = new StringBuilder();
|
||||
commandText.append("- `");
|
||||
if (cmd instanceof ContextCommand){
|
||||
commandText.append(((ContextCommand)cmd).getUsage(context.getGuild()));
|
||||
} else {
|
||||
commandText.append(cmd.getUsage());
|
||||
}
|
||||
commandText.append("`\n").append(cmd.getDescription()).append("\n\n");
|
||||
if (sb.length() + commandText.length() > 2000){
|
||||
pm.sendMessage(sb.toString());
|
||||
sb = commandText;
|
||||
} else {
|
||||
sb.append(commandText);
|
||||
}
|
||||
}
|
||||
|
||||
pm.sendMessage(sb.toString());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
package handiebot.command.commands;
|
||||
|
||||
import handiebot.command.CommandContext;
|
||||
import handiebot.command.commands.music.PlayCommand;
|
||||
import handiebot.command.commands.music.QueueCommand;
|
||||
import handiebot.command.types.ContextCommand;
|
||||
import handiebot.utils.DisappearingMessage;
|
||||
import sx.blah.discord.util.EmbedBuilder;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
/**
|
||||
* @author Andrew Lalis
|
||||
* Command to display information about the bot, and some common commands.
|
||||
*/
|
||||
public class InfoCommand extends ContextCommand {
|
||||
|
||||
public InfoCommand() {
|
||||
super("info",
|
||||
"",
|
||||
"Displays some common commands and information about the bot.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(CommandContext context) {
|
||||
EmbedBuilder builder = new EmbedBuilder();
|
||||
builder.withColor(new Color(255, 0, 0));
|
||||
builder.withDescription("HandieBot is a Discord bot created by Andrew Lalis. It can play music, manage playlists, and provide other assistance to users. Some useful commands are shown below.");
|
||||
builder.appendField("`"+new HelpCommand().getUsage(context.getGuild())+"`", "Receive a message with a detailed list of all commands and how to use them.", false);
|
||||
builder.appendField("`"+new PlayCommand().getUsage(context.getGuild())+"`", "Play a song, or add it to the queue if one is already playing. A URL can be a YouTube or SoundCloud link.", false);
|
||||
builder.appendField("`"+new QueueCommand().getUsage(context.getGuild())+"`", "Show a list of songs that will soon be played.", false);
|
||||
DisappearingMessage.deleteMessageAfter(10000, context.getChannel().sendMessage(builder.build()));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package handiebot.command.commands;
|
||||
|
||||
import handiebot.command.CommandContext;
|
||||
import handiebot.command.CommandHandler;
|
||||
import handiebot.command.types.ContextCommand;
|
||||
import handiebot.utils.DisappearingMessage;
|
||||
import handiebot.view.BotLog;
|
||||
|
||||
import static handiebot.HandieBot.log;
|
||||
|
||||
/**
|
||||
* @author Andrew Lalis
|
||||
* Command to set the prefix used for a particular server.
|
||||
*/
|
||||
public class SetPrefixCommand extends ContextCommand {
|
||||
|
||||
public SetPrefixCommand() {
|
||||
super("setprefix",
|
||||
"<PREFIX>",
|
||||
"Sets the prefix for commands.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(CommandContext context) {
|
||||
if (context.getArgs().length == 1) {
|
||||
CommandHandler.PREFIXES.put(context.getGuild(), context.getArgs()[0]);
|
||||
CommandHandler.saveGuildPrefixes();
|
||||
new DisappearingMessage(context.getChannel(), "Changed command prefix to \""+context.getArgs()[0]+"\"", 6000);
|
||||
log.log(BotLog.TYPE.INFO, "Changed command prefix to \""+context.getArgs()[0]+"\"");
|
||||
} else {
|
||||
new DisappearingMessage(context.getChannel(), "You must provide a new prefix.", 3000);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -13,7 +13,9 @@ import handiebot.utils.DisappearingMessage;
|
|||
public class PlayCommand extends ContextCommand {
|
||||
|
||||
public PlayCommand() {
|
||||
super("play");
|
||||
super("play",
|
||||
"[URL]",
|
||||
"Plays a song, or adds it to the queue.");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -23,7 +23,17 @@ import static handiebot.HandieBot.log;
|
|||
public class PlaylistCommand extends ContextCommand {
|
||||
|
||||
public PlaylistCommand(){
|
||||
super("playlist");
|
||||
super("playlist",
|
||||
"<create|delete|show|add|remove|rename|move|play> [PLAYLIST]",
|
||||
"Do something with a playlist.\n" +
|
||||
"\t`create <PLAYLIST>` - Creates a playlist.\n" +
|
||||
"\t`delete <PLAYLIST>` - Deletes a playlist.\n" +
|
||||
"\t`show [PLAYLIST]` - If a playlist given, show that, otherwise show a list of playlists.\n" +
|
||||
"\t`add <PLAYLIST> <URL> [URL]...` - Adds one or more songs to a playlist.\n" +
|
||||
"\t`remove <PLAYLIST> <SONGINDEX>` - Removes a song from a playlist.\n" +
|
||||
"\t`rename <PLAYLIST> <NEWNAME>` - Renames a playlist.\n" +
|
||||
"\t`move <PLAYLIST> <OLDINDEX> <NEWINDEX>` - Moves a song from one index to another.\n" +
|
||||
"\t`play <PLAYLIST>` - Queues all songs from a playlist.");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -69,7 +79,7 @@ public class PlaylistCommand extends ContextCommand {
|
|||
* @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);
|
||||
new DisappearingMessage(channel, "To use the playlist command: \n"+this.getUsage(channel.getGuild()), 5000);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -86,7 +96,7 @@ public class PlaylistCommand extends ContextCommand {
|
|||
}
|
||||
playlist.save();
|
||||
log.log(BotLog.TYPE.INFO, "Created playlist: "+playlist.getName()+" with "+playlist.getTrackCount()+" new tracks.");
|
||||
new DisappearingMessage(context.getChannel(), "Your playlist *"+playlist.getName()+"* has been created.\nType `"+ CommandHandler.PREFIX+"playlist play "+playlist.getName()+"` to play it.", 5000);
|
||||
new DisappearingMessage(context.getChannel(), "Your playlist *"+playlist.getName()+"* has been created.\nType `"+ CommandHandler.PREFIXES.get(context.getGuild())+"playlist play "+playlist.getName()+"` to play it.", 5000);
|
||||
} else {
|
||||
new DisappearingMessage(context.getChannel(), "You must specify a name for the new playlist.", 3000);
|
||||
}
|
||||
|
@ -109,7 +119,7 @@ public class PlaylistCommand extends ContextCommand {
|
|||
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);
|
||||
new DisappearingMessage(context.getChannel(), "The name you entered is not a playlist.\nType `"+CommandHandler.PREFIXES.get(context.getGuild())+"playlist show` to list the playlists available.", 5000);
|
||||
}
|
||||
} else {
|
||||
new DisappearingMessage(context.getChannel(), "You must specify the name of a playlist to delete.", 3000);
|
||||
|
@ -126,9 +136,9 @@ public class PlaylistCommand extends ContextCommand {
|
|||
Playlist playlist = new Playlist(context.getArgs()[1]);
|
||||
playlist.load();
|
||||
IMessage message = context.getChannel().sendMessage(playlist.toString());
|
||||
DisappearingMessage.deleteMessageAfter(6000, message);
|
||||
DisappearingMessage.deleteMessageAfter(12000, message);
|
||||
} else {
|
||||
new DisappearingMessage(context.getChannel(), "The playlist you specified does not exist.\nUse `"+CommandHandler.PREFIX+"playlist show` to view available playlists.", 5000);
|
||||
new DisappearingMessage(context.getChannel(), "The playlist you specified does not exist.\nUse `"+CommandHandler.PREFIXES.get(context.getGuild())+"playlist show` to view available playlists.", 5000);
|
||||
}
|
||||
} else {
|
||||
List<String> playlists = Playlist.getAvailablePlaylists();
|
||||
|
@ -137,7 +147,7 @@ public class PlaylistCommand extends ContextCommand {
|
|||
sb.append(playlist).append('\n');
|
||||
}
|
||||
IMessage message = context.getChannel().sendMessage(sb.toString());
|
||||
DisappearingMessage.deleteMessageAfter(6000, message);
|
||||
DisappearingMessage.deleteMessageAfter(12000, message);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -163,7 +173,7 @@ public class PlaylistCommand extends ContextCommand {
|
|||
DisappearingMessage.deleteMessageAfter(6000, message);
|
||||
} else {
|
||||
if (context.getArgs().length == 1){
|
||||
new DisappearingMessage(context.getChannel(), "You must provide the name of a playlist to add a URL to.\nUse '"+CommandHandler.PREFIX+"playlist show` to view available playlists.", 5000);
|
||||
new DisappearingMessage(context.getChannel(), "You must provide the name of a playlist to add a URL to.\nUse '"+CommandHandler.PREFIXES.get(context.getGuild())+"playlist show` to view available playlists.", 5000);
|
||||
} else {
|
||||
new DisappearingMessage(context.getChannel(), "You must provide at least one URL to add.", 3000);
|
||||
}
|
||||
|
@ -187,7 +197,7 @@ public class PlaylistCommand extends ContextCommand {
|
|||
log.log(BotLog.TYPE.INFO, "Loaded playlist ["+playlist.getName()+"].");
|
||||
new DisappearingMessage(context.getChannel(), "Now playing from playlist: *"+playlist.getName()+"*.", 6000);
|
||||
} else {
|
||||
new DisappearingMessage(context.getChannel(), "You must provide a playlist to play.\nUse '"+CommandHandler.PREFIX+"playlist show` to view available playlists.", 3000);
|
||||
new DisappearingMessage(context.getChannel(), "You must provide a playlist to play.\nUse '"+CommandHandler.PREFIXES.get(context.getGuild())+"playlist show` to view available playlists.", 3000);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -228,9 +238,10 @@ public class PlaylistCommand extends ContextCommand {
|
|||
Playlist playlist = new Playlist(context.getArgs()[1]);
|
||||
playlist.load();
|
||||
try{
|
||||
int index = Integer.parseInt(context.getArgs()[2]);
|
||||
int index = Integer.parseInt(context.getArgs()[2]) - 1;
|
||||
UnloadedTrack track = playlist.getTracks().get(index);
|
||||
playlist.removeTrack(track);
|
||||
playlist.save();
|
||||
new DisappearingMessage(context.getChannel(), "Removed song: *"+track.getTitle()+"* from playlist **"+playlist.getName()+"**.", 6000);
|
||||
log.log(BotLog.TYPE.MUSIC, "Removed song: "+track.getTitle()+" from playlist ["+playlist.getName()+"].");
|
||||
DisappearingMessage.deleteMessageAfter(6000, context.getChannel().sendMessage(playlist.toString()));
|
||||
|
@ -265,18 +276,16 @@ public class PlaylistCommand extends ContextCommand {
|
|||
} catch (NumberFormatException e){
|
||||
new DisappearingMessage(context.getChannel(), "You must enter two integer values for the song indices.", 5000);
|
||||
}
|
||||
UnloadedTrack track = null;
|
||||
if (oldIndex > -1 && oldIndex < playlist.getTrackCount()){
|
||||
UnloadedTrack track;
|
||||
if ((oldIndex > -1 && oldIndex < playlist.getTrackCount()) &&
|
||||
(newIndex > -1 && newIndex <= playlist.getTrackCount())){
|
||||
track = playlist.getTracks().remove(oldIndex);
|
||||
if (newIndex > -1 && newIndex <= playlist.getTrackCount()){
|
||||
playlist.getTracks().add(newIndex, track);
|
||||
playlist.save();
|
||||
new DisappearingMessage(context.getChannel(), "Moved song *"+track.getTitle()+"* from position "+(oldIndex+1)+" to position "+(newIndex+1), 6000);
|
||||
log.log(BotLog.TYPE.MUSIC, "Moved song "+track.getTitle()+" from position "+(oldIndex+1)+" to position "+(newIndex+1));
|
||||
} else {
|
||||
new DisappearingMessage(context.getChannel(), "The index of the song's new position is invalid. You entered "+newIndex, 5000);
|
||||
}
|
||||
} else {
|
||||
new DisappearingMessage(context.getChannel(), "The index of the song is invalid. You entered "+oldIndex, 5000);
|
||||
new DisappearingMessage(context.getChannel(), "The song indices are invalid. You specified moving song "+oldIndex+" to position "+newIndex+". ", 5000);
|
||||
}
|
||||
} else {
|
||||
new DisappearingMessage(context.getChannel(), "You must provide a playlist name, followed by the song index, and a new index for that song.", 5000);
|
||||
|
|
|
@ -3,6 +3,11 @@ package handiebot.command.commands.music;
|
|||
import handiebot.HandieBot;
|
||||
import handiebot.command.CommandContext;
|
||||
import handiebot.command.types.ContextCommand;
|
||||
import handiebot.lavaplayer.playlist.Playlist;
|
||||
import handiebot.utils.DisappearingMessage;
|
||||
import handiebot.view.BotLog;
|
||||
|
||||
import static handiebot.HandieBot.log;
|
||||
|
||||
/**
|
||||
* @author Andrew Lalis
|
||||
|
@ -10,12 +15,32 @@ import handiebot.command.types.ContextCommand;
|
|||
*/
|
||||
public class QueueCommand extends ContextCommand {
|
||||
public QueueCommand() {
|
||||
super("queue");
|
||||
super("queue",
|
||||
"[all|clear|save]",
|
||||
"Shows the first 10 songs in the queue.\n" +
|
||||
"\t`all` - Shows all songs.\n" +
|
||||
"\t`clear` - Clears the queue and stops playing.\n" +
|
||||
"\t`save <PLAYLIST>` - Saves the queue to a playlist.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(CommandContext context) {
|
||||
HandieBot.musicPlayer.showQueueList(context.getGuild(), (context.getArgs() != null && context.getArgs()[0].equals("all")));
|
||||
if (context.getArgs().length > 0){
|
||||
if (context.getArgs()[0].equals("all")){
|
||||
HandieBot.musicPlayer.showQueueList(context.getGuild(), true);
|
||||
} else if (context.getArgs()[0].equals("clear")){
|
||||
HandieBot.musicPlayer.clearQueue(context.getGuild());
|
||||
log.log(BotLog.TYPE.MUSIC, context.getGuild(), "Cleared queue.");
|
||||
} else if (context.getArgs()[0].equals("save") && context.getArgs().length == 2){
|
||||
Playlist p = HandieBot.musicPlayer.getAllSongsInQueue(context.getGuild());
|
||||
p.setName(context.getArgs()[1]);
|
||||
p.save();
|
||||
new DisappearingMessage(context.getChannel(), "Saved "+p.getTrackCount()+" tracks to playlist **"+p.getName()+"**.", 6000);
|
||||
log.log(BotLog.TYPE.INFO, "Saved queue to playlist ["+p.getName()+"].");
|
||||
}
|
||||
} else {
|
||||
HandieBot.musicPlayer.showQueueList(context.getGuild(), false);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,10 +3,6 @@ package handiebot.command.commands.music;
|
|||
import handiebot.HandieBot;
|
||||
import handiebot.command.CommandContext;
|
||||
import handiebot.command.types.ContextCommand;
|
||||
import handiebot.utils.DisappearingMessage;
|
||||
import handiebot.view.BotLog;
|
||||
|
||||
import static handiebot.HandieBot.log;
|
||||
|
||||
/**
|
||||
* @author Andrew Lalis
|
||||
|
@ -15,7 +11,9 @@ import static handiebot.HandieBot.log;
|
|||
public class RepeatCommand extends ContextCommand {
|
||||
|
||||
public RepeatCommand(){
|
||||
super("repeat");
|
||||
super("repeat",
|
||||
"[true|false]",
|
||||
"Sets repeating.");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -26,7 +24,5 @@ public class RepeatCommand extends ContextCommand {
|
|||
} else {
|
||||
HandieBot.musicPlayer.toggleRepeat(context.getGuild());
|
||||
}
|
||||
log.log(BotLog.TYPE.MUSIC, context.getGuild(), "Set repeat to "+HandieBot.musicPlayer.getMusicManager(context.getGuild()).scheduler.isRepeating());
|
||||
new DisappearingMessage(context.getChannel(), "Set repeat to "+HandieBot.musicPlayer.getMusicManager(context.getGuild()).scheduler.isRepeating(), 3000);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,10 +3,6 @@ package handiebot.command.commands.music;
|
|||
import handiebot.HandieBot;
|
||||
import handiebot.command.CommandContext;
|
||||
import handiebot.command.types.ContextCommand;
|
||||
import handiebot.utils.DisappearingMessage;
|
||||
import handiebot.view.BotLog;
|
||||
|
||||
import static handiebot.HandieBot.log;
|
||||
|
||||
/**
|
||||
* @author Andrew Lalis
|
||||
|
@ -15,7 +11,9 @@ import static handiebot.HandieBot.log;
|
|||
public class ShuffleCommand extends ContextCommand {
|
||||
|
||||
public ShuffleCommand(){
|
||||
super("shuffle");
|
||||
super("shuffle",
|
||||
"[true|false]",
|
||||
"Sets shuffling.");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -26,7 +24,5 @@ public class ShuffleCommand extends ContextCommand {
|
|||
} else {
|
||||
HandieBot.musicPlayer.toggleShuffle(context.getGuild());
|
||||
}
|
||||
log.log(BotLog.TYPE.MUSIC, context.getGuild(), "Set shuffle to "+Boolean.toString(HandieBot.musicPlayer.getMusicManager(context.getGuild()).scheduler.isShuffling()));
|
||||
new DisappearingMessage(context.getChannel(), "Set shuffle to "+Boolean.toString(HandieBot.musicPlayer.getMusicManager(context.getGuild()).scheduler.isShuffling()), 3000);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,9 @@ import handiebot.command.types.ContextCommand;
|
|||
public class SkipCommand extends ContextCommand {
|
||||
|
||||
public SkipCommand() {
|
||||
super("skip");
|
||||
super("skip",
|
||||
"",
|
||||
"Skips the current song.");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
package handiebot.command.commands.music;
|
||||
|
||||
import handiebot.HandieBot;
|
||||
import handiebot.command.CommandContext;
|
||||
import handiebot.command.types.ContextCommand;
|
||||
|
||||
/**
|
||||
* @author Andrew Lalis
|
||||
* Command to stop playback of music on a server.
|
||||
*/
|
||||
public class StopCommand extends ContextCommand {
|
||||
|
||||
public StopCommand(){
|
||||
super("stop",
|
||||
"",
|
||||
"Stops playing music.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(CommandContext context) {
|
||||
HandieBot.musicPlayer.stop(context.getGuild());
|
||||
}
|
||||
}
|
|
@ -7,13 +7,25 @@ package handiebot.command.types;
|
|||
public abstract class Command {
|
||||
|
||||
private String name;
|
||||
private String usage;
|
||||
private String description;
|
||||
|
||||
public Command(String name){
|
||||
public Command(String name, String usage, String description){
|
||||
this.name = name;
|
||||
this.usage = usage;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getName(){
|
||||
return this.name;
|
||||
};
|
||||
|
||||
public String getUsage() {
|
||||
return this.name+" "+this.usage;
|
||||
};
|
||||
|
||||
public String getDescription() {
|
||||
return this.description;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package handiebot.command.types;
|
||||
|
||||
import handiebot.command.CommandContext;
|
||||
import handiebot.command.CommandHandler;
|
||||
import sx.blah.discord.handle.obj.IGuild;
|
||||
|
||||
/**
|
||||
* @author Andrew Lalis
|
||||
|
@ -8,10 +10,19 @@ import handiebot.command.CommandContext;
|
|||
*/
|
||||
public abstract class ContextCommand extends Command {
|
||||
|
||||
public ContextCommand(String s) {
|
||||
super(s);
|
||||
public ContextCommand(String name, String usage, String description) {
|
||||
super(name, usage, description);
|
||||
}
|
||||
|
||||
public abstract void execute(CommandContext context);
|
||||
|
||||
/**
|
||||
* Gets the usage of a command, including the guild, so that the prefix is known.
|
||||
* @param guild The guild the command should be used on.
|
||||
* @return A string representing the usage for this command.
|
||||
*/
|
||||
public String getUsage(IGuild guild){
|
||||
return CommandHandler.PREFIXES.get(guild)+this.getUsage();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
package handiebot.command.types;
|
||||
|
||||
import sx.blah.discord.handle.impl.events.guild.channel.message.reaction.ReactionEvent;
|
||||
|
||||
/**
|
||||
* @author Andrew Lalis
|
||||
* Class which handles user reactions to songs and performs necessary actions.
|
||||
*/
|
||||
public class ReactionHandler {
|
||||
|
||||
/**
|
||||
* Processes a reaction.
|
||||
* @param event The reaction event to process.
|
||||
*/
|
||||
public static void handleReaction(ReactionEvent event){
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -6,8 +6,8 @@ package handiebot.command.types;
|
|||
*/
|
||||
public abstract class StaticCommand extends Command {
|
||||
|
||||
public StaticCommand(String s) {
|
||||
super(s);
|
||||
public StaticCommand(String name, String usage, String description) {
|
||||
super(name, usage, description);
|
||||
}
|
||||
|
||||
public abstract void execute();
|
||||
|
|
|
@ -3,7 +3,9 @@ package handiebot.lavaplayer;
|
|||
import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager;
|
||||
import com.sedmelluq.discord.lavaplayer.player.DefaultAudioPlayerManager;
|
||||
import com.sedmelluq.discord.lavaplayer.source.AudioSourceManagers;
|
||||
import handiebot.HandieBot;
|
||||
import handiebot.command.CommandHandler;
|
||||
import handiebot.lavaplayer.playlist.Playlist;
|
||||
import handiebot.lavaplayer.playlist.UnloadedTrack;
|
||||
import handiebot.utils.DisappearingMessage;
|
||||
import handiebot.utils.Pastebin;
|
||||
|
@ -25,6 +27,7 @@ import static handiebot.HandieBot.log;
|
|||
* @author Andrew Lalis
|
||||
* This class is a container for all the music related functions, and contains methods for easy playback and queue
|
||||
* management.
|
||||
* The goal is to abstract all functions to this layer, rather than have the bot interact directly with any schedulers.
|
||||
*/
|
||||
public class MusicPlayer {
|
||||
|
||||
|
@ -113,8 +116,7 @@ public class MusicPlayer {
|
|||
* @param guild The guild to repeat for.
|
||||
*/
|
||||
public void toggleRepeat(IGuild guild){
|
||||
GuildMusicManager musicManager = this.getMusicManager(guild);
|
||||
musicManager.scheduler.setRepeat(!musicManager.scheduler.isRepeating());
|
||||
setRepeat(guild, !getMusicManager(guild).scheduler.isRepeating());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -124,6 +126,8 @@ public class MusicPlayer {
|
|||
*/
|
||||
public void setRepeat(IGuild guild, boolean value){
|
||||
getMusicManager(guild).scheduler.setRepeat(value);
|
||||
log.log(BotLog.TYPE.MUSIC, guild, "Set repeat to "+getMusicManager(guild).scheduler.isRepeating());
|
||||
new DisappearingMessage(getChatChannel(guild), "Set repeat to "+getMusicManager(guild).scheduler.isRepeating(), 3000);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -131,8 +135,7 @@ public class MusicPlayer {
|
|||
* @param guild The guild to toggle shuffling for.
|
||||
*/
|
||||
public void toggleShuffle(IGuild guild){
|
||||
GuildMusicManager musicManager = this.getMusicManager(guild);
|
||||
musicManager.scheduler.setShuffle(!musicManager.scheduler.isShuffling());
|
||||
setShuffle(guild, !getMusicManager(guild).scheduler.isShuffling());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -142,6 +145,8 @@ public class MusicPlayer {
|
|||
*/
|
||||
public void setShuffle(IGuild guild, boolean value){
|
||||
getMusicManager(guild).scheduler.setShuffle(value);
|
||||
log.log(BotLog.TYPE.MUSIC, guild, "Set shuffle to "+Boolean.toString(HandieBot.musicPlayer.getMusicManager(guild).scheduler.isShuffling()));
|
||||
new DisappearingMessage(getChatChannel(guild), "Set shuffle to "+Boolean.toString(HandieBot.musicPlayer.getMusicManager(guild).scheduler.isShuffling()), 3000);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -150,7 +155,7 @@ public class MusicPlayer {
|
|||
public void showQueueList(IGuild guild, boolean showAll) {
|
||||
List<UnloadedTrack> tracks = getMusicManager(guild).scheduler.queueList();
|
||||
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.PREFIXES.get(guild)+"play** *URL* to add songs.", 3000);
|
||||
} else {
|
||||
if (tracks.size() > 10 && showAll) {
|
||||
String result = Pastebin.paste("Current queue for discord server: "+guild.getName()+".", getMusicManager(guild).scheduler.getActivePlaylist().toString());
|
||||
|
@ -169,7 +174,7 @@ public class MusicPlayer {
|
|||
sb.append(tracks.get(i).getURL()).append(")");
|
||||
sb.append(tracks.get(i).getFormattedDuration()).append('\n');
|
||||
}
|
||||
builder.appendField("Showing " + (tracks.size() <= 10 ? tracks.size() : "the first 10") + " track" + (tracks.size() > 1 ? "s" : "") + ".", sb.toString(), false);
|
||||
builder.appendField("Showing " + (tracks.size() <= 10 ? tracks.size() : "the first 10") + " track" + (tracks.size() > 1 ? "s" : "") + " out of "+tracks.size()+".", sb.toString(), false);
|
||||
IMessage message = getChatChannel(guild).sendMessage(builder.build());
|
||||
DisappearingMessage.deleteMessageAfter(6000, message);
|
||||
}
|
||||
|
@ -200,9 +205,11 @@ public class MusicPlayer {
|
|||
TimeUnit.MILLISECONDS.toSeconds(timeUntilPlay) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(timeUntilPlay))
|
||||
));
|
||||
}
|
||||
if (sb.length() > 0) {
|
||||
IMessage message = getChatChannel(guild).sendMessage(sb.toString());
|
||||
DisappearingMessage.deleteMessageAfter(3000, message);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -217,6 +224,11 @@ public class MusicPlayer {
|
|||
getMusicManager(guild).scheduler.nextTrack();
|
||||
}
|
||||
|
||||
public void clearQueue(IGuild guild){
|
||||
getMusicManager(guild).scheduler.clearQueue();
|
||||
new DisappearingMessage(getChatChannel(guild), "Cleared the queue.", 5000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Skips the current track.
|
||||
*/
|
||||
|
@ -228,18 +240,36 @@ public class MusicPlayer {
|
|||
|
||||
/**
|
||||
* Stops playback and disconnects from the voice channel, to cease music actions.
|
||||
* @param guild The guild to quit from.
|
||||
* @param guild The guild to stop from.
|
||||
*/
|
||||
public void quit(IGuild guild){
|
||||
getMusicManager(guild).scheduler.quit();
|
||||
public void stop(IGuild guild){
|
||||
getMusicManager(guild).scheduler.stop();
|
||||
new DisappearingMessage(getChatChannel(guild), "Stopped playing music.", 5000);
|
||||
log.log(BotLog.TYPE.MUSIC, guild, "Stopped playing music.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the same functions as quit, but with every guild.
|
||||
* Returns a playlist of all songs either in the queue or being played now.
|
||||
* @param guild The guild to get songs from.
|
||||
* @return A list of songs in the form of a playlist.
|
||||
*/
|
||||
public Playlist getAllSongsInQueue(IGuild guild){
|
||||
GuildMusicManager musicManager = getMusicManager(guild);
|
||||
Playlist p = new Playlist("Active Queue");
|
||||
p.copy(musicManager.scheduler.getActivePlaylist());
|
||||
UnloadedTrack track = musicManager.scheduler.getPlayingTrack();
|
||||
if (track != null){
|
||||
p.addTrack(track);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the same functions as stop, but with every guild.
|
||||
*/
|
||||
public void quitAll(){
|
||||
this.musicManagers.forEach((guild, musicManager) -> {
|
||||
musicManager.scheduler.quit();
|
||||
musicManager.scheduler.stop();
|
||||
});
|
||||
this.playerManager.shutdown();
|
||||
}
|
||||
|
|
|
@ -50,13 +50,21 @@ public class TrackScheduler extends AudioEventAdapter {
|
|||
* @param playlist the playlist to load from.
|
||||
*/
|
||||
public void setPlaylist(Playlist playlist){
|
||||
this.activePlaylist = playlist;
|
||||
this.activePlaylist.copy(playlist);
|
||||
}
|
||||
|
||||
public Playlist getActivePlaylist(){
|
||||
return this.activePlaylist;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the queue.
|
||||
*/
|
||||
public void clearQueue(){
|
||||
this.stop();
|
||||
this.activePlaylist.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether or not songs get placed back into the queue once they're played.
|
||||
* @param value True if the playlist should repeat.
|
||||
|
@ -105,6 +113,18 @@ public class TrackScheduler extends AudioEventAdapter {
|
|||
return t;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the currently playing track, in unloaded form.
|
||||
* @return The currently playing track, or null.
|
||||
*/
|
||||
public UnloadedTrack getPlayingTrack(){
|
||||
AudioTrack track = this.player.getPlayingTrack();
|
||||
if (track == null){
|
||||
return null;
|
||||
}
|
||||
return new UnloadedTrack(track);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of tracks in the queue.
|
||||
* @return A list of tracks in the queue.
|
||||
|
@ -141,29 +161,31 @@ public class TrackScheduler extends AudioEventAdapter {
|
|||
}
|
||||
player.startTrack(track, false);
|
||||
} else {
|
||||
this.quit();
|
||||
this.stop();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If the user wishes to quit, stop the currently played track.
|
||||
* If the user wishes to stop, stop the currently played track.
|
||||
*/
|
||||
public void quit(){
|
||||
public void stop(){
|
||||
IVoiceChannel voiceChannel = HandieBot.musicPlayer.getVoiceChannel(this.guild);
|
||||
if (voiceChannel.isConnected()){
|
||||
voiceChannel.leave();
|
||||
}
|
||||
if (this.player.getPlayingTrack() != null) {
|
||||
this.player.stopTrack();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTrackStart(AudioPlayer player, AudioTrack track) {
|
||||
log.log(BotLog.TYPE.MUSIC, this.guild, "Started audio track: "+track.getInfo().title);
|
||||
List<IChannel> channels = this.guild.getChannelsByName(MusicPlayer.CHANNEL_NAME.toLowerCase());
|
||||
if (channels.size() > 0){
|
||||
IMessage message = channels.get(0).sendMessage("Now playing: **"+track.getInfo().title+"**\n"+track.getInfo().uri);
|
||||
IMessage message = channels.get(0).sendMessage("Now playing: **"+track.getInfo().title+"** "+new UnloadedTrack(track).getFormattedDuration()+"\n"+track.getInfo().uri);
|
||||
RequestBuffer.request(() -> {message.addReaction(":thumbsup:");}).get();
|
||||
RequestBuffer.request(() -> {message.addReaction(":thumbsdown:");});
|
||||
RequestBuffer.request(() -> {message.addReaction(":thumbsdown:");}).get();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -174,8 +196,6 @@ public class TrackScheduler extends AudioEventAdapter {
|
|||
}
|
||||
if (endReason.mayStartNext){
|
||||
nextTrack();
|
||||
} else {
|
||||
log.log(BotLog.TYPE.MUSIC, this.guild, "Unable to go to the next track. Reason: "+endReason.name());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -40,6 +40,10 @@ public class Playlist {
|
|||
return this.name;
|
||||
}
|
||||
|
||||
public void setName(String name){
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getTrackCount(){
|
||||
return this.tracks.size();
|
||||
}
|
||||
|
@ -56,6 +60,21 @@ public class Playlist {
|
|||
this.tracks.remove(track);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies all the tracks from another playlist onto this one.
|
||||
* @param playlist A playlist.
|
||||
*/
|
||||
public void copy(Playlist playlist){
|
||||
this.getTracks().clear();
|
||||
for (UnloadedTrack track : playlist.getTracks()){
|
||||
this.tracks.add(track.clone());
|
||||
}
|
||||
}
|
||||
|
||||
public void clear(){
|
||||
this.tracks.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads and returns the audio track that's first on the list.
|
||||
* This removes that track from the playlist.
|
||||
|
@ -63,6 +82,9 @@ public class Playlist {
|
|||
* @return The AudioTrack corresponding to the next UnloadedTrack in the list.
|
||||
*/
|
||||
public AudioTrack loadNextTrack(boolean shouldShuffle){
|
||||
if (this.getTrackCount() == 0){
|
||||
return null;
|
||||
}
|
||||
if (shouldShuffle){
|
||||
return this.tracks.remove(getShuffledIndex(this.tracks.size())).loadAudioTrack();
|
||||
} else {
|
||||
|
@ -188,10 +210,14 @@ public class Playlist {
|
|||
|
||||
@Override
|
||||
public String toString(){
|
||||
StringBuilder sb = new StringBuilder("HandieBot Playlist: "+this.getName()+'\n');
|
||||
StringBuilder sb = new StringBuilder("Playlist: "+this.getName()+'\n');
|
||||
if (this.getTrackCount() == 0){
|
||||
sb.append("There are no songs in this playlist.");
|
||||
} else {
|
||||
for (int i = 0; i < this.getTrackCount(); i++) {
|
||||
sb.append(i + 1).append(". ").append(this.tracks.get(i).getTitle()).append(" ").append(this.tracks.get(i).getFormattedDuration()).append("\n");
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
package handiebot.utils;
|
||||
|
||||
import handiebot.view.BotLog;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.nio.file.Files;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static handiebot.HandieBot.log;
|
||||
|
||||
/**
|
||||
* @author Andrew Lalis
|
||||
* Class to simplify file operations.
|
||||
*/
|
||||
public class FileUtil {
|
||||
|
||||
public static String getDataDirectory(){
|
||||
return System.getProperty("user.home")+"/.handiebot/";
|
||||
}
|
||||
|
||||
public static List<String> getLinesFromFile(File file){
|
||||
try {
|
||||
return Files.readAllLines(file.toPath());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
||||
public static void writeLinesToFile(List<String> lines, File file){
|
||||
if (lines.size() == 0){
|
||||
return;
|
||||
}
|
||||
if (!file.exists()){
|
||||
try {
|
||||
boolean success = file.createNewFile();
|
||||
if (!success) {
|
||||
log.log(BotLog.TYPE.ERROR, "Unable to create file. "+file.getAbsolutePath());
|
||||
return;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
log.log(BotLog.TYPE.ERROR, "Unable to create file. "+file.getAbsolutePath());
|
||||
return;
|
||||
}
|
||||
}
|
||||
try (PrintWriter writer = new PrintWriter(file)){
|
||||
while (lines.size() > 0) {
|
||||
writer.println(lines.remove(0));
|
||||
}
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
log.log(BotLog.TYPE.ERROR, "Unable to write to file. "+file.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -41,7 +41,7 @@ public class CommandLineListener implements KeyListener {
|
|||
* @param args The list of arguments for the command.
|
||||
*/
|
||||
private void executeCommand(String command, String[] args){
|
||||
if (command.equals("quit")){
|
||||
if (command.equals("stop")){
|
||||
new QuitAction().actionPerformed(null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package handiebot.view;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
/**
|
||||
* @author Andrew Lalis
|
||||
|
@ -18,4 +19,47 @@ public class View {
|
|||
return this.outputArea;
|
||||
}
|
||||
|
||||
{
|
||||
// GUI initializer generated by IntelliJ IDEA GUI Designer
|
||||
// >>> IMPORTANT!! <<<
|
||||
// DO NOT EDIT OR ADD ANY CODE HERE!
|
||||
$$$setupUI$$$();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method generated by IntelliJ IDEA GUI Designer
|
||||
* >>> IMPORTANT!! <<<
|
||||
* DO NOT edit this method OR call it in your code!
|
||||
*
|
||||
* @noinspection ALL
|
||||
*/
|
||||
private void $$$setupUI$$$() {
|
||||
mainPanel = new JPanel();
|
||||
mainPanel.setLayout(new com.intellij.uiDesigner.core.GridLayoutManager(2, 1, new Insets(0, 0, 0, 0), -1, -1));
|
||||
final JScrollPane scrollPane1 = new JScrollPane();
|
||||
scrollPane1.setFont(new Font("Consolas", scrollPane1.getFont().getStyle(), 12));
|
||||
mainPanel.add(scrollPane1, new com.intellij.uiDesigner.core.GridConstraints(0, 0, 1, 1, com.intellij.uiDesigner.core.GridConstraints.ANCHOR_CENTER, com.intellij.uiDesigner.core.GridConstraints.FILL_BOTH, com.intellij.uiDesigner.core.GridConstraints.SIZEPOLICY_CAN_SHRINK | com.intellij.uiDesigner.core.GridConstraints.SIZEPOLICY_WANT_GROW, com.intellij.uiDesigner.core.GridConstraints.SIZEPOLICY_CAN_SHRINK | com.intellij.uiDesigner.core.GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false));
|
||||
outputArea = new JTextPane();
|
||||
outputArea.setEditable(false);
|
||||
outputArea.setFont(new Font("Consolas", outputArea.getFont().getStyle(), 12));
|
||||
outputArea.setSelectedTextColor(new Color(-1));
|
||||
outputArea.setSelectionColor(new Color(-9843846));
|
||||
outputArea.setText("");
|
||||
scrollPane1.setViewportView(outputArea);
|
||||
final JPanel panel1 = new JPanel();
|
||||
panel1.setLayout(new com.intellij.uiDesigner.core.GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1));
|
||||
mainPanel.add(panel1, new com.intellij.uiDesigner.core.GridConstraints(1, 0, 1, 1, com.intellij.uiDesigner.core.GridConstraints.ANCHOR_CENTER, com.intellij.uiDesigner.core.GridConstraints.FILL_BOTH, com.intellij.uiDesigner.core.GridConstraints.SIZEPOLICY_CAN_SHRINK | com.intellij.uiDesigner.core.GridConstraints.SIZEPOLICY_CAN_GROW, com.intellij.uiDesigner.core.GridConstraints.SIZEPOLICY_CAN_SHRINK | com.intellij.uiDesigner.core.GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false));
|
||||
commandField = new JTextField();
|
||||
commandField.setFont(new Font("DialogInput", commandField.getFont().getStyle(), 16));
|
||||
commandField.setForeground(new Color(-16118999));
|
||||
commandField.setMargin(new Insets(0, 0, 0, 0));
|
||||
panel1.add(commandField, new com.intellij.uiDesigner.core.GridConstraints(0, 0, 1, 1, com.intellij.uiDesigner.core.GridConstraints.ANCHOR_WEST, com.intellij.uiDesigner.core.GridConstraints.FILL_HORIZONTAL, com.intellij.uiDesigner.core.GridConstraints.SIZEPOLICY_WANT_GROW, com.intellij.uiDesigner.core.GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(150, -1), null, 0, false));
|
||||
}
|
||||
|
||||
/**
|
||||
* @noinspection ALL
|
||||
*/
|
||||
public JComponent $$$getRootComponent$$$() {
|
||||
return mainPanel;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ public class QuitAction implements ActionListener {
|
|||
public void actionPerformed(ActionEvent e) {
|
||||
if (guild != null){
|
||||
HandieBot.musicPlayer.getChatChannel(this.guild).sendMessage("Quiting HandieBot");
|
||||
HandieBot.musicPlayer.quit(this.guild);
|
||||
HandieBot.musicPlayer.stop(this.guild);
|
||||
} else {
|
||||
HandieBot.quit();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue