Skip to content

Commit

Permalink
Merge pull request #275 from tipi-tapi/develop
Browse files Browse the repository at this point in the history
Release 1.2.1
  • Loading branch information
akalswl14 authored Nov 9, 2023
2 parents d3ebb04 + 5c6cd35 commit e6e0726
Show file tree
Hide file tree
Showing 30 changed files with 964 additions and 182 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,13 @@ public ResponseEntity<SuccessResponse<Page<GetDiaryAdminResponse>>> getDiaries(
@RequestParam(name = "direction", required = false, defaultValue = "DESC") Direction direction,
@Parameter(name = "emotion", description = "필터링할 감정 ID", in = ParameterIn.QUERY)
@RequestParam(name = "emotion", required = false) Long emotionId,
@Parameter(name = "with_test", description = "테스트용 일기 포함 여부", in = ParameterIn.QUERY)
@RequestParam(name = "with_test", required = false, defaultValue = "true") boolean withTest,
@AuthUser @Parameter(hidden = true) JwtTokenInfo tokenInfo
) {
return SuccessResponse.of(
adminService.getDiaries(tokenInfo.getUserId(), size, page, direction, emotionId)
adminService.getDiaries(tokenInfo.getUserId(), size, page, direction, emotionId,
withTest)
).asHttp(HttpStatus.OK);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,19 @@ public class GetDiaryAdminResponse {
@Schema(description = "평가 점수 (1~5 사이의 숫자)")
private final String review;

@Schema(description = "테스트 일기 여부", requiredMode = RequiredMode.REQUIRED)
private final boolean isTest;

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

public void updateImageUrl(String imageUrl) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ public class AdminService {
private final AdminDiaryService adminDiaryService;

public Page<GetDiaryAdminResponse> getDiaries(Long userId, int size, int page,
Direction direction, Long emotionId) {
Direction direction, Long emotionId, boolean withTest) {
validateUserService.validateAdminUserById(userId);
return adminDiaryService.getDiaries(size, page, direction, emotionId);
return adminDiaryService.getDiaries(size, page, direction, emotionId, withTest);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -169,23 +169,13 @@ public ResponseEntity<SuccessResponse<GetLastCreationResponse>> getLastCreation(
@PostMapping()
public ResponseEntity<SuccessResponse<CreateDiaryResponse>> createDiary(
@RequestBody @Valid CreateDiaryRequest createDiaryRequest,
@AuthUser @Parameter(hidden = true) JwtTokenInfo tokenInfo,
@Parameter(description = "테스트 여부", in = ParameterIn.QUERY)
@RequestParam(value = "test", required = false, defaultValue = "false") boolean test
@AuthUser @Parameter(hidden = true) JwtTokenInfo tokenInfo
) throws ImageGeneratorException {
CreateDiaryResponse response;
if (test) {
response = createDiaryService.createTestDiary(tokenInfo.getUserId(),
createDiaryRequest.getEmotionId(),
createDiaryRequest.getKeyword(), createDiaryRequest.getNotes(),
createDiaryRequest.getDiaryDate(), createDiaryRequest.getUserTime());
} else {
response = createDiaryService.createDiary(tokenInfo.getUserId(),
createDiaryRequest.getEmotionId(),
createDiaryRequest.getKeyword(), createDiaryRequest.getNotes(),
createDiaryRequest.getDiaryDate(), createDiaryRequest.getUserTime());
}
return SuccessResponse.of(response).asHttp(HttpStatus.CREATED);
return SuccessResponse.of(createDiaryService.createDiary(tokenInfo.getUserId(),
createDiaryRequest.getEmotionId(),
createDiaryRequest.getKeyword(), createDiaryRequest.getNotes(),
createDiaryRequest.getDiaryDate(), createDiaryRequest.getUserTime())
).asHttp(HttpStatus.CREATED);
}

@Operation(summary = "일기 수정", description = "주어진 일기의 내용을 수정한다.")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package tipitapi.drawmytoday.domain.diary.controller;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import javax.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Profile;
import org.springframework.http.HttpStatus;
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 tipitapi.drawmytoday.common.resolver.AuthUser;
import tipitapi.drawmytoday.common.response.SuccessResponse;
import tipitapi.drawmytoday.common.security.jwt.JwtTokenInfo;
import tipitapi.drawmytoday.domain.diary.dto.CreateDiaryResponse;
import tipitapi.drawmytoday.domain.diary.dto.CreateTestDiaryRequest;
import tipitapi.drawmytoday.domain.diary.service.CreateDiaryService;
import tipitapi.drawmytoday.domain.generator.exception.ImageGeneratorException;

@Profile("!prod")
@RestController
@RequiredArgsConstructor
@RequestMapping("/diary")
@SecurityRequirement(name = "Bearer Authentication")
public class TestDiaryController {

private final CreateDiaryService createDiaryService;

@Operation(summary = "테스트 일기 생성", description = "테스트 일기를 생성합니다.(티켓 소모 x)")
@ApiResponses(value = {
@ApiResponse(
responseCode = "201",
description = "테스트 일기 생성 성공"),
@ApiResponse(
responseCode = "400",
description = "U004 : 이미 그림일기를 그린 유저입니다.",
content = @Content(schema = @Schema(hidden = true))),
@ApiResponse(
responseCode = "404",
description = "E001 : 감정을 찾을 수 없습니다.",
content = @Content(schema = @Schema(hidden = true))),
@ApiResponse(
responseCode = "409",
description = "D001 : 이미 일기를 그린 날짜입니다.",
content = @Content(schema = @Schema(hidden = true))),
@ApiResponse(
responseCode = "500",
description = "DE001 : DALL-E 이미지 생성에 실패하였습니다. \r\n "
+ "IIS001 : 이미지 스트림을 가져오는데 실패하였습니다.",
content = @Content(schema = @Schema(hidden = true))),
})
@PostMapping("/test")
public ResponseEntity<SuccessResponse<CreateDiaryResponse>> createTestDiary(
@RequestBody @Valid CreateTestDiaryRequest createTestDiaryRequest,
@AuthUser @Parameter(hidden = true) JwtTokenInfo tokenInfo) throws ImageGeneratorException {
return SuccessResponse.of(createDiaryService.createTestDiary(
tokenInfo.getUserId(), createTestDiaryRequest
)).asHttp(HttpStatus.CREATED);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package tipitapi.drawmytoday.domain.diary.dto;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import io.swagger.v3.oas.annotations.media.Schema;
import java.time.LocalDate;
import java.time.LocalTime;
import java.util.Objects;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Positive;
import javax.validation.constraints.Size;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import tipitapi.drawmytoday.common.validator.ValidDiaryDate;

@Getter
@Schema(description = "태스트 일기 생성 Request")
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
public class CreateTestDiaryRequest {

@NotNull
@Schema(description = "감정 ID")
private Long emotionId;

@Size(max = 6010)
@Schema(description = "일기 내용", nullable = true)
private String notes;

@NotNull
@ValidDiaryDate
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
@JsonDeserialize(using = LocalDateDeserializer.class)
@Schema(description = "일기 날짜")
private LocalDate diaryDate;

@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "HH:mm:ss")
@JsonDeserialize(using = LocalTimeDeserializer.class)
@Schema(description = "현재 유저 시간", nullable = true, example = "12:00:00")
private LocalTime userTime;

@Valid
private KarloParameter karloParameter;

@Getter
@NoArgsConstructor
@AllArgsConstructor
public static class KarloParameter {

@NotBlank
@Schema(description = "프롬프트", nullable = false)
private String prompt;

@Schema(description = "부정 프롬프트", nullable = true)
private String negativePrompt;

@Positive
@NotNull
@Schema(description = "이미지 개수. (양수여야 한다)", nullable = false)
private Integer samples;

@Schema(description = "이미지 생성 과정의 노이즈 제거 단계 수 (기본값: 25, 최소: 10, 최대 100)",
nullable = true)
private Integer priorNumInferenceSteps;

@Schema(description = "이미지 생성 과정의 노이즈 제거 척도 (기본값: 5.0, 최소: 1.0, 최대: 20.0)",
nullable = true)
private Double priorGuidanceScale;

@Schema(description = "디코더를 통한 노이즈 제거 단계 (기본값: 50, 최소: 10, 최대: 100)",
nullable = true)
private Integer numInferenceSteps;

@Schema(description = "디코더를 통한 노이즈 제거 척도 (기본값: 5.0, 최소: 1.0, 최대: 20.0)",
nullable = true)
private Double guidanceScale;

@Schema(description = "디코더를 통한 노이즈 제거 단계에서 사용할 스케줄러(Scheduler), 다음 중 하나"
+ "decoder_ddim_v_prediction, decoder_ddpm_v_prediction "
+ "(기본값: decoder_ddim_v_prediction)", nullable = true)
private String scheduler;

@Schema(description = "각 이미지 생성 작업에 사용할 시드(Seed) 값. "
+ "생성할 이미지 수와 같은 길이의 배열이어야 함. 0 이상 4,294,967,295 이하 숫자로 구성", nullable = true)
private Long[] seed;

public String getScheduler() {
if (Objects.equals(scheduler, "decoder_ddpm_v_prediction")) {
return "decoder_ddpm_v_prediction";
}
return "decoder_ddim_v_prediction";
}
}

public LocalTime getUserTime() {
if (userTime == null) {
return LocalTime.now();
}
return userTime;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
public interface DiaryQueryRepository {

Page<GetDiaryAdminResponse> getDiariesForMonitorAsPage(Pageable pageable,
Direction direction, Long emotionId);
Direction direction, Long emotionId, boolean withTest);

Optional<Diary> getDiaryExistsByDiaryDate(Long userId, LocalDate diaryDate);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ public class DiaryQueryRepositoryImpl implements DiaryQueryRepository {

@Override
public Page<GetDiaryAdminResponse> getDiariesForMonitorAsPage(Pageable pageable,
Direction direction, Long emotionId) {
Direction direction, Long emotionId, boolean withTest) {

BooleanExpression withoutTest = diary.isTest.eq(false);
BooleanExpression withoutTest = withTest ? null : diary.isTest.eq(false);
BooleanExpression withEmotion = null;
if (emotionId != null) {
Emotion filterEmotion = queryFactory.selectFrom(emotion)
Expand All @@ -46,7 +46,7 @@ public Page<GetDiaryAdminResponse> getDiariesForMonitorAsPage(Pageable pageable,

List<GetDiaryAdminResponse> content = queryFactory.select(
new QGetDiaryAdminResponse(diary.diaryId, image.imageUrl, prompt.promptText,
diary.createdAt, image.createdAt, image.review))
diary.createdAt, image.createdAt, image.review, diary.isTest))
.from(diary)
.leftJoin(image).on(diary.diaryId.eq(image.diary.diaryId))
.leftJoin(prompt).on(diary.diaryId.eq(prompt.diary.diaryId))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ public class AdminDiaryService {
private int imageExpiration;

public Page<GetDiaryAdminResponse> getDiaries(int size, int page, Direction direction,
Long emotionId) {
Long emotionId, boolean withTest) {
return diaryRepository.getDiariesForMonitorAsPage(
Pageable.ofSize(size).withPage(page), direction, emotionId)
Pageable.ofSize(size).withPage(page), direction, emotionId, withTest)
.map(this::generatePresignedURL);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tipitapi.drawmytoday.common.utils.Encryptor;
import tipitapi.drawmytoday.domain.diary.domain.Diary;
import tipitapi.drawmytoday.domain.diary.domain.Prompt;
import tipitapi.drawmytoday.domain.diary.dto.CreateDiaryResponse;
import tipitapi.drawmytoday.domain.diary.dto.CreateTestDiaryRequest;
import tipitapi.drawmytoday.domain.diary.exception.PromptNotExistException;
import tipitapi.drawmytoday.domain.diary.repository.DiaryRepository;
import tipitapi.drawmytoday.domain.emotion.domain.Emotion;
Expand All @@ -34,9 +36,7 @@ public class CreateDiaryService {
private final ValidateTicketService validateTicketService;
private final ImageGeneratorService karloService;
private final PromptService promptService;
private final PromptTextService promptTextService;
private final Encryptor encryptor;
private final String DUMMY_IMAGE_PATH = "test/dummy.png";

@Transactional(noRollbackFor = {ImageGeneratorException.class})
public CreateDiaryResponse createDiary(Long userId, Long emotionId, String keyword,
Expand All @@ -59,19 +59,22 @@ public CreateDiaryResponse createDiary(Long userId, Long emotionId, String keywo
return new CreateDiaryResponse(diary.getDiaryId());
}

@Transactional
public CreateDiaryResponse createTestDiary(Long userId, Long emotionId, String keyword,
String notes, LocalDate diaryDate, LocalTime userTime) {
@Transactional(noRollbackFor = {ImageGeneratorException.class})
public CreateDiaryResponse createTestDiary(Long userId, CreateTestDiaryRequest request)
throws ImageGeneratorException {
LocalDate diaryDate = request.getDiaryDate();
User user = validateUserService.validateAdminUserById(userId);
validateDiaryService.validateExistsByDate(userId, diaryDate);
validateTicketService.findAndUseTicket(userId);
Emotion emotion = validateEmotionService.validateEmotionById(emotionId);
LocalDateTime diaryDateTime = diaryDate.atTime(userTime);
Emotion emotion = validateEmotionService.validateEmotionById(request.getEmotionId());
LocalDateTime diaryDateTime = diaryDate.atTime(request.getUserTime());

Diary diary = saveDiary(notes, user, emotion, diaryDateTime, true);
String prompt = promptTextService.createPromptText(emotion, keyword);
promptService.createPrompt(diary, prompt, true);
imageService.createImage(diary, DUMMY_IMAGE_PATH, true);
List<byte[]> images = karloService.generateTestImage(request);

Diary diary = saveDiary(request.getNotes(), user, emotion, diaryDateTime, true);
promptService.createPrompt(diary, request.getKarloParameter().getPrompt(), true);
for (int i = 0; i < images.size(); i++) {
imageService.uploadAndCreateImage(diary, images.get(i), i == 0);
}

return new CreateDiaryResponse(diary.getDiaryId());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ public String createPromptText(Emotion emotion, String keyword) {
return promptTextBuilder(
emotion.getEmotionPrompt(),
emotion.getColorPrompt(),
"canvas-textured",
"Oil Pastel",
"Impressionist oil painting",
keyword);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,19 @@ public class GetActiveEmotionsResponse {
@Schema(description = "감정 색깔 HEX", requiredMode = RequiredMode.REQUIRED)
private final String color;

public static GetActiveEmotionsResponse of(Long id, String name, String color) {
return new GetActiveEmotionsResponse(id, name, color);
@Schema(description = "감정 색깔 프롬프트값", requiredMode = RequiredMode.REQUIRED)
private final String colorPrompt;

public static GetActiveEmotionsResponse of(Long id, String name, String color,
String colorPrompt) {
return new GetActiveEmotionsResponse(id, name, color, colorPrompt);
}

public static List<GetActiveEmotionsResponse> buildWithEmotions(List<Emotion> emotions,
Language language) {
return emotions.stream()
.map(e -> GetActiveEmotionsResponse.of(
e.getEmotionId(), getEmotionName(language, e), e.getColor()))
e.getEmotionId(), getEmotionName(language, e), e.getColor(), e.getColorPrompt()))
.collect(
Collectors.toList());
}
Expand Down
Loading

0 comments on commit e6e0726

Please sign in to comment.