package cc.fascinated.bat.features.spotify; import cc.fascinated.bat.Emojis; import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.SpotifyUtils; import cc.fascinated.bat.features.Feature; import cc.fascinated.bat.features.FeatureProfile; import cc.fascinated.bat.features.spotify.command.SpotifyCommand; import cc.fascinated.bat.features.spotify.profile.SpotifyProfile; import cc.fascinated.bat.model.BatUser; import cc.fascinated.bat.service.CommandService; import cc.fascinated.bat.service.SpotifyService; import lombok.NonNull; import lombok.SneakyThrows; import net.dv8tion.jda.api.EmbedBuilder; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Component; import se.michaelthelin.spotify.enums.Action; 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) */ @Component public class SpotifyFeature extends Feature { @Autowired public SpotifyFeature(@NonNull ApplicationContext context, @NonNull CommandService commandService) { super("Spotify", FeatureProfile.FeatureState.DISABLED, true); super.registerCommand(commandService, context.getBean(SpotifyCommand.class)); } /** * Pre-checks for Spotify commands. * * @param spotifyService The Spotify service. * @param user The user. */ public static EmbedBuilder checkSpotify(@NonNull SpotifyService spotifyService, @NonNull BatUser user) { SpotifyProfile profile = user.getProfile(SpotifyProfile.class); if (!profile.hasLinkedAccount()) { return EmbedUtils.errorEmbed() .setDescription("%s You need to link your Spotify account before you can use this command.".formatted(Emojis.CROSS_MARK_EMOJI)); } if (!spotifyService.hasTrackPlaying(user)) { return EmbedUtils.errorEmbed() .setDescription("%s You need to have Spotify Premium to use this command.".formatted(Emojis.CROSS_MARK_EMOJI)); } return null; } /** * Gets the currently playing song. * * @param spotifyService The Spotify service. * @param user The user. */ @SneakyThrows public static EmbedBuilder currentSong(@NonNull SpotifyService spotifyService, @NonNull BatUser user) { SpotifyProfile profile = user.getProfile(SpotifyProfile.class); if (!profile.hasLinkedAccount() || !spotifyService.hasTrackPlaying(user)) { return checkSpotify(spotifyService, user); } 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() .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() || !spotifyService.hasTrackPlaying(user)) { return checkSpotify(spotifyService, user); } CurrentlyPlaying currentlyPlaying = spotifyService.getCurrentlyPlayingTrack(user); Track track = (Track) currentlyPlaying.getItem(); String trackName = track.getName(); spotifyService.skipTrack(user); // Skip the track // Get the new track 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() || !spotifyService.hasTrackPlaying(user)) { return checkSpotify(spotifyService, user); } CurrentlyPlaying currentlyPlaying = spotifyService.getCurrentlyPlayingTrack(user); for (Action action : currentlyPlaying.getActions().getDisallows().getDisallowedActions()) { if (action.equals(Action.PAUSING)) { return EmbedUtils.errorEmbed() .setDescription("%s This track is already paused.".formatted(Emojis.CROSS_MARK_EMOJI)); } } spotifyService.pausePlayback(user); Track track = (Track) currentlyPlaying.getItem(); return EmbedUtils.successEmbed() .setDescription("%s Paused the track **[%s | %s](%s)**".formatted( Emojis.CHECK_MARK_EMOJI, track.getName(), track.getArtists()[0].getName(), SpotifyUtils.getTrackUrl(currentlyPlaying) )); } /** * 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() || !spotifyService.hasTrackPlaying(user)) { return checkSpotify(spotifyService, user); } CurrentlyPlaying currentlyPlaying = spotifyService.getCurrentlyPlayingTrack(user); for (Action action : currentlyPlaying.getActions().getDisallows().getDisallowedActions()) { if (action.equals(Action.RESUMING)) { return EmbedUtils.errorEmbed() .setDescription("%s This track is already playing.".formatted(Emojis.CROSS_MARK_EMOJI)); } } spotifyService.resumePlayback(user); Track track = (Track) currentlyPlaying.getItem(); return EmbedUtils.successEmbed() .setDescription("%s Resumed the track **[%s | %s](%s)**".formatted( Emojis.CHECK_MARK_EMOJI, track.getName(), track.getArtists()[0].getName(), SpotifyUtils.getTrackUrl(currentlyPlaying) )); } }