Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into feat/#9
Browse files Browse the repository at this point in the history
  • Loading branch information
youKeon committed Mar 2, 2023
2 parents 10470f5 + 3b5e6a6 commit fe99df0
Show file tree
Hide file tree
Showing 8 changed files with 175 additions and 9 deletions.
3 changes: 3 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'io.springfox:springfox-boot-starter:3.0.0'
implementation 'io.springfox:springfox-swagger-ui:3.0.0'
implementation 'org.apache.httpcomponents:httpclient:4.5.12'
implementation 'org.apache.httpcomponents:httpmime:4.3.1'
implementation 'com.google.code.gson:gson:2.8.5'
compileOnly 'org.projectlombok:lombok'
runtimeOnly 'com.mysql:mysql-connector-j'
annotationProcessor 'org.projectlombok:lombok'
Expand Down
109 changes: 109 additions & 0 deletions src/main/java/com/tecst/tecst/domain/answer/ClovaSpeechClient.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package com.tecst.tecst.domain.answer;

import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

import com.google.gson.JsonObject;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicHeader;
import org.apache.http.util.EntityUtils;

import com.google.gson.Gson;
import com.google.gson.JsonParser;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class ClovaSpeechClient {

// Clova Speech secret key
private static String SECRET;
@Value("${clova.SECRET}")
private void setSECRET(String value){
SECRET = value;
}
// Clova Speech invoke URL
private static String INVOKE_URL;
@Value("${clova.INVOKE-URL}")
private void setINVOKE_URL (String value){
INVOKE_URL = value;
}

private final CloseableHttpClient httpClient = HttpClients.createDefault();
private final Gson gson = new Gson();

private static Header[] HEADERS;

private void setHEADERS() {
HEADERS = new Header[]{
new BasicHeader("Accept", "application/json;UTF-8"),
new BasicHeader("X-CLOVASPEECH-API-KEY", SECRET),
};
}

public static class NestRequestEntity {
private static final String language = "ko-KR";
//completion optional, sync/async
private static final String completion = "sync";
private final Boolean fullText = Boolean.TRUE;
//도메인 생성시 선택한 저장소(object storage)에 결과 저장
private final Boolean resultToObs = Boolean.TRUE;
public String getLanguage() {
return language;
}

public String getCompletion() {
return completion;
}

public Boolean getFullText() {
return fullText;
}

public Boolean getResultToObs() {
return resultToObs;
}
}

/**
* objectStorage 파일 STT 실행
* recognize media using Object Storage
* @param dataKey required, the Object Storage key
* @param nestRequestEntity optional
* @return string
*/
public String objectStorage(String dataKey, NestRequestEntity nestRequestEntity) {
HttpPost httpPost = new HttpPost(INVOKE_URL + "/recognizer/object-storage");
setHEADERS();
httpPost.setHeaders(HEADERS);
Map<String, Object> body = new HashMap<>();
body.put("dataKey", dataKey);
body.put("language", nestRequestEntity.getLanguage());
body.put("completion", nestRequestEntity.getCompletion());
body.put("fullText", nestRequestEntity.getFullText());
body.put("resultToObs", nestRequestEntity.getResultToObs());
StringEntity httpEntity = new StringEntity(gson.toJson(body), ContentType.APPLICATION_JSON);
httpPost.setEntity(httpEntity);
return execute(httpPost);
}

private String execute(HttpPost httpPost) {
try (final CloseableHttpResponse httpResponse = httpClient.execute(httpPost)) {
final HttpEntity entity = httpResponse.getEntity();
String result = EntityUtils.toString(entity, StandardCharsets.UTF_8);
JsonParser jsonParser = new JsonParser();
JsonObject jsonObject = (JsonObject) jsonParser.parse(result);
return jsonObject.get("text").toString().replace("\"", "");
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.tecst.tecst.domain.answer.controller;

import com.tecst.tecst.domain.answer.dto.request.SaveAnswerRequestDto;
import com.tecst.tecst.domain.answer.dto.response.GetVoiceAnswerResponseDto;
import com.tecst.tecst.domain.answer.service.AnswerService;
import com.tecst.tecst.domain.common_question.entity.CommonQuestion;
import com.tecst.tecst.domain.common_question.service.CommonQuestionService;
Expand All @@ -11,14 +12,13 @@
import lombok.AccessLevel;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
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 springfox.documentation.annotations.ApiIgnore;


import java.util.UUID;

import static com.tecst.tecst.global.result.ResultCode.REGISTER_ANSWER_SUCCESS;
import static com.tecst.tecst.global.result.ResultCode.USER_REGISTRATION_SUCCESS;

@Api(tags = "Common Question API")
@RestController
Expand All @@ -36,4 +36,19 @@ public ResponseEntity<ResultResponse> SaveAnswer(@RequestBody SaveAnswerRequestD
answerService.saveAnswer(dto, user, commonQuestion);
return ResponseEntity.ok(ResultResponse.of(REGISTER_ANSWER_SUCCESS, dto));
}

@ApiOperation(value = "녹음 파일을 버킷에 전달 후 STT 실행")
@PostMapping("/voice-answers/new")
// 답변 저장
public ResponseEntity<ResultResponse> SaveVoiceAnswer(@RequestBody SaveAnswerRequestDto dto, @ApiIgnore User user) {
CommonQuestion commonQuestion = commonQuestionService.findCommonQuestionById(dto.getCommon_questions_id());
answerService.saveAnswer(dto, user, commonQuestion);
return ResponseEntity.ok(ResultResponse.of(REGISTER_ANSWER_SUCCESS, dto));
}

@ApiOperation(value = "녹음 조회")
@GetMapping("/voice-answers/{id}")
public GetVoiceAnswerResponseDto GetRecord(@PathVariable UUID id) {
return answerService.GetInterviewRecord(id);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.tecst.tecst.domain.answer.dto.response;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;

import java.util.UUID;

@Setter
@Getter
@AllArgsConstructor
@Builder
public class GetVoiceAnswerResponseDto {
private UUID answerId;
private String response;

public GetVoiceAnswerResponseDto() {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import com.tecst.tecst.domain.answer.dto.request.SaveAnswerRequestDto;
import com.tecst.tecst.domain.answer.entity.Answer;
import com.tecst.tecst.domain.common_question.entity.CommonQuestion;
import com.tecst.tecst.domain.user.dto.request.CreateUserRequestDto;
import com.tecst.tecst.domain.user.entity.User;
import org.springframework.stereotype.Component;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@
import java.util.UUID;

public interface AnswerRepository extends JpaRepository<Answer, UUID> {
Answer findByAnswerId(UUID id);
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.tecst.tecst.domain.answer.service;

import com.tecst.tecst.domain.answer.ClovaSpeechClient;
import com.tecst.tecst.domain.answer.dto.request.SaveAnswerRequestDto;
import com.tecst.tecst.domain.answer.dto.response.GetVoiceAnswerResponseDto;
import com.tecst.tecst.domain.answer.entity.Answer;
import com.tecst.tecst.domain.answer.mapper.AnswerMapper;
import com.tecst.tecst.domain.answer.repository.AnswerRepository;
Expand All @@ -12,6 +14,7 @@
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;
import java.util.UUID;

@Service
@Log4j2
Expand All @@ -20,9 +23,26 @@
public class AnswerService {
private final AnswerRepository answerRepository;
private final AnswerMapper answerMapper;
private final ClovaSpeechClient clovaSpeechClient;

public void saveAnswer(SaveAnswerRequestDto dto, @Lazy User user, CommonQuestion commonquestion) {
// Type이 voice면 STT 실행
if(dto.getType().equals("voice")){
ClovaSpeechClient.NestRequestEntity requestEntity = new ClovaSpeechClient.NestRequestEntity();
final String result = clovaSpeechClient.objectStorage(dto.getResponse(), requestEntity);
dto.setResponse(result);

}

Answer answer = answerMapper.toEntity(dto, user, commonquestion);
answerRepository.save(answer);
}

public GetVoiceAnswerResponseDto GetInterviewRecord(UUID id) {
Answer result = answerRepository.findByAnswerId(id);
GetVoiceAnswerResponseDto dto = new GetVoiceAnswerResponseDto();
dto.setAnswerId(id);
dto.setResponse(result.getResponse());
return dto;
}
}
6 changes: 3 additions & 3 deletions src/main/resources/application.properties
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/tecst?serverTimezone=UTC&characterEncoding=UTF-8
spring.mvc.pathmatch.matching-strategy=ant_path_matcher
spring.profiles.include=dbconfig
spring.profiles.include=dbconfig,clova
spring.datasource.username=username
spring.datasource.password=password

spring.jpa.database=mysql
spring.jpa.hibernate.ddl-auto=create
spring.jpa.hibernate.ddl-auto=update
spring.jpa.generate-ddl=false
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true
spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true

0 comments on commit fe99df0

Please sign in to comment.