Skip to content

Commit

Permalink
Merge pull request #263 from tipi-tapi/develop
Browse files Browse the repository at this point in the history
Release 1.2.0
  • Loading branch information
akalswl14 authored Oct 20, 2023
2 parents 5f9f80c + 6b10dd8 commit d3ebb04
Show file tree
Hide file tree
Showing 74 changed files with 1,622 additions and 340 deletions.
9 changes: 9 additions & 0 deletions .github/workflows/cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ env:
AWS_PATH: ./src/main/resources/application-aws.yml
OPENAI_PATH: ./src/main/resources/application-openai.yml
R2_PATH: ./src/main/resources/application-r2.yml
KAKAO_PATH: ./src/main/resources/application-kakao.yml

jobs:
deploy:
Expand Down Expand Up @@ -83,6 +84,14 @@ jobs:
r2.bucket: ${{ secrets.R2_BUCKET_NAME }}
r2.account-id: ${{ secrets.R2_ACCOUNT_ID }}

- name: application-kakao.yml setting
uses: microsoft/variable-substitution@v1
with:
files: ${{ env.KAKAO_PATH }}
env:
kakao.api.key: ${{ secrets.KAKAO_API_KEY }}
kakao.karlo.image_generate_url: ${{ secrets.KARLO_API_URL }}

- name: Set up JDK 11
uses: actions/setup-java@v3
with:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@
import org.springframework.web.client.RestTemplate;

@Configuration
public class OpenAIRestTemplateConfig {
public class ImageGenerateRestTemplateConfig {

@Value("${openai.api.key}")
private String openaiApiKey;

@Value("${kakao.api.key}")
private String kakaoApiKey;

@Bean
@Qualifier("openaiRestTemplate")
public RestTemplate openaiRestTemplate() {
Expand All @@ -22,4 +25,14 @@ public RestTemplate openaiRestTemplate() {
});
return restTemplate;
}

@Bean
public RestTemplate karloRestTemplate() {
RestTemplate restTemplate = new RestTemplate();
restTemplate.getInterceptors().add((request, body, execution) -> {
request.getHeaders().add("Authorization", "KakaoAK " + kakaoApiKey);
return execution.execute(request, body);
});
return restTemplate;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
description = "프로그라피 8기 4팀 TipiTapi의 오늘 하루를 그려줘 프로젝트의 API 문서입니다.",
version = "v1"),
servers = {
@Server(url = "https://choihyeok.site", description = "테스트 서버"),
@Server(url = "https://draw-my-today-dev.devstory.co.kr", description = "테스트 서버"),
@Server(url = "https://draw-my-today.devstory.co.kr", description = "운영 서버")
}
)
Expand Down Expand Up @@ -118,4 +118,15 @@ public GroupedOpenApi adminOpenAPi() {
.pathsToMatch(paths)
.build();
}

