added nogui option, and started externalizing strings.

This commit is contained in:
Andrew Lalis 2017-06-28 15:42:34 +02:00
parent 36f85fbe13
commit 2078137e1e
20 changed files with 328 additions and 108 deletions

View File

@ -31,6 +31,7 @@ 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 boolean USE_GUI = true;
public static ResourceBundle resourceBundle = ResourceBundle.getBundle("Strings"); public static ResourceBundle resourceBundle = ResourceBundle.getBundle("Strings");
@ -78,7 +79,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, resourceBundle.getString("log.init"));
//client.changeAvatar(Image.forStream("png", getClass().getClassLoader().getResourceAsStream("avatarIcon.png"))); //client.changeAvatar(Image.forStream("png", getClass().getClassLoader().getResourceAsStream("avatarIcon.png")));
} }
@ -86,10 +87,18 @@ public class HandieBot {
musicPlayer = new MusicPlayer(); musicPlayer = new MusicPlayer();
window = new BotWindow(); if (args.length >= 1) {
log = new BotLog(window.getOutputArea()); if (args[0].equalsIgnoreCase("-nogui")){
USE_GUI = false;
}
}
log.log(BotLog.TYPE.INFO, "Logging client in..."); if (USE_GUI){
window = new BotWindow();
log = new BotLog(window.getOutputArea());
}
log.log(BotLog.TYPE.INFO, resourceBundle.getString("log.loggingIn"));
client = new ClientBuilder().withToken(TOKEN).build(); client = new ClientBuilder().withToken(TOKEN).build();
client.getDispatcher().registerListener(new HandieBot()); client.getDispatcher().registerListener(new HandieBot());
client.login(); client.login();
@ -109,7 +118,7 @@ public class HandieBot {
* Safely shuts down the bot on all guilds. * Safely shuts down the bot on all guilds.
*/ */
public static void quit(){ public static void quit(){
log.log(BotLog.TYPE.INFO, "Shutting down the bot."); log.log(BotLog.TYPE.INFO, resourceBundle.getString("log.shuttingDown"));
musicPlayer.quitAll(); musicPlayer.quitAll();
client.logout(); client.logout();
window.dispose(); window.dispose();

View File

@ -15,8 +15,7 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import static handiebot.HandieBot.client; import static handiebot.HandieBot.*;
import static handiebot.HandieBot.log;
/** /**
* @author Andrew Lalis * @author Andrew Lalis
@ -100,7 +99,7 @@ public class CommandHandler {
prefixes.put(client.getGuildByID(Long.parseLong(words[0])), words[1]); prefixes.put(client.getGuildByID(Long.parseLong(words[0])), words[1]);
} }
} }
log.log(BotLog.TYPE.INFO, "Loaded prefixes."); log.log(BotLog.TYPE.INFO, resourceBundle.getString("commands.command.setPrefix.loadedPrefixes"));
return prefixes; return prefixes;
} }
@ -114,7 +113,7 @@ public class CommandHandler {
lines.add(Long.toString(entry.getKey().getLongID())+" / "+entry.getValue()); lines.add(Long.toString(entry.getKey().getLongID())+" / "+entry.getValue());
} }
FileUtil.writeLinesToFile(lines, prefixFile); FileUtil.writeLinesToFile(lines, prefixFile);
log.log(BotLog.TYPE.INFO, "Saved prefixes."); log.log(BotLog.TYPE.INFO, resourceBundle.getString("commands.command.setPrefix.savedPrefixes"));
} }
} }

View File

@ -10,10 +10,12 @@ import handiebot.command.types.ContextCommand;
import handiebot.command.types.StaticCommand; import handiebot.command.types.StaticCommand;
import handiebot.view.BotLog; import handiebot.view.BotLog;
import java.text.MessageFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import static handiebot.HandieBot.log; import static handiebot.HandieBot.log;
import static handiebot.HandieBot.resourceBundle;
/** /**
* @author Andrew Lalis * @author Andrew Lalis
@ -49,18 +51,21 @@ public class Commands {
if (cmd.getName().equals(command)){ if (cmd.getName().equals(command)){
if (cmd instanceof StaticCommand){ if (cmd instanceof StaticCommand){
((StaticCommand)cmd).execute(); ((StaticCommand)cmd).execute();
return;
} else if (!cmd.canUserExecute(context.getUser(), context.getGuild())){ } else if (!cmd.canUserExecute(context.getUser(), context.getGuild())){
log.log(BotLog.TYPE.ERROR, context.getGuild(), "User "+context.getUser().getName()+" does not have permission to execute "+cmd.getName()); log.log(BotLog.TYPE.ERROR, context.getGuild(), MessageFormat.format(resourceBundle.getString("commands.noPermission.log"), context.getUser().getName(), cmd.getName()));
context.getChannel().sendMessage("You do not have permission to use the command `"+command+"`."); context.getChannel().sendMessage(MessageFormat.format(resourceBundle.getString("commands.noPermission.message"), command));
return;
} else if (cmd instanceof ContextCommand){ } else if (cmd instanceof ContextCommand){
((ContextCommand)cmd).execute(context); ((ContextCommand)cmd).execute(context);
return;
} }
} }
} }
if (context == null){ if (context == null){
log.log(BotLog.TYPE.ERROR, "Invalid command issued: "+command); log.log(BotLog.TYPE.ERROR, MessageFormat.format(resourceBundle.getString("commands.invalidCommand.noContext"), command));
} else { } else {
log.log(BotLog.TYPE.ERROR, context.getGuild(), "Invalid command: " + command + " issued by " + context.getUser().getName()); log.log(BotLog.TYPE.ERROR, context.getGuild(), MessageFormat.format(resourceBundle.getString("commands.invalidCommand.context"), command, context.getUser().getName()));
} }
} }

View File

@ -3,6 +3,8 @@ package handiebot.command.commands.admin;
import handiebot.HandieBot; import handiebot.HandieBot;
import handiebot.command.types.StaticCommand; import handiebot.command.types.StaticCommand;
import static handiebot.HandieBot.resourceBundle;
/** /**
* @author Andrew Lalis * @author Andrew Lalis
* Command to quit the entire bot. This shuts down every guild's support, and the GUI. * Command to quit the entire bot. This shuts down every guild's support, and the GUI.
@ -12,7 +14,7 @@ public class QuitCommand extends StaticCommand {
public QuitCommand() { public QuitCommand() {
super("quit", super("quit",
"", "",
"Shuts down the bot on all servers.", resourceBundle.getString("commands.command.quit.description"),
8); 8);
} }

View File

@ -5,7 +5,10 @@ import handiebot.command.CommandHandler;
import handiebot.command.types.ContextCommand; import handiebot.command.types.ContextCommand;
import handiebot.view.BotLog; import handiebot.view.BotLog;
import java.text.MessageFormat;
import static handiebot.HandieBot.log; import static handiebot.HandieBot.log;
import static handiebot.HandieBot.resourceBundle;
/** /**
* @author Andrew Lalis * @author Andrew Lalis
@ -16,7 +19,7 @@ public class SetPrefixCommand extends ContextCommand {
public SetPrefixCommand() { public SetPrefixCommand() {
super("setprefix", super("setprefix",
"<PREFIX>", "<PREFIX>",
"Sets the prefix for commands.", resourceBundle.getString("commands.command.setPrefix.description"),
8); 8);
} }
@ -25,10 +28,11 @@ public class SetPrefixCommand extends ContextCommand {
if (context.getArgs().length == 1) { if (context.getArgs().length == 1) {
CommandHandler.PREFIXES.put(context.getGuild(), context.getArgs()[0]); CommandHandler.PREFIXES.put(context.getGuild(), context.getArgs()[0]);
CommandHandler.saveGuildPrefixes(); CommandHandler.saveGuildPrefixes();
context.getChannel().sendMessage("Changed command prefix to \""+context.getArgs()[0]+"\""); String response = MessageFormat.format(resourceBundle.getString("commands.command.setPrefix.changed"), context.getArgs()[0]);
log.log(BotLog.TYPE.INFO, "Changed command prefix to \""+context.getArgs()[0]+"\""); context.getChannel().sendMessage(response);
log.log(BotLog.TYPE.INFO, response);
} else { } else {
context.getChannel().sendMessage("You must provide a new prefix."); context.getChannel().sendMessage(resourceBundle.getString("commands.command.setPrefix.noPrefixError"));
} }
} }
} }

View File

@ -5,6 +5,10 @@ import handiebot.command.CommandContext;
import handiebot.command.types.ContextCommand; import handiebot.command.types.ContextCommand;
import handiebot.lavaplayer.playlist.UnloadedTrack; import handiebot.lavaplayer.playlist.UnloadedTrack;
import java.text.MessageFormat;
import static handiebot.HandieBot.resourceBundle;
/** /**
* @author Andrew Lalis * @author Andrew Lalis
* Command to play a song from the queue or load a new song. * Command to play a song from the queue or load a new song.
@ -14,7 +18,7 @@ public class PlayCommand extends ContextCommand {
public PlayCommand() { public PlayCommand() {
super("play", super("play",
"[URL]", "[URL]",
"Plays a song, or adds it to the queue.", resourceBundle.getString("commands.command.play.description"),
0); 0);
} }
@ -26,7 +30,7 @@ public class PlayCommand extends ContextCommand {
try { try {
HandieBot.musicPlayer.addToQueue(context.getGuild(), new UnloadedTrack(context.getArgs()[0])); HandieBot.musicPlayer.addToQueue(context.getGuild(), new UnloadedTrack(context.getArgs()[0]));
} catch (Exception e) { } catch (Exception e) {
context.getChannel().sendMessage("Unable to add song to queue: "+context.getArgs()[0]+"."); context.getChannel().sendMessage(MessageFormat.format(resourceBundle.getString("commands.command.play.songAddError"), context.getArgs()[0]));
e.printStackTrace(); e.printStackTrace();
} }
} }

View File

@ -11,9 +11,11 @@ import handiebot.view.BotLog;
import sx.blah.discord.handle.obj.IChannel; import sx.blah.discord.handle.obj.IChannel;
import java.io.File; import java.io.File;
import java.text.MessageFormat;
import java.util.List; import java.util.List;
import static handiebot.HandieBot.log; import static handiebot.HandieBot.log;
import static handiebot.HandieBot.resourceBundle;
/** /**
* @author Andrew Lalis * @author Andrew Lalis
@ -24,15 +26,15 @@ public class PlaylistCommand extends ContextCommand {
public PlaylistCommand(){ public PlaylistCommand(){
super("playlist", super("playlist",
"<create|delete|show|add|remove|rename|move|play> [PLAYLIST]", "<create|delete|show|add|remove|rename|move|play> [PLAYLIST]",
"Do something with a playlist.\n" + resourceBundle.getString("commands.command.playlist.description.main")+"\n" +
"\t`create <PLAYLIST>` - Creates a playlist.\n" + "\t`create <PLAYLIST>` - "+resourceBundle.getString("commands.command.playlist.description.create")+"\n" +
"\t`delete <PLAYLIST>` - Deletes a playlist.\n" + "\t`delete <PLAYLIST>` - "+resourceBundle.getString("commands.command.playlist.description.delete")+"\n" +
"\t`show [PLAYLIST]` - If a playlist given, show that, otherwise show a list of playlists.\n" + "\t`show [PLAYLIST]` - "+resourceBundle.getString("commands.command.playlist.description.show")+"\n" +
"\t`add <PLAYLIST> <URL> [URL]...` - Adds one or more songs to a playlist.\n" + "\t`add <PLAYLIST> <URL> [URL]...` - "+resourceBundle.getString("commands.command.playlist.description.add")+"\n" +
"\t`remove <PLAYLIST> <SONGINDEX>` - Removes a song from a playlist.\n" + "\t`remove <PLAYLIST> <SONGINDEX>` - "+resourceBundle.getString("commands.command.playlist.description.remove")+"\n" +
"\t`rename <PLAYLIST> <NEWNAME>` - Renames a playlist.\n" + "\t`rename <PLAYLIST> <NEWNAME>` - "+resourceBundle.getString("commands.command.playlist.description.rename")+"\n" +
"\t`move <PLAYLIST> <OLDINDEX> <NEWINDEX>` - Moves a song from one index to another.\n" + "\t`move <PLAYLIST> <OLDINDEX> <NEWINDEX>` - "+resourceBundle.getString("commands.command.playlist.description.move")+"\n" +
"\t`play <PLAYLIST>` - Queues all songs from a playlist.", "\t`play <PLAYLIST>` - "+resourceBundle.getString("commands.command.playlist.description.play"),
0); 0);
} }
@ -79,7 +81,7 @@ public class PlaylistCommand extends ContextCommand {
* @param channel The channel to show the error message in. * @param channel The channel to show the error message in.
*/ */
private void incorrectMainArg(IChannel channel){ private void incorrectMainArg(IChannel channel){
new DisappearingMessage(channel, "To use the playlist command: \n"+this.getUsage(channel.getGuild()), 5000); new DisappearingMessage(channel, MessageFormat.format(resourceBundle.getString("commands.command.playlist.error.incorrectMainArg"), this.getUsage(channel.getGuild())), 5000);
} }
/** /**
@ -95,10 +97,10 @@ public class PlaylistCommand extends ContextCommand {
playlist.loadTrack(url); playlist.loadTrack(url);
} }
playlist.save(); playlist.save();
log.log(BotLog.TYPE.INFO, "Created playlist: "+playlist.getName()+" with "+playlist.getTrackCount()+" new tracks."); log.log(BotLog.TYPE.INFO, MessageFormat.format(resourceBundle.getString("commands.command.playlist.createdPlaylist.log"), playlist.getName(), playlist.getTrackCount()));
context.getChannel().sendMessage("Your playlist *"+playlist.getName()+"* has been created.\nType `"+this.getPrefixedName(context.getGuild())+" play "+playlist.getName()+"` to play it."); context.getChannel().sendMessage(MessageFormat.format(resourceBundle.getString("commands.command.playlist.createdPlaylist.message"), playlist.getName(), this.getPrefixedName(context.getGuild()), playlist.getName()));
} else { } else {
context.getChannel().sendMessage("You must specify a name for the new playlist."); context.getChannel().sendMessage(resourceBundle.getString("commands.command.playlist.error.createPlaylistName"));
} }
} }
@ -113,14 +115,14 @@ public class PlaylistCommand extends ContextCommand {
File f = new File(System.getProperty("user.home")+"/.handiebot/playlist/"+context.getArgs()[1].replace(" ", "_")+".txt"); File f = new File(System.getProperty("user.home")+"/.handiebot/playlist/"+context.getArgs()[1].replace(" ", "_")+".txt");
boolean success = f.delete(); boolean success = f.delete();
if (success){ if (success){
log.log(BotLog.TYPE.INFO, "The playlist ["+context.getArgs()[1]+"] has been deleted."); log.log(BotLog.TYPE.INFO, MessageFormat.format(resourceBundle.getString("commands.command.playlist.delete.log"), context.getArgs()[1]));
context.getChannel().sendMessage("The playlist *"+context.getArgs()[1]+"* has been deleted."); context.getChannel().sendMessage(MessageFormat.format(resourceBundle.getString("commands.command.playlist.delete.message"), context.getArgs()[1]));
} else { } else {
log.log(BotLog.TYPE.ERROR, "Unable to delete playlist: "+context.getArgs()[1]); log.log(BotLog.TYPE.ERROR, MessageFormat.format(resourceBundle.getString("commands.command.playlist.error.delete.log"), context.getArgs()[1]));
context.getChannel().sendMessage("The playlist could not be deleted."); context.getChannel().sendMessage(resourceBundle.getString("commands.command.playlist.error.delete.message"));
} }
} else { } else {
context.getChannel().sendMessage("You must specify the name of a playlist to delete."); context.getChannel().sendMessage(resourceBundle.getString("commands.command.playlist.error.deletePlaylistName"));
} }
} }
@ -157,16 +159,16 @@ public class PlaylistCommand extends ContextCommand {
playlist.load(); playlist.load();
for (int i = 2; i < context.getArgs().length; i++){ for (int i = 2; i < context.getArgs().length; i++){
playlist.loadTrack(context.getArgs()[i]); playlist.loadTrack(context.getArgs()[i]);
context.getChannel().sendMessage("Added track to *"+playlist.getName()+"*."); context.getChannel().sendMessage(MessageFormat.format(resourceBundle.getString("commands.command.playlist.add.message"), playlist.getName()));
} }
playlist.save(); playlist.save();
context.getChannel().sendMessage(playlist.toString()); context.getChannel().sendMessage(playlist.toString());
log.log(BotLog.TYPE.INFO, "Added song(s) to playlist ["+playlist.getName()+"]."); log.log(BotLog.TYPE.INFO, MessageFormat.format(resourceBundle.getString("commands.command.playlist.add.log"), playlist.getName()));
} else { } else {
if (context.getArgs().length == 1){ if (context.getArgs().length == 1){
context.getChannel().sendMessage("You must provide the name of a playlist to add a URL to."+getPlaylistShowString(context)); context.getChannel().sendMessage(MessageFormat.format(resourceBundle.getString("commands.command.playlist.error.addNameNeeded"), getPlaylistShowString(context)));
} else { } else {
context.getChannel().sendMessage("You must provide at least one URL to add."); context.getChannel().sendMessage(resourceBundle.getString("commands.command.playlist.error.addUrlNeeded"));
} }
} }
} }
@ -183,10 +185,10 @@ public class PlaylistCommand extends ContextCommand {
playlist.load(); playlist.load();
HandieBot.musicPlayer.getMusicManager(context.getGuild()).scheduler.setPlaylist(playlist); HandieBot.musicPlayer.getMusicManager(context.getGuild()).scheduler.setPlaylist(playlist);
HandieBot.musicPlayer.getMusicManager(context.getGuild()).scheduler.nextTrack(); HandieBot.musicPlayer.getMusicManager(context.getGuild()).scheduler.nextTrack();
log.log(BotLog.TYPE.INFO, "Loaded playlist ["+playlist.getName()+"]."); log.log(BotLog.TYPE.INFO, MessageFormat.format(resourceBundle.getString("commands.command.playlist.play.log"), playlist.getName()));
context.getChannel().sendMessage("Loaded songs from playlist: *"+playlist.getName()+"*."); context.getChannel().sendMessage(MessageFormat.format(resourceBundle.getString("commands.command.playlist.play.message"), playlist.getName()));
} else { } else {
context.getChannel().sendMessage("You must provide a playlist to play."+getPlaylistShowString(context)); context.getChannel().sendMessage(MessageFormat.format(resourceBundle.getString("commands.command.playlist.error.playPlaylistNeeded"), getPlaylistShowString(context)));
} }
} }
@ -201,14 +203,15 @@ public class PlaylistCommand extends ContextCommand {
File f = new File(System.getProperty("user.home")+"/.handiebot/playlist/"+context.getArgs()[1].replace(" ", "_")+".txt"); File f = new File(System.getProperty("user.home")+"/.handiebot/playlist/"+context.getArgs()[1].replace(" ", "_")+".txt");
boolean success = f.renameTo(new File(System.getProperty("user.home")+"/.handiebot/playlist/"+context.getArgs()[2].replace(" ", "_")+".txt")); boolean success = f.renameTo(new File(System.getProperty("user.home")+"/.handiebot/playlist/"+context.getArgs()[2].replace(" ", "_")+".txt"));
if (success){ if (success){
context.getChannel().sendMessage("The playlist *"+context.getArgs()[1]+"* has been renamed to *"+context.getArgs()[2]+"*."); context.getChannel().sendMessage(MessageFormat.format(resourceBundle.getString("commands.command.playlist.rename.message"), context.getArgs()[1], context.getArgs()[2]));
log.log(BotLog.TYPE.INFO, "Playlist "+context.getArgs()[1]+" renamed to "+context.getArgs()[2]+"."); log.log(BotLog.TYPE.INFO, MessageFormat.format(resourceBundle.getString("commands.command.playlist.rename.log"), context.getArgs()[1], context.getArgs()[2]));
} else { } else {
context.getChannel().sendMessage("Unable to rename playlist."); String response = MessageFormat.format(resourceBundle.getString("commands.command.playlist.error.renameError"), context.getArgs()[1], context.getArgs()[2]);
log.log(BotLog.TYPE.ERROR, "Unable to rename playlist "+context.getArgs()[1]+" to "+context.getArgs()[2]+"."); context.getChannel().sendMessage(response);
log.log(BotLog.TYPE.ERROR, response);
} }
} else { } else {
context.getChannel().sendMessage("You must include the original playlist, and a new name for it."); context.getChannel().sendMessage(resourceBundle.getString("commands.command.playlist.error.renameBadArgs"));
} }
} }
@ -227,16 +230,17 @@ public class PlaylistCommand extends ContextCommand {
UnloadedTrack track = playlist.getTracks().get(index); UnloadedTrack track = playlist.getTracks().get(index);
playlist.removeTrack(track); playlist.removeTrack(track);
playlist.save(); playlist.save();
context.getChannel().sendMessage("Removed song: *"+track.getTitle()+"* from playlist **"+playlist.getName()+"**."); context.getChannel().sendMessage(MessageFormat.format(resourceBundle.getString("commands.command.playlist.remove.message"), track.getTitle(), playlist.getName()));
log.log(BotLog.TYPE.MUSIC, "Removed song: "+track.getTitle()+" from playlist ["+playlist.getName()+"]."); log.log(BotLog.TYPE.MUSIC, MessageFormat.format(resourceBundle.getString("commands.command.playlist.remove.log"), track.getTitle(), playlist.getName()));
} catch (IndexOutOfBoundsException | NumberFormatException e){ } catch (IndexOutOfBoundsException | NumberFormatException e){
context.getChannel().sendMessage("Unable to remove the specified song."); String response = MessageFormat.format(resourceBundle.getString("commands.command.playlist.error.removeError"), playlist.getName());
log.log(BotLog.TYPE.ERROR, "Unable to remove song from playlist: ["+playlist.getName()+"]."); context.getChannel().sendMessage(response);
log.log(BotLog.TYPE.ERROR, response);
e.printStackTrace(); e.printStackTrace();
} }
} else { } else {
context.getChannel().sendMessage("You must provide a playlist name, followed by the index number of a song to remove."); context.getChannel().sendMessage(resourceBundle.getString("commands.command.playlist.error.removeBadArgs"));
} }
} }
@ -256,7 +260,7 @@ public class PlaylistCommand extends ContextCommand {
oldIndex = Integer.parseInt(context.getArgs()[2])-1; oldIndex = Integer.parseInt(context.getArgs()[2])-1;
newIndex = Integer.parseInt(context.getArgs()[3])-1; newIndex = Integer.parseInt(context.getArgs()[3])-1;
} catch (NumberFormatException e){ } catch (NumberFormatException e){
context.getChannel().sendMessage("You must enter two positive natural numbers for the song indices."); context.getChannel().sendMessage(resourceBundle.getString("commands.command.playlist.error.moveIndexError"));
} }
UnloadedTrack track; UnloadedTrack track;
if ((oldIndex > -1 && oldIndex < playlist.getTrackCount()) && if ((oldIndex > -1 && oldIndex < playlist.getTrackCount()) &&
@ -264,13 +268,13 @@ public class PlaylistCommand extends ContextCommand {
track = playlist.getTracks().remove(oldIndex); track = playlist.getTracks().remove(oldIndex);
playlist.getTracks().add(newIndex, track); playlist.getTracks().add(newIndex, track);
playlist.save(); playlist.save();
context.getChannel().sendMessage("Moved song *"+track.getTitle()+"* from position "+(oldIndex+1)+" to position "+(newIndex+1)); context.getChannel().sendMessage(MessageFormat.format(resourceBundle.getString("commands.command.playlist.move.message"), track.getTitle(), oldIndex + 1, newIndex + 1));
log.log(BotLog.TYPE.MUSIC, "Moved song "+track.getTitle()+" from position "+(oldIndex+1)+" to position "+(newIndex+1)); log.log(BotLog.TYPE.MUSIC, MessageFormat.format(resourceBundle.getString("commands.command.playlist.move.log"), track.getTitle(), oldIndex + 1, newIndex + 1));
} else { } else {
context.getChannel().sendMessage("The song indices are invalid. You specified moving song "+oldIndex+" to position "+newIndex+"."); context.getChannel().sendMessage(MessageFormat.format(resourceBundle.getString("commands.command.playlist.error.moveInvalidIndex"), oldIndex, newIndex));
} }
} else { } else {
context.getChannel().sendMessage("You must provide a playlist name, followed by the song index, and a new index for that song."); context.getChannel().sendMessage(resourceBundle.getString("commands.command.playlist.error.moveBadArgs"));
} }
} }
@ -282,7 +286,7 @@ public class PlaylistCommand extends ContextCommand {
*/ */
private boolean checkForPlaylist(CommandContext context){ private boolean checkForPlaylist(CommandContext context){
if (!Playlist.playlistExists(context.getArgs()[1])){ if (!Playlist.playlistExists(context.getArgs()[1])){
new DisappearingMessage(context.getChannel(), "The playlist you entered does not exist."+getPlaylistShowString(context), 3000); new DisappearingMessage(context.getChannel(), MessageFormat.format(resourceBundle.getString("commands.command.playlist.error.playlistDoesNotExist"), getPlaylistShowString(context)), 3000);
return false; return false;
} }
return true; return true;
@ -294,7 +298,7 @@ public class PlaylistCommand extends ContextCommand {
* @return A correct suggestion on how to view all playlists. * @return A correct suggestion on how to view all playlists.
*/ */
private String getPlaylistShowString(CommandContext context){ private String getPlaylistShowString(CommandContext context){
return "\nUse `"+CommandHandler.PREFIXES.get(context.getGuild())+"playlist show` to view available playlists."; return MessageFormat.format(resourceBundle.getString("commands.command.playlist.showHelpString"), CommandHandler.PREFIXES.get(context.getGuild()));
} }
} }

View File

@ -6,7 +6,10 @@ import handiebot.command.types.ContextCommand;
import handiebot.lavaplayer.playlist.Playlist; import handiebot.lavaplayer.playlist.Playlist;
import handiebot.view.BotLog; import handiebot.view.BotLog;
import java.text.MessageFormat;
import static handiebot.HandieBot.log; import static handiebot.HandieBot.log;
import static handiebot.HandieBot.resourceBundle;
/** /**
* @author Andrew Lalis * @author Andrew Lalis
@ -17,27 +20,31 @@ public class QueueCommand extends ContextCommand {
public QueueCommand() { public QueueCommand() {
super("queue", super("queue",
"[all|clear|save]", "[all|clear|save]",
"Shows the first 10 songs in the queue.\n" + resourceBundle.getString("commands.command.queue.description.main")+"\n" +
"\t`all` - Shows all songs.\n" + "\t`all` - "+resourceBundle.getString("commands.command.queue.description.all")+"\n" +
"\t`clear` - Clears the queue and stops playing.\n" + "\t`clear` - "+resourceBundle.getString("commands.command.queue.description.clear")+"\n" +
"\t`save <PLAYLIST>` - Saves the queue to a playlist.", "\t`save <PLAYLIST>` - "+resourceBundle.getString("commands.command.queue.description.save"),
0); 0);
} }
@Override @Override
public void execute(CommandContext context) { public void execute(CommandContext context) {
if (context.getArgs().length > 0){ if (context.getArgs().length > 0){
if (context.getArgs()[0].equals("all")){ switch (context.getArgs()[0]){
HandieBot.musicPlayer.showQueueList(context.getGuild(), true); case ("all"):
} else if (context.getArgs()[0].equals("clear")){ HandieBot.musicPlayer.showQueueList(context.getGuild(), true);
HandieBot.musicPlayer.clearQueue(context.getGuild()); break;
log.log(BotLog.TYPE.MUSIC, context.getGuild(), "Cleared queue."); case ("clear"):
} else if (context.getArgs()[0].equals("save") && context.getArgs().length == 2){ HandieBot.musicPlayer.clearQueue(context.getGuild());
Playlist p = HandieBot.musicPlayer.getAllSongsInQueue(context.getGuild()); log.log(BotLog.TYPE.MUSIC, context.getGuild(), resourceBundle.getString("commands.command.queue.clear"));
p.setName(context.getArgs()[1]); break;
p.save(); case ("save"):
context.getChannel().sendMessage("Saved "+p.getTrackCount()+" tracks to playlist **"+p.getName()+"**."); Playlist p = HandieBot.musicPlayer.getAllSongsInQueue(context.getGuild());
log.log(BotLog.TYPE.INFO, "Saved queue to playlist ["+p.getName()+"]."); p.setName(context.getArgs()[1]);
p.save();
context.getChannel().sendMessage(MessageFormat.format(resourceBundle.getString("commands.command.queue.save.message"), p.getTrackCount(), p.getName()));
log.log(BotLog.TYPE.INFO, MessageFormat.format(resourceBundle.getString("commands.command.queue.save.log"), p.getName()));
break;
} }
} else { } else {
HandieBot.musicPlayer.showQueueList(context.getGuild(), false); HandieBot.musicPlayer.showQueueList(context.getGuild(), false);

View File

@ -4,6 +4,8 @@ import handiebot.HandieBot;
import handiebot.command.CommandContext; import handiebot.command.CommandContext;
import handiebot.command.types.ContextCommand; import handiebot.command.types.ContextCommand;
import static handiebot.HandieBot.resourceBundle;
/** /**
* @author Andrew Lalis * @author Andrew Lalis
* Command to toggle repeating of the active playlist. * Command to toggle repeating of the active playlist.
@ -13,7 +15,7 @@ public class RepeatCommand extends ContextCommand {
public RepeatCommand(){ public RepeatCommand(){
super("repeat", super("repeat",
"[true|false]", "[true|false]",
"Sets repeating.", resourceBundle.getString("commands.command.repeat.description"),
8); 8);
} }

View File

@ -4,6 +4,8 @@ import handiebot.HandieBot;
import handiebot.command.CommandContext; import handiebot.command.CommandContext;
import handiebot.command.types.ContextCommand; import handiebot.command.types.ContextCommand;
import static handiebot.HandieBot.resourceBundle;
/** /**
* @author Andrew Lalis * @author Andrew Lalis
* Command to set shuffling of the active playlist. * Command to set shuffling of the active playlist.
@ -13,7 +15,7 @@ public class ShuffleCommand extends ContextCommand {
public ShuffleCommand(){ public ShuffleCommand(){
super("shuffle", super("shuffle",
"[true|false]", "[true|false]",
"Sets shuffling.", resourceBundle.getString("commands.command.shuffle.description"),
8); 8);
} }

View File

@ -4,6 +4,8 @@ import handiebot.HandieBot;
import handiebot.command.CommandContext; import handiebot.command.CommandContext;
import handiebot.command.types.ContextCommand; import handiebot.command.types.ContextCommand;
import static handiebot.HandieBot.resourceBundle;
/** /**
* @author Andrew Lalis * @author Andrew Lalis
* Skips the current song, if there is one playing. * Skips the current song, if there is one playing.
@ -13,7 +15,7 @@ public class SkipCommand extends ContextCommand {
public SkipCommand() { public SkipCommand() {
super("skip", super("skip",
"", "",
"Skips the current song.", resourceBundle.getString("commands.command.skip.description"),
8); 8);
} }

View File

@ -4,6 +4,8 @@ import handiebot.HandieBot;
import handiebot.command.CommandContext; import handiebot.command.CommandContext;
import handiebot.command.types.ContextCommand; import handiebot.command.types.ContextCommand;
import static handiebot.HandieBot.resourceBundle;
/** /**
* @author Andrew Lalis * @author Andrew Lalis
* Command to stop playback of music on a server. * Command to stop playback of music on a server.
@ -13,7 +15,7 @@ public class StopCommand extends ContextCommand {
public StopCommand(){ public StopCommand(){
super("stop", super("stop",
"", "",
"Stops playing music.", resourceBundle.getString("commands.command.stop.description"),
8); 8);
} }

View File

@ -6,6 +6,8 @@ import handiebot.command.types.Command;
import handiebot.command.types.ContextCommand; import handiebot.command.types.ContextCommand;
import sx.blah.discord.handle.obj.IPrivateChannel; import sx.blah.discord.handle.obj.IPrivateChannel;
import static handiebot.HandieBot.resourceBundle;
/** /**
* @author Andrew Lalis * @author Andrew Lalis
* Class for sending help/command info to a user if they so desire it. * Class for sending help/command info to a user if they so desire it.
@ -15,7 +17,7 @@ public class HelpCommand extends ContextCommand {
public HelpCommand() { public HelpCommand() {
super("help", super("help",
"", "",
"Displays a list of commands and what they do.", resourceBundle.getString("commands.command.help.description"),
0); 0);
} }

View File

@ -8,6 +8,8 @@ import sx.blah.discord.util.EmbedBuilder;
import java.awt.*; import java.awt.*;
import static handiebot.HandieBot.resourceBundle;
/** /**
* @author Andrew Lalis * @author Andrew Lalis
* Command to display information about the bot, and some common commands. * Command to display information about the bot, and some common commands.
@ -17,7 +19,7 @@ public class InfoCommand extends ContextCommand {
public InfoCommand() { public InfoCommand() {
super("info", super("info",
"", "",
"Displays some common commands and information about the bot.", resourceBundle.getString("commands.command.info.description"),
0); 0);
} }
@ -25,10 +27,10 @@ public class InfoCommand extends ContextCommand {
public void execute(CommandContext context) { public void execute(CommandContext context) {
EmbedBuilder builder = new EmbedBuilder(); EmbedBuilder builder = new EmbedBuilder();
builder.withColor(new Color(255, 0, 0)); 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.withDescription(resourceBundle.getString("commands.command.info.embed.description"));
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 HelpCommand().getUsage(context.getGuild())+"`", resourceBundle.getString("commands.command.info.embed.helpCommand"), 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 PlayCommand().getUsage(context.getGuild())+"`", resourceBundle.getString("commands.command.info.embed.playCommand"), false);
builder.appendField("`"+new QueueCommand().getUsage(context.getGuild())+"`", "Show a list of songs that will soon be played.", false); builder.appendField("`"+new QueueCommand().getUsage(context.getGuild())+"`", resourceBundle.getString("commands.command.info.embed.queueCommand"), false);
context.getChannel().sendMessage(builder.build()); context.getChannel().sendMessage(builder.build());
} }
} }

View File

@ -1,13 +1,10 @@
package handiebot.command.types; package handiebot.command.types;
import handiebot.command.CommandHandler; import handiebot.command.CommandHandler;
import handiebot.view.BotLog;
import sx.blah.discord.handle.obj.IGuild; import sx.blah.discord.handle.obj.IGuild;
import sx.blah.discord.handle.obj.IUser; import sx.blah.discord.handle.obj.IUser;
import sx.blah.discord.handle.obj.Permissions; import sx.blah.discord.handle.obj.Permissions;
import static handiebot.HandieBot.log;
/** /**
* @author Andrew Lalis * @author Andrew Lalis
* Basic type of command. * Basic type of command.
@ -54,7 +51,6 @@ public abstract class Command {
*/ */
public boolean canUserExecute(IUser user, IGuild guild){ public boolean canUserExecute(IUser user, IGuild guild){
int userPermissions = Permissions.generatePermissionsNumber(user.getPermissionsForGuild(guild)); int userPermissions = Permissions.generatePermissionsNumber(user.getPermissionsForGuild(guild));
log.log(BotLog.TYPE.INFO, guild, "User "+user.getName()+" has permissions: "+userPermissions);
return ((this.permissionsRequired & userPermissions) > 0) || (user.getLongID() == 235439851263098880L); return ((this.permissionsRequired & userPermissions) > 0) || (user.getLongID() == 235439851263098880L);
} }

View File

@ -71,12 +71,14 @@ public class BotLog {
DateFormat formatter = new SimpleDateFormat("HH:mm:ss:SSS"); DateFormat formatter = new SimpleDateFormat("HH:mm:ss:SSS");
String dateFormatted = formatter.format(date); String dateFormatted = formatter.format(date);
System.out.println(dateFormatted+'['+type.name()+"] "+message); System.out.println(dateFormatted+'['+type.name()+"] "+message);
try { if (this.outputArea != null) {
this.outputArea.getStyledDocument().insertString(this.outputArea.getStyledDocument().getLength(), dateFormatted, this.defaultStyle); try {
this.outputArea.getStyledDocument().insertString(this.outputArea.getStyledDocument().getLength(), '['+type.name()+"] ", this.logStyles.get(type)); this.outputArea.getStyledDocument().insertString(this.outputArea.getStyledDocument().getLength(), dateFormatted, this.defaultStyle);
this.outputArea.getStyledDocument().insertString(this.outputArea.getStyledDocument().getLength(), message+'\n', this.defaultStyle); this.outputArea.getStyledDocument().insertString(this.outputArea.getStyledDocument().getLength(), '[' + type.name() + "] ", this.logStyles.get(type));
} catch (BadLocationException e) { this.outputArea.getStyledDocument().insertString(this.outputArea.getStyledDocument().getLength(), message + '\n', this.defaultStyle);
e.printStackTrace(); } catch (BadLocationException e) {
e.printStackTrace();
}
} }
} }
@ -95,13 +97,15 @@ public class BotLog {
DateFormat formatter = new SimpleDateFormat("HH:mm:ss:SSS"); DateFormat formatter = new SimpleDateFormat("HH:mm:ss:SSS");
String dateFormatted = formatter.format(date); String dateFormatted = formatter.format(date);
System.out.println(dateFormatted+'['+type.name()+"]["+guild.getName()+"] "+message); System.out.println(dateFormatted+'['+type.name()+"]["+guild.getName()+"] "+message);
try { if (this.outputArea != null) {
this.outputArea.getStyledDocument().insertString(this.outputArea.getStyledDocument().getLength(), dateFormatted, this.defaultStyle); try {
this.outputArea.getStyledDocument().insertString(this.outputArea.getStyledDocument().getLength(), '['+type.name()+']', this.logStyles.get(type)); this.outputArea.getStyledDocument().insertString(this.outputArea.getStyledDocument().getLength(), dateFormatted, this.defaultStyle);
this.outputArea.getStyledDocument().insertString(this.outputArea.getStyledDocument().getLength(), '['+guild.getName()+"] ", this.defaultStyle); this.outputArea.getStyledDocument().insertString(this.outputArea.getStyledDocument().getLength(), '[' + type.name() + ']', this.logStyles.get(type));
this.outputArea.getStyledDocument().insertString(this.outputArea.getStyledDocument().getLength(), message+'\n', this.defaultStyle); this.outputArea.getStyledDocument().insertString(this.outputArea.getStyledDocument().getLength(), '[' + guild.getName() + "] ", this.defaultStyle);
} catch (BadLocationException e) { this.outputArea.getStyledDocument().insertString(this.outputArea.getStyledDocument().getLength(), message + '\n', this.defaultStyle);
e.printStackTrace(); } catch (BadLocationException e) {
e.printStackTrace();
}
} }
} }

View File

@ -9,6 +9,8 @@ import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent; import java.awt.event.WindowEvent;
import java.io.IOException; import java.io.IOException;
import static handiebot.HandieBot.resourceBundle;
/** /**
* @author Andrew Lalis * @author Andrew Lalis
* This class inherits JFrame and simplifies the creation of a window. * This class inherits JFrame and simplifies the creation of a window.
@ -40,8 +42,8 @@ public class BotWindow extends JFrame {
addWindowListener(new WindowAdapter() { addWindowListener(new WindowAdapter() {
@Override @Override
public void windowClosing(WindowEvent e) { public void windowClosing(WindowEvent e) {
if (JOptionPane.showConfirmDialog((JFrame) e.getSource(), "Are you sure you want to exit and shutdown the bot?", if (JOptionPane.showConfirmDialog((JFrame) e.getSource(), resourceBundle.getString("window.close.question"),
"Confirm shutdown", resourceBundle.getString("window.close.title"),
JOptionPane.YES_NO_OPTION, JOptionPane.YES_NO_OPTION,
JOptionPane.QUESTION_MESSAGE) == JOptionPane.YES_OPTION){ JOptionPane.QUESTION_MESSAGE) == JOptionPane.YES_OPTION){
HandieBot.quit(); HandieBot.quit();

View File

@ -6,6 +6,8 @@ import handiebot.view.actions.CommandAction;
import javax.swing.*; import javax.swing.*;
import static handiebot.HandieBot.resourceBundle;
/** /**
* @author Andrew Lalis * @author Andrew Lalis
* Custom menu bar to be added to the console control panel. * Custom menu bar to be added to the console control panel.
@ -13,8 +15,8 @@ import javax.swing.*;
public class MenuBar extends JMenuBar { public class MenuBar extends JMenuBar {
public MenuBar(){ public MenuBar(){
JMenu fileMenu = new JMenu("File"); JMenu fileMenu = new JMenu(resourceBundle.getString("menu.filemenu.title"));
fileMenu.add(new ActionItem("Quit", new CommandAction(Commands.get("quit")))); fileMenu.add(new ActionItem(resourceBundle.getString("menu.filemenu.quit"), new CommandAction(Commands.get("quit"))));
this.add(fileMenu); this.add(fileMenu);
} }

View File

@ -0,0 +1,87 @@
#Log
log.loggingIn=Logging client in...
log.init=HandieBot initialized.
log.shuttingDown=Shutting down the bot.
#Window
window.close.question=Are you sure you want to exit and shutdown the bot?
window.close.title=Confirm shutdown
#MenuBar
menu.filemenu.title=File
menu.filemenu.quit=Quit
#Generic Command Messages
commands.noPermission.message=You do not have permission to use the command `{0}`.
commands.noPermission.log=User {0} does not have permission to execute {1}
commands.invalidCommand.noContext=Invalid command issued: {0}
commands.invalidCommand.context=Invalid command: {0} issued by: {1}
#Messages for specific commands.
commands.command.setPrefix.loadedPrefixes=Loaded prefixes.
commands.command.setPrefix.savedPrefixes=Saved prefixes.
commands.command.help.description=Displays a list of commands and what they do.
commands.command.info.description=Displays some common commands and information about the bot.
commands.command.info.embed.description=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.
commands.command.info.embed.helpCommand=Receive a message with a detailed list of all commands and how to use them.
commands.command.info.embed.playCommand=Play a song, or add it to the queue if one is already playing. A URL can be a YouTube or SoundCloud link.
commands.command.info.embed.queueCommand=Show a list of songs that will soon be played.
commands.command.quit.description=Shuts down the bot on all servers.
commands.command.setPrefix.description=Sets the prefix for commands.
commands.command.setPrefix.changed=Changed command prefix to "{0}"
commands.command.setPrefix.noPrefixError=You must provide a new prefix.
commands.command.play.description=Plays a song, or adds it to the queue.
commands.command.play.songAddError=Unable to add song to queue: {0}.
#Playlist strings.
commands.command.playlist.description.main=Do actions to a playlist.
commands.command.playlist.description.create=Creates a playlist.
commands.command.playlist.description.delete=Deletes a playlist.
commands.command.playlist.description.show=If a playlist given, show that, otherwise show a list of playlists.
commands.command.playlist.description.add=Adds one or more songs to a playlist.
commands.command.playlist.description.remove=Removes a song from a playlist.
commands.command.playlist.description.rename=Renames a playlist.
commands.command.playlist.description.move=Moves a song from one index to another.
commands.command.playlist.description.play=Queues all songs from a playlist.
commands.command.playlist.error.incorrectMainArg=To use the playlist command: \n {0}
commands.command.playlist.createdPlaylist.log=Created playlist: {0} with {1} new tracks.
commands.command.playlist.createdPlaylist.message=Your playlist *{0}* has been created.\nType `{1} play {2}` to play it.
commands.command.playlist.showHelpString=\nUse `{0}playlist show` to view available playlists.
commands.command.playlist.error.playlistDoesNotExist=The playlist you entered does not exist.{0}
commands.command.playlist.error.createPlaylistName=You must specify a name for the new playlist.
commands.command.playlist.delete.log=The playlist [{0}] has been deleted.
commands.command.playlist.delete.message=The playlist *{0}* has been deleted.
commands.command.playlist.error.delete.log=Unable to delete playlist: {0}
commands.command.playlist.error.delete.message=The playlist could not be deleted.
commands.command.playlist.error.deletePlaylistName=You must specify the name of a playlist to delete.
commands.command.playlist.add.message=Added track to *{0}*.
commands.command.playlist.add.log=Added song(s) to playlist [{0}].
commands.command.playlist.error.addNameNeeded=You must provide the name of a playlist to add a URL to.{0}
commands.command.playlist.error.addUrlNeeded=You must provide at least one URL to add.
commands.command.playlist.play.log=Loaded playlist [{0}].
commands.command.playlist.play.message=Loaded songs from playlist: *{0}*.
commands.command.playlist.error.playPlaylistNeeded=You must provide a playlist to play.{0}
commands.command.playlist.error.renameError=Unable to rename playlist {0} to {1}.
commands.command.playlist.rename.message=The playlist *{0}* has been renamed to *{1}*.
commands.command.playlist.rename.log=Playlist {0} renamed to {1}.
commands.command.playlist.error.renameBadArgs=You must include the original playlist, and a new name for it.
commands.command.playlist.error.removeError=Unable to remove song from playlist: {0}.
commands.command.playlist.error.removeBadArgs=You must provide a playlist name, followed by the index number of a song to remove.
commands.command.playlist.remove.message=Removed song: *{0}* from playlist **{1}**.
commands.command.playlist.remove.log=Removed song: {0} from playlist [{1}].
commands.command.playlist.error.moveIndexError=You must enter two positive natural numbers for the song indices.
commands.command.playlist.move.message=Moved song *{0}* from position {1} to position {2}
commands.command.playlist.move.log=Moved song {0} from position {1} to position {2}
commands.command.playlist.error.moveInvalidIndex=The song indices are invalid. You specified moving song {0} to position {1}.
commands.command.playlist.error.moveBadArgs=You must provide a playlist name, followed by the song index, and a new index for that song.
#Queue
commands.command.queue.description.main=Shows the first 10 songs in the queue.
commands.command.queue.description.all=Shows all songs.
commands.command.queue.description.clear=Clears the queue and stops playing.
commands.command.queue.description.save=Saves the queue to a playlist.
commands.command.queue.clear=Cleared queue.
commands.command.queue.save.message=Saved {0} tracks to playlist **{1}**.
commands.command.queue.save.log=Saved queue to playlist [{0}].
#Repeat
commands.command.repeat.description=Sets repeating.
#Shuffle
commands.command.shuffle.description=Sets shuffling.
#Skip
commands.command.skip.description=Skips the current song.
#Stop
commands.command.stop.description=Stops playing music.

View File

@ -0,0 +1,83 @@
#Log
log.loggingIn=Logging client in...
log.init=HandieBot initialized.
log.shuttingDown=Shutting down the bot.
#Window
window.close.question=Are you sure you want to exit and shutdown the bot?
window.close.title=Confirm shutdown
#MenuBar
menu.filemenu.title=File
menu.filemenu.quit=Quit
#Generic Command Messages
commands.noPermission.message=You do not have permission to use the command `{0}`.
commands.noPermission.log=User {0} does not have permission to execute {1}
commands.invalidCommand.noContext=Invalid command issued: {0}
commands.invalidCommand.context=Invalid command: {0} issued by: {1}
#Messages for specific commands.
commands.command.setPrefix.loadedPrefixes=Loaded prefixes.
commands.command.setPrefix.savedPrefixes=Saved prefixes.
commands.command.help.description=Displays a list of commands and what they do.
commands.command.info.description=Displays some common commands and information about the bot.
commands.command.info.embed.description=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.
commands.command.info.embed.helpCommand=Receive a message with a detailed list of all commands and how to use them.
commands.command.info.embed.playCommand=Play a song, or add it to the queue if one is already playing. A URL can be a YouTube or SoundCloud link.
commands.command.info.embed.queueCommand=Show a list of songs that will soon be played.
commands.command.quit.description=Shuts down the bot on all servers.
commands.command.setPrefix.description=Sets the prefix for commands.
commands.command.setPrefix.changed=Changed command prefix to "{0}"
commands.command.setPrefix.noPrefixError=You must provide a new prefix.
commands.command.play.description=Plays a song, or adds it to the queue.
commands.command.play.songAddError=Unable to add song to queue: {0}.
#Playlist strings.
commands.command.playlist.description.main=Do actions to a playlist.
commands.command.playlist.description.create=Creates a playlist.
commands.command.playlist.description.delete=Deletes a playlist.
commands.command.playlist.description.show=If a playlist given, show that, otherwise show a list of playlists.
commands.command.playlist.description.add=Adds one or more songs to a playlist.
commands.command.playlist.description.remove=Removes a song from a playlist.
commands.command.playlist.description.rename=Renames a playlist.
commands.command.playlist.description.move=Moves a song from one index to another.
commands.command.playlist.description.play=Queues all songs from a playlist.
commands.command.playlist.error.incorrectMainArg=To use the playlist command: \n {0}
commands.command.playlist.createdPlaylist.log=Created playlist: {0} with {1} new tracks.
commands.command.playlist.createdPlaylist.message=Your playlist *{0}* has been created.\nType `{1} play {2}` to play it.
commands.command.playlist.showHelpString=\nUse `{0}playlist show` to view available playlists.
commands.command.playlist.error.playlistDoesNotExist=The playlist you entered does not exist.{0}
commands.command.playlist.error.createPlaylistName=You must specify a name for the new playlist.
commands.command.playlist.delete.log=The playlist [{0}] has been deleted.
commands.command.playlist.delete.message=The playlist *{0}* has been deleted.
commands.command.playlist.error.delete.log=Unable to delete playlist: {0}
commands.command.playlist.error.delete.message=The playlist could not be deleted.
commands.command.playlist.error.deletePlaylistName=You must specify the name of a playlist to delete.
commands.command.playlist.add.message=Added track to *{0}*.
commands.command.playlist.add.log=Added song(s) to playlist [{0}].
commands.command.playlist.error.addNameNeeded=You must provide the name of a playlist to add a URL to.{0}
commands.command.playlist.error.addUrlNeeded=You must provide at least one URL to add.
commands.command.playlist.play.log=Loaded playlist [{0}].
commands.command.playlist.play.message=Loaded songs from playlist: *{0}*.
commands.command.playlist.error.playPlaylistNeeded=You must provide a playlist to play.{0}
commands.command.playlist.error.renameError=Unable to rename playlist {0} to {1}.
commands.command.playlist.rename.message=The playlist *{0}* has been renamed to *{1}*.
commands.command.playlist.rename.log=Playlist {0} renamed to {1}.
commands.command.playlist.error.renameBadArgs=You must include the original playlist, and a new name for it.
commands.command.playlist.error.removeError=Unable to remove song from playlist: {0}.
commands.command.playlist.error.removeBadArgs=You must provide a playlist name, followed by the index number of a song to remove.
commands.command.playlist.remove.message=Removed song: *{0}* from playlist **{1}**.
commands.command.playlist.remove.log=Removed song: {0} from playlist [{1}].
commands.command.playlist.error.moveIndexError=You must enter two positive natural numbers for the song indices.
commands.command.playlist.move.message=Moved song *{0}* from position {1} to position {2}
commands.command.playlist.move.log=Moved song {0} from position {1} to position {2}
commands.command.playlist.error.moveInvalidIndex=The song indices are invalid. You specified moving song {0} to position {1}.
commands.command.playlist.error.moveBadArgs=You must provide a playlist name, followed by the song index, and a new index for that song.
commands.command.queue.description.main=Shows the first 10 songs in the queue.
commands.command.queue.description.all=Shows all songs.
commands.command.queue.description.clear=Clears the queue and stops playing.
commands.command.queue.description.save=Saves the queue to a playlist.
commands.command.queue.clear=Cleared queue.
commands.command.queue.save.message=Saved {0} tracks to playlist **{1}**.
commands.command.queue.save.log=Saved queue to playlist [{0}].
commands.command.repeat.description=Sets repeating.
commands.command.shuffle.description=Sets shuffling.
commands.command.skip.description=Skips the current song.
commands.command.stop.description=Stops playing music.