Skip to content

Commit

Permalink
Merge pull request #89 from tukcomCD2024/feat#87/search-voice
Browse files Browse the repository at this point in the history
Feat#87/search voice
  • Loading branch information
JunRain2 authored May 15, 2024
2 parents 6bb7a4f + be725d6 commit ae30ca0
Show file tree
Hide file tree
Showing 12 changed files with 199 additions and 10 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package com.example.memetory.domain.voice.controller;

import com.example.memetory.domain.voice.dto.request.GenerateVoiceRequestDto;
import com.example.memetory.domain.voice.dto.response.ElevenlabsVoiceLibraryResponse;
import com.example.memetory.domain.voice.dto.response.ElevenlabsVoiceResponse;
import com.example.memetory.global.response.ResultResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
Expand All @@ -25,8 +28,36 @@ public interface VoiceApi {
description = "목소리 추출!"
)
})
ResponseEntity<Object> register(
ResponseEntity<ResultResponse> register(
@Parameter(hidden = true) String email,
GenerateVoiceRequestDto generateVoiceRequestDto
) throws IOException;

@Operation(
summary = "멤버별 목소리 조회",
description = "voice_id에 해당하는 목소리를 조회한다.",
security = {@SecurityRequirement(name = "access_token")}
)
@ApiResponses(value = {
@ApiResponse(
responseCode = "200",
description = "멤버별 목소리 조회!"
)
})
ResponseEntity<ResultResponse> findByMemberId(
@Parameter(hidden = true) String email
) throws IOException;

@Operation(
summary = "기본 라이브러리 목소리 조회",
description = "기본 라이브러리 목소리를 조회한다.",
security = {@SecurityRequirement(name = "access_token")}
)
@ApiResponses(value = {
@ApiResponse(
responseCode = "200",
description = "기본 라이브러리 목소리 조회!"
)
})
ResponseEntity<ResultResponse> getVoiceLibrary() throws IOException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,20 @@

import com.example.memetory.domain.voice.dto.VoiceServiceDto;
import com.example.memetory.domain.voice.dto.request.GenerateVoiceRequestDto;
import com.example.memetory.domain.voice.dto.response.ElevenlabsVoiceLibraryResponse;
import com.example.memetory.domain.voice.dto.response.ElevenlabsVoiceResponse;
import com.example.memetory.domain.voice.dto.response.GenerateVoiceResponseDto;
import com.example.memetory.domain.voice.service.VoiceService;
import com.example.memetory.global.annotation.LoginMemberEmail;
import com.example.memetory.global.response.ResultCode;
import com.example.memetory.global.response.ResultResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
Expand All @@ -30,21 +31,27 @@ public class VoiceController implements VoiceApi {
private final VoiceService voiceService;

@Value("${elevenlabs.api.url.add}")
private String apiUrl;
private String addApiUrl;

@Value("${elevenlabs.api.url.get}")
private String getApiUrl;

@Value("${elevenlabs.api.url.library}")
private String getLibraryApiUrl;

@Value("${elevenlabs.api.key}")
private String apiKey;

@PostMapping
@Override
public ResponseEntity<Object> register(@LoginMemberEmail String email, @RequestBody GenerateVoiceRequestDto generateVoiceRequestDto) throws IOException {
public ResponseEntity<ResultResponse> register(@LoginMemberEmail String email, @RequestBody GenerateVoiceRequestDto generateVoiceRequestDto) throws IOException {

// s3 url을 받아서 음성파일을 가져오는 ServiceDto 로직 1개
VoiceServiceDto voiceServiceDtoS3 = generateVoiceRequestDto.toServiceDtoS3(email);
MultiValueMap<String, Object> formData = voiceService.generateVoice(voiceServiceDtoS3);

return WebClient
.create(apiUrl)
.create(addApiUrl)
.post()
.header("xi-api-key", apiKey)
.contentType(MediaType.MULTIPART_FORM_DATA)
Expand All @@ -56,7 +63,50 @@ public ResponseEntity<Object> register(@LoginMemberEmail String email, @RequestB
VoiceServiceDto voiceServiceDtoElevenlabs =
generateVoiceRequestDto.toServiceDtoElevenlabs(email, response.getElevenlabsVoiceId());
voiceService.register(voiceServiceDtoElevenlabs);
return Mono.just(ResponseEntity.status(HttpStatus.CREATED).build());
return Mono.just(ResponseEntity.ok(ResultResponse.of(ResultCode.CREATE_VOICE_SUCCESS)));
})
.onErrorResume(error -> {
System.out.println(("An error occurred while processing the request: {}" + error.getMessage()));
return Mono.just(ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build());
})
.block();
}

@GetMapping("/member")
@Override
public ResponseEntity<ResultResponse> findByMemberId(@LoginMemberEmail String email) throws IOException {
VoiceServiceDto voiceServiceDto = VoiceServiceDto.create(email);
String voiceId = voiceService.findVoiceByMemberId(voiceServiceDto);

return WebClient
.create(getApiUrl + "/" + voiceId)
.get()
.header("xi-api-key", apiKey)
.retrieve()
.bodyToMono(ElevenlabsVoiceResponse.class)
.flatMap(response -> {
// elevenlabs API 호출이 완료 되면 실행할 로직
return Mono.just(ResponseEntity.ok(ResultResponse.of(ResultCode.GET_MEMBER_VOICE_SUCCESS, response)));
})
.onErrorResume(error -> {
System.out.println(("An error occurred while processing the request: {}" + error.getMessage()));
return Mono.just(ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build());
})
.block();
}

@GetMapping("/library")
@Override
public ResponseEntity<ResultResponse> getVoiceLibrary() throws IOException {
return WebClient
.create(getLibraryApiUrl)
.get()
.header("xi-api-key", apiKey)
.retrieve()
.bodyToMono(ElevenlabsVoiceLibraryResponse.class)
.flatMap(response -> {
// elevenlabs API 호출이 완료 되면 실행할 로직
return Mono.just(ResponseEntity.ok(ResultResponse.of(ResultCode.GET_VOICE_LIBRARY_SUCCESS, response)));
})
.onErrorResume(error -> {
System.out.println(("An error occurred while processing the request: {}" + error.getMessage()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ public class VoiceServiceDto {
private String description;
private String elevenlabsVoiceId;

public static VoiceServiceDto create(String email) {
return VoiceServiceDto.builder()
.email(email)
.build();
}

public Voice toEntity(Member member) {
return Voice.builder()
.member(member)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.example.memetory.domain.voice.dto.response;

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.util.List;

@Getter
@NoArgsConstructor
public class ElevenlabsVoiceLibraryResponse {

@JsonProperty("voices")
private List<ElevenlabsVoiceResponse> voices;

@JsonProperty("has_more")
private boolean hasMore;

@JsonProperty("last_sort_id")
private String lastSortId;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.example.memetory.domain.voice.dto.response;

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor
public class ElevenlabsVoiceResponse {

@JsonProperty("voice_id")
private String elevenlabsVoiceId;

@JsonProperty("name")
private String name;

@JsonProperty("description")
private String description;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.example.memetory.domain.voice.exception;

import com.example.memetory.global.exception.BusinessException;
import com.example.memetory.global.response.ErrorCode;

public class NotFoundVoiceException extends BusinessException {
public NotFoundVoiceException() {
super(ErrorCode.VOICE_NOT_FOUND);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.example.memetory.domain.voice.repository;

import com.example.memetory.domain.voice.entity.Voice;

import java.util.Optional;

public interface VoiceQueryRepository {
Optional<Voice> findByMemberId(Long memberId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.example.memetory.domain.voice.repository;

import com.example.memetory.domain.voice.entity.Voice;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;

import java.util.Optional;

import static com.example.memetory.domain.member.entity.QMember.member;
import static com.example.memetory.domain.voice.entity.QVoice.voice;

@Repository
@RequiredArgsConstructor
public class VoiceQueryRepositoryImpl implements VoiceQueryRepository{

private final JPAQueryFactory jpaQueryFactory;

@Override
public Optional<Voice> findByMemberId(Long memberId) {
return Optional.ofNullable(jpaQueryFactory.selectFrom(voice)
.where(voice.member.id.eq(memberId))
.join(voice.member, member)
.fetchOne());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
import com.example.memetory.domain.voice.entity.Voice;
import org.springframework.data.jpa.repository.JpaRepository;

public interface VoiceRepository extends JpaRepository<Voice, Long> {
public interface VoiceRepository extends JpaRepository<Voice, Long>, VoiceQueryRepository{
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import com.example.memetory.domain.member.service.MemberService;
import com.example.memetory.domain.voice.dto.VoiceServiceDto;
import com.example.memetory.domain.voice.entity.Voice;
import com.example.memetory.domain.voice.exception.NotFoundVoiceException;
import com.example.memetory.domain.voice.repository.VoiceRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
Expand Down Expand Up @@ -37,6 +38,14 @@ public void register(VoiceServiceDto voiceServiceDto) {
voiceRepository.save(newVoice);
}

@Transactional(readOnly = true)
public String findVoiceByMemberId(VoiceServiceDto voiceServiceDto) {
Member foundMember = memberService.findByEmail(voiceServiceDto.getEmail());
Voice foundVoice = voiceRepository.findByMemberId(foundMember.getId()).orElseThrow(NotFoundVoiceException::new);

return foundVoice.getElevenlabsVoiceId();
}

// 목소리 생성
public MultiValueMap<String, Object> generateVoice(VoiceServiceDto voiceServiceDto) throws IOException {
S3Object s3Object = getS3File(voiceServiceDto);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ public enum ErrorCode {

// Comment
COMMENT_NOT_FOUND(404, "댓글 찾기 실패"),

// Voice
VOICE_NOT_FOUND(404, "보이스 찾기 실패")
;

private final int status;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ public enum ResultCode {
CREATE_COMPLAIN_SUCCESS(201, "신고 생성 성공"),
DELETE_COMPLAIN_SUCCESS(201, "신고 삭제 성공"),

// voice
CREATE_VOICE_SUCCESS(201, "목소리 생성 성공"),
GET_MEMBER_VOICE_SUCCESS(200, "멤버별 목소리 조회 성공"),
GET_VOICE_LIBRARY_SUCCESS(200, "기본 목소리 라이브러리 조회 성공")

;
private final int status;
private final String message;
Expand Down

0 comments on commit ae30ca0

Please sign in to comment.