made all send messages safe with request buffers, and externalized the token for extra security.

This commit is contained in:
Andrew Lalis 2017-07-12 15:25:25 +02:00 committed by Andrew Lalis
parent fde75385bd
commit a55bb49f1c
19 changed files with 183 additions and 95 deletions

View File

@ -6,7 +6,7 @@
<groupId>com.github.andrewlalis</groupId>
<artifactId>HandieBot</artifactId>
<version>1.4.1</version>
<version>1.5.0</version>
<build>
<plugins>
<plugin>

View File

@ -3,7 +3,7 @@ package handiebot;
import handiebot.command.CommandHandler;
import handiebot.command.ReactionHandler;
import handiebot.lavaplayer.MusicPlayer;
import handiebot.utils.YoutubeSearch;
import handiebot.utils.FileUtil;
import handiebot.view.BotLog;
import handiebot.view.BotWindow;
import sx.blah.discord.api.ClientBuilder;
@ -17,6 +17,9 @@ import sx.blah.discord.handle.obj.Permissions;
import sx.blah.discord.util.DiscordException;
import sx.blah.discord.util.RateLimitException;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.*;
/**
@ -28,7 +31,14 @@ import java.util.*;
public class HandieBot {
public static final String APPLICATION_NAME = "HandieBot";
private static final String TOKEN = "MjgzNjUyOTg5MjEyNjg4Mzg0.C45A_Q.506b0G6my1FEFa7_YY39lxLBHUY";
private static final String TOKEN;
static {
TOKEN = readToken();
if (TOKEN.isEmpty()){
System.out.println("You do not have the token required to start the bot. Shutting down.");
System.exit(-1);
}
}
private static boolean USE_GUI = true;
public static final ResourceBundle resourceBundle = ResourceBundle.getBundle("Strings");
@ -102,7 +112,6 @@ public class HandieBot {
client = new ClientBuilder().withToken(TOKEN).build();
client.getDispatcher().registerListener(new HandieBot());
client.login();
YoutubeSearch.query("two steps from hell");
}
/**
@ -115,6 +124,21 @@ public class HandieBot {
return channel.getModifiedPermissions(client.getOurUser()).contains(permission);
}
/**
* Reads the private discord token necessary to start the bot. If this fails, the bot will shut down.
* @return The string token needed to log in.
*/
private static String readToken(){
String path = FileUtil.getDataDirectory()+"token.txt";
String result = "";
try(BufferedReader reader = new BufferedReader(new FileReader(path))){
result = reader.readLine();
} catch (IOException e) {
System.err.println("IOException while trying to read token. "+e.getMessage());
}
return result;
}
/**
* Safely shuts down the bot on all guilds.
*/

View File

