Bat/src/main/java/cc/fascinated/bat/service/SpotifyService.java

189 lines
5.7 KiB
Java
Raw Normal View History

2024-06-28 03:01:21 +01:00
package cc.fascinated.bat.service;
import cc.fascinated.bat.common.StringUtils;
import cc.fascinated.bat.features.spotify.profile.SpotifyProfile;
import cc.fascinated.bat.model.BatUser;
import lombok.Getter;
import lombok.NonNull;
import lombok.SneakyThrows;
import net.jodah.expiringmap.ExpiringMap;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import se.michaelthelin.spotify.SpotifyApi;
import se.michaelthelin.spotify.enums.AuthorizationScope;
import se.michaelthelin.spotify.model_objects.credentials.AuthorizationCodeCredentials;
import se.michaelthelin.spotify.model_objects.miscellaneous.CurrentlyPlaying;
import java.net.URI;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* @author Fascinated (fascinated7)
*/
@Service
@Getter
public class SpotifyService {
/**
* The access token map.
*/
private final Map<String, AuthorizationCodeCredentials> accessToken = ExpiringMap.builder()
.expiration(30, TimeUnit.MINUTES)
.build();
/**
* The client ID.
*/
private final String clientId;
/**
* The client secret.
*/
private final String clientSecret;
/**
* The Spotify API instance.
*/
private final SpotifyApi spotifyApi;
/**
* The user service.
*/
private final UserService userService;
/**
* The authorization URL.
*/
private final String authorizationUrl;
2024-06-28 03:05:36 +01:00
public SpotifyService(@Value("${spotify.client-id}") String clientId, @Value("${spotify.client-secret}") String clientSecret,
@Value("${spotify.redirect-uri}") String redirectUri, @NonNull UserService userService) {
2024-06-28 03:01:21 +01:00
this.clientId = clientId;
this.clientSecret = clientSecret;
this.userService = userService;
this.spotifyApi = new SpotifyApi.Builder()
.setClientId(clientId)
.setClientSecret(clientSecret)
2024-06-28 03:05:36 +01:00
.setRedirectUri(URI.create(redirectUri))
2024-06-28 03:01:21 +01:00
.build();
this.authorizationUrl = spotifyApi.authorizationCodeUri()
.response_type("code")
.scope(
AuthorizationScope.APP_REMOTE_CONTROL,
AuthorizationScope.USER_READ_PLAYBACK_POSITION,
AuthorizationScope.USER_READ_PLAYBACK_STATE,
AuthorizationScope.USER_MODIFY_PLAYBACK_STATE,
AuthorizationScope.USER_READ_CURRENTLY_PLAYING,
AuthorizationScope.APP_REMOTE_CONTROL,
AuthorizationScope.STREAMING
)
.build().execute().toString();
}
/**
* Gets the currently playing track for the user.
*
* @param user the user to check
* @return the currently playing track
*/
public CurrentlyPlaying getCurrentlyPlayingTrack(BatUser user) {
try {
return getSpotifyApi(user).getUsersCurrentlyPlayingTrack().build().execute();
} catch (Exception e) {
return null;
}
}
/**
* Checks if the user has a track playing.
*
* @param user the user to check
* @return whether a track is playing
*/
public boolean hasTrackPlaying(BatUser user) {
return getCurrentlyPlayingTrack(user) != null;
}
/**
* Pauses playback for the user.
*
* @param user the user to start playback for
* @return if the playback was paused
*/
@SneakyThrows
public boolean pausePlayback(BatUser user) {
try {
getSpotifyApi(user).pauseUsersPlayback().build().execute();
return true;
} catch (Exception e) {
return false;
}
}
/**
* Pauses playback for the user.
*
* @param user the user to start playback for
* @return if the playback was paused
*/
@SneakyThrows
public boolean resumePlayback(BatUser user) {
try {
getSpotifyApi(user).startResumeUsersPlayback().build().execute();
return true;
} catch (Exception e) {
return false;
}
}
/**
* Gets the authorization key to link the user's
* Spotify account with their Discord account.
*
* @param code the code to authorize with
* @return the authorization details
*/
@SneakyThrows
public String authorize(String code) {
2024-06-28 03:13:54 +01:00
if (code == null) {
return "Missing code param";
}
2024-06-28 03:01:21 +01:00
AuthorizationCodeCredentials credentials = spotifyApi.authorizationCode(code).build().execute();
String key = StringUtils.randomString(16);
accessToken.put(key, credentials);
2024-06-28 03:13:54 +01:00
return "Authorization Key: " + key;
2024-06-28 03:01:21 +01:00
}
/**
* Links the user's Spotify account with their Discord account.
*
* @param user the user to link the account with
* @param key the key to link the account with
*/
public void linkAccount(BatUser user, String key) {
AuthorizationCodeCredentials credentials = accessToken.get(key);
if (credentials == null) {
return;
}
// Link the user's Spotify account
SpotifyProfile profile = user.getProfile(SpotifyProfile.class);
profile.setAccessToken(credentials.getAccessToken());
profile.setRefreshToken(credentials.getRefreshToken());
userService.saveUser(user);
}
/**
* Gets a new Spotify API instance.
*
* @return the Spotify API
*/
public SpotifyApi getSpotifyApi(BatUser user) {
SpotifyProfile profile = user.getProfile(SpotifyProfile.class);
return new SpotifyApi.Builder()
.setAccessToken(profile.getAccessToken())
.setClientSecret(clientSecret)
.build();
}
}