add emojis to the spotify commands

This commit is contained in:
Lee 2024-06-29 16:54:39 +01:00
parent 4cb34fbb9a
commit 4821e2a4fa
13 changed files with 100 additions and 56 deletions

@ -0,0 +1,27 @@
package cc.fascinated.bat;
import cc.fascinated.bat.service.DiscordService;
import lombok.extern.log4j.Log4j2;
import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.entities.emoji.Emoji;
/**
* @author Fascinated (fascinated7)
*/
@Log4j2
public class Emojis {
public static final Emoji SPOTIFY_EMOJI;
public static final Emoji CHECK_MARK_EMOJI;
public static final Emoji CROSS_MARK_EMOJI;
public static final Emoji SAD_FACE_EMOJI;
static {
log.info("Loading emojis...");
JDA jda = DiscordService.JDA;
SPOTIFY_EMOJI = jda.getEmojiById("1256629771975266479");
CHECK_MARK_EMOJI = jda.getEmojiById("1256633734065557676");
CROSS_MARK_EMOJI = jda.getEmojiById("1256634487429922897");
SAD_FACE_EMOJI = jda.getEmojiById("1256636078258131055");
log.info("Loaded emojis!");
}
}

@ -7,7 +7,6 @@ import cc.fascinated.bat.common.WebRequest;
import cc.fascinated.bat.model.BatGuild; import cc.fascinated.bat.model.BatGuild;
import cc.fascinated.bat.model.BatUser; import cc.fascinated.bat.model.BatUser;
import cc.fascinated.bat.model.token.randomd.RandomDuck; import cc.fascinated.bat.model.token.randomd.RandomDuck;
import cc.fascinated.bat.model.token.thecatapi.CatImageToken;
import lombok.NonNull; import lombok.NonNull;
import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;

@ -6,8 +6,8 @@ import lombok.experimental.StandardException;
* @author Fascinated (fascinated7) * @author Fascinated (fascinated7)
*/ */
@StandardException @StandardException
public class SpotifyForbiddenException extends RuntimeException { public class SpotifyTokenRefreshException extends RuntimeException {
public SpotifyForbiddenException(String message) { public SpotifyTokenRefreshException(String message) {
super(message); super(message);
} }
} }

@ -1,5 +1,6 @@
package cc.fascinated.bat.features.spotify; package cc.fascinated.bat.features.spotify;
import cc.fascinated.bat.Emojis;
import cc.fascinated.bat.command.Category; import cc.fascinated.bat.command.Category;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.features.Feature; import cc.fascinated.bat.features.Feature;
@ -24,7 +25,7 @@ public class SpotifyFeature extends Feature {
*/ */
public static MessageEmbed linkAccountEmbed() { public static MessageEmbed linkAccountEmbed() {
return EmbedUtils.genericEmbed() return EmbedUtils.genericEmbed()
.setDescription("You need to link your Spotify account before you can use this command.") .setDescription("%s You need to link your Spotify account before you can use this command.".formatted(Emojis.CROSS_MARK_EMOJI))
.build(); .build();
} }
} }

