Skip to content

Commit

Permalink
SpotifyPlayList-dev-015-be-code-refactor (#178)
Browse files Browse the repository at this point in the history
* split request to method, remove attr, add logging

* refactor authService

* add initializeSpotifyApi method, refactor AlbumService.java

* refactor searchService, disable PersonalizationService

* refactor RecommendationsService, UserDataService

* refactor playListService, rename method in controller, update todo

* add refreshClient method, update PlayListService
  • Loading branch information
yennanliu authored Sep 28, 2024
1 parent 95555c0 commit ee97754
Show file tree
Hide file tree
Showing 9 changed files with 283 additions and 242 deletions.
12 changes: 12 additions & 0 deletions springSpotifyPlayList/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,4 +122,16 @@ docker rmi -f $(docker images -q -a)

</details>


## TODO

<details>
<summary>TODO</summary>

1. code refactor
- dep injection : `spotifyApi`
2. integrate with chatGPT
3. CICD, dockerize project
4. UI redesign

</details>
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,6 @@ public class UserDataController {
@GetMapping("/playlist")
public PlaylistSimplified[] getUserPlayList(){
//String userId = "62kytpy7jswykfjtnjn9zv3ou";
return userDataService.getUserAllPlayList(userId);
return userDataService.getUserAllPlaylists(userId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,44 +21,46 @@ public class AlbumService {
@Autowired
private AuthService authService;

private SpotifyApi spotifyApi;

public AlbumService() {
}

/**
* Fetches the album by the given album ID.
*
* @param albumId The ID of the album to fetch.
* @return The album details.
* @throws SpotifyWebApiException If an error occurs during the API request.
*/
public Album getAlbum(String albumId) throws SpotifyWebApiException {
SpotifyApi spotifyApi = authService.initializeSpotifyApi();

Album album = null;
try {
// TODO : move below to controller / config
this.spotifyApi = authService.getSpotifyClient();
final GetAlbumRequest getAlbumRequest = this.spotifyApi
.getAlbum(albumId)
.build();
album = getAlbumRequest.execute();
log.info("album = " + album);
final GetAlbumRequest getAlbumRequest = spotifyApi.getAlbum(albumId).build();
Album album = getAlbumRequest.execute();
log.info("Album fetched: {}", album);
return album;
} catch (IOException | SpotifyWebApiException | ParseException e) {
throw new SpotifyWebApiException("getAlbum error: " + e.getMessage());
log.error("Error fetching album: {}", e.getMessage());
throw new SpotifyWebApiException("Error fetching album: " + e.getMessage(), e);
}
return album;
}

/**
* Fetches the tracks of the given album ID.
*
* @param albumId The ID of the album whose tracks are to be fetched.
* @return A Paging object containing the simplified tracks.
* @throws SpotifyWebApiException If an error occurs during the API request.
*/
public Paging<TrackSimplified> getAlbumTrack(String albumId) throws SpotifyWebApiException {

Paging<TrackSimplified> trackSimplifiedPaging = null;
SpotifyApi spotifyApi = authService.initializeSpotifyApi();

try {
// TODO : move below to controller / config
this.spotifyApi = authService.getSpotifyClient();
final GetAlbumsTracksRequest getAlbumsTracksRequest = spotifyApi
.getAlbumsTracks(albumId)
.build();
trackSimplifiedPaging = getAlbumsTracksRequest.execute();
log.info("Track count: " + trackSimplifiedPaging.getTotal());
final GetAlbumsTracksRequest getAlbumsTracksRequest = spotifyApi.getAlbumsTracks(albumId).build();
Paging<TrackSimplified> trackSimplifiedPaging = getAlbumsTracksRequest.execute();
log.info("Fetched {} tracks for album {}", trackSimplifiedPaging.getTotal(), albumId);
return trackSimplifiedPaging;
} catch (IOException | SpotifyWebApiException | ParseException e) {
throw new SpotifyWebApiException("getAlbumTrack error: " + e.getMessage());
log.error("Error fetching album tracks: {}", e.getMessage());
throw new SpotifyWebApiException("Error fetching album tracks: " + e.getMessage(), e);
}
return trackSimplifiedPaging;
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ public void setRefreshToken(String refreshToken) {

private String refreshToken;

private String authCode;

private SpotifyApi spotifyApi;

public String getAuthCode() {
return authCode;
}
Expand All @@ -58,59 +62,61 @@ public void setAuthCode(String authCode) {
this.authCode = authCode;
}

private String authCode;
public AuthService() {
}

private SpotifyApi spotifyApi;
/**
* Initializes the SpotifyApi instance if not already initialized.
* @return the SpotifyApi instance.
*/
public SpotifyApi initializeSpotifyApi() {
if (this.spotifyApi == null) {
this.spotifyApi = getSpotifyClient();
log.info("SpotifyApi initialized with access token: {}", this.spotifyApi.getAccessToken());
}
return this.spotifyApi;
}

public AuthService() {
public SpotifyApi getSpotifyClientWithIdAndSecret() {

return new SpotifyApi
.Builder()
.setClientId(clientId)
.setClientSecret(clientSecret)
.build();
}

public SpotifyApi getBasicSpotifyClient() {
public SpotifyApi getSpotifyClientWithIdAndSecretAndRedirectUrlAndToken() {

return new SpotifyApi
.Builder()
.setClientId(clientId)
.setClientSecret(clientSecret)
.setRedirectUri(getRedirectURL(redirectURL))
.setAccessToken(accessToken) // use accessToken here
.build();
}

public SpotifyApi getSpotifyClient() {

final URI redirectUri = SpotifyHttpManager
.makeUri(redirectURL);
public SpotifyApi getSpotifyClient() {

log.info("(getSpotifyApi) current accessToken = " + this.accessToken);
// lazy approach
if (this.accessToken == null) {
this.accessToken = this.getToken();
log.info("(getSpotifyApi) new accessToken = " + accessToken);
this.spotifyApi = new SpotifyApi.Builder()
.setClientId(clientId)
.setClientSecret(clientSecret)
.setRedirectUri(redirectUri)
.setAccessToken(accessToken) // use accessToken here
.build();
this.spotifyApi = this.getSpotifyClientWithIdAndSecretAndRedirectUrlAndToken();
}

return this.spotifyApi;
}

public SpotifyApi getSpotifyClientWithRefreshCode(String refreshToken) {

return new SpotifyApi.Builder()
.setClientId(clientId)
.setClientSecret(clientSecret)
.setRefreshToken(refreshToken)
.build();
}


public String getToken() {

log.info("getToken ...");
String token = "";
try {
final SpotifyApi spotifyApi = this.getBasicSpotifyClient();
final SpotifyApi spotifyApi = this.getSpotifyClientWithIdAndSecret();

final ClientCredentialsRequest clientCredentialsRequest = spotifyApi
.clientCredentials()
Expand Down Expand Up @@ -165,6 +171,10 @@ public SpotifyApi authClientWithAuthCode(SpotifyApi spotifyApi, String authCode)
return spotifyApi;
}

public void refreshClient(SpotifyApi spotifyApi){
spotifyApi.setRefreshToken(spotifyApi.getRefreshToken());
}

/**
* Authorization flow
* <p>
Expand All @@ -174,41 +184,46 @@ public SpotifyApi authClientWithAuthCode(SpotifyApi spotifyApi, String authCode)
* Step 2) When the code has been retrieved, it can be used in another request to get an access token as well as a refresh token.
* Step 3) Now, the refresh token in turn can be used in a loop to retrieve new access and refresh tokens.
*/
public SpotifyApi refreshSpotifyClient(String authCode) throws SpotifyWebApiException, IOException, ParseException {

// https://github.com/spotify-web-api-java/spotify-web-api-java/blob/cfd0dae1262bd7f95f90c37b28d27b9c944d471a/examples/authorization/authorization_code/AuthorizationCodeRefreshExample.java#L22
// https://github.com/spotify-web-api-java/spotify-web-api-java/blob/master/examples/authorization/authorization_code/AuthorizationCodeExample.java

log.info("refreshSpotifyApi start ... authCode = {}", authCode);
//this.spotifyApi = this.getSpotifyClient();
if (this.spotifyApi == null || this.accessToken == null || this.refreshToken == null){
this.spotifyApi = this.getSpotifyClient();
}

try{
spotifyApi.setAccessToken(this.accessToken);
spotifyApi.setRefreshToken(this.refreshToken);
}catch (Exception e){
log.error("refreshSpotifyClient error : " + e.getMessage());
}

// try {
// final AuthorizationCodeRequest authorizationCodeRequest = spotifyApi
// .authorizationCode(authCode)
// .build();
// public SpotifyApi refreshSpotifyClient(String authCode) throws SpotifyWebApiException, IOException, ParseException {
//
// final AuthorizationCodeCredentials authorizationCodeCredentials = authorizationCodeRequest
// .execute();
// // https://github.com/spotify-web-api-java/spotify-web-api-java/blob/cfd0dae1262bd7f95f90c37b28d27b9c944d471a/examples/authorization/authorization_code/AuthorizationCodeRefreshExample.java#L22
// // https://github.com/spotify-web-api-java/spotify-web-api-java/blob/master/examples/authorization/authorization_code/AuthorizationCodeExample.java
//
// // Set access and refresh token for further "spotifyApi" object usage
// spotifyApi.setAccessToken(authorizationCodeCredentials.getAccessToken());
// spotifyApi.setRefreshToken(authorizationCodeCredentials.getRefreshToken());
// log.info("refreshSpotifyApi OK");
// } catch (IOException | SpotifyWebApiException | ParseException e) {
// log.error(">>> refreshSpotifyApi Error: " + e.getMessage());
// log.info("refreshSpotifyApi start ... authCode = {}", authCode);
// //this.spotifyApi = this.getSpotifyClient();
// if (this.spotifyApi == null || this.accessToken == null || this.refreshToken == null){
// this.spotifyApi = this.getSpotifyClient();
// }
//
// try{
// spotifyApi.setAccessToken(this.accessToken);
// spotifyApi.setRefreshToken(this.refreshToken);
// }catch (Exception e){
// log.error("refreshSpotifyClient error : " + e.getMessage());
// }
//
//// try {
//// final AuthorizationCodeRequest authorizationCodeRequest = spotifyApi
//// .authorizationCode(authCode)
//// .build();
////
//// final AuthorizationCodeCredentials authorizationCodeCredentials = authorizationCodeRequest
//// .execute();
////
//// // Set access and refresh token for further "spotifyApi" object usage
//// spotifyApi.setAccessToken(authorizationCodeCredentials.getAccessToken());
//// spotifyApi.setRefreshToken(authorizationCodeCredentials.getRefreshToken());
//// log.info("refreshSpotifyApi OK");
//// } catch (IOException | SpotifyWebApiException | ParseException e) {
//// log.error(">>> refreshSpotifyApi Error: " + e.getMessage());
//// }
//
// return this.spotifyApi;
// }

return this.spotifyApi;
private URI getRedirectURL(String redirectURL){
return SpotifyHttpManager
.makeUri(redirectURL);
}

}
Original file line number Diff line number Diff line change
@@ -1,45 +1,45 @@
package com.yen.SpotifyPlayList.service;

import lombok.extern.slf4j.Slf4j;
import org.apache.hc.core5.http.ParseException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import se.michaelthelin.spotify.SpotifyApi;
import se.michaelthelin.spotify.exceptions.SpotifyWebApiException;
import se.michaelthelin.spotify.model_objects.specification.Paging;
import se.michaelthelin.spotify.model_objects.specification.Track;
import se.michaelthelin.spotify.requests.data.personalization.simplified.GetUsersTopTracksRequest;

import java.io.IOException;

@Service
@Slf4j
public class PersonalizationService {

@Autowired
private AuthService authService;

private SpotifyApi spotifyApi;

public PersonalizationService() {

}

public Paging<Track> getUserTopTracks() throws SpotifyWebApiException {

Paging<Track> trackPaging = null;
try {
// TODO : move below to controller / config
this.spotifyApi = authService.getSpotifyClient();
final GetUsersTopTracksRequest getUsersTopTracksRequest = spotifyApi
.getUsersTopTracks()
.build();
trackPaging = getUsersTopTracksRequest.execute();
log.info("trackPaging = " + trackPaging);
} catch (IOException | SpotifyWebApiException | ParseException e) {
throw new SpotifyWebApiException("getUserTopTracks error: " + e.getMessage());
}
return trackPaging;
}

}
//package com.yen.SpotifyPlayList.service;
//
//import lombok.extern.slf4j.Slf4j;
//import org.apache.hc.core5.http.ParseException;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.stereotype.Service;
//import se.michaelthelin.spotify.SpotifyApi;
//import se.michaelthelin.spotify.exceptions.SpotifyWebApiException;
//import se.michaelthelin.spotify.model_objects.specification.Paging;
//import se.michaelthelin.spotify.model_objects.specification.Track;
//import se.michaelthelin.spotify.requests.data.personalization.simplified.GetUsersTopTracksRequest;
//
//import java.io.IOException;
//
//@Service
//@Slf4j
//public class PersonalizationService {
//
// @Autowired
// private AuthService authService;
//
// private SpotifyApi spotifyApi;
//
// public PersonalizationService() {
//
// }
//
// public Paging<Track> getUserTopTracks() throws SpotifyWebApiException {
//
// Paging<Track> trackPaging = null;
// try {
// // TODO : move below to controller / config
// this.spotifyApi = authService.getSpotifyClient();
// final GetUsersTopTracksRequest getUsersTopTracksRequest = spotifyApi
// .getUsersTopTracks()
// .build();
// trackPaging = getUsersTopTracksRequest.execute();
// log.info("trackPaging = " + trackPaging);
// } catch (IOException | SpotifyWebApiException | ParseException e) {
// throw new SpotifyWebApiException("getUserTopTracks error: " + e.getMessage());
// }
// return trackPaging;
// }
//
//}
Loading

0 comments on commit ee97754

Please sign in to comment.