Version 1.4.0 merge from development. #6
|
@ -1,4 +1,3 @@
|
|||
!.jar
|
||||
.idea/
|
||||
modules/
|
||||
src/test/
|
||||
|
|
27
README.md
27
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 <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.
|
||||
* **`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.
|
||||
* **`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 <PLAYLIST>` - The queue will be saved as a playlist with the given name.
|
||||
* **`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.
|
||||
* `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 <create|show|play|delete|add|remove|rename>` - 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 <create|show|play|delete|add|remove|rename|move>`** - Various commands to manipulate playlists. The specific sub-commands are explained below.
|
||||
* `create <PLAYLIST> [URL]...` - Creates a new playlist, optionally with some starting URLs.
|
||||
|
||||
* `delete <PLAYLIST>` - 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 <PLAYLIST> <SONGNUMBER> <NEWNUMBER>` - Moves a song from one index to another index, shifting other elements as necessary.
|
||||
|
||||
### Miscellaneous
|
||||
|
||||
* `tengwar <to|from> <TEXT>` - 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 <TEXT>` - Translates some text to tengwar, and responds with both the raw, UTF-8 string, and an image generated using a Tengwar font.
|
||||
|
||||
* `from <TEXT>` - Translates some tengwar text to normal, human readable text.
|
4
pom.xml
4
pom.xml
|
@ -6,7 +6,7 @@
|
|||
|
||||
<groupId>com.github.andrewlalis</groupId>
|
||||
<artifactId>HandieBot</artifactId>
|
||||
<version>1.3.1</version>
|
||||
<version>1.4.0</version>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
|
@ -70,7 +70,7 @@
|
|||
<dependency>
|
||||
<groupId>com.github.andrewlalis</groupId>
|
||||
<artifactId>TengwarTranslatorLibrary</artifactId>
|
||||
<version>1.2</version>
|
||||
<version>1.3</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
|
|
@ -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<Permissions> requiredPermissions = new ArrayList<>();
|
||||
requiredPermissions.add(Permissions.CHANGE_NICKNAME);
|
||||
|
@ -87,13 +84,13 @@ public class HandieBot {
|
|||
|
||||
musicPlayer = new MusicPlayer();
|
||||
|
||||
if (args.length >= 1) {
|
||||
if (args[0].equalsIgnoreCase("-nogui")){
|
||||
List<String> 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){
|
||||
window = new BotWindow();
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -25,7 +25,7 @@ import static handiebot.HandieBot.resourceBundle;
|
|||
*/
|
||||
public class Commands {
|
||||
|
||||
public static List<Command> commands = new ArrayList<Command>();
|
||||
public static List<Command> commands = new ArrayList<>();
|
||||
|
||||
static {
|
||||
//Music commands.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -175,6 +175,7 @@ public class MusicPlayer {
|
|||
public void showQueueList(IGuild guild, boolean showAll) {
|
||||
List<UnloadedTrack> 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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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<UnloadedTrack> tracks;
|
||||
|
@ -186,7 +187,7 @@ public class Playlist {
|
|||
*/
|
||||
public static List<String> getAvailablePlaylists(){
|
||||
File playlistFolder = new File(System.getProperty("user.home")+"/.handiebot/playlist");
|
||||
List<String> names = new ArrayList<String>(Arrays.asList(playlistFolder.list()));
|
||||
@SuppressWarnings("ConstantConditions") List<String> 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");
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue