Skip to content

Commit

Permalink
feat [#85] 아티스트 검색 API 구현
Browse files Browse the repository at this point in the history
  • Loading branch information
ch1hyun committed Jan 18, 2025
1 parent 5f73308 commit 29fcd26
Show file tree
Hide file tree
Showing 10 changed files with 141 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package org.sopt.confeti.api.artist.controller;

import lombok.RequiredArgsConstructor;
import org.sopt.confeti.api.artist.dto.response.SearchArtistResponse;
import org.sopt.confeti.api.artist.facade.ArtistFacade;
import org.sopt.confeti.api.artist.facade.dto.response.SearchArtistDTO;
import org.sopt.confeti.api.user.facade.UserInfoFacade;
import org.sopt.confeti.global.common.BaseResponse;
import org.sopt.confeti.global.message.SuccessMessage;
import org.sopt.confeti.global.util.ApiResponseUtil;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequiredArgsConstructor
@RequestMapping("/artists")
public class ArtistController {

private final ArtistFacade artistFacade;

@GetMapping
public ResponseEntity<BaseResponse<?>> search(
@RequestHeader(name = "Authorization", required = false) Long userId,
@RequestParam(name = "search") String keyword
) {
SearchArtistDTO artist = artistFacade.searchByKeyword(userId, keyword);
return ApiResponseUtil.success(SuccessMessage.SUCCESS, SearchArtistResponse.from(artist));
}
}
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.sopt.confeti.api.artist.dto.response;

import org.sopt.confeti.api.artist.facade.dto.response.SearchArtistDTO;

public record SearchArtistResponse(
SearchArtistSingleResponse artist
) {
public static SearchArtistResponse from(final SearchArtistDTO searchArtistDTO) {
return new SearchArtistResponse(
SearchArtistSingleResponse.from(searchArtistDTO)
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package org.sopt.confeti.api.artist.dto.response;

import java.time.LocalDate;
import org.sopt.confeti.api.artist.facade.dto.response.SearchArtistDTO;

public record SearchArtistSingleResponse(
String artistId,
String name,
String profileUrl,
LocalDate latestReleaseAt,
boolean isFavorite,
boolean isMultipleArtists
) {
public static SearchArtistSingleResponse from(final SearchArtistDTO searchArtistDTO) {
return new SearchArtistSingleResponse(
searchArtistDTO.artistId(),
searchArtistDTO.name(),
searchArtistDTO.profileUrl(),
searchArtistDTO.latestReleaseAt(),
searchArtistDTO.isFavorite(),
searchArtistDTO.isMultipleArtists()
);
}
}
34 changes: 34 additions & 0 deletions src/main/java/org/sopt/confeti/api/artist/facade/ArtistFacade.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package org.sopt.confeti.api.artist.facade;

import java.util.Optional;
import lombok.RequiredArgsConstructor;
import org.sopt.confeti.annotation.Facade;
import org.sopt.confeti.api.artist.facade.dto.response.SearchArtistDTO;
import org.sopt.confeti.domain.artistfavorite.application.ArtistFavoriteService;
import org.sopt.confeti.global.util.artistsearcher.ConfetiArtist;
import org.sopt.confeti.global.util.artistsearcher.SpotifyAPIHandler;
import org.springframework.transaction.annotation.Transactional;

@Facade
@RequiredArgsConstructor
public class ArtistFacade {

private final ArtistFavoriteService artistFavoriteService;
private final SpotifyAPIHandler spotifyAPIHandler;

@Transactional(readOnly = true)
public SearchArtistDTO searchByKeyword(final Long userId, final String keyword) {
Optional<ConfetiArtist> confetiArtist = spotifyAPIHandler.findArtistsByKeyword(keyword);

boolean isFavorite = false;

if (confetiArtist.isPresent() && userId != null) {
isFavorite = artistFavoriteService.isFavorite(userId, confetiArtist.get().getArtistId());
}

return SearchArtistDTO.from(
confetiArtist.orElse(ConfetiArtist.empty()),
isFavorite
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package org.sopt.confeti.api.artist.facade.dto.response;

import java.time.LocalDate;
import org.sopt.confeti.global.util.artistsearcher.ConfetiArtist;

public record SearchArtistDTO(
String artistId,
String name,
String profileUrl,
LocalDate latestReleaseAt,
boolean isFavorite,
boolean isMultipleArtists
) {
private static final boolean fixedIsMultipleArtists = false;

public static SearchArtistDTO from(final ConfetiArtist confetiArtist, final boolean isFavorite) {
return new SearchArtistDTO(
confetiArtist.getArtistId(),
confetiArtist.getName(),
confetiArtist.getProfileUrl(),
confetiArtist.getLatestReleaseAt(),
isFavorite,
fixedIsMultipleArtists
);
}
}
Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,9 @@ public List<ArtistFavorite> getArtistList(Long userId) {

return artistList;
}

@Transactional(readOnly = true)
public boolean isFavorite(final long userId, final String artistId) {
return artistFavoriteRepository.existsByUserIdAndArtist_ArtistId(userId, artistId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,6 @@
public interface ArtistFavoriteRepository extends JpaRepository<ArtistFavorite, Long> {
@Query(value = "select * from artist_favorites where user_id = :userId order by rand() limit 3", nativeQuery = true)
List<ArtistFavorite> findTop3ByUserIdOrderByRand(@Param("userId") Long userId);

boolean existsByUserIdAndArtist_ArtistId(long userId, String artistId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,8 @@ public static ConfetiArtist toConfetiArtist(final Artist artist, final LocalDate
public static ConfetiArtist from(final String artistId) {
return new ConfetiArtist(artistId);
}

public static ConfetiArtist empty() {
return new ConfetiArtist();
}
}

0 comments on commit 29fcd26

Please sign in to comment.