diff --git a/pom.xml b/pom.xml index 00ca576..4603f79 100644 --- a/pom.xml +++ b/pom.xml @@ -168,7 +168,7 @@ net.dv8tion JDA - 4.0.0_47 + 4.0.0_50 com.fasterxml.jackson.core diff --git a/src/main/java/net/locusworks/discord/eighttrack/database/repos/GuildSongRepository.java b/src/main/java/net/locusworks/discord/eighttrack/database/repos/GuildSongRepository.java index 8226858..fc6e85d 100644 --- a/src/main/java/net/locusworks/discord/eighttrack/database/repos/GuildSongRepository.java +++ b/src/main/java/net/locusworks/discord/eighttrack/database/repos/GuildSongRepository.java @@ -50,4 +50,7 @@ public interface GuildSongRepository extends CrudRepository { @Query("SELECT gs FROM GuildSong gs WHERE gs.guild.guildId = ?1") List findByGuild(Long guildId); + @Query("SELECT gs FROM GuildSong gs WHERE gs.guild.guildId = ?1 ORDER BY RAND()") + List findRandomSong(Long guildId); + } diff --git a/src/main/java/net/locusworks/discord/eighttrack/handlers/DiscordEventHandler.java b/src/main/java/net/locusworks/discord/eighttrack/handlers/DiscordEventHandler.java index 475efca..d7a0c2b 100644 --- a/src/main/java/net/locusworks/discord/eighttrack/handlers/DiscordEventHandler.java +++ b/src/main/java/net/locusworks/discord/eighttrack/handlers/DiscordEventHandler.java @@ -40,7 +40,6 @@ import net.dv8tion.jda.api.events.guild.GuildJoinEvent; import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent; import net.dv8tion.jda.api.hooks.ListenerAdapter; import net.locusworks.discord.eighttrack.database.entities.DiscordGuild; -import net.locusworks.discord.eighttrack.database.repos.GuildRepository; import net.locusworks.discord.eighttrack.services.ConfigurationService; import net.locusworks.discord.eighttrack.services.GuildMusicService; import net.locusworks.discord.eighttrack.services.GuildSongRepoService; @@ -57,18 +56,12 @@ public class DiscordEventHandler extends ListenerAdapter { @Autowired private ConfigurationService confService; - @Autowired - private GuildRepository guildRepo; - - @Autowired - private GuildMusicService musicService; - @Autowired private Mp3UploadHandler uploadHandler; @Autowired private GuildSongRepoService guildSongRepoService; - + @PostConstruct private void init() throws IOException { this.musicDir = confService.getMusicDirectory(); @@ -81,7 +74,7 @@ public class DiscordEventHandler extends ListenerAdapter { public void onGuildJoin(GuildJoinEvent event) { try { long guildId = event.getGuild().getIdLong(); - DiscordGuild discordGuild = guildRepo.findByGuildId(guildId); + DiscordGuild discordGuild = guildSongRepoService.getGuildRepo().findByGuildId(guildId); if (discordGuild != null) return; logger.debug("Joining Server: " + event.getGuild().getName()); @@ -91,7 +84,7 @@ public class DiscordEventHandler extends ListenerAdapter { discordGuild.setGuildName(event.getGuild().getName()); discordGuild.setDateJoined(new Date()); - guildRepo.save(discordGuild); + guildSongRepoService.getGuildRepo().save(discordGuild); } catch (Exception ex) { logger.error("Unable to persist server information to database: " + ex.getMessage(), ex); } @@ -107,14 +100,15 @@ public class DiscordEventHandler extends ListenerAdapter { } } - private void onGuildMessageReceivedHelper(GuildMessageReceivedEvent event) throws IOException { + private void onGuildMessageReceivedHelper(GuildMessageReceivedEvent event) throws Exception { - if (!musicService.containsKey(event.getGuild().getIdLong())) { - musicService.put(event.getGuild().getIdLong(), + if (!GuildMusicService.getMap().containsKey(event.getGuild().getIdLong())) { + GuildMusicService.getMap().put(event.getGuild().getIdLong(), new GuildMusicHandler(musicDir, event.getGuild().getIdLong(), uploadHandler, guildSongRepoService)); } - GuildMusicHandler gmh = musicService.get(event.getGuild().getIdLong()); - gmh.accept((id) -> musicService.remove(id)); + + GuildMusicHandler gmh = GuildMusicService.getMap().get(event.getGuild().getIdLong()); + gmh.accept((id) -> GuildMusicService.getMap().remove(id)); String command = event.getMessage().getContentRaw().trim().toLowerCase(); @@ -129,6 +123,7 @@ public class DiscordEventHandler extends ListenerAdapter { case "-stop": gmh.isPlaying(false); gmh.stop(event); + event.getGuild().getAudioManager().closeAudioConnection(); return; case "-next": gmh.next(event); @@ -140,9 +135,6 @@ public class DiscordEventHandler extends ListenerAdapter { case "-whatsnext": gmh.whatsNext(event); break; - case "-index": - gmh.index(event); - break; default: return; } diff --git a/src/main/java/net/locusworks/discord/eighttrack/handlers/GuildMusicHandler.java b/src/main/java/net/locusworks/discord/eighttrack/handlers/GuildMusicHandler.java index e584b9a..c8efa24 100644 --- a/src/main/java/net/locusworks/discord/eighttrack/handlers/GuildMusicHandler.java +++ b/src/main/java/net/locusworks/discord/eighttrack/handlers/GuildMusicHandler.java @@ -35,6 +35,7 @@ import java.nio.file.Path; import java.time.OffsetDateTime; import java.util.Date; import java.util.List; +import java.util.Random; import java.util.UUID; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Consumer; @@ -94,9 +95,12 @@ public class GuildMusicHandler { this.ts = new TrackScheduler(); player.addListener(ts); - indexFiles(); } - + + public Long getCurrentVoiceChannelId() { + return voiceChannelId; + } + public OffsetDateTime getLastPlayed() { return lastPlayed; } @@ -109,34 +113,10 @@ public class GuildMusicHandler { this.playing.set(playing); } - public void indexFiles() throws IOException { - List songs = guildSongRepoService.getGuildSongRepo().findByGuild(guildId); - - logger.info("Adding %d songs from directory %s", songs.size(), musicDir); - - for (GuildSong song : songs) { - logger.debug("Loading song: %s", song.getSong().getFilePath()); - try { - apm.loadItem(song.getSong().getFilePath(), ts); - } catch (IllegalStateException ex) { - logger.warn("Unable to load song :%s -> %s", song.getSong().getFilePath(), ex.getMessage()); - } + public void whatsNext(GuildMessageReceivedEvent event) throws Exception { + if (ts.peek() == null) { + loadRandomSong(); } - } - - public void index(GuildMessageReceivedEvent event) { - event.getChannel().sendMessage(String.format("<@%s>, Please wait as i reindex the music files", event.getAuthor().getId())).queue(); - try { - indexFiles(); - } catch (IOException e) { - event.getChannel().sendMessage(String.format("<@%s>, Unable to reindex the music files: %s", event.getAuthor().getId(), e.getMessage())).queue(); - return; - } - - event.getChannel().sendMessage(String.format("<@%s>, Reindexing complete", event.getAuthor().getId())).queue(); - } - - public void whatsNext(GuildMessageReceivedEvent event) { AudioTrack track = ts.peek(); MessageEmbed embed = new EmbedBuilder() .setAuthor(event.getMember().getEffectiveName(), null, event.getAuthor().getAvatarUrl()) @@ -147,15 +127,19 @@ public class GuildMusicHandler { event.getChannel().sendMessage(embed).queue(); } - public void repeat(GuildMessageReceivedEvent event) { + public void repeat(GuildMessageReceivedEvent event) throws Exception { next(event); ts.setFinishedCallback((ater) -> { if (!playing.get()) return; - next(event); + try { + next(event); + } catch (Exception e) { + logger.error(e); + } }); } - public void next(GuildMessageReceivedEvent event) { + public void next(GuildMessageReceivedEvent event) throws Exception { GuildChannel gc = event.getGuild().getGuildChannelById(ChannelType.VOICE, voiceChannelId); if (gc != null && gc.getMembers().size() == 1) { @@ -173,9 +157,10 @@ public class GuildMusicHandler { public void stop(GuildMessageReceivedEvent event) { player.stopTrack(); + voiceChannelId = null; } - public void play(GuildMessageReceivedEvent event) { + public void play(GuildMessageReceivedEvent event) throws Exception { VoiceChannel vc = event.getMember().getVoiceState().getChannel(); if (vc == null) { event.getChannel().sendMessage(String.format("<@%s> you are not in a voice channel to play music", event.getMember().getId())).queue(); @@ -187,13 +172,25 @@ public class GuildMusicHandler { event.getMember().getId(), vc.getName())).queue(); return; } - - voiceChannelId = vc.getIdLong(); + + Long tmpId = vc.getIdLong(); + if (voiceChannelId != null && voiceChannelId != tmpId) { + String channelName = event.getGuild().getVoiceChannelById(voiceChannelId).getName(); + event.getChannel().sendMessage(String.format("<@%s> I am currently playing in channel %s. Cannot switch channels until I am stopped.", + event.getMember().getId(), channelName)).queue(); + return; + } + + voiceChannelId = tmpId; AudioManager manager = event.getGuild().getAudioManager(); manager.openAudioConnection(vc); manager.setSendingHandler(new EightTrackAudioSendHandler(player)); + + if (!ts.hasTracks()) { + loadRandomSong(); + } if (ts.hasTracks()) { lastPlayed = OffsetDateTime.now(); @@ -209,7 +206,6 @@ public class GuildMusicHandler { event.getChannel().sendMessage(embed).queue(); player.playTrack(track); - ts.trackLoaded(track); } } @@ -329,6 +325,19 @@ public class GuildMusicHandler { .build(); return embed; - + } + + private void loadRandomSong() throws Exception { + List gsList = guildSongRepoService.getGuildSongRepo().findByGuild(guildId); + if (gsList == null || gsList.isEmpty()) return; + + Random random = new Random(System.currentTimeMillis()); + int item = random.nextInt(gsList.size()); + + GuildSong song = gsList.get(item); + + apm.loadItem(song.getSong().getFilePath(), ts).get(); } + + } diff --git a/src/main/java/net/locusworks/discord/eighttrack/services/DatabaseCleanupService.java b/src/main/java/net/locusworks/discord/eighttrack/services/DatabaseCleanupService.java index c0fd67f..914b64c 100644 --- a/src/main/java/net/locusworks/discord/eighttrack/services/DatabaseCleanupService.java +++ b/src/main/java/net/locusworks/discord/eighttrack/services/DatabaseCleanupService.java @@ -42,6 +42,7 @@ import org.springframework.stereotype.Service; import net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.entities.Guild; +import net.dv8tion.jda.api.entities.VoiceChannel; import net.locusworks.discord.eighttrack.database.repos.GuildRepository; import net.locusworks.discord.eighttrack.handlers.GuildMusicHandler; @@ -58,15 +59,15 @@ public class DatabaseCleanupService { @Autowired private GuildRepository guildRepo; - @Autowired - private GuildMusicService musicService; - private JDA client; public void setClient(JDA client) { this.client = client; } + /** + * Close out connections that are no long being played. clean up resources + */ @Scheduled(fixedRate = 5 * MINUTE) private void checkPlayers() { if (client == null) { @@ -76,22 +77,35 @@ public class DatabaseCleanupService { logger.debug("Checking players to see if anyone is listening"); OffsetDateTime now = OffsetDateTime.now(); - for(Iterator> iterator = musicService.entrySet().iterator(); iterator.hasNext();) { + for(Iterator> iterator = GuildMusicService.getMap().entrySet().iterator(); iterator.hasNext();) { Entry entry = iterator.next(); GuildMusicHandler gmh = entry.getValue(); long guildId = entry.getKey(); + Guild guild = client.getGuildById(guildId); + if (guild == null) { + iterator.remove(); + continue; + } + OffsetDateTime lastPlayed = gmh.getLastPlayed(); Duration duration = Duration.between(lastPlayed, now); - if (duration.getSeconds() > 300) { - Guild guild = client.getGuildById(guildId); - if (guild == null) { - iterator.remove(); - continue; - } + if (duration.toMillis() > 5 * MINUTE) { guild.getAudioManager().closeAudioConnection(); iterator.remove(); } + + Long voiceChannelId = gmh.getCurrentVoiceChannelId(); + if (voiceChannelId == null) { + guild.getAudioManager().closeAudioConnection(); + iterator.remove(); + } else { + VoiceChannel vc = guild.getVoiceChannelById(voiceChannelId); + if (vc != null && vc.getMembers().size() == 1) { + guild.getAudioManager().closeAudioConnection(); + iterator.remove(); + } + } } } diff --git a/src/main/java/net/locusworks/discord/eighttrack/services/GuildMusicService.java b/src/main/java/net/locusworks/discord/eighttrack/services/GuildMusicService.java index 4db286c..0f8fa49 100644 --- a/src/main/java/net/locusworks/discord/eighttrack/services/GuildMusicService.java +++ b/src/main/java/net/locusworks/discord/eighttrack/services/GuildMusicService.java @@ -27,15 +27,17 @@ */ package net.locusworks.discord.eighttrack.services; +import java.util.Map; import java.util.concurrent.ConcurrentHashMap; -import org.springframework.stereotype.Service; - import net.locusworks.discord.eighttrack.handlers.GuildMusicHandler; -@Service -public class GuildMusicService extends ConcurrentHashMap { - - private static final long serialVersionUID = -120204711554552975L; +public class GuildMusicService { + + private static Map handlerMap = new ConcurrentHashMap<>(); + + public static Map getMap() { + return handlerMap; + } }