@ -1,5 +1,6 @@
package cc.fascinated.bat.features.spotify.command; package cc.fascinated.bat.features.spotify.command;
import cc.fascinated.bat.Emojis;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatSubCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
@ -44,7 +45,7 @@ public class CurrentSubCommand extends BatSubCommand {
if (!spotifyService.hasTrackPlaying(user)) { if (!spotifyService.hasTrackPlaying(user)) {
interaction.replyEmbeds(EmbedUtils.errorEmbed() interaction.replyEmbeds(EmbedUtils.errorEmbed()
.setDescription("You are not currently playing a track.") .setDescription("%s You are not currently playing a track.".formatted(Emojis.CROSS_MARK_EMOJI))
.build()) .build())
.queue(); .queue();
return; return;

@ -1,5 +1,7 @@
package cc.fascinated.bat.features.spotify.command; package cc.fascinated.bat.features.spotify.command;
import cc.fascinated.bat.Consts;
import cc.fascinated.bat.Emojis;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatSubCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
@ -38,25 +40,33 @@ public class LinkSubCommand extends BatSubCommand implements EventListener {
@Override @Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction interaction) { 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() interaction.replyEmbeds(EmbedUtils.genericEmbed()
.setDescription("We are currently awaiting Spotify's approval for our application. Please check back later.") .setDescription("""
%s We are currently awaiting Spotify's approval for our application. Please check back later.
Submitted on: <t:1719583353>
""".formatted(Emojis.CROSS_MARK_EMOJI))
.build()).queue(); .build()).queue();
// SpotifyProfile profile = user.getProfile(SpotifyProfile.class); return;
// if (profile.hasLinkedAccount()) { }
// interaction.replyEmbeds(EmbedUtils.errorEmbed() SpotifyProfile profile = user.getProfile(SpotifyProfile.class);
// .setDescription("You have already linked your Spotify account!") if (profile.hasLinkedAccount()) {
// .build()) interaction.replyEmbeds(EmbedUtils.errorEmbed()
// .setEphemeral(true) .setDescription("%s You have already linked your Spotify account!".formatted(Emojis.CROSS_MARK_EMOJI))
// .queue(); .build())
// return; .setEphemeral(true)
// } .queue();
// return;
// interaction.replyEmbeds(EmbedUtils.genericEmbed() }
// .setDescription("You can link your Spotify account by clicking [here](%s)".formatted(spotifyService.getAuthorizationUrl()))
// .build()) interaction.replyEmbeds(EmbedUtils.genericEmbed()
// .addComponents(ActionRow.of(Button.primary("spotify_link", "Link Spotify"))) .setDescription("%s You can link your Spotify account by clicking [here](%s)".formatted(
// .setEphemeral(true) Emojis.SPOTIFY_EMOJI.getFormatted(),
// .queue(); spotifyService.getAuthorizationUrl()
)).build())
.addComponents(ActionRow.of(Button.primary("spotify_link", "Link Code").withEmoji(Emojis.SPOTIFY_EMOJI)))
.setEphemeral(true)
.queue();
} }
@Override @Override
@ -91,7 +101,7 @@ public class LinkSubCommand extends BatSubCommand implements EventListener {
String code = codeMapping.getAsString(); String code = codeMapping.getAsString();
spotifyService.linkAccount(user, code); spotifyService.linkAccount(user, code);
event.replyEmbeds(EmbedUtils.successEmbed() event.replyEmbeds(EmbedUtils.successEmbed()
.setDescription("Successfully linked your Spotify account!") .setDescription("%s You have linked your Spotify account!".formatted(Emojis.CHECK_MARK_EMOJI.getFormatted()))
.build()) .build())
.setEphemeral(true) .setEphemeral(true)
.queue(); .queue();

@ -1,5 +1,6 @@
package cc.fascinated.bat.features.spotify.command; package cc.fascinated.bat.features.spotify.command;
import cc.fascinated.bat.Emojis;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatSubCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
@ -38,7 +39,7 @@ public class PauseSubCommand extends BatSubCommand {
if (!spotifyService.hasTrackPlaying(user)) { if (!spotifyService.hasTrackPlaying(user)) {
interaction.replyEmbeds(EmbedUtils.errorEmbed() interaction.replyEmbeds(EmbedUtils.errorEmbed()
.setDescription("You need to be playing a track to pause it.") .setDescription("%s You need to be playing a track to pause it.".formatted(Emojis.CROSS_MARK_EMOJI))
.build()) .build())
.queue(); .queue();
return; return;
@ -46,7 +47,8 @@ public class PauseSubCommand extends BatSubCommand {
boolean didPause = spotifyService.pausePlayback(user); boolean didPause = spotifyService.pausePlayback(user);
interaction.replyEmbeds(EmbedUtils.successEmbed() interaction.replyEmbeds(EmbedUtils.successEmbed()
.setDescription(didPause ? "Paused the current track." : "The current track is already paused.") .setDescription(didPause ? ":pause_button: Paused the current track.".formatted(Emojis.CHECK_MARK_EMOJI) :
"%s The current track is already paused.".formatted(Emojis.CROSS_MARK_EMOJI))
.build()) .build())
.queue(); .queue();
} }

@ -1,5 +1,6 @@
package cc.fascinated.bat.features.spotify.command; package cc.fascinated.bat.features.spotify.command;
import cc.fascinated.bat.Emojis;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatSubCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
@ -38,7 +39,7 @@ public class ResumeSubCommand extends BatSubCommand {
if (!spotifyService.hasTrackPlaying(user)) { if (!spotifyService.hasTrackPlaying(user)) {
interaction.replyEmbeds(EmbedUtils.errorEmbed() interaction.replyEmbeds(EmbedUtils.errorEmbed()
.setDescription("You need to be playing a track to resume it.") .setDescription("%s You need to be playing a track to resume it.".formatted(Emojis.CROSS_MARK_EMOJI))
.build()) .build())
.queue(); .queue();
return; return;
@ -46,7 +47,8 @@ public class ResumeSubCommand extends BatSubCommand {
boolean didPause = spotifyService.resumePlayback(user); boolean didPause = spotifyService.resumePlayback(user);
interaction.replyEmbeds(EmbedUtils.successEmbed() interaction.replyEmbeds(EmbedUtils.successEmbed()
.setDescription(didPause ? "Resumed the current track." : "The current track is already playing.") .setDescription(didPause ? "%s Resumed the current track.".formatted(Emojis.CHECK_MARK_EMOJI) :
"%s The current track is already playing.".formatted(Emojis.CROSS_MARK_EMOJI))
.build()) .build())
.queue(); .queue();
} }

@ -1,5 +1,6 @@
package cc.fascinated.bat.features.spotify.command; package cc.fascinated.bat.features.spotify.command;
import cc.fascinated.bat.Emojis;
import cc.fascinated.bat.command.BatSubCommand; import cc.fascinated.bat.command.BatSubCommand;
import cc.fascinated.bat.command.CommandInfo; import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils; import cc.fascinated.bat.common.EmbedUtils;
@ -33,7 +34,7 @@ public class UnlinkSubCommand extends BatSubCommand implements EventListener {
SpotifyProfile profile = user.getProfile(SpotifyProfile.class); SpotifyProfile profile = user.getProfile(SpotifyProfile.class);
if (!profile.hasLinkedAccount()) { if (!profile.hasLinkedAccount()) {
interaction.replyEmbeds(EmbedUtils.errorEmbed() interaction.replyEmbeds(EmbedUtils.errorEmbed()
.setDescription("You do not have a linked Spotify account.") .setDescription("%s You do not have a linked Spotify account.".formatted(Emojis.CROSS_MARK_EMOJI))
.build()) .build())
.setEphemeral(true) .setEphemeral(true)
.queue(); .queue();
@ -43,7 +44,7 @@ public class UnlinkSubCommand extends BatSubCommand implements EventListener {
profile.reset(); profile.reset();
userService.saveUser(user); userService.saveUser(user);
interaction.replyEmbeds(EmbedUtils.successEmbed() interaction.replyEmbeds(EmbedUtils.successEmbed()
.setDescription("Successfully unlinked your Spotify account.") .setDescription("%s Successfully unlinked your Spotify account.".formatted(Emojis.CHECK_MARK_EMOJI))
.build()) .build())
.setEphemeral(true) .setEphemeral(true)
.queue(); .queue();

@ -1,7 +1,6 @@
package cc.fascinated.bat.model.token.randomd; package cc.fascinated.bat.model.token.randomd;
import lombok.Getter; import lombok.Getter;
import lombok.Setter;
/** /**
* @author Fascinated (fascinated7) * @author Fascinated (fascinated7)

@ -216,7 +216,7 @@ public class CommandService extends ListenerAdapter {
log.error("An error occurred while executing command \"{}\"", commandName, ex); log.error("An error occurred while executing command \"{}\"", commandName, ex);
event.replyEmbeds(EmbedUtils.successEmbed() event.replyEmbeds(EmbedUtils.successEmbed()
.setDescription("An error occurred while executing the command\n\n" + ex.getLocalizedMessage()) .setDescription("An error occurred while executing the command:\n```java%s```".formatted(ex.getLocalizedMessage()))
.build()) .build())
.queue(); .queue();
} }

@ -40,13 +40,12 @@ public class DiscordService {
JDA = JDABuilder.create(token, EnumSet.of( JDA = JDABuilder.create(token, EnumSet.of(
GatewayIntent.GUILD_MESSAGES, GatewayIntent.GUILD_MESSAGES,
GatewayIntent.MESSAGE_CONTENT, GatewayIntent.MESSAGE_CONTENT,
GatewayIntent.GUILD_MEMBERS GatewayIntent.GUILD_MEMBERS,
GatewayIntent.GUILD_EMOJIS_AND_STICKERS
)) ))
.disableCache( .disableCache(
CacheFlag.ACTIVITY, CacheFlag.ACTIVITY,
CacheFlag.VOICE_STATE, CacheFlag.VOICE_STATE,
CacheFlag.EMOJI,
CacheFlag.STICKER,
CacheFlag.CLIENT_STATUS, CacheFlag.CLIENT_STATUS,
CacheFlag.ONLINE_STATUS, CacheFlag.ONLINE_STATUS,
CacheFlag.SCHEDULED_EVENTS CacheFlag.SCHEDULED_EVENTS

@ -1,6 +1,7 @@
package cc.fascinated.bat.service; package cc.fascinated.bat.service;
import cc.fascinated.bat.common.StringUtils; import cc.fascinated.bat.common.StringUtils;
import cc.fascinated.bat.exception.spotify.SpotifyTokenRefreshException;
import cc.fascinated.bat.features.spotify.profile.SpotifyProfile; import cc.fascinated.bat.features.spotify.profile.SpotifyProfile;
import cc.fascinated.bat.model.BatUser; import cc.fascinated.bat.model.BatUser;
import lombok.Getter; import lombok.Getter;
@ -12,6 +13,7 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import se.michaelthelin.spotify.SpotifyApi; import se.michaelthelin.spotify.SpotifyApi;
import se.michaelthelin.spotify.enums.AuthorizationScope; import se.michaelthelin.spotify.enums.AuthorizationScope;
import se.michaelthelin.spotify.exceptions.SpotifyWebApiException;
import se.michaelthelin.spotify.model_objects.credentials.AuthorizationCodeCredentials; import se.michaelthelin.spotify.model_objects.credentials.AuthorizationCodeCredentials;
import se.michaelthelin.spotify.model_objects.miscellaneous.CurrentlyPlaying; import se.michaelthelin.spotify.model_objects.miscellaneous.CurrentlyPlaying;
@ -81,12 +83,9 @@ public class SpotifyService {
* @param user the user to check * @param user the user to check
* @return the currently playing track * @return the currently playing track
*/ */
@SneakyThrows
public CurrentlyPlaying getCurrentlyPlayingTrack(BatUser user) { public CurrentlyPlaying getCurrentlyPlayingTrack(BatUser user) {
try {
return getSpotifyApi(user).getUsersCurrentlyPlayingTrack().build().execute(); return getSpotifyApi(user).getUsersCurrentlyPlayingTrack().build().execute();
} catch (Exception e) {
throw new RuntimeException("Failed to get currently playing track", e);
}
} }
/** /**
@ -117,13 +116,10 @@ public class SpotifyService {
* @param user the user to start playback for * @param user the user to start playback for
* @return if the playback was paused * @return if the playback was paused
*/ */
@SneakyThrows
public boolean resumePlayback(BatUser user) { public boolean resumePlayback(BatUser user) {
try {
getSpotifyApi(user).startResumeUsersPlayback().build().execute(); getSpotifyApi(user).startResumeUsersPlayback().build().execute();
return true; return true;
} catch (Exception e) {
throw new RuntimeException("Failed to resume playback", e);
}
} }
/** /**
@ -177,10 +173,7 @@ public class SpotifyService {
public SpotifyApi getSpotifyApi(BatUser user) { public SpotifyApi getSpotifyApi(BatUser user) {
SpotifyProfile profile = user.getProfile(SpotifyProfile.class); SpotifyProfile profile = user.getProfile(SpotifyProfile.class);
ensureValidToken(profile, user); ensureValidToken(profile, user);
return new SpotifyApi.Builder() return new SpotifyApi.Builder().setAccessToken(profile.getAccessToken()).build();
.setAccessToken(profile.getAccessToken())
.setRefreshToken(profile.getRefreshToken())
.build();
} }
/** /**
@ -193,10 +186,20 @@ public class SpotifyService {
if (profile.getExpiresAt() == null || profile.getExpiresAt() > System.currentTimeMillis()) { if (profile.getExpiresAt() == null || profile.getExpiresAt() > System.currentTimeMillis()) {
return; return;
} }
AuthorizationCodeCredentials credentials = spotifyApi.authorizationCodeRefresh().build().execute(); SpotifyApi api = new SpotifyApi.Builder()
.setClientId(clientId)
.setClientSecret(clientSecret)
.setAccessToken(profile.getAccessToken())
.setRefreshToken(profile.getRefreshToken())
.build();
try {
AuthorizationCodeCredentials credentials = api.authorizationCodeRefresh().build().execute();
profile.setAccessToken(credentials.getAccessToken()); profile.setAccessToken(credentials.getAccessToken());
profile.setRefreshToken(credentials.getRefreshToken());
profile.setExpiresAt(System.currentTimeMillis() + (credentials.getExpiresIn() * 1000)); profile.setExpiresAt(System.currentTimeMillis() + (credentials.getExpiresIn() * 1000));
userService.saveUser(user); userService.saveUser(user);
} catch (SpotifyWebApiException ex) {
log.error("Failed to refresh Spotify token", ex);
throw new SpotifyTokenRefreshException("Failed to refresh Spotify token", ex);
}
} }
} }