@ -18,6 +18,7 @@ import java.util.List;
import static handiebot.HandieBot.log;
import static handiebot.HandieBot.resourceBundle;
import static handiebot.utils.MessageUtils.sendMessage;
/**
* @author Andrew Lalis
@ -59,7 +60,7 @@ public class Commands {
return;
} else if (!cmd.canUserExecute(context.getUser(), context.getGuild())){
log.log(BotLog.TYPE.COMMAND, context.getGuild(), MessageFormat.format(resourceBundle.getString("commands.noPermission.log"), context.getUser().getName(), cmd.getName()));
context.getChannel().sendMessage(MessageFormat.format(resourceBundle.getString("commands.noPermission.message"), command));
sendMessage(MessageFormat.format(resourceBundle.getString("commands.noPermission.message"), command), context.getChannel());
return;
} else if (cmd instanceof ContextCommand){
log.log(BotLog.TYPE.COMMAND, context.getGuild(), context.getUser().getName()+" has issued the command: "+command);
@ -101,7 +102,7 @@ public class Commands {
(context.getUser().getLongID() == 235439851263098880L) ||
(permission == 0);
if (!result){
context.getChannel().sendMessage(resourceBundle.getString("commands.noPermission.subcommand"));
sendMessage(resourceBundle.getString("commands.noPermission.subcommand"), context.getChannel());
}
return result;
}

View File

@ -9,6 +9,7 @@ import java.text.MessageFormat;
import static handiebot.HandieBot.log;
import static handiebot.HandieBot.resourceBundle;
import static handiebot.utils.MessageUtils.sendMessage;
/**
* @author Andrew Lalis
@ -29,10 +30,10 @@ public class SetPrefixCommand extends ContextCommand {
CommandHandler.PREFIXES.put(context.getGuild(), context.getArgs()[0]);
CommandHandler.saveGuildPrefixes();
String response = MessageFormat.format(resourceBundle.getString("commands.command.setPrefix.changed"), context.getArgs()[0]);
context.getChannel().sendMessage(response);
sendMessage(response, context.getChannel());
log.log(BotLog.TYPE.INFO, response);
} else {
context.getChannel().sendMessage(resourceBundle.getString("commands.command.setPrefix.noPrefixError"));
sendMessage(resourceBundle.getString("commands.command.setPrefix.noPrefixError"), context.getChannel());
}
}
}

View File

@ -2,12 +2,14 @@ package handiebot.command.commands.misc;
import handiebot.command.CommandContext;
import handiebot.command.types.ContextCommand;
import handiebot.utils.MessageUtils;
import net.agspace.TengwarImageGenerator;
import net.agspace.Translator;
import java.io.FileNotFoundException;
import static handiebot.HandieBot.resourceBundle;
import static handiebot.utils.MessageUtils.sendMessage;
/**
* @author Andrew Lalis
@ -24,12 +26,13 @@ public class TengwarCommand extends ContextCommand {
@Override
public void execute(CommandContext context) {
if (context.getArgs().length == 0){
context.getChannel().sendMessage(this.getUsage(context.getGuild()));
sendMessage(this.getUsage(context.getGuild()), context.getChannel());
} else if (context.getArgs().length >= 2){
String input = readTextFromArgs(context.getArgs());
String input = MessageUtils.getTextFromArgs(context.getArgs(), 1);
if (context.getArgs()[0].equalsIgnoreCase("to")){
String result = Translator.translateToTengwar(input);
try {
//TODO: replace with rate-limited send method.
context.getChannel().sendFile("Raw text: `" +result+'`', TengwarImageGenerator.generateImage(result,
600,
24f,
@ -40,18 +43,11 @@ public class TengwarCommand extends ContextCommand {
e.printStackTrace();
}
} else if (context.getArgs()[0].equalsIgnoreCase("from")){
context.getChannel().sendMessage(Translator.translateToEnglish(input));
sendMessage(Translator.translateToEnglish(input), context.getChannel());
}
} else {
context.getChannel().sendMessage(this.getUsage(context.getGuild()));
sendMessage(this.getUsage(context.getGuild()), context.getChannel());
}
}
private String readTextFromArgs(String[] args){
StringBuilder sb = new StringBuilder();
for (int i = 1; i < args.length; i++){
sb.append(args[i]).append(' ');
}
return sb.toString().trim();
}
}

View File

@ -7,6 +7,7 @@ import handiebot.command.ReactionHandler;
import handiebot.command.reactionListeners.YoutubePlayListener;
import handiebot.command.types.ContextCommand;
import handiebot.lavaplayer.playlist.UnloadedTrack;
import handiebot.utils.MessageUtils;
import handiebot.utils.YoutubeSearch;
import sx.blah.discord.handle.obj.IMessage;
@ -15,6 +16,7 @@ import java.util.ArrayList;
import java.util.List;
import static handiebot.HandieBot.resourceBundle;
import static handiebot.utils.MessageUtils.sendMessage;
import static handiebot.utils.YoutubeSearch.WATCH_URL;
/**
@ -40,16 +42,12 @@ public class PlayCommand extends ContextCommand {
try {
HandieBot.musicPlayer.addToQueue(context.getGuild(), new UnloadedTrack(context.getArgs()[0]), context.getUser());
} catch (Exception e) {
context.getChannel().sendMessage(MessageFormat.format(resourceBundle.getString("commands.command.play.songAddError"), context.getArgs()[0]));
sendMessage(MessageFormat.format(resourceBundle.getString("commands.command.play.songAddError"), context.getArgs()[0]), context.getChannel());
e.printStackTrace();
}
} else {
//Construct a Youtube song choice.
StringBuilder sb = new StringBuilder();
for (int i = 0; i < context.getArgs().length; i++){
sb.append(context.getArgs()[i]).append(' ');
}
List<Video> videos = YoutubeSearch.query(sb.toString().trim());
List<Video> videos = YoutubeSearch.query(MessageUtils.getTextFromArgs(context.getArgs(), 0));
if (videos != null) {
List<String> urls = new ArrayList<>(videos.size());
videos.forEach((video) -> urls.add(WATCH_URL+video.getId()));

View File

@ -14,7 +14,6 @@ import handiebot.utils.YoutubeSearch;
import handiebot.view.BotLog;
import sx.blah.discord.handle.obj.IChannel;
import sx.blah.discord.handle.obj.IMessage;
import sx.blah.discord.util.RequestBuffer;
import java.io.File;
import java.text.MessageFormat;
@ -23,6 +22,7 @@ import java.util.List;
import static handiebot.HandieBot.log;
import static handiebot.HandieBot.resourceBundle;
import static handiebot.utils.MessageUtils.sendMessage;
import static handiebot.utils.YoutubeSearch.WATCH_URL;
/**
@ -89,7 +89,7 @@ public class PlaylistCommand extends ContextCommand {
* @param channel The channel to show the error message in.
*/
private void incorrectMainArg(IChannel channel){
IMessage message = channel.sendMessage(MessageFormat.format(resourceBundle.getString("commands.command.playlist.error.incorrectMainArg"), this.getUsage(channel.getGuild())));
IMessage message = sendMessage(MessageFormat.format(resourceBundle.getString("commands.command.playlist.error.incorrectMainArg"), this.getUsage(channel.getGuild())), channel);
MessageUtils.deleteMessageAfter(5000, message);
}
@ -107,9 +107,9 @@ public class PlaylistCommand extends ContextCommand {
}
playlist.save();
log.log(BotLog.TYPE.INFO, MessageFormat.format(resourceBundle.getString("commands.command.playlist.createdPlaylist.log"), playlist.getName(), playlist.getTrackCount()));
context.getChannel().sendMessage(MessageFormat.format(resourceBundle.getString("commands.command.playlist.createdPlaylist.message"), playlist.getName(), this.getPrefixedName(context.getGuild()), playlist.getName()));
sendMessage(MessageFormat.format(resourceBundle.getString("commands.command.playlist.createdPlaylist.message"), playlist.getName(), this.getPrefixedName(context.getGuild()), playlist.getName()), context.getChannel());
} else {
context.getChannel().sendMessage(resourceBundle.getString("commands.command.playlist.error.createPlaylistName"));
sendMessage(resourceBundle.getString("commands.command.playlist.error.createPlaylistName"), context.getChannel());
}
}
@ -125,13 +125,13 @@ public class PlaylistCommand extends ContextCommand {
boolean success = f.delete();
if (success){
log.log(BotLog.TYPE.INFO, MessageFormat.format(resourceBundle.getString("commands.command.playlist.delete.log"), context.getArgs()[1]));
context.getChannel().sendMessage(MessageFormat.format(resourceBundle.getString("commands.command.playlist.delete.message"), context.getArgs()[1]));
sendMessage(MessageFormat.format(resourceBundle.getString("commands.command.playlist.delete.message"), context.getArgs()[1]), context.getChannel());
} else {
log.log(BotLog.TYPE.ERROR, MessageFormat.format(resourceBundle.getString("commands.command.playlist.error.delete.log"), context.getArgs()[1]));
context.getChannel().sendMessage(resourceBundle.getString("commands.command.playlist.error.delete.message"));
sendMessage(resourceBundle.getString("commands.command.playlist.error.delete.message"), context.getChannel());
}
} else {
context.getChannel().sendMessage(resourceBundle.getString("commands.command.playlist.error.deletePlaylistName"));
sendMessage(resourceBundle.getString("commands.command.playlist.error.deletePlaylistName"), context.getChannel());
}
}
@ -145,14 +145,14 @@ public class PlaylistCommand extends ContextCommand {
return;
Playlist playlist = new Playlist(context.getArgs()[1]);
playlist.load();
context.getChannel().sendMessage(playlist.toString());
sendMessage(playlist.toString(), context.getChannel());
} else {
List<String> playlists = Playlist.getAvailablePlaylists();
StringBuilder sb = new StringBuilder("**Playlists:**\n");
for (String playlist : playlists) {
sb.append(playlist).append('\n');
}
context.getChannel().sendMessage(sb.toString());
sendMessage(sb.toString(), context.getChannel());
}
}
@ -170,18 +170,14 @@ public class PlaylistCommand extends ContextCommand {
//These are songs, so add them immediately.
for (int i = 2; i < context.getArgs().length; i++){
playlist.loadTrack(context.getArgs()[i]);
RequestBuffer.request(() -> context.getChannel().sendMessage(MessageFormat.format(resourceBundle.getString("commands.command.playlist.add.message"), playlist.getName()))).get();
sendMessage(MessageFormat.format(resourceBundle.getString("commands.command.playlist.add.message"), playlist.getName()), context.getChannel());
}
playlist.save();
context.getChannel().sendMessage(playlist.toString());
sendMessage(playlist.toString(), context.getChannel());
log.log(BotLog.TYPE.INFO, MessageFormat.format(resourceBundle.getString("commands.command.playlist.add.log"), playlist.getName()));
} else {
//This is a youtube search query.
StringBuilder sb = new StringBuilder();
for (int i = 2; i < context.getArgs().length; i++){
sb.append(context.getArgs()[i]).append(' ');
}
List<Video> videos = YoutubeSearch.query(sb.toString().trim());
List<Video> videos = YoutubeSearch.query(MessageUtils.getTextFromArgs(context.getArgs(), 2));
if (videos != null) {
List<String> urls = new ArrayList<>(videos.size());
videos.forEach((video) -> urls.add(WATCH_URL+video.getId()));
@ -191,9 +187,9 @@ public class PlaylistCommand extends ContextCommand {
}
} else {
if (context.getArgs().length == 1){
context.getChannel().sendMessage(MessageFormat.format(resourceBundle.getString("commands.command.playlist.error.addNameNeeded"), getPlaylistShowString(context)));
sendMessage(MessageFormat.format(resourceBundle.getString("commands.command.playlist.error.addNameNeeded"), getPlaylistShowString(context)), context.getChannel());
} else {
context.getChannel().sendMessage(resourceBundle.getString("commands.command.playlist.error.addUrlNeeded"));
sendMessage(resourceBundle.getString("commands.command.playlist.error.addUrlNeeded"), context.getChannel());
}
}
}
@ -209,11 +205,11 @@ public class PlaylistCommand extends ContextCommand {
Playlist playlist = new Playlist(context.getArgs()[1]);
playlist.load();
log.log(BotLog.TYPE.INFO, MessageFormat.format(resourceBundle.getString("commands.command.playlist.play.log"), playlist.getName()));
context.getChannel().sendMessage(MessageFormat.format(resourceBundle.getString("commands.command.playlist.play.message"), playlist.getName()));
sendMessage(MessageFormat.format(resourceBundle.getString("commands.command.playlist.play.message"), playlist.getName()), context.getChannel());
HandieBot.musicPlayer.getMusicManager(context.getGuild()).scheduler.setPlaylist(playlist);
HandieBot.musicPlayer.getMusicManager(context.getGuild()).scheduler.nextTrack();
} else {
context.getChannel().sendMessage(MessageFormat.format(resourceBundle.getString("commands.command.playlist.error.playPlaylistNeeded"), getPlaylistShowString(context)));
sendMessage(MessageFormat.format(resourceBundle.getString("commands.command.playlist.error.playPlaylistNeeded"), getPlaylistShowString(context)), context.getChannel());
}
}
@ -228,15 +224,15 @@ public class PlaylistCommand extends ContextCommand {
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"));
if (success){
context.getChannel().sendMessage(MessageFormat.format(resourceBundle.getString("commands.command.playlist.rename.message"), context.getArgs()[1], context.getArgs()[2]));
sendMessage(MessageFormat.format(resourceBundle.getString("commands.command.playlist.rename.message"), context.getArgs()[1], context.getArgs()[2]), context.getChannel());
log.log(BotLog.TYPE.INFO, MessageFormat.format(resourceBundle.getString("commands.command.playlist.rename.log"), context.getArgs()[1], context.getArgs()[2]));
} else {
String response = MessageFormat.format(resourceBundle.getString("commands.command.playlist.error.renameError"), context.getArgs()[1], context.getArgs()[2]);
context.getChannel().sendMessage(response);
sendMessage(response, context.getChannel());
log.log(BotLog.TYPE.ERROR, response);
}
} else {
context.getChannel().sendMessage(resourceBundle.getString("commands.command.playlist.error.renameBadArgs"));
sendMessage(resourceBundle.getString("commands.command.playlist.error.renameBadArgs"), context.getChannel());
}
}
@ -255,17 +251,17 @@ public class PlaylistCommand extends ContextCommand {
UnloadedTrack track = playlist.getTracks().get(index);
playlist.removeTrack(track);
playlist.save();
context.getChannel().sendMessage(MessageFormat.format(resourceBundle.getString("commands.command.playlist.remove.message"), track.getTitle(), playlist.getName()));
sendMessage(MessageFormat.format(resourceBundle.getString("commands.command.playlist.remove.message"), track.getTitle(), playlist.getName()), context.getChannel());
log.log(BotLog.TYPE.MUSIC, MessageFormat.format(resourceBundle.getString("commands.command.playlist.remove.log"), track.getTitle(), playlist.getName()));
} catch (IndexOutOfBoundsException | NumberFormatException e){
String response = MessageFormat.format(resourceBundle.getString("commands.command.playlist.error.removeError"), playlist.getName());
context.getChannel().sendMessage(response);
sendMessage(response, context.getChannel());
log.log(BotLog.TYPE.ERROR, response);
e.printStackTrace();
}
} else {
context.getChannel().sendMessage(resourceBundle.getString("commands.command.playlist.error.removeBadArgs"));
sendMessage(resourceBundle.getString("commands.command.playlist.error.removeBadArgs"), context.getChannel());
}
}
@ -285,7 +281,7 @@ public class PlaylistCommand extends ContextCommand {
oldIndex = Integer.parseInt(context.getArgs()[2])-1;
newIndex = Integer.parseInt(context.getArgs()[3])-1;
} catch (NumberFormatException e){
context.getChannel().sendMessage(resourceBundle.getString("commands.command.playlist.error.moveIndexError"));
sendMessage(resourceBundle.getString("commands.command.playlist.error.moveIndexError"), context.getChannel());
}
UnloadedTrack track;
if ((oldIndex > -1 && oldIndex < playlist.getTrackCount()) &&
@ -293,13 +289,13 @@ public class PlaylistCommand extends ContextCommand {
track = playlist.getTracks().remove(oldIndex);
playlist.getTracks().add(newIndex, track);
playlist.save();
context.getChannel().sendMessage(MessageFormat.format(resourceBundle.getString("commands.command.playlist.move.message"), track.getTitle(), oldIndex + 1, newIndex + 1));
sendMessage(MessageFormat.format(resourceBundle.getString("commands.command.playlist.move.message"), track.getTitle(), oldIndex + 1, newIndex + 1), context.getChannel());
log.log(BotLog.TYPE.MUSIC, MessageFormat.format(resourceBundle.getString("commands.command.playlist.move.log"), track.getTitle(), oldIndex + 1, newIndex + 1));
} else {
context.getChannel().sendMessage(MessageFormat.format(resourceBundle.getString("commands.command.playlist.error.moveInvalidIndex"), oldIndex, newIndex));
sendMessage(MessageFormat.format(resourceBundle.getString("commands.command.playlist.error.moveInvalidIndex"), oldIndex, newIndex), context.getChannel());
}
} else {
context.getChannel().sendMessage(resourceBundle.getString("commands.command.playlist.error.moveBadArgs"));
sendMessage(resourceBundle.getString("commands.command.playlist.error.moveBadArgs"), context.getChannel());
}
}
@ -313,7 +309,7 @@ public class PlaylistCommand extends ContextCommand {
if (Playlist.playlistExists(context.getArgs()[1])){
return true;
} else {
IMessage message = context.getChannel().sendMessage(MessageFormat.format(resourceBundle.getString("commands.command.playlist.error.playlistDoesNotExist"), getPlaylistShowString(context)));
IMessage message = sendMessage(MessageFormat.format(resourceBundle.getString("commands.command.playlist.error.playlistDoesNotExist"), getPlaylistShowString(context)), context.getChannel());
MessageUtils.deleteMessageAfter(3000, message);
return false;
}

View File

@ -11,6 +11,7 @@ import java.text.MessageFormat;
import static handiebot.HandieBot.log;
import static handiebot.HandieBot.resourceBundle;
import static handiebot.utils.MessageUtils.sendMessage;
/**
* @author Andrew Lalis
@ -42,11 +43,12 @@ public class QueueCommand extends ContextCommand {
}
break;
case ("save"):
//TODO: add some error messages so users know how to use this.
if (context.getArgs().length == 2 && Commands.hasPermission(context, 8)) {
Playlist p = HandieBot.musicPlayer.getAllSongsInQueue(context.getGuild());
p.setName(context.getArgs()[1]);
p.save();
context.getChannel().sendMessage(MessageFormat.format(resourceBundle.getString("commands.command.queue.save.message"), p.getTrackCount(), p.getName()));
sendMessage(MessageFormat.format(resourceBundle.getString("commands.command.queue.save.message"), p.getTrackCount(), p.getName()), context.getChannel());
log.log(BotLog.TYPE.INFO, MessageFormat.format(resourceBundle.getString("commands.command.queue.save.log"), p.getName()));
}
break;

View File

@ -8,6 +8,7 @@ import handiebot.command.types.ContextCommand;
import java.text.MessageFormat;
import static handiebot.HandieBot.resourceBundle;
import static handiebot.utils.MessageUtils.sendMessage;
/**
* @author Andrew Lalis
@ -28,7 +29,7 @@ public class RepeatCommand extends ContextCommand {
boolean shouldRepeat = (context.getArgs()[0].toLowerCase().equals("true"));
HandieBot.musicPlayer.setRepeat(context.getGuild(), shouldRepeat);
} else {
context.getChannel().sendMessage(MessageFormat.format(resourceBundle.getString("player.getRepeat"), HandieBot.musicPlayer.isRepeating(context.getGuild())));
sendMessage(MessageFormat.format(resourceBundle.getString("player.getRepeat"), HandieBot.musicPlayer.isRepeating(context.getGuild())), context.getChannel());
}
}
}

View File

@ -8,6 +8,7 @@ import handiebot.command.types.ContextCommand;
import java.text.MessageFormat;
import static handiebot.HandieBot.resourceBundle;
import static handiebot.utils.MessageUtils.sendMessage;
/**
* @author Andrew Lalis
@ -28,7 +29,7 @@ public class ShuffleCommand extends ContextCommand {
boolean shouldShuffle = (context.getArgs()[0].toLowerCase().equals("true"));
HandieBot.musicPlayer.setShuffle(context.getGuild(), shouldShuffle);
} else {
context.getChannel().sendMessage(MessageFormat.format(resourceBundle.getString("player.getShuffle"), HandieBot.musicPlayer.isShuffling(context.getGuild())));
sendMessage(MessageFormat.format(resourceBundle.getString("player.getShuffle"), HandieBot.musicPlayer.isShuffling(context.getGuild())), context.getChannel());
}
}
}

View File

@ -7,6 +7,7 @@ import handiebot.command.types.ContextCommand;
import sx.blah.discord.handle.obj.IPrivateChannel;
import static handiebot.HandieBot.resourceBundle;
import static handiebot.utils.MessageUtils.sendMessage;
/**
* @author Andrew Lalis
@ -24,7 +25,6 @@ public class HelpCommand extends ContextCommand {
@Override
public void execute(CommandContext context) {
IPrivateChannel pm = context.getUser().getOrCreatePMChannel();
StringBuilder sb = new StringBuilder("HandieBot Commands:\n");
for (Command cmd : Commands.commands){
StringBuilder commandText = new StringBuilder();
@ -36,13 +36,12 @@ public class HelpCommand extends ContextCommand {
}
commandText.append("`\n").append(cmd.getDescription()).append("\n\n");
if (sb.length() + commandText.length() > 2000){
pm.sendMessage(sb.toString());
sendMessage(sb.toString(), pm);
sb = commandText;
} else {
sb.append(commandText);
}
}
pm.sendMessage(sb.toString());
sendMessage(sb.toString(), pm);
}
}

View File

@ -20,11 +20,12 @@ import static java.lang.Thread.sleep;
*/
public abstract class YoutubeChoiceListener implements ReactionListener {
protected final IMessage message;
protected final IUser user;
protected final List<String> urls;
protected final IMessage message;//The message generated that this listener should attach to.
protected final IUser user;//The user who needs to make a decision.
protected final List<String> urls;//The list of URLs to display information about.
protected static final long timeout = 30000;//Time until the choice times out and deletes itself.
//These are just the raw characters for the numbers 1 - 5.
private static final String[] choices = {
"1⃣",
"2⃣",

View File

@ -15,7 +15,7 @@ import static handiebot.HandieBot.log;
* Specific Listener for choices in the Play command, where songs chosen are added to the active queue.
*/
public class YoutubePlayListener extends YoutubeChoiceListener {
//TODO: Externalize strings
public YoutubePlayListener(IMessage message, IUser user, List<String> urls) {
super(message, user, urls);
}

View File

@ -1,18 +1,19 @@
package handiebot.command.reactionListeners;
import handiebot.lavaplayer.playlist.Playlist;
import handiebot.utils.MessageUtils;
import sx.blah.discord.handle.obj.IMessage;
import sx.blah.discord.handle.obj.IUser;
import java.util.List;
import static handiebot.utils.MessageUtils.sendMessage;
/**
* @author Andrew Lalis
* Specific Listener for adding songs to a playlist that must be saved.
*/
public class YoutubePlaylistAddListener extends YoutubeChoiceListener {
//TODO: externalize strings
private Playlist playlist;
public YoutubePlaylistAddListener(IMessage message, IUser user, List<String> urls, Playlist playlist) {
@ -24,6 +25,6 @@ public class YoutubePlaylistAddListener extends YoutubeChoiceListener {
protected void onChoice(int choice) {
this.playlist.loadTrack(this.urls.get(choice));
this.playlist.save();
MessageUtils.sendMessage("Added song to *"+this.playlist.getName()+"*.", message.getChannel());
sendMessage("Added song to *"+this.playlist.getName()+"*.", message.getChannel());
}
}

View File

@ -0,0 +1,5 @@
/**
* @author Andrew Lalis
* Package for listeners of reactions, such as in-text menus.
*/
package handiebot.command.reactionListeners;

View File

@ -20,6 +20,7 @@ import java.util.concurrent.TimeUnit;
import static handiebot.HandieBot.log;
import static handiebot.HandieBot.resourceBundle;
import static handiebot.utils.MessageUtils.sendMessage;
/**
* @author Andrew Lalis
@ -125,7 +126,7 @@ public class MusicPlayer {
getMusicManager(guild).scheduler.setRepeat(value);
String message = MessageFormat.format(resourceBundle.getString("player.setRepeat"), getMusicManager(guild).scheduler.isRepeating());
log.log(BotLog.TYPE.MUSIC, guild, message);
getChatChannel(guild).sendMessage(":repeat: "+message);
sendMessage(":repeat: "+message, getChatChannel(guild));
}
/**
@ -154,7 +155,7 @@ public class MusicPlayer {
getMusicManager(guild).scheduler.setShuffle(value);
String message = MessageFormat.format(resourceBundle.getString("player.setShuffle"), getMusicManager(guild).scheduler.isShuffling());
log.log(BotLog.TYPE.MUSIC, guild, message);
getChatChannel(guild).sendMessage(":twisted_rightwards_arrows: "+message);
sendMessage(":twisted_rightwards_arrows: "+message, getChatChannel(guild));
}
/**
@ -173,14 +174,14 @@ public class MusicPlayer {
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()));
sendMessage(MessageFormat.format(resourceBundle.getString("player.queueEmpty"), Commands.get("play").getUsage()), getChatChannel(guild));
} else {
if (tracks.size() > 10 && showAll) {
String result = Pastebin.paste("Current queue for discord server: "+guild.getName()+".", getMusicManager(guild).scheduler.getActivePlaylist().toString());
if (result != null && result.startsWith("https://pastebin.com/")){
log.log(BotLog.TYPE.INFO, guild, MessageFormat.format(resourceBundle.getString("player.queueUploaded"), result));
//Only display the pastebin link for 10 minutes.
IMessage message = getChatChannel(guild).sendMessage(MessageFormat.format(resourceBundle.getString("player.pastebinLink"), result));
IMessage message = sendMessage(MessageFormat.format(resourceBundle.getString("player.pastebinLink"), result), getChatChannel(guild));
MessageUtils.deleteMessageAfter(600000, message);
} else {
log.log(BotLog.TYPE.ERROR, guild, MessageFormat.format(resourceBundle.getString("player.pastebinError"), result));
@ -224,7 +225,7 @@ public class MusicPlayer {
));
}
if (sb.length() > 0) {
getChatChannel(guild).sendMessage(sb.toString());
sendMessage(sb.toString(), getChatChannel(guild));
}
}
@ -232,10 +233,11 @@ public class MusicPlayer {
/**
* If possible, try to begin playing from the track scheduler's queue.
* @param guild The guild to play music on.
*/
public void playQueue(IGuild guild){
if (getMusicManager(guild).scheduler.getActivePlaylist().getTrackCount() == 0){
getChatChannel(guild).sendMessage(resourceBundle.getString("player.playQueueEmpty"));
sendMessage(resourceBundle.getString("player.playQueueEmpty"), getChatChannel(guild));
return;
}
IVoiceChannel vc = this.getVoiceChannel(guild);
@ -245,18 +247,23 @@ public class MusicPlayer {
getMusicManager(guild).scheduler.nextTrack();
}
/**
* Clears the queue for a specified guild.
* @param guild The guild to clear the queue for.
*/
public void clearQueue(IGuild guild){
getMusicManager(guild).scheduler.clearQueue();
getChatChannel(guild).sendMessage(resourceBundle.getString("player.queueCleared"));
sendMessage(resourceBundle.getString("player.queueCleared"), getChatChannel(guild));
}
/**
* Skips the current track.
* @param guild The guild to skip the track for.
*/
public void skipTrack(IGuild guild){
String message = resourceBundle.getString("player.skippingCurrent");
log.log(BotLog.TYPE.MUSIC, guild, message);
getChatChannel(guild).sendMessage(":track_next: "+message);
sendMessage(":track_next: "+message, getChatChannel(guild));
getMusicManager(guild).scheduler.nextTrack();
}
@ -267,7 +274,7 @@ public class MusicPlayer {
public void stop(IGuild guild){
getMusicManager(guild).scheduler.stop();
String message = resourceBundle.getString("player.musicStopped");
getChatChannel(guild).sendMessage(":stop_button: "+message);
sendMessage(":stop_button: "+message, getChatChannel(guild));
log.log(BotLog.TYPE.MUSIC, guild, message);
}

View File

@ -15,13 +15,14 @@ import sx.blah.discord.handle.obj.IChannel;
import sx.blah.discord.handle.obj.IGuild;
import sx.blah.discord.handle.obj.IMessage;
import sx.blah.discord.handle.obj.IVoiceChannel;
import sx.blah.discord.util.RequestBuffer;
import java.text.MessageFormat;
import java.util.List;
import static handiebot.HandieBot.log;
import static handiebot.HandieBot.resourceBundle;
import static handiebot.utils.MessageUtils.addReaction;
import static handiebot.utils.MessageUtils.sendMessage;
/**
* @author Andrew Lalis
@ -192,9 +193,9 @@ public class TrackScheduler extends AudioEventAdapter {
log.log(BotLog.TYPE.MUSIC, this.guild, MessageFormat.format(resourceBundle.getString("trackSchedule.trackStarted"), track.getInfo().title));
List<IChannel> channels = this.guild.getChannelsByName(MusicPlayer.CHANNEL_NAME.toLowerCase());
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()));
RequestBuffer.request(() -> message.addReaction(":thumbsup:")).get();
RequestBuffer.request(() -> message.addReaction(":thumbsdown:")).get();
IMessage message = sendMessage(MessageFormat.format(":arrow_forward: "+resourceBundle.getString("trackSchedule.nowPlaying"), track.getInfo().title, new UnloadedTrack(track).getFormattedDuration()), channels.get(0));
addReaction(message, ":thumbsup:");
addReaction(message, ":thumbsdown:");
ReactionHandler.addListener(new DownvoteListener(message));
}
}

View File

@ -8,17 +8,21 @@ import sx.blah.discord.handle.obj.IMessage;
import sx.blah.discord.handle.obj.Permissions;
import sx.blah.discord.util.RequestBuffer;
import java.io.File;
import java.io.FileNotFoundException;
import static handiebot.HandieBot.log;
import static handiebot.HandieBot.resourceBundle;
import static java.lang.Thread.sleep;
/**
* @author Andrew Lalis
* Creates a message on a channel that will disappear after some time.
*/
public class MessageUtils extends Thread implements Runnable {
public class MessageUtils {
private MessageUtils(){}
//TODO: Replace all 'sendMessage' calls with the new rate-limited calls.
/**
* Sends a message to a channel safely, using a request buffer.
* @param content The string content of the message.
@ -39,6 +43,33 @@ public class MessageUtils extends Thread implements Runnable {
return RequestBuffer.request(() -> (IMessage)channel.sendMessage(embed)).get();
}
/**
* Sends a file object to a channel safely, using a request buffer.
* @param file The file to send.
* @param channel The channel to send the message on.
* @return The message that was sent, or null if the file could not be found.
*/
public static IMessage sendFile(File file, IChannel channel){
return RequestBuffer.request(() -> {
IMessage msg = null;
try {
msg = channel.sendFile(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return msg;
}).get();
}
/**
* Adds a reaction to a message safely, using the request buffer.
* @param message The message to add a reaction to.
* @param reaction The reaction to add, in string format.
*/
public static void addReaction(IMessage message, String reaction){
RequestBuffer.request(() -> message.addReaction(reaction)).get();
}
/**
* Deletes a message after a set amount of time.
* @param timeout The delay until deletion, in milliseconds.
@ -88,6 +119,11 @@ public class MessageUtils extends Thread implements Runnable {
return sb.toString();
}
/**
* Gets the 'emoji' for a specific digit. If the digit given is not one digit, zero is used.
* @param digit The digit to convert.
* @return A String representation of the emoji.
*/
private static String getDigitEmoji(int digit){
switch (digit){
case 1:
@ -113,4 +149,22 @@ public class MessageUtils extends Thread implements Runnable {
}
}
/**
* Generates a space-separated list of words from a given index until the end of an arguments list.
* @param args The args list, as it is given from a command context.
* @param firstWordIndex The index of the first word to read as text.
* @return A string of all the words combined, with spaces between each one, just as they would appear in the
* user's actual input string.
*/
public static String getTextFromArgs(String[] args, int firstWordIndex){
StringBuilder sb = new StringBuilder();
for (int i = firstWordIndex; i < args.length; i++){
sb.append(args[i]);
if (i < args.length-1){
sb.append(' ');
}
}
return sb.toString();
}
}

View File

@ -22,7 +22,6 @@ import sx.blah.discord.api.internal.json.objects.EmbedObject;
import sx.blah.discord.handle.obj.IChannel;
import sx.blah.discord.handle.obj.IMessage;
import sx.blah.discord.util.EmbedBuilder;
import sx.blah.discord.util.RequestBuffer;
import java.awt.*;
import java.io.File;
@ -37,6 +36,8 @@ import java.util.List;
import java.util.Locale;
import static handiebot.HandieBot.APPLICATION_NAME;
import static handiebot.utils.MessageUtils.addReaction;
import static handiebot.utils.MessageUtils.sendMessage;
/**
* @author Andrew Lalis
@ -84,8 +85,7 @@ public class YoutubeSearch {
.setDataStoreFactory(DATA_STORE_FACTORY)
.setAccessType("offline")
.build();
Credential credential = new AuthorizationCodeInstalledApp(flow, new LocalServerReceiver()).authorize("user");
return credential;
return new AuthorizationCodeInstalledApp(flow, new LocalServerReceiver()).authorize("user");
}
/**
@ -198,15 +198,15 @@ public class YoutubeSearch {
*/
public static IMessage displayChoicesDialog(List<Video> videos, IChannel channel){
EmbedObject e = YoutubeSearch.createEmbed(videos);
IMessage message = channel.sendMessage(e);
IMessage message = sendMessage(e, channel);
List<String> urls = new ArrayList<>(videos.size());
videos.forEach((video) -> urls.add(WATCH_URL + video.getId()));
RequestBuffer.request(() -> message.addReaction(":one:")).get();
RequestBuffer.request(() -> message.addReaction(":two:")).get();
RequestBuffer.request(() -> message.addReaction(":three:")).get();
RequestBuffer.request(() -> message.addReaction(":four:")).get();
RequestBuffer.request(() -> message.addReaction(":five:")).get();
RequestBuffer.request(() -> message.addReaction(":x:")).get();
addReaction(message, ":one:");
addReaction(message, ":two:");
addReaction(message, ":three:");
addReaction(message, ":four:");
addReaction(message, ":five:");
addReaction(message, ":x:");
return message;
}