Merge branch 'feature/playlist' of Locusworks/eight-track into develop
Some checks failed
Locusworks Team/eight-track/pipeline/head There was a failure building this commit
Some checks failed
Locusworks Team/eight-track/pipeline/head There was a failure building this commit
This commit is contained in:
@ -0,0 +1,56 @@
|
||||
/**
|
||||
*
|
||||
* Project: Eight Track, File: GuildSongRepository.java
|
||||
*
|
||||
* Copyright 2019-2019 Locusworks LLC.
|
||||
* All rights reserved. Federal copyright law prohibits unauthorized reproduction by
|
||||
* any means and imposes fines up to $25,000 for violation. No part of this material
|
||||
* may be reproduced, transmitted, transcribed, stored in a retrieval system, copied,
|
||||
* modified, duplicated, adapted or translated into another program language in any
|
||||
* form or by any means, electronic, mechanical, photocopying, recording, or
|
||||
* otherwise, without the prior written permission from Locusworks. Locusworks
|
||||
* affirms that Eight-Track(R) software and data is subject to United States
|
||||
* Government Purpose Rights. Contact Locusworks, 1313 Lawnview Drive
|
||||
* Forney TX 75126, (802) 488-0438, for commercial licensing opportunities.
|
||||
*
|
||||
* IN NO EVENT SHALL LOCUSWORKS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL,
|
||||
* INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT
|
||||
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF LOCUSWORKS HAS BEEN
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. NO RESPONSIBILITY IS ASSUMED BY
|
||||
* LOCUSWORKS FOR ITS USE, OR FOR ANY INFRINGEMENTS OF PATENTS OR OTHER RIGHTS OF
|
||||
* THIRD PARTIES RESULTING FROM ITS USE. LOCUSWORKS SPECIFICALLY DISCLAIMS ANY
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE AND
|
||||
* ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS
|
||||
* IS". LOCUSWORKS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
|
||||
* ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*/
|
||||
package net.locusworks.discord.eighttrack.database.repos;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
|
||||
import net.locusworks.discord.eighttrack.database.entities.DiscordGuild;
|
||||
import net.locusworks.discord.eighttrack.database.entities.GuildPlaylist;
|
||||
|
||||
public interface GuildPlaylistRepository extends CrudRepository<GuildPlaylist, Long> {
|
||||
|
||||
GuildPlaylist findByGuildAndUserIdAndPlaylist(DiscordGuild guild, Long userId, String playlist);
|
||||
|
||||
@Query("SELECT gpl FROM GuildPlaylist gpl WHERE gpl.guild.guildId = ?1 AND gpl.userId = ?2 AND gpl.playlist = ?3")
|
||||
GuildPlaylist findByGuildAndUserIdAndPlaylist(Long guild, Long userId, String playlist);
|
||||
|
||||
List<GuildPlaylist> findByGuildAndUserId(DiscordGuild guild, Long userId);
|
||||
|
||||
@Query("SELECT gpl FROM GuildPlaylist gpl WHERE gpl.guild.guildId = ?1 AND gpl.userId = ?2")
|
||||
List<GuildPlaylist> findByGuildAndUserId(Long guild, Long userId);
|
||||
|
||||
@Query("SELECT DISTINCT gpl FROM GuildPlaylist gpl LEFT JOIN FETCH gpl.guildPlaylistSongList WHERE gpl.guild.guildId = ?1 AND gpl.userId = ?2")
|
||||
List<GuildPlaylist> findByGuildAndUserIdFetchSongs(Long guild, Long userId);
|
||||
|
||||
@Query("SELECT DISTINCT gpl FROM GuildPlaylist gpl LEFT JOIN FETCH gpl.guildPlaylistSongList WHERE gpl.guild.guildId = ?1 AND gpl.userId = ?2 AND gpl.playlist = ?3")
|
||||
GuildPlaylist findGuildUserPlaylistFetchSongs(Long guild, Long userId, String playlist);
|
||||
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
/**
|
||||
*
|
||||
* Project: Eight Track, File: GuildSongRepository.java
|
||||
*
|
||||
* Copyright 2019-2019 Locusworks LLC.
|
||||
* All rights reserved. Federal copyright law prohibits unauthorized reproduction by
|
||||
* any means and imposes fines up to $25,000 for violation. No part of this material
|
||||
* may be reproduced, transmitted, transcribed, stored in a retrieval system, copied,
|
||||
* modified, duplicated, adapted or translated into another program language in any
|
||||
* form or by any means, electronic, mechanical, photocopying, recording, or
|
||||
* otherwise, without the prior written permission from Locusworks. Locusworks
|
||||
* affirms that Eight-Track(R) software and data is subject to United States
|
||||
* Government Purpose Rights. Contact Locusworks, 1313 Lawnview Drive
|
||||
* Forney TX 75126, (802) 488-0438, for commercial licensing opportunities.
|
||||
*
|
||||
* IN NO EVENT SHALL LOCUSWORKS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL,
|
||||
* INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT
|
||||
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF LOCUSWORKS HAS BEEN
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. NO RESPONSIBILITY IS ASSUMED BY
|
||||
* LOCUSWORKS FOR ITS USE, OR FOR ANY INFRINGEMENTS OF PATENTS OR OTHER RIGHTS OF
|
||||
* THIRD PARTIES RESULTING FROM ITS USE. LOCUSWORKS SPECIFICALLY DISCLAIMS ANY
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE AND
|
||||
* ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS
|
||||
* IS". LOCUSWORKS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
|
||||
* ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*/
|
||||
package net.locusworks.discord.eighttrack.database.repos;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
|
||||
import net.locusworks.discord.eighttrack.database.entities.GuildPlaylist;
|
||||
import net.locusworks.discord.eighttrack.database.entities.GuildPlaylistSong;
|
||||
|
||||
public interface GuildPlaylistSongRepository extends CrudRepository<GuildPlaylistSong, Long> {
|
||||
|
||||
List<GuildPlaylistSong> findByGuildPlaylist(GuildPlaylist gpl);
|
||||
|
||||
@Query("SELECT gpls FROM GuildPlaylistSong gpls WHERE gpls.guildPlaylist = ?1 AND gpls.guildSong.uuid IN ?2")
|
||||
List<GuildPlaylistSong> findByGuildPlaylistAndSongIds(GuildPlaylist gpl, List<String> songIds);
|
||||
|
||||
|
||||
}
|
@ -38,10 +38,14 @@ import java.util.List;
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import net.dv8tion.jda.api.entities.ChannelType;
|
||||
import net.dv8tion.jda.api.entities.TextChannel;
|
||||
import net.dv8tion.jda.api.events.guild.GuildJoinEvent;
|
||||
import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent;
|
||||
import net.dv8tion.jda.api.events.message.react.MessageReactionAddEvent;
|
||||
import net.dv8tion.jda.api.hooks.ListenerAdapter;
|
||||
import net.locusworks.discord.eighttrack.database.entities.DiscordGuild;
|
||||
import net.locusworks.discord.eighttrack.services.ConfigurationService;
|
||||
@ -66,6 +70,9 @@ public class DiscordEventHandler extends ListenerAdapter {
|
||||
@Autowired
|
||||
private GuildSongRepoService guildSongRepoService;
|
||||
|
||||
@Autowired
|
||||
private ReactionHandler reactionHandler;
|
||||
|
||||
@PostConstruct
|
||||
private void init() throws IOException {
|
||||
this.musicDir = confService.getMusicDirectory();
|
||||
@ -74,6 +81,26 @@ public class DiscordEventHandler extends ListenerAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
@Scheduled(fixedRate = 300000L, initialDelay=300000L)
|
||||
private void clearHandlerCache() {
|
||||
logger.debug("Clearing reaction handler cache of dead reactions");
|
||||
reactionHandler.cleanCache();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMessageReactionAdd(MessageReactionAddEvent e) {
|
||||
if (e.getUser().isBot()) {
|
||||
return;
|
||||
}
|
||||
if (!e.getChannel().getType().equals(ChannelType.TEXT)) {
|
||||
return;
|
||||
}
|
||||
TextChannel channel = (TextChannel) e.getChannel();
|
||||
if (reactionHandler.canHandle(channel.getGuild().getIdLong(), e.getMessageIdLong())) {
|
||||
reactionHandler.handle(channel, e.getMessageIdLong(), e.getUser().getIdLong(), e.getReaction());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGuildJoin(GuildJoinEvent event) {
|
||||
try {
|
||||
@ -108,7 +135,7 @@ public class DiscordEventHandler extends ListenerAdapter {
|
||||
|
||||
if (!GuildMusicService.getMap().containsKey(event.getGuild().getIdLong())) {
|
||||
GuildMusicService.getMap().put(event.getGuild().getIdLong(),
|
||||
new GuildMusicHandler(musicDir, event.getGuild().getIdLong(), uploadHandler, guildSongRepoService));
|
||||
new GuildMusicHandler(musicDir, event.getGuild().getIdLong(), uploadHandler, reactionHandler, guildSongRepoService));
|
||||
}
|
||||
|
||||
GuildMusicHandler gmh = GuildMusicService.getMap().get(event.getGuild().getIdLong());
|
||||
|
@ -33,12 +33,16 @@ import java.math.BigInteger;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
@ -51,17 +55,24 @@ import net.dv8tion.jda.api.EmbedBuilder;
|
||||
import net.dv8tion.jda.api.Permission;
|
||||
import net.dv8tion.jda.api.entities.ChannelType;
|
||||
import net.dv8tion.jda.api.entities.GuildChannel;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.entities.Message.Attachment;
|
||||
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||
import net.dv8tion.jda.api.entities.VoiceChannel;
|
||||
import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent;
|
||||
import net.dv8tion.jda.api.exceptions.ErrorResponseException;
|
||||
import net.dv8tion.jda.api.managers.AudioManager;
|
||||
import net.dv8tion.jda.api.requests.ErrorResponse;
|
||||
import net.locusworks.crypto.utils.HashUtils;
|
||||
import net.locusworks.discord.eighttrack.database.entities.DiscordGuild;
|
||||
import net.locusworks.discord.eighttrack.database.entities.GuildPlaylist;
|
||||
import net.locusworks.discord.eighttrack.database.entities.GuildPlaylistSong;
|
||||
import net.locusworks.discord.eighttrack.database.entities.GuildSong;
|
||||
import net.locusworks.discord.eighttrack.database.entities.Song;
|
||||
import net.locusworks.discord.eighttrack.listeners.ReactionListener;
|
||||
import net.locusworks.discord.eighttrack.scheduler.TrackScheduler;
|
||||
import net.locusworks.discord.eighttrack.services.GuildSongRepoService;
|
||||
import net.locusworks.discord.eighttrack.utils.Reactions;
|
||||
import net.locusworks.logger.ApplicationLogger;
|
||||
import net.locusworks.logger.ApplicationLoggerFactory;
|
||||
|
||||
@ -80,9 +91,12 @@ public class GuildMusicHandler {
|
||||
private Consumer<Long> callback;
|
||||
private Mp3UploadHandler uploadHandler;
|
||||
private GuildSongRepoService guildSongRepoService;
|
||||
private ReactionHandler reactionHandler;
|
||||
private long guildId;
|
||||
|
||||
public GuildMusicHandler(Path musicDir, long guildId, Mp3UploadHandler uploadHandler, GuildSongRepoService guildSongRepoService) throws IOException {
|
||||
private GuildPlaylist currentPlaylist;
|
||||
|
||||
public GuildMusicHandler(Path musicDir, long guildId, Mp3UploadHandler uploadHandler, ReactionHandler reactionHandler, GuildSongRepoService guildSongRepoService) throws IOException {
|
||||
this.logger = ApplicationLoggerFactory.getLogger(GuildMusicHandler.class);
|
||||
this.playing = new AtomicBoolean(false);
|
||||
this.musicDir = musicDir;
|
||||
@ -90,6 +104,7 @@ public class GuildMusicHandler {
|
||||
this.uploadHandler = uploadHandler;
|
||||
this.guildSongRepoService = guildSongRepoService;
|
||||
this.guildId = guildId;
|
||||
this.reactionHandler = reactionHandler;
|
||||
this.apm = new DefaultAudioPlayerManager();
|
||||
|
||||
AudioSourceManagers.registerLocalSource(apm);
|
||||
@ -98,11 +113,31 @@ public class GuildMusicHandler {
|
||||
this.ts = new TrackScheduler();
|
||||
player.addListener(ts);
|
||||
}
|
||||
|
||||
|
||||
public void playlist(GuildMessageReceivedEvent event, List<String> commands) throws Exception {
|
||||
|
||||
String command = commands.remove(0);
|
||||
|
||||
switch(command) {
|
||||
case "add":
|
||||
addPlayList(event, commands);
|
||||
return;
|
||||
case "delete":
|
||||
deletePlayList(event, commands);
|
||||
return;
|
||||
case "list":
|
||||
listPlayList(event, commands);
|
||||
return;
|
||||
case "play":
|
||||
playPlayList(event, commands);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public Long getCurrentVoiceChannelId() {
|
||||
return voiceChannelId;
|
||||
}
|
||||
|
||||
|
||||
public OffsetDateTime getLastPlayed() {
|
||||
return lastPlayed;
|
||||
}
|
||||
@ -114,7 +149,7 @@ public class GuildMusicHandler {
|
||||
public void isPlaying(boolean playing) {
|
||||
this.playing.set(playing);
|
||||
}
|
||||
|
||||
|
||||
public void upNext(GuildMessageReceivedEvent event) throws Exception {
|
||||
upNext(event, null);
|
||||
}
|
||||
@ -152,7 +187,7 @@ public class GuildMusicHandler {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public void next(GuildMessageReceivedEvent event) throws Exception {
|
||||
next(event, null);
|
||||
}
|
||||
@ -172,23 +207,30 @@ public class GuildMusicHandler {
|
||||
}
|
||||
|
||||
playing.set(false);
|
||||
stop(event);
|
||||
stop(event, true);
|
||||
play(event, commands);
|
||||
playing.set(true);
|
||||
}
|
||||
|
||||
public void stop(GuildMessageReceivedEvent event) {
|
||||
stop(event, false);
|
||||
}
|
||||
|
||||
public void stop(GuildMessageReceivedEvent event, boolean stoppedFromRepeat) {
|
||||
player.stopTrack();
|
||||
voiceChannelId = null;
|
||||
if (!stoppedFromRepeat) {
|
||||
currentPlaylist = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void play(GuildMessageReceivedEvent event) throws Exception {
|
||||
play(event, null);
|
||||
}
|
||||
|
||||
public void play(GuildMessageReceivedEvent event, List<String> commands) throws Exception {
|
||||
if (playing.get()) return;
|
||||
|
||||
|
||||
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();
|
||||
@ -200,7 +242,7 @@ public class GuildMusicHandler {
|
||||
event.getMember().getId(), vc.getName())).queue();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Long tmpId = vc.getIdLong();
|
||||
if (voiceChannelId != null && voiceChannelId != tmpId) {
|
||||
String channelName = event.getGuild().getVoiceChannelById(voiceChannelId).getName();
|
||||
@ -208,14 +250,14 @@ public class GuildMusicHandler {
|
||||
event.getMember().getId(), channelName)).queue();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
voiceChannelId = tmpId;
|
||||
|
||||
AudioManager manager = event.getGuild().getAudioManager();
|
||||
manager.openAudioConnection(vc);
|
||||
|
||||
manager.setSendingHandler(new EightTrackAudioSendHandler(player));
|
||||
|
||||
|
||||
if (commands != null && !commands.isEmpty()) {
|
||||
String uuid = commands.remove(0);
|
||||
boolean foundSong = findSong(uuid);
|
||||
@ -223,9 +265,9 @@ public class GuildMusicHandler {
|
||||
event.getChannel().sendMessageFormat("Unable to find song with identifier: %s", uuid).queue();
|
||||
return;
|
||||
}
|
||||
stop(event);
|
||||
stop(event, true);
|
||||
}
|
||||
|
||||
|
||||
if (!ts.hasTracks()) {
|
||||
loadRandomSong();
|
||||
}
|
||||
@ -285,7 +327,31 @@ public class GuildMusicHandler {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void playPlayList(GuildMessageReceivedEvent event, List<String> commands) throws Exception {
|
||||
if (commands == null || commands.isEmpty()) {
|
||||
event.getChannel().sendMessage(event.getAuthor().getAsMention() + " please provide the name of the playlist to play").queue();
|
||||
return;
|
||||
}
|
||||
String playlist = commands.remove(0);
|
||||
currentPlaylist = guildSongRepoService.getGuildPlaylistRepo().findByGuildAndUserIdAndPlaylist(guildId, event.getMember().getIdLong(), playlist);
|
||||
if (currentPlaylist == null) {
|
||||
event.getChannel().sendMessage(event.getAuthor().getAsMention() + ", no playlist with the name of " + playlist + " exists").queue();
|
||||
return;
|
||||
}
|
||||
|
||||
ts.clearTracks();
|
||||
|
||||
for(GuildPlaylistSong gpls : guildSongRepoService.getGuildPlaylistSongRepo().findByGuildPlaylist(currentPlaylist)) {
|
||||
Song s = gpls.getGuildSong().getSong();
|
||||
apm.loadItem(s.getFilePath(), ts).get();
|
||||
}
|
||||
|
||||
playing.set(false);
|
||||
play(event);
|
||||
playing.set(true);
|
||||
}
|
||||
|
||||
private MessageEmbed error(GuildMessageReceivedEvent event, Throwable ex, String fileName) {
|
||||
return new EmbedBuilder()
|
||||
.setTitle("Unable to upload file: " + fileName)
|
||||
@ -348,9 +414,9 @@ public class GuildMusicHandler {
|
||||
gs.setDateAdded(new Date());
|
||||
gs.setGuild(guild);
|
||||
gs.setSong(song);
|
||||
|
||||
|
||||
String[] uuidArray = UUID.randomUUID().toString().split("-");
|
||||
|
||||
|
||||
gs.setUuid(uuidArray[uuidArray.length - 1]);
|
||||
|
||||
guildSongRepoService.getGuildSongRepo().save(gs);
|
||||
@ -373,71 +439,316 @@ public class GuildMusicHandler {
|
||||
|
||||
return embed;
|
||||
}
|
||||
|
||||
|
||||
public void list(GuildMessageReceivedEvent event) {
|
||||
List<GuildSong> gsList = guildSongRepoService.getGuildSongRepo().findByGuild(guildId);
|
||||
|
||||
|
||||
if (gsList == null || gsList.isEmpty()) {
|
||||
event.getChannel().sendMessage("There is no music for this guild.").queue();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
int longestSong = 0;
|
||||
int longestArtist = 0;
|
||||
for(GuildSong gs : gsList) {
|
||||
if (gs.getSong().getTitle().length() > longestSong) longestSong = gs.getSong().getTitle().length();
|
||||
if (gs.getSong().getArtist().length() > longestArtist) longestArtist = gs.getSong().getArtist().length();
|
||||
}
|
||||
|
||||
|
||||
String fmt = "%6s | %-" + longestSong +"s | %-" + longestArtist +"s | %s%n";
|
||||
int count = 0;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("**" + "Currently available songs for " + event.getGuild().getName() + "**\n\n```");
|
||||
sb.append(String.format(fmt, "Track", "Title", "Artist", "id"));
|
||||
sb.append(StringUtils.repeat("-", 27 + longestSong + longestArtist)).append("\n");
|
||||
|
||||
|
||||
for(GuildSong gs : gsList) {
|
||||
sb.append(String.format(fmt, ++count, gs.getSong().getTitle(), gs.getSong().getArtist(), gs.getUuid()));
|
||||
}
|
||||
sb.append("```");
|
||||
event.getChannel().sendMessage(sb.toString()).queue();
|
||||
}
|
||||
|
||||
|
||||
private void loadRandomSong() throws Exception {
|
||||
List<GuildSong> gsList = guildSongRepoService.getGuildSongRepo().findByGuild(guildId);
|
||||
List<GuildSong> gsList = null;
|
||||
|
||||
if (currentPlaylist == null) {
|
||||
gsList = guildSongRepoService.getGuildSongRepo().findByGuild(guildId);
|
||||
} else {
|
||||
gsList = guildSongRepoService.getGuildPlaylistSongRepo().findByGuildPlaylist(currentPlaylist).stream().map(gpl -> gpl.getGuildSong()).collect(Collectors.toList());
|
||||
}
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
private boolean findSong(String uuid) throws Exception {
|
||||
GuildSong gs = guildSongRepoService.getGuildSongRepo().findByUuid(uuid);
|
||||
if (gs == null) return false;
|
||||
|
||||
|
||||
apm.loadItem(gs.getSong().getFilePath(), ts).get();
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void playlist(GuildMessageReceivedEvent event, List<String> commands) {
|
||||
|
||||
String command = commands.remove(0);
|
||||
|
||||
switch(command) {
|
||||
case "add":
|
||||
addPlayList(event, commands);
|
||||
private void listPlayList(GuildMessageReceivedEvent event, List<String> commands) {
|
||||
if (commands == null || commands.isEmpty()) {
|
||||
List<GuildPlaylist> userPlaylist = guildSongRepoService.getGuildPlaylistRepo().findByGuildAndUserIdFetchSongs(event.getGuild().getIdLong(), event.getMember().getIdLong());
|
||||
if (userPlaylist.isEmpty()) {
|
||||
event.getChannel().sendMessage(event.getMember().getAsMention() + " you have no defined playlists on this server").queue();
|
||||
return;
|
||||
}
|
||||
|
||||
int longestPlaylist = 0;
|
||||
for(GuildPlaylist gpl : userPlaylist) {
|
||||
if (gpl.getPlaylist().length() > longestPlaylist) longestPlaylist = gpl.getPlaylist().length();
|
||||
}
|
||||
|
||||
String fmt = "%6s | %-" + longestPlaylist +"s | %s%n";
|
||||
|
||||
StringBuilder sb = new StringBuilder("```");
|
||||
sb.append(String.format(fmt, "", "Playlist", "Song Count"));
|
||||
sb.append(StringUtils.repeat("-", 24 + longestPlaylist)).append("\n");
|
||||
|
||||
int count = 0;
|
||||
for(GuildPlaylist gpl : userPlaylist) {
|
||||
sb.append(String.format(fmt, ++count, gpl.getPlaylist(), gpl.getGuildPlaylistSongList().size()));
|
||||
}
|
||||
sb.append("```");
|
||||
event.getChannel().sendMessage("**" + "Currently available playlists for " + event.getMember().getAsMention() + "**").queue((succcess)->
|
||||
event.getChannel().sendMessage(sb.toString()).queue()
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
String playlist = commands.remove(0);
|
||||
|
||||
GuildPlaylist gpl = guildSongRepoService.getGuildPlaylistRepo().findGuildUserPlaylistFetchSongs(event.getGuild().getIdLong(), event.getMember().getIdLong(), playlist);
|
||||
if (gpl == null) {
|
||||
event.getChannel().sendMessage(event.getMember().getAsMention() + " you have no defined playlists on this server by the name of " + playlist).queue();
|
||||
return;
|
||||
}
|
||||
|
||||
if (gpl.getGuildPlaylistSongList().isEmpty()) {
|
||||
event.getChannel().sendMessage(event.getMember().getAsMention() + " you have no defined songs for playlist " + playlist).queue();
|
||||
return;
|
||||
}
|
||||
|
||||
int longestSong = 0;
|
||||
int longestArtist = 0;
|
||||
for(GuildPlaylistSong gpls : gpl.getGuildPlaylistSongList()) {
|
||||
GuildSong gs = gpls.getGuildSong();
|
||||
if (gs.getSong().getTitle().length() > longestSong) longestSong = gs.getSong().getTitle().length();
|
||||
if (gs.getSong().getArtist().length() > longestArtist) longestArtist = gs.getSong().getArtist().length();
|
||||
}
|
||||
|
||||
String fmt = "%6s | %-" + longestSong +"s | %-" + longestArtist +"s | %s%n";
|
||||
int count = 0;
|
||||
StringBuilder sb = new StringBuilder("```");
|
||||
sb.append(String.format(fmt, "Track", "Title", "Artist", "id"));
|
||||
sb.append(StringUtils.repeat("-", 27 + longestSong + longestArtist)).append("\n");
|
||||
|
||||
for(GuildPlaylistSong gpls : gpl.getGuildPlaylistSongList()) {
|
||||
GuildSong gs = gpls.getGuildSong();
|
||||
sb.append(String.format(fmt, ++count, gs.getSong().getTitle(), gs.getSong().getArtist(), gs.getUuid()));
|
||||
}
|
||||
sb.append("```");
|
||||
event.getChannel().sendMessage("**" + "Current songs in playlists " + playlist + " for " + event.getMember().getAsMention() + "**").queue((succcess)->
|
||||
event.getChannel().sendMessage(sb.toString()).queue()
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
private void deletePlayList(GuildMessageReceivedEvent event, List<String> commands) {
|
||||
if (commands == null || commands.isEmpty()) {
|
||||
event.getChannel().sendMessage(event.getAuthor().getAsMention() + " you have to provide the playlist to create a new playlist (no spaces in name) and optionally a list of uuids for songs to add").queue();
|
||||
return;
|
||||
}
|
||||
|
||||
Long guildId = event.getGuild().getIdLong();
|
||||
|
||||
DiscordGuild guild = guildSongRepoService.getGuildRepo().findByGuildId(guildId);
|
||||
if (guild == null) {
|
||||
event.getChannel().sendMessage("Unable to find guild in local database. Please contact administrator").queue();
|
||||
return;
|
||||
}
|
||||
|
||||
String playlist = commands.remove(0);
|
||||
|
||||
long userId = event.getMember().getIdLong();
|
||||
|
||||
GuildPlaylist gpl = guildSongRepoService.getGuildPlaylistRepo().findByGuildAndUserIdAndPlaylist(guild, userId, playlist);
|
||||
|
||||
if (commands.isEmpty()) {
|
||||
|
||||
MessageEmbed embed = new EmbedBuilder()
|
||||
.setColor(Color.RED)
|
||||
.setTitle("Delete Playlist " + playlist)
|
||||
.setDescription("Are you sure you want to delete the playlist " + playlist)
|
||||
.setTimestamp(OffsetDateTime.now())
|
||||
.setFooter(event.getGuild().getSelfMember().getEffectiveName(), event.getGuild().getSelfMember().getUser().getAvatarUrl())
|
||||
.build();
|
||||
|
||||
event.getChannel().sendMessage(embed).queue((msg) -> {
|
||||
|
||||
ReactionListener<String> handler = new ReactionListener<>(userId, msg.getId());
|
||||
handler.setExpiresIn(TimeUnit.MINUTES, 1);
|
||||
handler.registerReaction(Reactions.CHECK_MARK_BUTTON, (ret) -> deletePlayListConfirm(gpl, event.getMember().getAsMention(), msg));
|
||||
handler.registerReaction(Reactions.CROSS_MARK_BUTTON, (ret) -> deleteMessage(msg));
|
||||
|
||||
reactionHandler.addReactionListener(guildId, msg, handler);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
List<GuildPlaylistSong> songs = guildSongRepoService.getGuildPlaylistSongRepo().findByGuildPlaylistAndSongIds(gpl, commands);
|
||||
|
||||
StringBuilder sb = new StringBuilder("Are you sure you want to delete the following songs from playlist " + playlist + "?\n");
|
||||
for (GuildPlaylistSong gpls : songs) {
|
||||
GuildSong gs = gpls.getGuildSong();
|
||||
sb.append(String.format("**%s** by __%s__%n", gs.getSong().getTitle(), gs.getSong().getArtist()));
|
||||
}
|
||||
|
||||
MessageEmbed embed = new EmbedBuilder()
|
||||
.setColor(Color.RED)
|
||||
.setTitle("Delete Playlist Songs")
|
||||
.setDescription(sb.toString())
|
||||
.setTimestamp(OffsetDateTime.now())
|
||||
.setFooter(event.getGuild().getSelfMember().getEffectiveName(), event.getGuild().getSelfMember().getUser().getAvatarUrl())
|
||||
.build();
|
||||
|
||||
event.getChannel().sendMessage(embed).queue((msg) -> {
|
||||
|
||||
ReactionListener<String> handler = new ReactionListener<>(userId, msg.getId());
|
||||
handler.setExpiresIn(TimeUnit.MINUTES, 1);
|
||||
handler.registerReaction(Reactions.CHECK_MARK_BUTTON, (ret) -> deletePlayListSongConfirm(songs, event.getMember().getAsMention(), msg));
|
||||
handler.registerReaction(Reactions.CROSS_MARK_BUTTON, (ret) -> deleteMessage(msg));
|
||||
|
||||
reactionHandler.addReactionListener(guildId, msg, handler);
|
||||
});
|
||||
}
|
||||
|
||||
private void deletePlayListSongConfirm(List<GuildPlaylistSong> songs, String user, Message msg) {
|
||||
try {
|
||||
guildSongRepoService.getGuildPlaylistSongRepo().deleteAll(songs);
|
||||
msg.getChannel().sendMessage(user + ", songs removed successfully fom playlist").complete();
|
||||
} catch (Exception ex) {
|
||||
msg.getChannel().sendMessage("Sorry " + user + " I was unable to remove songs from the playlist. Reason: " + ex.getMessage()).complete();
|
||||
logger.error("Unable to delete songs from playlist : " + ex.getMessage());
|
||||
logger.error(ex);
|
||||
} finally {
|
||||
deleteMessage(msg);
|
||||
}
|
||||
}
|
||||
|
||||
private void deletePlayListConfirm(GuildPlaylist gpl, String user, Message msg) {
|
||||
String playlist = gpl.getPlaylist();
|
||||
try {
|
||||
guildSongRepoService.getGuildPlaylistRepo().delete(gpl);
|
||||
msg.getChannel().sendMessage(user + " " + playlist + " deleted successfully").complete();
|
||||
} catch (Exception ex) {
|
||||
msg.getChannel().sendMessage("Sorry " + user + " I was unable to remove playlist " + playlist + ". Reason: " + ex.getMessage()).complete();
|
||||
logger.error("Unable to delete playlist " + playlist + ": " + ex.getMessage());
|
||||
logger.error(ex);
|
||||
} finally {
|
||||
deleteMessage(msg);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void addPlayList(GuildMessageReceivedEvent event, List<String> commands) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
if (commands == null || commands.isEmpty()) {
|
||||
event.getChannel().sendMessage(event.getAuthor().getAsMention() + " you have to provide the playlist to create a new playlist (no spaces in name) and optionally a list of uuids for songs to add").queue();
|
||||
return;
|
||||
}
|
||||
|
||||
Long guildId = event.getGuild().getIdLong();
|
||||
|
||||
DiscordGuild guild = guildSongRepoService.getGuildRepo().findByGuildId(guildId);
|
||||
if (guild == null) {
|
||||
event.getChannel().sendMessage("Unable to find guild in local database. Please contact administrator").queue();
|
||||
return;
|
||||
}
|
||||
|
||||
String playlist = commands.remove(0);
|
||||
|
||||
long userId = event.getMember().getIdLong();
|
||||
|
||||
GuildPlaylist gpl = guildSongRepoService.getGuildPlaylistRepo().findByGuildAndUserIdAndPlaylist(guild, userId, playlist);
|
||||
boolean newList = false;
|
||||
if (gpl != null && commands.isEmpty()) {
|
||||
event.getChannel().sendMessage(event.getAuthor().getAsMention() + " a playlist with the name " + playlist + " already exist for you.").queue();
|
||||
return;
|
||||
} else if (gpl == null) {
|
||||
newList = true;
|
||||
gpl = new GuildPlaylist();
|
||||
gpl.setDateAdded(new Date());
|
||||
gpl.setGuild(guild);
|
||||
gpl.setPlaylist(playlist);
|
||||
gpl.setUserId(userId);
|
||||
guildSongRepoService.getGuildPlaylistRepo().save(gpl);
|
||||
}
|
||||
|
||||
if (commands.isEmpty() && newList) {
|
||||
event.getChannel().sendMessage(event.getAuthor().getAsMention() + " playlist " + playlist + " successfully created.").queue();
|
||||
return;
|
||||
}
|
||||
|
||||
Set<String> songIds = guildSongRepoService.getGuildPlaylistSongRepo()
|
||||
.findByGuildPlaylistAndSongIds(gpl, commands).stream()
|
||||
.map(g -> g.getGuildSong().getUuid())
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
List<GuildPlaylistSong> gplsList = new ArrayList<>();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for(String id : commands.stream().collect(Collectors.toSet())) {
|
||||
GuildSong gs = guildSongRepoService.getGuildSongRepo().findByUuid(id);
|
||||
if (songIds.contains(id)) {
|
||||
sb.append(String.format("**%s** by __%s__ already exists in this playlist.%n", gs.getSong().getTitle(), gs.getSong().getArtist()));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (gs == null) {
|
||||
sb.append("Song with id `" + id + "` not found. Please check id\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
GuildPlaylistSong gpls = new GuildPlaylistSong();
|
||||
gpls.setDateAdded(new Date());
|
||||
gpls.setGuildPlaylist(gpl);
|
||||
gpls.setGuildSong(gs);
|
||||
gplsList.add(gpls);
|
||||
|
||||
sb.append(String.format("**%s** by __%s__ added to playlist.%n", gs.getSong().getTitle(), gs.getSong().getArtist()));
|
||||
}
|
||||
|
||||
if (!gplsList.isEmpty()) {
|
||||
guildSongRepoService.getGuildPlaylistSongRepo().saveAll(gplsList);
|
||||
}
|
||||
|
||||
MessageEmbed embed = new EmbedBuilder()
|
||||
.setTitle("Results for adding playlist " + playlist)
|
||||
.setAuthor(event.getMember().getEffectiveName(), null, event.getAuthor().getAvatarUrl())
|
||||
.setColor(Color.GREEN)
|
||||
.setDescription(sb.toString())
|
||||
.setFooter("", event.getGuild().getSelfMember().getUser().getAvatarUrl())
|
||||
.setTimestamp(OffsetDateTime.now())
|
||||
.build();
|
||||
|
||||
event.getChannel().sendMessage(embed).queue();
|
||||
}
|
||||
|
||||
private void deleteMessage(Message msg) {
|
||||
try {
|
||||
msg.delete().complete();
|
||||
reactionHandler.removeReactionListener(guildId, msg.getIdLong());
|
||||
} catch (ErrorResponseException ex) {
|
||||
if (ex.getErrorResponse() != ErrorResponse.UNKNOWN_MESSAGE) throw ex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,133 @@
|
||||
/**
|
||||
*
|
||||
* Project: Pseudo-Bot, File: ReactionHandler.java
|
||||
*
|
||||
* Copyright 2019 Locusworks LLC.
|
||||
* All rights reserved. Federal copyright law prohibits unauthorized reproduction by
|
||||
* any means and imposes fines up to $25,000 for violation. No part of this material
|
||||
* may be reproduced, transmitted, transcribed, stored in a retrieval system, copied,
|
||||
* modified, duplicated, adapted or translated into another program language in any
|
||||
* form or by any means, electronic, mechanical, photocopying, recording, or
|
||||
* otherwise, without the prior written permission from Locusworks. Locusworks
|
||||
* affirms that PSEUDO-BOT(R) software and data is subject to United States
|
||||
* Government Purpose Rights. Contact Locusworks, 1313 Lawnview Drive
|
||||
* Forney TX 75126, (802) 488-0438, for commercial licensing opportunities.
|
||||
*
|
||||
* IN NO EVENT SHALL LOCUSWORKS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL,
|
||||
* INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT
|
||||
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF LOCUSWORKS HAS BEEN
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. NO RESPONSIBILITY IS ASSUMED BY
|
||||
* LOCUSWORKS FOR ITS USE, OR FOR ANY INFRINGEMENTS OF PATENTS OR OTHER RIGHTS OF
|
||||
* THIRD PARTIES RESULTING FROM ITS USE. LOCUSWORKS SPECIFICALLY DISCLAIMS ANY
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE AND
|
||||
* ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS
|
||||
* IS". LOCUSWORKS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
|
||||
* ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*/
|
||||
package net.locusworks.discord.eighttrack.handlers;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import net.dv8tion.jda.api.Permission;
|
||||
import net.dv8tion.jda.api.entities.ChannelType;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.entities.MessageReaction;
|
||||
import net.dv8tion.jda.api.entities.TextChannel;
|
||||
import net.dv8tion.jda.api.requests.RestAction;
|
||||
import net.dv8tion.jda.internal.utils.PermissionUtil;
|
||||
import net.locusworks.discord.eighttrack.listeners.ReactionListener;
|
||||
|
||||
@Component
|
||||
public class ReactionHandler {
|
||||
|
||||
private final ConcurrentHashMap<Long, ConcurrentHashMap<Long, ReactionListener<?>>> reactions;
|
||||
|
||||
private ReactionHandler() {
|
||||
reactions = new ConcurrentHashMap<>();
|
||||
}
|
||||
|
||||
public synchronized void addReactionListener(long guildId, Message message, ReactionListener<?> handler) {
|
||||
addReactionListener(guildId, message, handler, true);
|
||||
}
|
||||
|
||||
public synchronized void addReactionListener(long guildId, Message message, ReactionListener<?> handler, boolean queue) {
|
||||
if (handler == null) {
|
||||
return;
|
||||
}
|
||||
if (message.getChannelType().equals(ChannelType.TEXT)) {
|
||||
if (!PermissionUtil.checkPermission(message.getTextChannel(), message.getGuild().getSelfMember(), Permission.MESSAGE_ADD_REACTION)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!reactions.containsKey(guildId)) {
|
||||
reactions.put(guildId, new ConcurrentHashMap<>());
|
||||
}
|
||||
if (!reactions.get(guildId).containsKey(message.getIdLong())) {
|
||||
for (String emote : handler.getEmotes()) {
|
||||
RestAction<Void> action = message.addReaction(emote);
|
||||
if (queue) action.queue(); else action.complete();
|
||||
}
|
||||
}
|
||||
reactions.get(guildId).put(message.getIdLong(), handler);
|
||||
}
|
||||
|
||||
public synchronized void removeReactionListener(long guildId, long messageId) {
|
||||
if (!reactions.containsKey(guildId)) return;
|
||||
reactions.get(guildId).remove(messageId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the reaction
|
||||
*
|
||||
* @param channel TextChannel of the message
|
||||
* @param messageId id of the message
|
||||
* @param userId id of the user reacting
|
||||
* @param reaction the reaction
|
||||
*/
|
||||
public void handle(TextChannel channel, long messageId, long userId, MessageReaction reaction) {
|
||||
ReactionListener<?> listener = reactions.get(channel.getGuild().getIdLong()).get(messageId);
|
||||
if (!listener.isActive() || listener.getExpiresInTimestamp() < System.currentTimeMillis()) {
|
||||
reactions.get(channel.getGuild().getIdLong()).remove(messageId);
|
||||
} else if ((listener.hasReaction(reaction.getReactionEmote().getName())) && listener.getUserId() == userId) {
|
||||
reactions.get(channel.getGuild().getIdLong()).get(messageId).updateLastAction();
|
||||
Message message = channel.retrieveMessageById(messageId).complete();
|
||||
listener.react(reaction.getReactionEmote().getName(), message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Do we have an event for a message?
|
||||
*
|
||||
* @param guildId discord guild-id of the message
|
||||
* @param messageId id of the message
|
||||
* @return do we have an handler?
|
||||
*/
|
||||
public boolean canHandle(long guildId, long messageId) {
|
||||
return reactions.containsKey(guildId) && reactions.get(guildId).containsKey(messageId);
|
||||
}
|
||||
|
||||
public synchronized void removeGuild(long guildId) {
|
||||
reactions.remove(guildId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete expired handlers
|
||||
*/
|
||||
public synchronized void cleanCache() {
|
||||
long now = System.currentTimeMillis();
|
||||
for (Iterator<Map.Entry<Long, ConcurrentHashMap<Long, ReactionListener<?>>>> iterator = reactions.entrySet().iterator(); iterator.hasNext(); ) {
|
||||
Map.Entry<Long, ConcurrentHashMap<Long, ReactionListener<?>>> mapEntry = iterator.next();
|
||||
mapEntry.getValue().values().removeIf(listener -> !listener.isActive() || listener.getExpiresInTimestamp() < now);
|
||||
if (mapEntry.getValue().values().isEmpty()) {
|
||||
reactions.remove(mapEntry.getKey());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,139 @@
|
||||
/**
|
||||
*
|
||||
* Project: Pseudo-Bot, File: ReactionListener.java
|
||||
*
|
||||
* Copyright 2019 Locusworks LLC.
|
||||
* All rights reserved. Federal copyright law prohibits unauthorized reproduction by
|
||||
* any means and imposes fines up to $25,000 for violation. No part of this material
|
||||
* may be reproduced, transmitted, transcribed, stored in a retrieval system, copied,
|
||||
* modified, duplicated, adapted or translated into another program language in any
|
||||
* form or by any means, electronic, mechanical, photocopying, recording, or
|
||||
* otherwise, without the prior written permission from Locusworks. Locusworks
|
||||
* affirms that PSEUDO-BOT(R) software and data is subject to United States
|
||||
* Government Purpose Rights. Contact Locusworks, 1313 Lawnview Drive
|
||||
* Forney TX 75126, (802) 488-0438, for commercial licensing opportunities.
|
||||
*
|
||||
* IN NO EVENT SHALL LOCUSWORKS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL,
|
||||
* INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT
|
||||
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF LOCUSWORKS HAS BEEN
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. NO RESPONSIBILITY IS ASSUMED BY
|
||||
* LOCUSWORKS FOR ITS USE, OR FOR ANY INFRINGEMENTS OF PATENTS OR OTHER RIGHTS OF
|
||||
* THIRD PARTIES RESULTING FROM ITS USE. LOCUSWORKS SPECIFICALLY DISCLAIMS ANY
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE AND
|
||||
* ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS
|
||||
* IS". LOCUSWORKS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
|
||||
* ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*/
|
||||
package net.locusworks.discord.eighttrack.listeners;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
|
||||
public class ReactionListener<T> {
|
||||
|
||||
private final Map<String, Consumer<Message>> reactions;
|
||||
private final long userId;
|
||||
private volatile T data;
|
||||
private Long expiresIn, lastAction;
|
||||
private boolean active;
|
||||
|
||||
public ReactionListener(long userId, T data) {
|
||||
this.data = data;
|
||||
this.userId = userId;
|
||||
reactions = new LinkedHashMap<>();
|
||||
active = true;
|
||||
lastAction = System.currentTimeMillis();
|
||||
expiresIn = TimeUnit.MINUTES.toMillis(5);
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return active;
|
||||
}
|
||||
|
||||
public void disable() {
|
||||
this.active = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* The time after which this listener expires which is now + specified time
|
||||
* Defaults to now+5min
|
||||
*
|
||||
* @param timeUnit time units
|
||||
* @param time amount of time units
|
||||
*/
|
||||
public void setExpiresIn(TimeUnit timeUnit, long time) {
|
||||
expiresIn = timeUnit.toMillis(time);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this listener has specified emote
|
||||
*
|
||||
* @param emote the emote to check for
|
||||
* @return does this listener do anything with this emote?
|
||||
*/
|
||||
public boolean hasReaction(String emote) {
|
||||
return reactions.containsKey(emote);
|
||||
}
|
||||
|
||||
/**
|
||||
* React to the reaction :')
|
||||
*
|
||||
* @param emote the emote used
|
||||
* @param message the message bound to the reaction
|
||||
*/
|
||||
public void react(String emote, Message message) {
|
||||
if (hasReaction(emote)) reactions.get(emote).accept(message);
|
||||
}
|
||||
|
||||
public T getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(T data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a consumer for a specified emote
|
||||
* Multiple emote's will result in overriding the old one
|
||||
*
|
||||
* @param emote the emote to respond to
|
||||
* @param consumer the behaviour when emote is used
|
||||
*/
|
||||
public void registerReaction(String emote, Consumer<Message> consumer) {
|
||||
reactions.put(emote, consumer);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list of all emotes used in this reaction listener
|
||||
*/
|
||||
public Set<String> getEmotes() {
|
||||
return reactions.keySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* updates the timestamp when the reaction was last accessed
|
||||
*/
|
||||
public void updateLastAction() {
|
||||
lastAction = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
/**
|
||||
* When does this reaction listener expire?
|
||||
*
|
||||
* @return timestamp in millis
|
||||
*/
|
||||
public Long getExpiresInTimestamp() {
|
||||
return lastAction + expiresIn;
|
||||
}
|
||||
|
||||
public long getUserId() {
|
||||
return userId;
|
||||
}
|
||||
}
|
@ -78,6 +78,10 @@ public class TrackScheduler extends AudioEventAdapter implements AudioEventListe
|
||||
trackQueue.add(at);
|
||||
}
|
||||
}
|
||||
|
||||
public void clearTracks() {
|
||||
trackQueue.clear();
|
||||
}
|
||||
|
||||
public void noMatches() {
|
||||
// TODO Auto-generated method stub
|
||||
@ -106,6 +110,5 @@ public class TrackScheduler extends AudioEventAdapter implements AudioEventListe
|
||||
public boolean playing() {
|
||||
return started;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -30,6 +30,8 @@ package net.locusworks.discord.eighttrack.services;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import net.locusworks.discord.eighttrack.database.repos.GuildPlaylistRepository;
|
||||
import net.locusworks.discord.eighttrack.database.repos.GuildPlaylistSongRepository;
|
||||
import net.locusworks.discord.eighttrack.database.repos.GuildRepository;
|
||||
import net.locusworks.discord.eighttrack.database.repos.GuildSongRepository;
|
||||
import net.locusworks.discord.eighttrack.database.repos.SongRepository;
|
||||
@ -43,6 +45,12 @@ public class GuildSongRepoService {
|
||||
@Autowired
|
||||
private GuildSongRepository guildSongRepo;
|
||||
|
||||
@Autowired
|
||||
private GuildPlaylistRepository guildPlaylistRepo;
|
||||
|
||||
@Autowired
|
||||
private GuildPlaylistSongRepository guildPlaylistSongRepo;
|
||||
|
||||
@Autowired
|
||||
private SongRepository songRepo;
|
||||
|
||||
@ -60,6 +68,20 @@ public class GuildSongRepoService {
|
||||
return guildSongRepo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the guildPlaylistRepo
|
||||
*/
|
||||
public final GuildPlaylistRepository getGuildPlaylistRepo() {
|
||||
return guildPlaylistRepo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the guildPlaylistSongRepo
|
||||
*/
|
||||
public final GuildPlaylistSongRepository getGuildPlaylistSongRepo() {
|
||||
return guildPlaylistSongRepo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the songRepo
|
||||
*/
|
||||
|
@ -0,0 +1,37 @@
|
||||
/**
|
||||
*
|
||||
* Project: Pseudo-Bot, File: Reactions.java
|
||||
*
|
||||
* Copyright 2019 Locusworks LLC.
|
||||
* All rights reserved. Federal copyright law prohibits unauthorized reproduction by
|
||||
* any means and imposes fines up to $25,000 for violation. No part of this material
|
||||
* may be reproduced, transmitted, transcribed, stored in a retrieval system, copied,
|
||||
* modified, duplicated, adapted or translated into another program language in any
|
||||
* form or by any means, electronic, mechanical, photocopying, recording, or
|
||||
* otherwise, without the prior written permission from Locusworks. Locusworks
|
||||
* affirms that PSEUDO-BOT(R) software and data is subject to United States
|
||||
* Government Purpose Rights. Contact Locusworks, 1313 Lawnview Drive
|
||||
* Forney TX 75126, (802) 488-0438, for commercial licensing opportunities.
|
||||
*
|
||||
* IN NO EVENT SHALL LOCUSWORKS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL,
|
||||
* INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT
|
||||
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF LOCUSWORKS HAS BEEN
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. NO RESPONSIBILITY IS ASSUMED BY
|
||||
* LOCUSWORKS FOR ITS USE, OR FOR ANY INFRINGEMENTS OF PATENTS OR OTHER RIGHTS OF
|
||||
* THIRD PARTIES RESULTING FROM ITS USE. LOCUSWORKS SPECIFICALLY DISCLAIMS ANY
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE AND
|
||||
* ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS
|
||||
* IS". LOCUSWORKS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
|
||||
* ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*/
|
||||
package net.locusworks.discord.eighttrack.utils;
|
||||
|
||||
public class Reactions {
|
||||
|
||||
public static final String CHECK_MARK_BUTTON = "\u2705";
|
||||
public static final String CHECK_MARK = "\u2714";
|
||||
public static final String CROSS_MARK_BUTTON = "\u274e";
|
||||
public static final String CROSS_MARK = "\u274c";
|
||||
|
||||
}
|
Reference in New Issue
Block a user