diff --git a/.gitignore b/.gitignore index 808b8e3..4713549 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ -!.jar .idea/ modules/ src/test/ diff --git a/README.md b/README.md index e763802..78b8cf5 100644 --- a/README.md +++ b/README.md @@ -29,35 +29,39 @@ queue all Because the play command is defined as `play [URL]`, and the queue command is defined as `queue [all]`. +Commands shown in **`bold`** can only be executed by an administrator, for security reasons. + ### 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 ` - 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. +* **`setprefix `** - 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. +* **`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. +* **`skip`** - If a song is playing, the bot will skip it and play the next song in the queue. * `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. + * **`clear`** - The queue will be cleared and the current song will be stopped. - * `save ` - The queue will be saved as a playlist with the given name. + * **`save `** - 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. +* `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. If no argument is given, then this shows if the queue is currently repeating. -* `shuffle [true|false]` - Sets the bot to shuffle the playlist, as in pull a random song from the playlist, with some filters to prevent repeating songs. +* `shuffle [true|false]` - Sets the bot to shuffle the playlist, as in pull a random song from the playlist, with some filters to prevent repeating songs. If no argument is given, then this shows if the queue is currently shuffling. -* `playlist ` - Various commands to manipulate playlists. The specific sub-commands are explained below. + >Note that for `repeat` and `shuffle`, anyone may view the status of these values, but only administrators may set them. + +* **`playlist `** - Various commands to manipulate playlists. The specific sub-commands are explained below. * `create [URL]...` - Creates a new playlist, optionally with some starting URLs. * `delete ` - Deletes a playlist with the given name. @@ -74,3 +78,10 @@ Because the play command is defined as `play [URL]`, and the queue command is de * `move ` - Moves a song from one index to another index, shifting other elements as necessary. +### Miscellaneous + +* `tengwar ` - Uses the [TengwarTranslatorLibrary](https://github.com/andrewlalis/TengwarTranslatorLibrary) to translate text into a Tengwar script equivalent, or translate from Tengwar to normal text. Be aware that due to the nature of this font, capitalization is not saved in Tengwar. For more information on how this works, check out my [TengwarTranslator](https://github.com/andrewlalis/TengwarTranslator). + + * `to ` - Translates some text to tengwar, and responds with both the raw, UTF-8 string, and an image generated using a Tengwar font. + + * `from ` - Translates some tengwar text to normal, human readable text. \ No newline at end of file diff --git a/pom.xml b/pom.xml index 31b0c1b..9e3b612 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.github.andrewlalis HandieBot - 1.3.1 + 1.4.0 @@ -70,7 +70,7 @@ com.github.andrewlalis TengwarTranslatorLibrary - 1.2 + 1.3 diff --git a/src/main/java/handiebot/HandieBot.java b/src/main/java/handiebot/HandieBot.java index ddb116f..3c080a1 100644 --- a/src/main/java/handiebot/HandieBot.java +++ b/src/main/java/handiebot/HandieBot.java @@ -16,10 +16,7 @@ import sx.blah.discord.handle.obj.Permissions; import sx.blah.discord.util.DiscordException; import sx.blah.discord.util.RateLimitException; -import java.util.ArrayList; -import java.util.EnumSet; -import java.util.List; -import java.util.ResourceBundle; +import java.util.*; /** * @author Andrew Lalis @@ -33,7 +30,7 @@ public class HandieBot { 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 final ResourceBundle resourceBundle = ResourceBundle.getBundle("Strings"); //Discord client object. public static IDiscordClient client; @@ -46,7 +43,7 @@ public class HandieBot { public static MusicPlayer musicPlayer; //List of all permissions needed to operate this bot. - private static int permissionsNumber = 0; + private static final int permissionsNumber; static { List requiredPermissions = new ArrayList<>(); requiredPermissions.add(Permissions.CHANGE_NICKNAME); @@ -87,12 +84,12 @@ public class HandieBot { musicPlayer = new MusicPlayer(); - if (args.length >= 1) { - if (args[0].equalsIgnoreCase("-nogui")){ - System.out.println("Starting with no GUI."); - USE_GUI = false; - log = new BotLog(null); - } + List argsList = Arrays.asList(args); + + if (argsList.contains("-nogui")) { + System.out.println("Starting with no GUI."); + USE_GUI = false; + log = new BotLog(null); } if (USE_GUI){ diff --git a/src/main/java/handiebot/command/CommandHandler.java b/src/main/java/handiebot/command/CommandHandler.java index 996a72a..ade2f32 100644 --- a/src/main/java/handiebot/command/CommandHandler.java +++ b/src/main/java/handiebot/command/CommandHandler.java @@ -77,9 +77,7 @@ public class CommandHandler { String[] words = message.getContent().split(" "); 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]; - } + System.arraycopy(words, 1, args, 0, words.length - 1); return args; } return new String[0]; diff --git a/src/main/java/handiebot/command/Commands.java b/src/main/java/handiebot/command/Commands.java index ca23377..8fb960a 100644 --- a/src/main/java/handiebot/command/Commands.java +++ b/src/main/java/handiebot/command/Commands.java @@ -25,7 +25,7 @@ import static handiebot.HandieBot.resourceBundle; */ public class Commands { - public static List commands = new ArrayList(); + public static List commands = new ArrayList<>(); static { //Music commands. diff --git a/src/main/java/handiebot/command/commands/music/PlaylistCommand.java b/src/main/java/handiebot/command/commands/music/PlaylistCommand.java index 5e90469..5cffa92 100644 --- a/src/main/java/handiebot/command/commands/music/PlaylistCommand.java +++ b/src/main/java/handiebot/command/commands/music/PlaylistCommand.java @@ -286,11 +286,12 @@ public class PlaylistCommand extends ContextCommand { * @return True if the playlist exists, false otherwise. */ private boolean checkForPlaylist(CommandContext context){ - if (!Playlist.playlistExists(context.getArgs()[1])){ + if (Playlist.playlistExists(context.getArgs()[1])){ + return true; + } else { new DisappearingMessage(context.getChannel(), MessageFormat.format(resourceBundle.getString("commands.command.playlist.error.playlistDoesNotExist"), getPlaylistShowString(context)), 3000); return false; } - return true; } /** diff --git a/src/main/java/handiebot/lavaplayer/AudioProvider.java b/src/main/java/handiebot/lavaplayer/AudioProvider.java index 0155f4e..77b5c0c 100644 --- a/src/main/java/handiebot/lavaplayer/AudioProvider.java +++ b/src/main/java/handiebot/lavaplayer/AudioProvider.java @@ -6,7 +6,8 @@ import sx.blah.discord.handle.audio.AudioEncodingType; import sx.blah.discord.handle.audio.IAudioProvider; /** - * Created by Andrew's Computer on 18-Jun-17. + * @author Andrew Lalis + * Class to provide audio bytes to the music player. */ public class AudioProvider implements IAudioProvider { private final AudioPlayer audioPlayer; diff --git a/src/main/java/handiebot/lavaplayer/MusicPlayer.java b/src/main/java/handiebot/lavaplayer/MusicPlayer.java index 666990f..abf6771 100644 --- a/src/main/java/handiebot/lavaplayer/MusicPlayer.java +++ b/src/main/java/handiebot/lavaplayer/MusicPlayer.java @@ -175,6 +175,7 @@ public class MusicPlayer { public void showQueueList(IGuild guild, boolean showAll) { List tracks = getMusicManager(guild).scheduler.queueList(); if (tracks.size() == 0) { + //noinspection ConstantConditions getChatChannel(guild).sendMessage(MessageFormat.format(resourceBundle.getString("player.queueEmpty"), Commands.get("play").getUsage())); } else { if (tracks.size() > 10 && showAll) { @@ -295,9 +296,7 @@ public class MusicPlayer { * Performs the same functions as stop, but with every guild. */ public void quitAll(){ - this.musicManagers.forEach((guild, musicManager) -> { - musicManager.scheduler.stop(); - }); + this.musicManagers.forEach((guild, musicManager) -> musicManager.scheduler.stop()); this.playerManager.shutdown(); } diff --git a/src/main/java/handiebot/lavaplayer/TrackScheduler.java b/src/main/java/handiebot/lavaplayer/TrackScheduler.java index 90efcb8..e8e5331 100644 --- a/src/main/java/handiebot/lavaplayer/TrackScheduler.java +++ b/src/main/java/handiebot/lavaplayer/TrackScheduler.java @@ -197,8 +197,8 @@ public class TrackScheduler extends AudioEventAdapter { if (channels.size() > 0){ IMessage message = channels.get(0).sendMessage(MessageFormat.format(":arrow_forward: "+resourceBundle.getString("trackSchedule.nowPlaying"), track.getInfo().title, new UnloadedTrack(track).getFormattedDuration())); this.activePlayMessageId = message.getLongID(); - RequestBuffer.request(() -> {message.addReaction(":thumbsup:");}).get(); - RequestBuffer.request(() -> {message.addReaction(":thumbsdown:");}).get(); + RequestBuffer.request(() -> message.addReaction(":thumbsup:")).get(); + RequestBuffer.request(() -> message.addReaction(":thumbsdown:")).get(); } } diff --git a/src/main/java/handiebot/lavaplayer/playlist/Playlist.java b/src/main/java/handiebot/lavaplayer/playlist/Playlist.java index 47ae886..22b3645 100644 --- a/src/main/java/handiebot/lavaplayer/playlist/Playlist.java +++ b/src/main/java/handiebot/lavaplayer/playlist/Playlist.java @@ -12,6 +12,7 @@ import java.util.List; import java.util.Random; import static handiebot.HandieBot.log; +import static handiebot.HandieBot.resourceBundle; /** * @author Andrew Lalis @@ -21,7 +22,7 @@ import static handiebot.HandieBot.log; * on the playlist. */ public class Playlist { -//TODO: externalize strings + private String name; private List tracks; @@ -186,7 +187,7 @@ public class Playlist { */ public static List getAvailablePlaylists(){ File playlistFolder = new File(System.getProperty("user.home")+"/.handiebot/playlist"); - List names = new ArrayList(Arrays.asList(playlistFolder.list())); + @SuppressWarnings("ConstantConditions") List names = new ArrayList<>(Arrays.asList(playlistFolder.list())); for (int i = 0; i < names.size(); i++){ String name = names.get(i); name = name.replace(".txt", ""); @@ -215,7 +216,7 @@ public class Playlist { public String toString(){ StringBuilder sb = new StringBuilder("Playlist: "+this.getName()+'\n'); if (this.getTrackCount() == 0){ - sb.append("There are no songs in this playlist."); + sb.append(resourceBundle.getString("playlist.empty")); } 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"); diff --git a/src/main/java/handiebot/lavaplayer/playlist/UnloadedTrack.java b/src/main/java/handiebot/lavaplayer/playlist/UnloadedTrack.java index ed758f8..e2315c1 100644 --- a/src/main/java/handiebot/lavaplayer/playlist/UnloadedTrack.java +++ b/src/main/java/handiebot/lavaplayer/playlist/UnloadedTrack.java @@ -17,7 +17,7 @@ import static handiebot.HandieBot.log; * This is useful for quickly loading playlists and only loading a track when it is needed. */ public class UnloadedTrack implements Cloneable { -//TODO: externalize strings + private String title; private String url; private long duration; diff --git a/src/main/java/handiebot/utils/DisappearingMessage.java b/src/main/java/handiebot/utils/DisappearingMessage.java index fa54382..42d8615 100644 --- a/src/main/java/handiebot/utils/DisappearingMessage.java +++ b/src/main/java/handiebot/utils/DisappearingMessage.java @@ -30,7 +30,7 @@ public class DisappearingMessage extends Thread implements Runnable { e.printStackTrace(); } if (canDelete(sentMessage)) - RequestBuffer.request(() -> sentMessage.delete()); + RequestBuffer.request(sentMessage::delete); } /** @@ -46,7 +46,7 @@ public class DisappearingMessage extends Thread implements Runnable { e.printStackTrace(); } if (canDelete(message)) - RequestBuffer.request(() -> message.delete()); + RequestBuffer.request(message::delete); }).start(); } diff --git a/src/main/java/handiebot/utils/FileUtil.java b/src/main/java/handiebot/utils/FileUtil.java index 26749bd..5947214 100644 --- a/src/main/java/handiebot/utils/FileUtil.java +++ b/src/main/java/handiebot/utils/FileUtil.java @@ -7,17 +7,19 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.io.PrintWriter; import java.nio.file.Files; +import java.text.MessageFormat; import java.util.ArrayList; import java.util.List; import static handiebot.HandieBot.log; +import static handiebot.HandieBot.resourceBundle; /** * @author Andrew Lalis * Class to simplify file operations. */ public class FileUtil { -//TODO: externalize strings + public static String getDataDirectory(){ return System.getProperty("user.home")+"/.handiebot/"; } @@ -39,12 +41,12 @@ public class FileUtil { try { boolean success = file.createNewFile(); if (!success) { - log.log(BotLog.TYPE.ERROR, "Unable to create file. "+file.getAbsolutePath()); + log.log(BotLog.TYPE.ERROR, MessageFormat.format(resourceBundle.getString("fileutil.fileCreateError"), file.getAbsolutePath())); return; } } catch (IOException e) { e.printStackTrace(); - log.log(BotLog.TYPE.ERROR, "Unable to create file. "+file.getAbsolutePath()); + log.log(BotLog.TYPE.ERROR, MessageFormat.format(resourceBundle.getString("fileutil.fileCreateError"), file.getAbsolutePath())); return; } } @@ -54,7 +56,7 @@ public class FileUtil { } } catch (FileNotFoundException e) { e.printStackTrace(); - log.log(BotLog.TYPE.ERROR, "Unable to write to file. "+file.getAbsolutePath()); + log.log(BotLog.TYPE.ERROR, MessageFormat.format(resourceBundle.getString("fileutil.writeError"), file.getAbsolutePath())); } } diff --git a/src/main/java/handiebot/utils/Pastebin.java b/src/main/java/handiebot/utils/Pastebin.java index 46450cc..cec78dd 100644 --- a/src/main/java/handiebot/utils/Pastebin.java +++ b/src/main/java/handiebot/utils/Pastebin.java @@ -22,7 +22,7 @@ import java.util.List; */ public class Pastebin { - private static String PASTEBIN_KEY = "769adc01154922ece448cabd7a33b57c"; + private static final String PASTEBIN_KEY = "769adc01154922ece448cabd7a33b57c"; public static String paste(String title, String content){ HttpClient client = HttpClients.createDefault(); diff --git a/src/main/java/handiebot/view/CommandLineListener.java b/src/main/java/handiebot/view/CommandLineListener.java index 0678ee2..a71b9f3 100644 --- a/src/main/java/handiebot/view/CommandLineListener.java +++ b/src/main/java/handiebot/view/CommandLineListener.java @@ -25,9 +25,7 @@ public class CommandLineListener implements KeyListener { commandLine.setText(null); String command = words[0]; String[] args = new String[words.length-1]; - for (int i = 1; i < words.length; i++) { - args[i-1] = words[i]; - } + System.arraycopy(words, 1, args, 0, words.length - 1); executeCommand(command, args); } } diff --git a/src/main/resources/Strings.properties b/src/main/resources/Strings.properties index 8ec9027..c864ee9 100644 --- a/src/main/resources/Strings.properties +++ b/src/main/resources/Strings.properties @@ -111,5 +111,10 @@ player.playQueueEmpty=There's nothing in the queue to play. #Track scheduler trackSchedule.trackStarted=Started audio track: {0} trackSchedule.nowPlaying=Now playing: **{0}** {1} +#File utils +fileutil.fileCreateError=Unable to create file. {0} +fileutil.writeError=Unable to write to file. {0} +#Playlist strings +playlist.empty=There are no songs in this playlist. diff --git a/src/main/resources/Strings_nl.properties b/src/main/resources/Strings_nl.properties index 76f90c7..c864ee9 100644 --- a/src/main/resources/Strings_nl.properties +++ b/src/main/resources/Strings_nl.properties @@ -1,7 +1,12 @@ +#Strings for HandieBot: +# The following strings are organized in a way that it should be intuitive how it will be used. #Log log.loggingIn=Logging client in... log.init=HandieBot initialized. log.shuttingDown=Shutting down the bot. +log.deleteMessageError=Unable to delete message. Please ensure that the bot has MANAGE_MESSAGES enabled, especially for this channel. +log.creatingChatChannel=No chat channel found, creating a new one. +log.newVoiceChannel=No voice channel found, creating a new one. #Window window.close.question=Are you sure you want to exit and shutdown the bot? window.close.title=Confirm shutdown @@ -11,6 +16,7 @@ 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.noPermission.subcommand=You don't have permission to do that. commands.invalidCommand.noContext=Invalid command issued: {0} commands.invalidCommand.context=Invalid command: {0} issued by: {1} #Messages for specific commands. @@ -69,6 +75,7 @@ commands.command.playlist.move.message=Moved song *{0}* from position {1} to pos 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. @@ -76,30 +83,38 @@ 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. -log.deleteMessageError=Unable to delete message. Please ensure that the bot has MANAGE_MESSAGES enabled, especially for this channel. -log.creatingChatChannel=No chat channel found, creating a new one. -log.newVoiceChannel=No voice channel found, creating a new one. -player.setRepeat=Set repeat to {0} -player.setShuffle=Set shuffle to {0} +#Tengwar translator +commands.command.tengwar.description=Translates text to tengwar, or decodes tengwar text back into human readable form. +#Music Player +player.setRepeat=Set **Repeat** to *{0}*. +player.setShuffle=Set **Shuffle** to *{0}*. +player.getRepeat=**Repeat** is set to *{0}*. +player.getShuffle=**Shuffle** is set to *{0}*. player.queueEmpty=The queue is empty. Use `{0}` to add songs. -player.queueUploaded=Queue uploaded to pastebin: {0} -player.pastebinLink=You may view the full queue by following the link: {0}\ -Note that this link expires in 10 minutes. -player.pastebinError=Unable to upload to pastebin: {0} +player.queueUploaded=Queue uploaded to pastebin: {0}. +player.pastebinLink=You may view the full queue by following the link: {0}\nNote that this link expires in 10 minutes. +player.pastebinError=Unable to upload to pastebin: {0}. player.queueHeader=Showing {0} track{1} out of {2}. -player.addedToQueue=Added **{0}** to the queue. +player.addedToQueue={0} added **{1}** to the queue. player.queueCleared=Cleared the queue. player.skippingCurrent=Skipping the current track. player.musicStopped=Stopped playing music. -trackSchedule.trackStarted=Started audio track: {0} -trackSchedule.nowPlaying=Now playing: **{0}** {1}\ -{2} player.playQueueEmpty=There's nothing in the queue to play. -commands.command.tengwar.description=Translates text to tengwar, or decodes tengwar text back into human readable form. -commands.noPermissions=You don't have permission to do that. -player.getRepeat=Repeat is set to *{0}*. +#Track scheduler +trackSchedule.trackStarted=Started audio track: {0} +trackSchedule.nowPlaying=Now playing: **{0}** {1} +#File utils +fileutil.fileCreateError=Unable to create file. {0} +fileutil.writeError=Unable to write to file. {0} +#Playlist strings +playlist.empty=There are no songs in this playlist. +