diff --git a/src/main/java/net/dirtydeeds/discordsoundboard/ChatSoundBoardListener.java b/src/main/java/net/dirtydeeds/discordsoundboard/ChatSoundBoardListener.java index 78c251d..ae57079 100644 --- a/src/main/java/net/dirtydeeds/discordsoundboard/ChatSoundBoardListener.java +++ b/src/main/java/net/dirtydeeds/discordsoundboard/ChatSoundBoardListener.java @@ -23,6 +23,7 @@ public class ChatSoundBoardListener extends ListenerAdapter { private SoundPlayerImpl soundPlayer; private String commandCharacter = "?"; private Integer messageSizeLimit = 2000; + private boolean muted; public ChatSoundBoardListener(SoundPlayerImpl soundPlayer, String commandCharacter, String messageSizeLimit) { this.soundPlayer = soundPlayer; @@ -35,52 +36,91 @@ public ChatSoundBoardListener(SoundPlayerImpl soundPlayer, String commandCharact this.messageSizeLimit = 1994; } } + muted=false; } @Override public void onMessageReceived(MessageReceivedEvent event) { - String message = event.getMessage().getContent(); - String requestingUser = event.getAuthor().getUsername(); - final int maxLineLength = messageSizeLimit; - - //Respond - if (message.startsWith(commandCharacter + "list")) { - StringBuilder commandString = getCommandListString(); - List soundList = getCommandList(commandString); - - LOG.info("Responding to " + message + " command. Requested by " + requestingUser + "."); - if (message.equals(commandCharacter + "list")) { - if (commandString.length() > maxLineLength) { - replyByPrivateMessage(event, "You have " + soundList.size() + " pages of soundFiles. Reply: ```" + commandCharacter + "list pageNumber``` to request a specific page of results."); + if(!event.getAuthor().isBot()) { + String message = event.getMessage().getContent(); + String requestingUser = event.getAuthor().getUsername(); + final int maxLineLength = messageSizeLimit; + + //Respond + if (message.startsWith(commandCharacter + "list")) { + StringBuilder commandString = getCommandListString(); + List soundList = getCommandList(commandString); + + LOG.info("Responding to " + message + " command. Requested by " + requestingUser + "."); + if (message.equals(commandCharacter + "list")) { + if (commandString.length() > maxLineLength) { + replyByPrivateMessage(event, "You have " + soundList.size() + " pages of soundFiles. Reply: ```" + commandCharacter + "list pageNumber``` to request a specific page of results."); + } else { + replyByPrivateMessage(event, "Type any of the following into the chat to play the sound:"); + replyByPrivateMessage(event, soundList.get(0)); + } + } else { + String[] messageSplit = message.split(" "); + try { + Integer pageNumber = Integer.parseInt(messageSplit[1]); + replyByPrivateMessage(event, soundList.get(pageNumber - 1)); + } catch (IndexOutOfBoundsException e) { + replyByPrivateMessage(event, "The page number you entered is not valid."); + } catch (NumberFormatException e) { + replyByPrivateMessage(event, "The page number argument must be a number."); + } + } + //If the command is not list and starts with the specified command character try and play that "command" or sound file. + } else if (message.startsWith(commandCharacter + "help")) { + LOG.info("Responding to help command. Requested by " + requestingUser + "."); + replyByPrivateMessage(event, "Type ```" + commandCharacter + "list``` to get a list of available sound files. Type ```" + commandCharacter + "soundFileName``` to play the a sound from the list."); + } else if(message.startsWith(commandCharacter + "volume")) { + int newVol = Integer.parseInt(message.substring(8)); + if(newVol >= 1 && newVol <= 100) { + muted = false; + soundPlayer.setSoundPlayerVolume(newVol); + replyByPrivateMessage(event, "*Volume set to " + newVol + "%*"); + LOG.info("Volume set to " + newVol + "% by " + requestingUser + "."); + } else if(newVol == 0) { + muted = true; + soundPlayer.setSoundPlayerVolume(newVol); + replyByPrivateMessage(event, requestingUser + " muted me."); + LOG.info("Bot muted by " + requestingUser + "."); + soundPlayer.playFileForUser("stop",requestingUser); + } + } else if (message.startsWith(commandCharacter + "stop")) { + if (soundPlayer.stop()) { + replyByPrivateMessage(event, "Playback stopped."); } else { - replyByPrivateMessage(event, "Type any of the following into the chat to play the sound:\n"); - replyByPrivateMessage(event, soundList.get(0)); + replyByPrivateMessage(event, "Nothing was playing."); + } + + } else if (message.startsWith(commandCharacter) && message.length() >= 2) { + if(!muted) { + try { + String fileNameRequested = message.substring(1, message.length()); + LOG.info("Attempting to play file: " + fileNameRequested + ". Requested by " + requestingUser + "."); + soundPlayer.playFileForEvent(fileNameRequested, event); + } catch (Exception e) { + e.printStackTrace(); + } + } else { + replyByPrivateMessage(event, "I seem to be muted! Try " + commandCharacter + "help"); + LOG.info("Attempting to play a sound file while muted. Requested by " + requestingUser + "."); } } else { - String[] messageSplit = message.split(" "); - try { - Integer pageNumber = Integer.parseInt(messageSplit[1]); - replyByPrivateMessage(event, soundList.get(pageNumber - 1)); - } catch (IndexOutOfBoundsException e) { - replyByPrivateMessage(event, "The page number you entered is not valid."); - } catch (NumberFormatException e) { - replyByPrivateMessage(event, "The page number argument must be a number."); + if (message.startsWith(commandCharacter) || event.isPrivate()) { + nonRecognizedCommand(event, requestingUser); } } - //If the command is not list and starts with the specified command character try and play that "command" or sound file. - } else if (message.startsWith(commandCharacter + "help")) { - LOG.info("Responding to help command. Requested by " + requestingUser + "."); - replyByPrivateMessage(event, "Type ```" + commandCharacter + "list``` to get a list of available sound files. Type ```" + commandCharacter + "soundFileName``` to play the a sound from the list."); - } else if (message.startsWith(commandCharacter)) { - try { - String fileNameRequested = message.substring(1, message.length()); - LOG.info("Attempting to play file: " + fileNameRequested + ". Requested by " + requestingUser + "."); - soundPlayer.playFileForEvent(fileNameRequested, event); - } catch (Exception e) { - e.printStackTrace(); - } } } + + private void nonRecognizedCommand(MessageReceivedEvent event, String requestingUser) { + replyByPrivateMessage(event, "Hello @" + requestingUser + ". I don't know how to respond to this message!"); + replyByPrivateMessage(event, "You can type " + commandCharacter + "list to see a list of all playable Sounds. Type " + commandCharacter + "volume 0 - 100 to set the bots volume."); + LOG.info("Responding to PM of " + requestingUser + ". Unknown Command. Sending help text."); + } private List getCommandList(StringBuilder commandString) { final int maxLineLength = messageSizeLimit; @@ -92,13 +132,13 @@ private List getCommandList(StringBuilder commandString) { String[] tokens = commandString.toString().split(SPLIT_REGEXP); int lineLen = 0; StringBuilder output = new StringBuilder(); - output.append("```"); + output.append("```\n"); for (int i = 0; i < tokens.length; i++) { String word = tokens[i]; if (lineLen + (word).length() > maxLineLength) { if (i > 0) { - output.append("```"); + output.append("```\n"); soundFiles.add(output.toString()); output = new StringBuilder(maxLineLength); diff --git a/src/main/java/net/dirtydeeds/discordsoundboard/beans/SoundFile.java b/src/main/java/net/dirtydeeds/discordsoundboard/beans/SoundFile.java index f9ef745..695c081 100644 --- a/src/main/java/net/dirtydeeds/discordsoundboard/beans/SoundFile.java +++ b/src/main/java/net/dirtydeeds/discordsoundboard/beans/SoundFile.java @@ -13,12 +13,12 @@ public class SoundFile { private final String soundFileId; - private final File soundFile; + private final String soundFileLocation; private final String category; - public SoundFile(String soundFileId, File soundFile, String category) { + public SoundFile(String soundFileId, String soundFileLocation, String category) { this.soundFileId = soundFileId; - this.soundFile = soundFile; + this.soundFileLocation = soundFileLocation; this.category = category; } @@ -27,18 +27,13 @@ public String getSoundFileId() { } public String getSoundFileLocation() { - return soundFile.toString(); + return soundFileLocation; } public String getCategory() { return category; } - @JsonIgnore - public File getSoundFile() { - return soundFile; - } - @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/src/main/java/net/dirtydeeds/discordsoundboard/service/SoundPlayerImpl.java b/src/main/java/net/dirtydeeds/discordsoundboard/service/SoundPlayerImpl.java index 31a80ea..2b32d63 100644 --- a/src/main/java/net/dirtydeeds/discordsoundboard/service/SoundPlayerImpl.java +++ b/src/main/java/net/dirtydeeds/discordsoundboard/service/SoundPlayerImpl.java @@ -49,8 +49,8 @@ public class SoundPlayerImpl implements Observer { private Map availableSounds; private final MainWatch mainWatch; private boolean initialized = false; - private MusicPlayer player; - private Guild guild; + private MusicPlayer musicPlayer; + private FilePlayer player; private String playerSetting; @Inject @@ -64,16 +64,25 @@ public SoundPlayerImpl(MainWatch mainWatch) { playerSetting = appProperties.getProperty("player"); if (isMusicPlayer()) { - player = new MusicPlayer(); + musicPlayer = new MusicPlayer(); } initialized = true; } - private void setBotListener(ChatSoundBoardListener listener) { - bot.addEventListener(listener); + @Override + public void update(Observable o, Object arg) { + availableSounds = getFileList(); } - + + /** + * Gets a Map of the loaded sound files. + * @return Map of sound files that have been loaded. + */ + public Map getAvailableSoundFiles() { + return availableSounds; + } + /** * Sets volume of the player. * @param volume - The volume value to set. @@ -92,7 +101,7 @@ public void playFileForUser(String fileName, String userName) { userName = appProperties.getProperty("username_to_join_channel"); } try { - guild = getUsersGuild(userName); + Guild guild = getUsersGuild(userName); joinUsersCurrentChannel(userName); playFile(fileName, guild); @@ -110,9 +119,74 @@ public void playFileForUser(String fileName, String userName) { */ public void playFileForEvent(String fileName, MessageReceivedEvent event) throws Exception { if (event != null) { - guild = event.getGuild(); - moveToUserIdsChannel(event, guild); - playFile(fileName, guild); + Guild guild = event.getGuild(); + if (guild == null) { + guild = getUsersGuild(event.getAuthor().getUsername()); + } + if (guild != null) { + moveToUserIdsChannel(event, guild); + playFile(fileName, guild); + } else { + event.getAuthor().getPrivateChannel().sendMessage("I can not find a voice channel you are connected to."); + LOG.warn("no guild to play to."); + } + } + } + + /** + * Stops sound playback and returns true or false depending on if playback was stopped. + * @return boolean representing whether playback was stopped. + */ + public boolean stop() { + if (isMusicPlayer()) { + if (musicPlayer != null && musicPlayer.isPlaying()) { + musicPlayer.stop(); + return true; + } else { + return false; + } + } else { + if (player != null && player.isPlaying()) { + player.stop(); + return true; + } else { + return false; + } + } + } + + /** + * Get a list of users + */ + public List getUsers() { + String userNameToSelect = appProperties.getProperty("username_to_join_channel"); + List users = new ArrayList<>(); + for (net.dv8tion.jda.entities.User user : bot.getUsers()) { + if (user.getOnlineStatus().equals(OnlineStatus.ONLINE)) { + boolean selected = false; + String username = user.getUsername(); + if (userNameToSelect.equals(username)) { + selected = true; + } + users.add(new net.dirtydeeds.discordsoundboard.beans.User(user.getId(), username, selected)); + } + } + return users; + } + + /** + * Find the "author" of the event and join the voice channel they are in. + * @param event - The event + * @throws Exception + */ + private void moveToUserIdsChannel(MessageReceivedEvent event, Guild guild) throws Exception { + VoiceChannel channel = findUsersChannel(event, guild); + + if (channel == null) { + event.getAuthor().getPrivateChannel().sendMessage("Hello @"+ event.getAuthor().getUsername() +"! I can not find you in any Voice Channel. Are you sure you are connected to voice?."); + LOG.warn("Problem moving to requested users channel. Maybe user, " + event.getAuthor().getUsername() + " is not connected to Voice?"); + } else { + moveToChannel(channel, guild); } } @@ -133,11 +207,12 @@ private void moveToChannel(VoiceChannel channel, Guild guild){ } /** - * Find the "author" of the event and join the voice channel they are in. - * @param event - The event - * @throws Exception + * Finds a users voice channel based on event and what guild to look in. + * @param event - The event that triggered this search. This is used to get th events author. + * @param guild - The guild (discord server) to look in for the author. + * @return The VoiceChannel if one is found. Otherwise return null. */ - private void moveToUserIdsChannel(MessageReceivedEvent event, Guild guild) throws Exception { + private VoiceChannel findUsersChannel(MessageReceivedEvent event, Guild guild) { VoiceChannel channel = null; outerloop: @@ -150,20 +225,35 @@ private void moveToUserIdsChannel(MessageReceivedEvent event, Guild guild) throw } } - if (channel == null) { - event.getChannel().sendMessage("There isn't a VoiceChannel in this Guild with the name: event.getMessage().getChannelId() "); - throw new Exception("Problem moving to requested users channel" + event.getAuthor().getId()); - } + return channel; + } - moveToChannel(channel, guild); + //Join the users current channel. + private void joinUsersCurrentChannel(String userName) { + for (Guild guild : bot.getGuilds()) { + for (VoiceChannel channel : guild.getVoiceChannels()) { + channel.getUsers().stream().filter(user -> user.getUsername() + .equalsIgnoreCase(userName)).forEach(user -> moveToChannel(channel, guild)); + } + } } /** - * Gets a Map of the loaded sound files. - * @return Map of sound files that have been loaded. + * Looks through all the guilds the bot has access to and returns the VoiceChannel the requested user is connected to. + * @param userName - The username to look for. + * @return The voice channel the user is connected to. If user is not connected to a voice channel will return null. */ - public Map getAvailableSoundFiles() { - return availableSounds; + private Guild getUsersGuild(String userName) { + for (Guild guild : bot.getGuilds()) { + for (VoiceChannel channel : guild.getVoiceChannels()) { + for (net.dv8tion.jda.entities.User user : channel.getUsers()) { + if (user.getUsername().equalsIgnoreCase(userName)) { + return guild; + } + } + } + } + return null; } /** @@ -173,53 +263,39 @@ public Map getAvailableSoundFiles() { private void playFile(String fileName, Guild guild) { SoundFile fileToPlay = availableSounds.get(fileName); if (fileToPlay != null) { - playFile(fileToPlay.getSoundFile(), guild); + File soundFile = new File(fileToPlay.getSoundFileLocation()); + playFile(soundFile, guild); } } /** - * Get a list of users + * Play the provided File object + * @param audioFile - The File object to play. + * @param guild - The guild (discord server) the playback is going to happen in. */ - public List getUsers() { - String userNameToSelect = appProperties.getProperty("username_to_join_channel"); - List users = new ArrayList<>(); - for (net.dv8tion.jda.entities.User user : bot.getUsers()) { - if (user.getOnlineStatus().equals(OnlineStatus.ONLINE)) { - boolean selected = false; - String username = user.getUsername(); - if (userNameToSelect.equals(username)) { - selected = true; - } - users.add(new net.dirtydeeds.discordsoundboard.beans.User(user.getId(), username, selected)); - } - } - return users; - } - - //Play the file provided. private void playFile(File audioFile, Guild guild) { if (guild == null) { LOG.fatal("Guild is null. Have you added your bot to a guild? https://discordapp.com/developers/docs/topics/oauth2"); } else { if (isMusicPlayer()) { if (bot.getAudioManager(guild).getSendingHandler() == null) { - bot.getAudioManager(guild).setSendingHandler(player); + bot.getAudioManager(guild).setSendingHandler(musicPlayer); } - player.stop(); - player.getAudioQueue().clear(); + musicPlayer.stop(); + musicPlayer.getAudioQueue().clear(); AudioSource audioSource = new LocalSource(audioFile); - player.getAudioQueue().add(audioSource); + musicPlayer.getAudioQueue().add(audioSource); - player.setVolume(playerVolume); + musicPlayer.setVolume(playerVolume); bot.getAudioManager(guild).setConnectTimeout(100L); - player.play(); + musicPlayer.play(); } else { try { - FilePlayer player = new FilePlayer(audioFile); - + player = new FilePlayer(audioFile); + bot.getAudioManager(guild).setSendingHandler(player); player.stop(); @@ -235,32 +311,13 @@ private void playFile(File audioFile, Guild guild) { } } + /** + * Helper method that tells us if we are using MusicPlayer. If false we are using FilePlayer. + * @return boolean + */ private boolean isMusicPlayer() { return playerSetting != null && playerSetting.equals("musicPlayer"); } - - private Guild getUsersGuild(String userName) { - for (Guild guild : bot.getGuilds()) { - for (VoiceChannel channel : guild.getVoiceChannels()) { - for (net.dv8tion.jda.entities.User user : channel.getUsers()) { - if (user.getUsername().equalsIgnoreCase(userName)) { - return guild; - } - } - } - } - return null; - } - - //Join the users current channel. - private void joinUsersCurrentChannel(String userName) { - for (Guild guild : bot.getGuilds()) { - for (VoiceChannel channel : guild.getVoiceChannels()) { - channel.getUsers().stream().filter(user -> user.getUsername() - .equalsIgnoreCase(userName)).forEach(user -> moveToChannel(channel, guild)); - } - } - } //This method loads the files. This checks if you are running from a .jar file and loads from the /sounds dir relative //to the jar file. If not it assumes you are running from code and loads relative to your resource dir. @@ -301,7 +358,7 @@ private Map getFileList() { LOG.info(fileName); File file = filePath.toFile(); String parent = file.getParentFile().getName(); - SoundFile soundFile = new SoundFile(fileName, filePath.toFile(), parent); + SoundFile soundFile = new SoundFile(fileName, filePath.toString(), parent); returnFiles.put(fileName, soundFile); } }); @@ -376,12 +433,8 @@ private void loadProperties() { } } - @Override - public void update(Observable o, Object arg) { - availableSounds = getFileList(); - } - - public void stop() { - player.stop(); + //Sets listeners + private void setBotListener(ChatSoundBoardListener listener) { + bot.addEventListener(listener); } }