@Bean
public GroupedOpenApi imageOpenApi() {
String[] paths = {"/image/**"};

return GroupedOpenApi
.builder()
.group("일기 이미지 API")
.pathsToMatch(paths)
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,17 @@ public enum ErrorCode {
DIARY_DATE_ALREADY_EXISTS(409, "D004", "이미 일기를 그린 날짜입니다."),

// Image
IMAGE_NOT_FOUND(404, "I001", "선택된 이미지를 찾을 수 없습니다."),
IMAGE_NOT_FOUND(404, "I001", "이미지를 찾을 수 없습니다."),
SELECTED_IMAGE_DELETION_DENIED(403, "I002", "대표 이미지는 삭제할 수 없습니다."),
DIARY_NEEDS_IMAGE(403, "I003", "일기는 최소 한 장의 이미지가 필요합니다."),
IMAGE_NOT_OWNER(403, "I004", "자신의 이미지에만 접근할 수 있습니다."),

// Emotion
EMOTION_NOT_FOUND(404, "E001", "감정을 찾을 수 없습니다."),

// Prompt
PROMPT_NOT_EXIST(500, "P001", "프롬프트가 존재하지 않습니다."),

// R2
R2_SERVICE_ERROR(500, "R001", "R2Exception 에러가 발생하였습니다."),
R2_SDK_ERROR(500, "R002", "SdkClientException 에러가 발생하였습니다."),
Expand All @@ -57,6 +63,9 @@ public enum ErrorCode {
DALLE_REQUEST_FAIL(500, "DE001", "DALL-E 요청에 실패하였습니다."),
DALLE_CONTENT_POLICY_VIOLATION(500, "DE002", "DALL-E의 컨텐츠 정책에 위배되었습니다."),

// Karlo
KARLO_REQUEST_FAIL(500, "K001", "Karlo 요청에 실패하였습니다."),

// Image InputStream
IMAGE_INPUT_STREAM_FAIL(500, "IIS001", "이미지 스트림을 가져오는데 실패하였습니다."),

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
import software.amazon.awssdk.services.s3.model.S3Exception;
import tipitapi.drawmytoday.common.response.ErrorResponse;
import tipitapi.drawmytoday.common.response.ErrorResponse.ValidationError;
import tipitapi.drawmytoday.domain.dalle.exception.DallERequestFailException;
import tipitapi.drawmytoday.domain.dalle.exception.ImageInputStreamFailException;
import tipitapi.drawmytoday.domain.generator.exception.ImageGeneratorException;
import tipitapi.drawmytoday.domain.generator.exception.ImageInputStreamFailException;
import tipitapi.drawmytoday.domain.r2.exception.R2FailedException;

@RestControllerAdvice
Expand All @@ -28,7 +28,11 @@ public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {

@ExceptionHandler(BusinessException.class)
public ResponseEntity<Object> handleBusinessException(BusinessException e) {
log.warn("handleBusinessException", e);
if (e.getErrorCode().getStatus() == HttpStatus.INTERNAL_SERVER_ERROR.value()) {
log.error("handleBusinessException", e);
} else {
log.warn("handleBusinessException", e);
}
ErrorCode errorCode = e.getErrorCode();
return handleExceptionInternal(errorCode);
}
Expand Down Expand Up @@ -88,10 +92,10 @@ public ResponseEntity<Object> handleR2FailedException(R2FailedException e) {
return handleExceptionInternal(ErrorCode.R2_FAILED);
}

@ExceptionHandler(DallERequestFailException.class)
public ResponseEntity<Object> handleDallERequestFailException(DallERequestFailException e) {
log.error("DallERequestFailException", e);
return handleExceptionInternal(ErrorCode.DALLE_REQUEST_FAIL);
@ExceptionHandler(ImageGeneratorException.class)
public ResponseEntity<Object> handleImageGeneratorException(ImageGeneratorException e) {
log.error("ImageGeneratorException", e);
return handleExceptionInternal(e.getErrorCode());
}

@ExceptionHandler(ImageInputStreamFailException.class)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package tipitapi.drawmytoday.common.resolver;

import io.swagger.v3.oas.annotations.Parameter;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Parameter(hidden = true)
public @interface AuthUser {

}
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,26 @@ public class GetDiaryAdminResponse {
@Schema(description = "일기 작성 시간", requiredMode = RequiredMode.REQUIRED)
private final LocalDateTime createdAt;

@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS")
@JsonSerialize(using = LocalDateTimeSerializer.class)
@Schema(description = "이미지 생성 시간", requiredMode = RequiredMode.REQUIRED)
private final LocalDateTime imageCreatedAt;

@Schema(description = "일기 이미지 URL", requiredMode = RequiredMode.NOT_REQUIRED)
private String imageURL;

@Schema(description = "평가 점수 (1~5 사이의 숫자)")
private final String review;

@QueryProjection
public GetDiaryAdminResponse(Long id, String imageURL, String prompt,
LocalDateTime createdAt) {
LocalDateTime createdAt, LocalDateTime imageCreatedAt, String review) {
this.id = id;
this.imageURL = imageURL;
this.prompt = prompt;
this.createdAt = createdAt;
this.imageCreatedAt = imageCreatedAt;
this.review = review;
}

public void updateImageUrl(String imageUrl) {
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
import tipitapi.drawmytoday.common.resolver.AuthUser;
import tipitapi.drawmytoday.common.response.SuccessResponse;
import tipitapi.drawmytoday.common.security.jwt.JwtTokenInfo;
import tipitapi.drawmytoday.domain.dalle.exception.DallEException;
import tipitapi.drawmytoday.domain.diary.dto.CreateDiaryRequest;
import tipitapi.drawmytoday.domain.diary.dto.CreateDiaryResponse;
import tipitapi.drawmytoday.domain.diary.dto.GetDiaryExistByDateResponse;
Expand All @@ -37,6 +36,7 @@
import tipitapi.drawmytoday.domain.diary.dto.UpdateDiaryRequest;
import tipitapi.drawmytoday.domain.diary.service.CreateDiaryService;
import tipitapi.drawmytoday.domain.diary.service.DiaryService;
import tipitapi.drawmytoday.domain.generator.exception.ImageGeneratorException;

@RestController
@RequestMapping("/diary")
Expand Down Expand Up @@ -172,7 +172,7 @@ public ResponseEntity<SuccessResponse<CreateDiaryResponse>> createDiary(
@AuthUser @Parameter(hidden = true) JwtTokenInfo tokenInfo,
@Parameter(description = "테스트 여부", in = ParameterIn.QUERY)
@RequestParam(value = "test", required = false, defaultValue = "false") boolean test
) throws DallEException {
) throws ImageGeneratorException {
CreateDiaryResponse response;
if (test) {
response = createDiaryService.createTestDiary(tokenInfo.getUserId(),
Expand Down Expand Up @@ -250,4 +250,28 @@ public ResponseEntity<SuccessResponse<GetDiaryLimitResponse>> getDrawLimit(
diaryService.getDrawLimit(tokenInfo.getUserId())
).asHttp(HttpStatus.OK);
}

@Operation(summary = "일기 이미지 재생성", description = "주어진 ID에 해당하는 일기를 기반으로 이미지를 재생성한다.")
@ApiResponses(value = {
@ApiResponse(
responseCode = "201",
description = "일기 이미지 재생성 성공"),
@ApiResponse(
responseCode = "404",
description = "T001 : 유효한 티켓이 존재하지 않습니다.",
content = @Content(schema = @Schema(hidden = true))),
@ApiResponse(
responseCode = "500",
description = "DE001 : DALL-E 이미지 생성에 실패하였습니다.\t\nIIS001 : 이미지 스트림을 가져오는데 실패하였습니다."
+ "\t\nP001 : 기존에 그린 일기 이미지에 해당하는 프롬프트가 존재하지 않습니다.",
content = @Content(schema = @Schema(hidden = true))),
})
@PostMapping("/{id}/regenerate")
public ResponseEntity<Void> regenerateDiaryImage(
@AuthUser JwtTokenInfo tokenInfo,
@Parameter(description = "일기 id", in = ParameterIn.PATH) @PathVariable("id") Long diaryId
) throws ImageGeneratorException {
createDiaryService.regenerateDiaryImage(tokenInfo.getUserId(), diaryId);
return ResponseEntity.status(HttpStatus.CREATED).build();
}
}
Loading

0 comments on commit d3ebb04

Please sign in to comment.