From 86c7afac425bee076ccb0084fb9f4d75db015808 Mon Sep 17 00:00:00 2001 From: Liam Date: Sat, 29 Jun 2024 22:38:53 +0100 Subject: [PATCH] many changes --- src/main/java/cc/fascinated/bat/Emojis.java | 6 + .../fascinated/bat/common/SpotifyUtils.java | 69 ++++++++ .../bat/exception/BatException.java | 10 ++ .../bat/features/spotify/SpotifyFeature.java | 158 +++++++++++++++++- .../spotify/command/CurrentSubCommand.java | 105 ++++++------ .../spotify/command/LinkSubCommand.java | 26 +-- .../spotify/command/PauseSubCommand.java | 28 +--- .../spotify/command/ResumeSubCommand.java | 29 +--- .../spotify/command/SkipSubCommand.java | 66 +------- .../spotify/command/UnlinkSubCommand.java | 11 +- .../bat/service/CommandService.java | 7 +- 11 files changed, 314 insertions(+), 201 deletions(-) create mode 100644 src/main/java/cc/fascinated/bat/common/SpotifyUtils.java create mode 100644 src/main/java/cc/fascinated/bat/exception/BatException.java diff --git a/src/main/java/cc/fascinated/bat/Emojis.java b/src/main/java/cc/fascinated/bat/Emojis.java index 27b4bbb..84b52e0 100644 --- a/src/main/java/cc/fascinated/bat/Emojis.java +++ b/src/main/java/cc/fascinated/bat/Emojis.java @@ -14,6 +14,9 @@ public class Emojis { public static final Emoji CHECK_MARK_EMOJI; public static final Emoji CROSS_MARK_EMOJI; public static final Emoji SAD_FACE_EMOJI; + public static final Emoji PAUSE_EMOJI; + public static final Emoji PLAY_EMOJI; + public static final Emoji SKIP_EMOJI; /** * Presence Status Emojis @@ -34,6 +37,9 @@ public class Emojis { IDLE_EMOJI = jda.getEmojiById("1256662632203685991"); DND_EMOJI = jda.getEmojiById("1256662572933845032"); OFFLINE_EMOJI = jda.getEmojiById("1256662679402053662"); + PAUSE_EMOJI = Emoji.fromUnicode("⏸"); + PLAY_EMOJI = Emoji.fromUnicode("▶"); + SKIP_EMOJI = Emoji.fromUnicode("⏭"); log.info("Loaded emojis!"); } } diff --git a/src/main/java/cc/fascinated/bat/common/SpotifyUtils.java b/src/main/java/cc/fascinated/bat/common/SpotifyUtils.java new file mode 100644 index 0000000..28e90a4 --- /dev/null +++ b/src/main/java/cc/fascinated/bat/common/SpotifyUtils.java @@ -0,0 +1,69 @@ +package cc.fascinated.bat.common; + +import cc.fascinated.bat.model.BatUser; +import cc.fascinated.bat.service.SpotifyService; +import lombok.NonNull; +import lombok.extern.log4j.Log4j2; +import se.michaelthelin.spotify.model_objects.miscellaneous.CurrentlyPlaying; +import se.michaelthelin.spotify.model_objects.specification.Track; + +/** + * @author Fascinated (fascinated7) + */ +@Log4j2 +public class SpotifyUtils { + /** + * Gets the URL of the track that is currently playing. + * + * @param currentlyPlaying The currently playing object. + * @return The URL of the track that is currently playing. + */ + public static String getTrackUrl(CurrentlyPlaying currentlyPlaying) { + return "https://open.spotify.com/track/" + currentlyPlaying.getItem().getId(); + } + + /** + * Gets the formatted time of the currently playing track + * + * @param currentlyPlaying the currently playing track + * @return the formatted time + */ + public static String getFormattedTime(@NonNull CurrentlyPlaying currentlyPlaying) { + Track track = (Track) currentlyPlaying.getItem(); + int currentMinutes = currentlyPlaying.getProgress_ms() / 1000 / 60; + int currentSeconds = currentlyPlaying.getProgress_ms() / 1000 % 60; + int totalMinutes = track.getDurationMs() / 1000 / 60; + int totalSeconds = track.getDurationMs() / 1000 % 60; + + return "`%02d:%02d`/`%02d:%02d`".formatted(currentMinutes, currentSeconds, totalMinutes, totalSeconds); + } + + /** + * Get the next track that is playing + * + * @param user The user to get the track for + * @param oldName The name of the old track + * @return The new track + */ + public static CurrentlyPlaying getNewTrack(@NonNull SpotifyService spotifyService, @NonNull BatUser user, @NonNull String oldName) { + int checks = 0; + + try { + Thread.sleep(150); + while (checks < 10) { + CurrentlyPlaying currentlyPlaying = spotifyService.getCurrentlyPlayingTrack(user); + Track track = (Track) currentlyPlaying.getItem(); + if (track.getName().equals(oldName)) { + Thread.sleep(250); + checks++; + } else { + log.info("Found new track {} in {} checks", track.getName(), checks); + return currentlyPlaying; + } + } + } catch (InterruptedException e) { + e.printStackTrace(); + } + return null; + } +} diff --git a/src/main/java/cc/fascinated/bat/exception/BatException.java b/src/main/java/cc/fascinated/bat/exception/BatException.java new file mode 100644 index 0000000..7c9cf21 --- /dev/null +++ b/src/main/java/cc/fascinated/bat/exception/BatException.java @@ -0,0 +1,10 @@ +package cc.fascinated.bat.exception; + +/** + * @author Fascinated (fascinated7) + */ +public class BatException extends Exception { + public BatException(String message) { + super(message); + } +} diff --git a/src/main/java/cc/fascinated/bat/features/spotify/SpotifyFeature.java b/src/main/java/cc/fascinated/bat/features/spotify/SpotifyFeature.java index 8529cae..eb8cafe 100644 --- a/src/main/java/cc/fascinated/bat/features/spotify/SpotifyFeature.java +++ b/src/main/java/cc/fascinated/bat/features/spotify/SpotifyFeature.java @@ -3,10 +3,25 @@ package cc.fascinated.bat.features.spotify; import cc.fascinated.bat.Emojis; import cc.fascinated.bat.command.Category; import cc.fascinated.bat.common.EmbedUtils; +import cc.fascinated.bat.common.SpotifyUtils; +import cc.fascinated.bat.exception.BatException; import cc.fascinated.bat.features.Feature; +import cc.fascinated.bat.features.spotify.profile.SpotifyProfile; +import cc.fascinated.bat.model.BatUser; +import cc.fascinated.bat.service.SpotifyService; +import com.fasterxml.jackson.datatype.jsr310.deser.JSR310DateTimeDeserializerBase; +import lombok.NonNull; +import lombok.SneakyThrows; +import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.entities.MessageEmbed; +import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; +import net.dv8tion.jda.api.interactions.components.ComponentInteraction; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import se.michaelthelin.spotify.model_objects.miscellaneous.CurrentlyPlaying; +import se.michaelthelin.spotify.model_objects.specification.AlbumSimplified; +import se.michaelthelin.spotify.model_objects.specification.Image; +import se.michaelthelin.spotify.model_objects.specification.Track; /** * @author Fascinated (fascinated7) @@ -19,13 +34,146 @@ public class SpotifyFeature extends Feature { } /** - * The embed for when a user needs to link their Spotify account. + * Gets the currently playing song. * - * @return The embed. + * @param spotifyService The Spotify service. + * @param user The user. */ - public static MessageEmbed linkAccountEmbed() { + @SneakyThrows + public static EmbedBuilder currentSong(@NonNull SpotifyService spotifyService, @NonNull BatUser user) { + SpotifyProfile profile = user.getProfile(SpotifyProfile.class); + if (!profile.hasLinkedAccount()) { + throw new BatException("%s You need to link your Spotify account before you can use this command.".formatted(Emojis.CROSS_MARK_EMOJI)); + } + + if (!spotifyService.hasTrackPlaying(user)) { + throw new BatException("%s You are not currently playing a track.".formatted(Emojis.CROSS_MARK_EMOJI)); + } + + CurrentlyPlaying currentlyPlaying = spotifyService.getCurrentlyPlayingTrack(user); + Track track = (Track) currentlyPlaying.getItem(); + AlbumSimplified album = track.getAlbum(); + String trackUrl = SpotifyUtils.getTrackUrl(currentlyPlaying); + String albumUrl = "https://open.spotify.com/album/" + album.getId(); + + StringBuilder artists = new StringBuilder(); + for (int i = 0; i < track.getArtists().length; i++) { + artists.append("**[%s](%s)**".formatted(track.getArtists()[i].getName(), "https://open.spotify.com/artist/" + track.getArtists()[i].getId())); + if (i != track.getArtists().length - 1) { + artists.append(", "); + } + } + + Image albumCover = album.getImages()[0]; + return EmbedUtils.genericEmbed() - .setDescription("%s You need to link your Spotify account before you can use this command.".formatted(Emojis.CROSS_MARK_EMOJI)) - .build(); + .setAuthor("Listening to %s | %s".formatted(track.getName(), track.getArtists()[0].getName()), trackUrl) + .setThumbnail(albumCover.getUrl()) + .setDescription(""" + ➜ Song: **[%s](%s)** + ➜ Album: **[%s](%s)** + ➜ Artist%s: %s + ➜ Position: %s + """.formatted( + track.getName(), trackUrl, + album.getName(), albumUrl, + track.getArtists().length > 1 ? "s" : "", artists, + SpotifyUtils.getFormattedTime(currentlyPlaying) + )); + } + + /** + * Skips the current song. + * + * @param spotifyService The Spotify service. + * @param user The user. + */ + @SneakyThrows + public static EmbedBuilder skipSong(@NonNull SpotifyService spotifyService, @NonNull BatUser user) { + SpotifyProfile profile = user.getProfile(SpotifyProfile.class); + if (!profile.hasLinkedAccount()) { + throw new BatException("%s You need to link your Spotify account before you can use this command.".formatted(Emojis.CROSS_MARK_EMOJI)); + } + + if (!spotifyService.hasTrackPlaying(user)) { + throw new BatException("%s You are not currently playing a track.".formatted(Emojis.CROSS_MARK_EMOJI)); + } + + CurrentlyPlaying currentlyPlaying = spotifyService.getCurrentlyPlayingTrack(user); + Track track = (Track) currentlyPlaying.getItem(); + String trackName = track.getName(); + + spotifyService.skipTrack(user); + CurrentlyPlaying newCurrentlyPlaying = SpotifyUtils.getNewTrack(spotifyService, user, trackName); + if (newCurrentlyPlaying == null) { + return EmbedUtils.errorEmbed() + .setDescription("%s There are no more tracks in the queue.".formatted(Emojis.CROSS_MARK_EMOJI)); + } + Track newTrack = (Track) newCurrentlyPlaying.getItem(); + + return EmbedUtils.successEmbed() + .setDescription(""" + :track_next: Skipped the track: **[%s | %s](%s)** + %s New Track: **[%s | %s](%s)** + """.formatted( + trackName, track.getArtists()[0].getName(), SpotifyUtils.getTrackUrl(currentlyPlaying), + Emojis.CHECK_MARK_EMOJI, newTrack.getName(), newTrack.getArtists()[0].getName(), SpotifyUtils.getTrackUrl(newCurrentlyPlaying) + )); + } + + /** + * Pauses the current song. + * + * @param spotifyService The Spotify service. + * @param user The user. + */ + @SneakyThrows + public static EmbedBuilder pauseSong(@NonNull SpotifyService spotifyService, @NonNull BatUser user) { + SpotifyProfile profile = user.getProfile(SpotifyProfile.class); + if (!profile.hasLinkedAccount()) { + throw new BatException("%s You need to link your Spotify account before you can use this command.".formatted(Emojis.CROSS_MARK_EMOJI)); + } + + if (!spotifyService.hasTrackPlaying(user)) { + throw new BatException("%s You are not currently playing a track.".formatted(Emojis.CROSS_MARK_EMOJI)); + } + + boolean didPause = spotifyService.pausePlayback(user); + CurrentlyPlaying currentlyPlaying = spotifyService.getCurrentlyPlayingTrack(user); + Track track = (Track) currentlyPlaying.getItem(); + return EmbedUtils.successEmbed() + .setDescription(didPause ? ":pause_button: Paused the track **[%s | %s](%s)**".formatted( + track.getName(), + track.getArtists()[0].getName(), + SpotifyUtils.getTrackUrl(currentlyPlaying)) + : "%s The current track is already paused.".formatted(Emojis.CROSS_MARK_EMOJI)); + } + + /** + * Resumes the current song. + * + * @param spotifyService The Spotify service. + * @param user The user. + */ + @SneakyThrows + public static EmbedBuilder resumeSong(@NonNull SpotifyService spotifyService, @NonNull BatUser user) { + SpotifyProfile profile = user.getProfile(SpotifyProfile.class); + if (!profile.hasLinkedAccount()) { + throw new BatException("%s You need to link your Spotify account before you can use this command.".formatted(Emojis.CROSS_MARK_EMOJI)); + } + + if (!spotifyService.hasTrackPlaying(user)) { + throw new BatException("%s You are not currently playing a track.".formatted(Emojis.CROSS_MARK_EMOJI)); + } + + boolean didResume = spotifyService.resumePlayback(user); + CurrentlyPlaying currentlyPlaying = spotifyService.getCurrentlyPlayingTrack(user); + Track track = (Track) currentlyPlaying.getItem(); + return EmbedUtils.successEmbed() + .setDescription(didResume ? ":play_pause: Resumed the track **[%s | %s](%s)**".formatted( + track.getName(), + track.getArtists()[0].getName(), + SpotifyUtils.getTrackUrl(currentlyPlaying)) + : "%s The current track is already playing.".formatted(Emojis.CROSS_MARK_EMOJI)); } } diff --git a/src/main/java/cc/fascinated/bat/features/spotify/command/CurrentSubCommand.java b/src/main/java/cc/fascinated/bat/features/spotify/command/CurrentSubCommand.java index 2599e49..7bab2b5 100644 --- a/src/main/java/cc/fascinated/bat/features/spotify/command/CurrentSubCommand.java +++ b/src/main/java/cc/fascinated/bat/features/spotify/command/CurrentSubCommand.java @@ -4,22 +4,27 @@ import cc.fascinated.bat.Emojis; import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.common.EmbedUtils; +import cc.fascinated.bat.event.EventListener; +import cc.fascinated.bat.exception.BatException; import cc.fascinated.bat.features.spotify.SpotifyFeature; import cc.fascinated.bat.features.spotify.profile.SpotifyProfile; import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.model.BatUser; import cc.fascinated.bat.service.SpotifyService; import lombok.NonNull; +import lombok.SneakyThrows; import lombok.extern.log4j.Log4j2; import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; +import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; +import net.dv8tion.jda.api.interactions.components.ActionRow; +import net.dv8tion.jda.api.interactions.components.LayoutComponent; +import net.dv8tion.jda.api.interactions.components.buttons.Button; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import se.michaelthelin.spotify.model_objects.miscellaneous.CurrentlyPlaying; -import se.michaelthelin.spotify.model_objects.specification.AlbumSimplified; -import se.michaelthelin.spotify.model_objects.specification.Image; -import se.michaelthelin.spotify.model_objects.specification.Track; + +import java.util.concurrent.TimeUnit; /** * @author Fascinated (fascinated7) @@ -27,7 +32,7 @@ import se.michaelthelin.spotify.model_objects.specification.Track; @Component @Log4j2 @CommandInfo(name = "current", description = "Gets the currently playing Spotify track") -public class CurrentSubCommand extends BatSubCommand { +public class CurrentSubCommand extends BatSubCommand implements EventListener { private final SpotifyService spotifyService; @Autowired @@ -37,61 +42,59 @@ public class CurrentSubCommand extends BatSubCommand { @Override public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction interaction) { - SpotifyProfile profile = user.getProfile(SpotifyProfile.class); - if (!profile.hasLinkedAccount()) { - interaction.replyEmbeds(SpotifyFeature.linkAccountEmbed()).queue(); + interaction.replyEmbeds(SpotifyFeature.currentSong(spotifyService, user).build()).addComponents(createActions()).queue(); + } + + @Override @SneakyThrows + public void onButtonInteraction(BatGuild guild, @NonNull BatUser user, @NonNull ButtonInteractionEvent event) { + if (!event.getUser().getId().equals(user.getId())) { + throw new BatException("%s You cannot interact with this message.".formatted(Emojis.CROSS_MARK_EMOJI)); + } + + if (!event.getComponentId().equals("pause") + && !event.getComponentId().equals("resume") + && !event.getComponentId().equals("skip")) { return; } - if (!spotifyService.hasTrackPlaying(user)) { - interaction.replyEmbeds(EmbedUtils.errorEmbed() - .setDescription("%s You are not currently playing a track.".formatted(Emojis.CROSS_MARK_EMOJI)) - .build()) - .queue(); - return; - } - CurrentlyPlaying currentlyPlaying = spotifyService.getCurrentlyPlayingTrack(user); - Track track = (Track) currentlyPlaying.getItem(); - AlbumSimplified album = track.getAlbum(); - String trackUrl = "https://open.spotify.com/track/" + track.getId(); - String albumUrl = "https://open.spotify.com/album/" + album.getId(); - - StringBuilder artists = new StringBuilder(); - for (int i = 0; i < track.getArtists().length; i++) { - artists.append("**[%s](%s)**".formatted(track.getArtists()[i].getName(), "https://open.spotify.com/artist/" + track.getArtists()[i].getId())); - if (i != track.getArtists().length - 1) { - artists.append(", "); + switch (event.getComponentId()) { + case "pause" -> { + event.replyEmbeds(SpotifyFeature.pauseSong(spotifyService, user) + .appendDescription("\nThis message will disappear ".formatted(System.currentTimeMillis() / 1000 + 15)).build()) + .queue(message -> { + message.deleteOriginal().queueAfter(15, TimeUnit.SECONDS); + }); + } + case "resume" -> { + event.replyEmbeds(SpotifyFeature.resumeSong(spotifyService, user) + .appendDescription("\nThis message will disappear ".formatted(System.currentTimeMillis() / 1000 + 15)).build()) + .queue(message -> { + message.deleteOriginal().queueAfter(15, TimeUnit.SECONDS); + }); + } + case "skip" -> { + event.replyEmbeds(SpotifyFeature.skipSong(spotifyService, user) + .appendDescription("\nThis message will disappear ".formatted(System.currentTimeMillis() / 1000 + 15)).build()) + .queue(then -> { + then.deleteOriginal().queueAfter(15, TimeUnit.SECONDS); + event.getInteraction().getMessage().editMessageEmbeds(SpotifyFeature.currentSong(spotifyService, user).build()).queue(); + }); } } - - String description = - "➜ Song: **[%s](%s)**\n".formatted(track.getName(), trackUrl) + - "➜ Album: **[%s](%s)**\n".formatted(album.getName(), albumUrl) + - "➜ Artist%s: %s\n".formatted(track.getArtists().length > 1 ? "s" : "", artists) + - "➜ Position: %s\n".formatted(getFormattedTime(currentlyPlaying)); - - Image albumCover = album.getImages()[0]; - interaction.replyEmbeds(EmbedUtils.genericEmbed() - .setAuthor("Listening to %s | %s".formatted(track.getName(), track.getArtists()[0].getName()), trackUrl) - .setThumbnail(albumCover.getUrl()) - .setDescription(description) - .build()).queue(); } - /** - * Gets the formatted time of the currently playing track + * Creates the action buttons for the currently playing track * - * @param currentlyPlaying the currently playing track - * @return the formatted time + * @return The action buttons */ - private String getFormattedTime(@NonNull CurrentlyPlaying currentlyPlaying) { - Track track = (Track) currentlyPlaying.getItem(); - int currentMinutes = currentlyPlaying.getProgress_ms() / 1000 / 60; - int currentSeconds = currentlyPlaying.getProgress_ms() / 1000 % 60; - int totalMinutes = track.getDurationMs() / 1000 / 60; - int totalSeconds = track.getDurationMs() / 1000 % 60; - - return "`%02d:%02d`/`%02d:%02d`".formatted(currentMinutes, currentSeconds, totalMinutes, totalSeconds); + private LayoutComponent[] createActions() { + return new LayoutComponent[]{ + ActionRow.of( + Button.primary("pause", "Pause").withEmoji(Emojis.PAUSE_EMOJI), + Button.primary("resume", "Resume").withEmoji(Emojis.PLAY_EMOJI), + Button.primary("skip", "Skip").withEmoji(Emojis.SKIP_EMOJI) + ) + }; } } diff --git a/src/main/java/cc/fascinated/bat/features/spotify/command/LinkSubCommand.java b/src/main/java/cc/fascinated/bat/features/spotify/command/LinkSubCommand.java index 9e2a77f..1a8ea40 100644 --- a/src/main/java/cc/fascinated/bat/features/spotify/command/LinkSubCommand.java +++ b/src/main/java/cc/fascinated/bat/features/spotify/command/LinkSubCommand.java @@ -6,11 +6,13 @@ import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.event.EventListener; +import cc.fascinated.bat.exception.BatException; import cc.fascinated.bat.features.spotify.profile.SpotifyProfile; import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.model.BatUser; import cc.fascinated.bat.service.SpotifyService; import lombok.NonNull; +import lombok.SneakyThrows; import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; import net.dv8tion.jda.api.events.interaction.ModalInteractionEvent; @@ -38,25 +40,17 @@ public class LinkSubCommand extends BatSubCommand implements EventListener { this.spotifyService = spotifyService; } - @Override + @Override @SneakyThrows public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction interaction) { if (!user.getId().equals(Consts.BOT_OWNER)) { - interaction.replyEmbeds(EmbedUtils.genericEmbed() - .setDescription(""" + throw new BatException(""" %s We are currently awaiting Spotify's approval for our application. Please check back later. Submitted on: - """.formatted(Emojis.CROSS_MARK_EMOJI)) - .build()).queue(); - return; + """.formatted(Emojis.CROSS_MARK_EMOJI)); } SpotifyProfile profile = user.getProfile(SpotifyProfile.class); if (profile.hasLinkedAccount()) { - interaction.replyEmbeds(EmbedUtils.errorEmbed() - .setDescription("%s You have already linked your Spotify account!".formatted(Emojis.CROSS_MARK_EMOJI)) - .build()) - .setEphemeral(true) - .queue(); - return; + throw new BatException("%s You have already linked your Spotify account.".formatted(Emojis.CROSS_MARK_EMOJI)); } interaction.replyEmbeds(EmbedUtils.genericEmbed() @@ -88,7 +82,7 @@ public class LinkSubCommand extends BatSubCommand implements EventListener { event.replyModal(modal).queue(); } - @Override + @Override @SneakyThrows public void onModalInteraction(BatGuild guild, @NonNull BatUser user, @NonNull ModalInteractionEvent event) { if (!event.getModalId().equals("link_modal")) { return; @@ -100,11 +94,7 @@ public class LinkSubCommand extends BatSubCommand implements EventListener { } String code = codeMapping.getAsString(); if (!spotifyService.isValidLinkCode(code)) { - event.replyEmbeds(EmbedUtils.errorEmbed() - .setDescription("%s The link code you provided is invalid.".formatted(Emojis.CROSS_MARK_EMOJI)) - .build()) - .queue(); - return; + throw new BatException("%s The link code you provided is invalid.".formatted(Emojis.CROSS_MARK_EMOJI)); } spotifyService.linkAccount(user, code); diff --git a/src/main/java/cc/fascinated/bat/features/spotify/command/PauseSubCommand.java b/src/main/java/cc/fascinated/bat/features/spotify/command/PauseSubCommand.java index 58efc55..53f1837 100644 --- a/src/main/java/cc/fascinated/bat/features/spotify/command/PauseSubCommand.java +++ b/src/main/java/cc/fascinated/bat/features/spotify/command/PauseSubCommand.java @@ -4,6 +4,7 @@ import cc.fascinated.bat.Emojis; import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.common.EmbedUtils; +import cc.fascinated.bat.common.SpotifyUtils; import cc.fascinated.bat.features.spotify.SpotifyFeature; import cc.fascinated.bat.features.spotify.profile.SpotifyProfile; import cc.fascinated.bat.model.BatGuild; @@ -33,31 +34,6 @@ public class PauseSubCommand extends BatSubCommand { @Override public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction interaction) { - SpotifyProfile profile = user.getProfile(SpotifyProfile.class); - if (!profile.hasLinkedAccount()) { - interaction.replyEmbeds(SpotifyFeature.linkAccountEmbed()).queue(); - return; - } - - if (!spotifyService.hasTrackPlaying(user)) { - interaction.replyEmbeds(EmbedUtils.errorEmbed() - .setDescription("%s You need to be playing a track to pause it.".formatted(Emojis.CROSS_MARK_EMOJI)) - .build()) - .queue(); - return; - } - - boolean didPause = spotifyService.pausePlayback(user); - CurrentlyPlaying currentlyPlaying = spotifyService.getCurrentlyPlayingTrack(user); - Track track = (Track) currentlyPlaying.getItem(); - interaction.replyEmbeds(EmbedUtils.successEmbed() - .setDescription(didPause ? ":pause_button: Paused the track **[%s | %s](%s)**".formatted( - track.getName(), - track.getArtists()[0].getName(), - "https://open.spotify.com/track/%s".formatted(track.getId()) - ) - : "%s The current track is already paused.".formatted(Emojis.CROSS_MARK_EMOJI)) - .build()) - .queue(); + interaction.replyEmbeds(SpotifyFeature.pauseSong(spotifyService, user).build()).queue(); } } diff --git a/src/main/java/cc/fascinated/bat/features/spotify/command/ResumeSubCommand.java b/src/main/java/cc/fascinated/bat/features/spotify/command/ResumeSubCommand.java index 9599e1a..7eb8926 100644 --- a/src/main/java/cc/fascinated/bat/features/spotify/command/ResumeSubCommand.java +++ b/src/main/java/cc/fascinated/bat/features/spotify/command/ResumeSubCommand.java @@ -4,6 +4,7 @@ import cc.fascinated.bat.Emojis; import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.common.EmbedUtils; +import cc.fascinated.bat.common.SpotifyUtils; import cc.fascinated.bat.features.spotify.SpotifyFeature; import cc.fascinated.bat.features.spotify.profile.SpotifyProfile; import cc.fascinated.bat.model.BatGuild; @@ -33,32 +34,6 @@ public class ResumeSubCommand extends BatSubCommand { @Override public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction interaction) { - SpotifyProfile profile = user.getProfile(SpotifyProfile.class); - if (!profile.hasLinkedAccount()) { - interaction.replyEmbeds(SpotifyFeature.linkAccountEmbed()).queue(); - return; - } - - if (!spotifyService.hasTrackPlaying(user)) { - interaction.replyEmbeds(EmbedUtils.errorEmbed() - .setDescription("%s You need to be playing a track to resume it.".formatted(Emojis.CROSS_MARK_EMOJI)) - .build()) - .queue(); - return; - } - - boolean didPause = spotifyService.resumePlayback(user); - CurrentlyPlaying currentlyPlaying = spotifyService.getCurrentlyPlayingTrack(user); - Track track = (Track) currentlyPlaying.getItem(); - interaction.replyEmbeds(EmbedUtils.successEmbed() - .setDescription(didPause ? "%s Resumed the track **[%s | %s](%s)**".formatted( - Emojis.CHECK_MARK_EMOJI, - track.getName(), - track.getArtists()[0].getName(), - "https://open.spotify.com/track/%s".formatted(track.getId()) - ) - : "%s The current track is already playing.".formatted(Emojis.CROSS_MARK_EMOJI)) - .build()) - .queue(); + interaction.replyEmbeds(SpotifyFeature.resumeSong(spotifyService, user).build()).queue(); } } diff --git a/src/main/java/cc/fascinated/bat/features/spotify/command/SkipSubCommand.java b/src/main/java/cc/fascinated/bat/features/spotify/command/SkipSubCommand.java index 9a38b67..4b7bd52 100644 --- a/src/main/java/cc/fascinated/bat/features/spotify/command/SkipSubCommand.java +++ b/src/main/java/cc/fascinated/bat/features/spotify/command/SkipSubCommand.java @@ -4,6 +4,7 @@ import cc.fascinated.bat.Emojis; import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.common.EmbedUtils; +import cc.fascinated.bat.common.SpotifyUtils; import cc.fascinated.bat.features.spotify.SpotifyFeature; import cc.fascinated.bat.features.spotify.profile.SpotifyProfile; import cc.fascinated.bat.model.BatGuild; @@ -17,6 +18,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import se.michaelthelin.spotify.model_objects.IPlaylistItem; import se.michaelthelin.spotify.model_objects.miscellaneous.CurrentlyPlaying; import se.michaelthelin.spotify.model_objects.specification.Track; @@ -36,68 +38,6 @@ public class SkipSubCommand extends BatSubCommand { @Override public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction interaction) { - SpotifyProfile profile = user.getProfile(SpotifyProfile.class); - if (!profile.hasLinkedAccount()) { - interaction.replyEmbeds(SpotifyFeature.linkAccountEmbed()).queue(); - return; - } - - if (!spotifyService.hasTrackPlaying(user)) { - interaction.replyEmbeds(EmbedUtils.errorEmbed() - .setDescription("%s You need to be playing a track to skip a track.".formatted(Emojis.CROSS_MARK_EMOJI)) - .build()) - .queue(); - return; - } - - CurrentlyPlaying currentlyPlaying = spotifyService.getCurrentlyPlayingTrack(user); - Track track = (Track) currentlyPlaying.getItem(); - String trackName = track.getName(); - - spotifyService.skipTrack(user); - Track newTrack = getNewTrack(user, trackName); - interaction.replyEmbeds(EmbedUtils.successEmbed() - .setDescription(""" - :track_next: Skipped the track: **[%s | %s](%s)** - %s New Track: **[%s | %s](%s)** - """.formatted( - trackName, - track.getArtists()[0].getName(), - "https://open.spotify.com/track/" + track.getId(), - Emojis.CHECK_MARK_EMOJI, - newTrack.getName(), - newTrack.getArtists()[0].getName(), - "https://open.spotify.com/track/" + newTrack.getId() - )).build()) - .queue(); - } - - /** - * Get the next track that is playing - * - * @param user The user to get the track for - * @param oldName The name of the old track - * @return The new track - */ - public Track getNewTrack(BatUser user, String oldName) { - int checks = 0; - - try { - Thread.sleep(150); - while (checks < 10) { - CurrentlyPlaying currentlyPlaying = spotifyService.getCurrentlyPlayingTrack(user); - Track track = (Track) currentlyPlaying.getItem(); - if (track.getName().equals(oldName)) { - Thread.sleep(250); - checks++; - } else { - log.info("Found new track {} in {} checks", track.getName(), checks); - return (Track) currentlyPlaying.getItem(); - } - } - } catch (InterruptedException e) { - e.printStackTrace(); - } - return null; + interaction.replyEmbeds(SpotifyFeature.skipSong(spotifyService, user).build()).queue(); } } diff --git a/src/main/java/cc/fascinated/bat/features/spotify/command/UnlinkSubCommand.java b/src/main/java/cc/fascinated/bat/features/spotify/command/UnlinkSubCommand.java index ef0c3c3..28dd2ab 100644 --- a/src/main/java/cc/fascinated/bat/features/spotify/command/UnlinkSubCommand.java +++ b/src/main/java/cc/fascinated/bat/features/spotify/command/UnlinkSubCommand.java @@ -5,11 +5,13 @@ import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.event.EventListener; +import cc.fascinated.bat.exception.BatException; import cc.fascinated.bat.features.spotify.profile.SpotifyProfile; import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.model.BatUser; import cc.fascinated.bat.service.UserService; import lombok.NonNull; +import lombok.SneakyThrows; import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; @@ -29,16 +31,11 @@ public class UnlinkSubCommand extends BatSubCommand implements EventListener { this.userService = userService; } - @Override + @Override @SneakyThrows public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction interaction) { SpotifyProfile profile = user.getProfile(SpotifyProfile.class); if (!profile.hasLinkedAccount()) { - interaction.replyEmbeds(EmbedUtils.errorEmbed() - .setDescription("%s You do not have a linked Spotify account.".formatted(Emojis.CROSS_MARK_EMOJI)) - .build()) - .setEphemeral(true) - .queue(); - return; + throw new BatException("%s You do not have a linked Spotify account.".formatted(Emojis.CROSS_MARK_EMOJI)); } profile.reset(); diff --git a/src/main/java/cc/fascinated/bat/service/CommandService.java b/src/main/java/cc/fascinated/bat/service/CommandService.java index aadacb3..f1e6c2e 100644 --- a/src/main/java/cc/fascinated/bat/service/CommandService.java +++ b/src/main/java/cc/fascinated/bat/service/CommandService.java @@ -213,11 +213,10 @@ public class CommandService extends ListenerAdapter { executor.execute(guild, user, ranInsideGuild ? event.getChannel().asTextChannel() : event.getChannel().asPrivateChannel(), event.getMember(), event.getInteraction()); } catch (Exception ex) { - log.error("An error occurred while executing command \"{}\"", commandName, ex); - - event.replyEmbeds(EmbedUtils.successEmbed() - .setDescription("An error occurred while executing the command:\n```java%s```".formatted(ex.getLocalizedMessage())) + event.replyEmbeds(EmbedUtils.errorEmbed() + .setDescription(ex.getLocalizedMessage()) .build()) + .setEphemeral(true) .queue(); } }