Skip to content

Commit

Permalink
merge: 유사곡 5개 반환
Browse files Browse the repository at this point in the history
Feature/#67 유사곡 5개 반환
  • Loading branch information
hong-sile authored Aug 9, 2024
2 parents b4d698c + 03860bc commit 8045f95
Show file tree
Hide file tree
Showing 16 changed files with 178 additions and 94 deletions.
5 changes: 2 additions & 3 deletions src/main/java/play/pluv/music/application/MusicExplorer.java
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
package play.pluv.music.application;

import java.util.List;
import java.util.Optional;
import play.pluv.music.domain.DestinationMusic;
import play.pluv.music.domain.DestinationMusics;
import play.pluv.music.domain.MusicId;
import play.pluv.playlist.domain.MusicStreaming;
import play.pluv.playlist.domain.PlayListMusic;

public interface MusicExplorer {

Optional<DestinationMusic> searchMusic(final String accessToken, final PlayListMusic source);
DestinationMusics searchMusic(final String accessToken, final PlayListMusic source);

void transferMusics(
final String accessToken, final List<MusicId> musicIds, final String playlistName
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import java.util.Optional;
import java.util.Set;
import org.springframework.stereotype.Component;
import play.pluv.music.domain.DestinationMusic;
import play.pluv.music.domain.DestinationMusics;
import play.pluv.music.domain.MusicId;
import play.pluv.music.exception.MusicException;
import play.pluv.playlist.domain.MusicStreaming;
Expand All @@ -25,7 +25,7 @@ public MusicExplorerComposite(final Set<MusicExplorer> musicExplorers) {
.collect(toMap(MusicExplorer::supportedType, identity()));
}

public Optional<DestinationMusic> searchMusic(
public DestinationMusics searchMusic(
final MusicStreaming musicStreaming, final String accessToken, final PlayListMusic source
) {
return getClient(musicStreaming).searchMusic(accessToken, source);
Expand Down
19 changes: 9 additions & 10 deletions src/main/java/play/pluv/music/application/MusicService.java
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
package play.pluv.music.application;

import java.util.List;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import play.pluv.music.application.dto.MusicAddRequest;
import play.pluv.music.application.dto.MusicSearchRequest;
import play.pluv.music.application.dto.MusicSearchRequest.MusicQuery;
import play.pluv.music.application.dto.MusicSearchResponse;
import play.pluv.music.domain.DestinationMusic;
import play.pluv.music.domain.DestinationMusics;
import play.pluv.music.domain.MusicId;
import play.pluv.playlist.domain.MusicStreaming;
import play.pluv.playlist.domain.PlayListMusic;
Expand Down Expand Up @@ -39,14 +38,14 @@ public void transferMusics(final MusicAddRequest request, final MusicStreaming d
}

private MusicSearchResponse searchMusic(
final MusicStreaming musicStreaming, final PlayListMusic playlistMusic, final String accessToken
final MusicStreaming musicStreaming, final PlayListMusic playlistMusic,
final String accessToken
) {
final Optional<DestinationMusic> result
= musicExplorerComposite.searchMusic(musicStreaming, accessToken, playlistMusic);
return result
.map(
destination -> MusicSearchResponse.createFound(playlistMusic, destination)
)
.orElseGet(() -> MusicSearchResponse.createNotFound(playlistMusic));
final DestinationMusics destinationMusics = musicExplorerComposite
.searchMusic(musicStreaming, accessToken, playlistMusic);
if (destinationMusics.isEmpty()) {
return MusicSearchResponse.createNotFound(playlistMusic);
}
return MusicSearchResponse.createFound(playlistMusic, destinationMusics);
}
}
Original file line number Diff line number Diff line change
@@ -1,30 +1,32 @@
package play.pluv.music.application.dto;

import java.util.List;
import lombok.Builder;
import play.pluv.music.domain.DestinationMusic;
import play.pluv.music.domain.SourceMusic;
import play.pluv.music.domain.DestinationMusics;
import play.pluv.playlist.domain.PlayListMusic;

@Builder
public record MusicSearchResponse(
Boolean isEqual,
Boolean isFound,
SourceMusicResponse sourceMusic,
DestinationMusicResponse destinationMusic
List<DestinationMusicResponse> destinationMusics
) {

public static MusicSearchResponse createFound(
final PlayListMusic sourceMusic, final DestinationMusic destinationMusic
final PlayListMusic sourceMusic, final DestinationMusics destinationMusics
) {
final SourceMusicResponse sourceMusicResponse = SourceMusicResponse.from(sourceMusic);
final DestinationMusicResponse destinationMusicResponse
= DestinationMusicResponse.from(destinationMusic);
final List<DestinationMusicResponse> destinationMusicResponses
= DestinationMusicResponse.extractEqualOrConvert(destinationMusics.getDestinationMusics(),
sourceMusic);

return MusicSearchResponse.builder()
.sourceMusic(sourceMusicResponse)
.destinationMusic(destinationMusicResponse)
.destinationMusics(destinationMusicResponses)
.isFound(true)
.isEqual(destinationMusic.isSame(sourceMusic))
.isEqual(destinationMusics.containEqual(sourceMusic))
.build();
}

Expand Down Expand Up @@ -67,5 +69,23 @@ public static DestinationMusicResponse from(final DestinationMusic destinationMu
destinationMusic.getImageUrl()
);
}

public static List<DestinationMusicResponse> from(
final List<DestinationMusic> destinationMusics
) {
return destinationMusics.stream()
.map(DestinationMusicResponse::from)
.toList();
}

public static List<DestinationMusicResponse> extractEqualOrConvert(
final List<DestinationMusic> destinationMusics, final PlayListMusic playListMusic
) {
return destinationMusics.stream()
.filter(destinationMusic -> destinationMusic.isSame(playListMusic))
.findAny()
.map(destinationMusic -> List.of(DestinationMusicResponse.from(destinationMusic)))
.orElseGet(() -> DestinationMusicResponse.from(destinationMusics));
}
}
}
24 changes: 24 additions & 0 deletions src/main/java/play/pluv/music/domain/DestinationMusics.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package play.pluv.music.domain;

import java.util.List;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import play.pluv.playlist.domain.PlayListMusic;

@Getter
@RequiredArgsConstructor
public class DestinationMusics {

private final List<DestinationMusic> destinationMusics;

public Boolean containEqual(final PlayListMusic playListMusic) {
return destinationMusics.stream()
.map(destinationMusic -> destinationMusic.isSame(playListMusic))
//하나라도 동일하면 true 반환
.reduce(false, (a, b) -> a || b);
}

public Boolean isEmpty() {
return destinationMusics.isEmpty();
}
}
23 changes: 0 additions & 23 deletions src/main/java/play/pluv/music/domain/SourceMusic.java

This file was deleted.

7 changes: 3 additions & 4 deletions src/main/java/play/pluv/oauth/google/GoogleConnector.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,13 @@

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import play.pluv.music.application.MusicExplorer;
import play.pluv.music.domain.DestinationMusic;
import play.pluv.music.domain.DestinationMusics;
import play.pluv.music.domain.MusicId;
import play.pluv.oauth.application.SocialLoginClient;
import play.pluv.oauth.domain.OAuthMemberInfo;
Expand Down Expand Up @@ -72,12 +71,12 @@ public PlayListId createPlayList(final String accessToken, final String title) {
}

@Override
public Optional<DestinationMusic> searchMusic(
public DestinationMusics searchMusic(
final String accessToken, final PlayListMusic source
) {
final String q = source.getTitle() + String.join(",", source.getArtistNames());
return googleApiClient.searchMusic(CREATE_AUTH_HEADER.apply(accessToken), q)
.toDestinationMusic();
.toDestinationMusics();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import java.util.List;
import java.util.Optional;
import play.pluv.music.domain.DestinationMusic;
import play.pluv.music.domain.DestinationMusics;
import play.pluv.music.domain.MusicId;

public record YoutubeSearchMusicResponses(
Expand All @@ -27,11 +28,28 @@ public Optional<DestinationMusic> toDestinationMusic() {
);
}

public DestinationMusics toDestinationMusics() {
return new DestinationMusics(items.stream()
.map(YoutubeMusicVideo::toDestinationMusic)
.limit(5)
.toList());
}

private record YoutubeMusicVideo(
VideoId id,
YoutubeMusicDetail snippet
) {

public DestinationMusic toDestinationMusic() {
return DestinationMusic.builder()
.musicId(new MusicId(YOUTUBE, id.videoId()))
.imageUrl(snippet().thumbnails().getUrl())
.artistNames(List.of())
.title(snippet().title())
.isrcCode(null)
.build();
}

private String getId() {
return id.videoId();
}
Expand Down
7 changes: 3 additions & 4 deletions src/main/java/play/pluv/oauth/spotify/SpotifyConnector.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,13 @@

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import play.pluv.music.application.MusicExplorer;
import play.pluv.music.domain.DestinationMusic;
import play.pluv.music.domain.DestinationMusics;
import play.pluv.music.domain.MusicId;
import play.pluv.oauth.application.SocialLoginClient;
import play.pluv.oauth.domain.OAuthMemberInfo;
Expand Down Expand Up @@ -61,12 +60,12 @@ public MusicStreaming supportedType() {
}

@Override
public Optional<DestinationMusic> searchMusic(
public DestinationMusics searchMusic(
final String accessToken, final PlayListMusic source
) {
final MultiValueMap<String, String> param = createRequestParamForSearchMusic(source);
return spotifyApiClient.searchMusic(CREATE_AUTH_HEADER.apply(accessToken), param)
.toMusic();
.toDestinationMusics();
}

@Override
Expand Down
14 changes: 14 additions & 0 deletions src/main/java/play/pluv/oauth/spotify/dto/SpotifyMusic.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
package play.pluv.oauth.spotify.dto;

import static play.pluv.playlist.domain.MusicStreaming.SPOTIFY;

import com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import java.util.List;
import play.pluv.music.domain.DestinationMusic;
import play.pluv.music.domain.MusicId;

@JsonNaming(SnakeCaseStrategy.class)
public record SpotifyMusic(
Expand All @@ -13,6 +17,16 @@ public record SpotifyMusic(
List<Artist> artists
) {

public DestinationMusic toDestinationMusic() {
return DestinationMusic.builder()
.musicId(new MusicId(SPOTIFY, id()))
.imageUrl(getImageUrl())
.artistNames(getArtistNames())
.title(name())
.isrcCode(getIsrcCode())
.build();
}

public String getImageUrl() {
//TODO: 추후 로직 수정하기 images가 nullable함
return album.images().get(0).url();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,40 +1,25 @@
package play.pluv.oauth.spotify.dto;

import static play.pluv.playlist.domain.MusicStreaming.SPOTIFY;

import java.util.List;
import java.util.Optional;
import play.pluv.music.domain.DestinationMusic;
import play.pluv.music.domain.MusicId;
import play.pluv.music.domain.DestinationMusics;

public record SpotifySearchMusicResponse(
Track tracks
) {

public Optional<DestinationMusic> toMusic() {
return tracks.toMusic();
public DestinationMusics toDestinationMusics() {
return new DestinationMusics(tracks.toMusics());
}

public record Track(
List<SpotifyMusic> items
) {

public Optional<DestinationMusic> toMusic() {
if (items.isEmpty()) {
return Optional.empty();
}

final SpotifyMusic spotifyMusic = items.get(0);

return Optional.of(DestinationMusic.builder()
.musicId(new MusicId(SPOTIFY, spotifyMusic.id()))
.imageUrl(spotifyMusic.getImageUrl())
.artistNames(spotifyMusic.getArtistNames())
.title(spotifyMusic.name())
.isrcCode(spotifyMusic.getIsrcCode())
.build()
);
public List<DestinationMusic> toMusics() {
return items.stream()
.map(SpotifyMusic::toDestinationMusic)
.toList();
}

}
}
11 changes: 5 additions & 6 deletions src/test/java/play/pluv/api/MusicApiTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import static org.springframework.restdocs.payload.JsonFieldType.ARRAY;
import static org.springframework.restdocs.payload.JsonFieldType.BOOLEAN;
import static org.springframework.restdocs.payload.JsonFieldType.NUMBER;
import static org.springframework.restdocs.payload.JsonFieldType.OBJECT;
import static org.springframework.restdocs.payload.JsonFieldType.STRING;
import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath;
import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields;
Expand Down Expand Up @@ -47,14 +46,14 @@ public class MusicApiTest extends ApiTest {
fieldWithPath("data[].sourceMusic.imageUrl").type(STRING).description("음악 imageUrl"),
fieldWithPath("data[].sourceMusic.artistName").type(STRING)
.description("검색하려는 음악의 가수 이름"),
fieldWithPath("data[].destinationMusic").type(OBJECT).description("조회된 음악 정보")
fieldWithPath("data[].destinationMusics").type(ARRAY).description("조회된 음악 정보")
.optional(),
fieldWithPath("data[].destinationMusic.id").type(STRING).description("조회된 음악 id"),
fieldWithPath("data[].destinationMusic.title").type(STRING)
fieldWithPath("data[].destinationMusics[].id").type(STRING).description("조회된 음악 id"),
fieldWithPath("data[].destinationMusics[].title").type(STRING)
.description("조회된 음악의 이름"),
fieldWithPath("data[].destinationMusic.artistName").type(STRING)
fieldWithPath("data[].destinationMusics[].artistName").type(STRING)
.description("조회된 음악의 가수 이름"),
fieldWithPath("data[].destinationMusic.imageUrl").type(STRING)
fieldWithPath("data[].destinationMusics[].imageUrl").type(STRING)
.description("조회된 음악의 커버 이미지 url")
)};
private static final Snippet[] TRANSFER_MUSIC_SNIPPET = {requestFields(
Expand Down
Loading

0 comments on commit 8045f95

Please sign in to comment.