diff --git a/dodam-api/src/main/java/b1nd/dodamapi/auth/handler/AuthController.java b/dodam-api/src/main/java/b1nd/dodamapi/auth/handler/AuthController.java index b3d38ccf..c9f49f3e 100644 --- a/dodam-api/src/main/java/b1nd/dodamapi/auth/handler/AuthController.java +++ b/dodam-api/src/main/java/b1nd/dodamapi/auth/handler/AuthController.java @@ -1,7 +1,7 @@ package b1nd.dodamapi.auth.handler; import b1nd.dodamapi.auth.usecase.AuthUseCase; -import b1nd.dodamapi.common.response.ResponseData; +import b1nd.dodamcore.common.response.ResponseData; import b1nd.dodamcore.auth.application.dto.req.LoginReq; import b1nd.dodamcore.auth.application.dto.req.ReissueTokenReq; import b1nd.dodamcore.auth.application.dto.res.LoginRes; diff --git a/dodam-api/src/main/java/b1nd/dodamapi/auth/usecase/AuthUseCase.java b/dodam-api/src/main/java/b1nd/dodamapi/auth/usecase/AuthUseCase.java index 92e6d3e6..c2bf0d05 100644 --- a/dodam-api/src/main/java/b1nd/dodamapi/auth/usecase/AuthUseCase.java +++ b/dodam-api/src/main/java/b1nd/dodamapi/auth/usecase/AuthUseCase.java @@ -1,6 +1,6 @@ package b1nd.dodamapi.auth.usecase; -import b1nd.dodamapi.common.response.ResponseData; +import b1nd.dodamcore.common.response.ResponseData; import b1nd.dodamcore.auth.application.PasswordEncoder; import b1nd.dodamcore.auth.application.TokenClient; import b1nd.dodamcore.auth.application.dto.req.LoginReq; diff --git a/dodam-api/src/main/java/b1nd/dodamapi/banner/BannerController.java b/dodam-api/src/main/java/b1nd/dodamapi/banner/BannerController.java index 1ade4011..f0cc1f7c 100644 --- a/dodam-api/src/main/java/b1nd/dodamapi/banner/BannerController.java +++ b/dodam-api/src/main/java/b1nd/dodamapi/banner/BannerController.java @@ -1,7 +1,7 @@ package b1nd.dodamapi.banner; -import b1nd.dodamapi.common.response.Response; -import b1nd.dodamapi.common.response.ResponseData; +import b1nd.dodamcore.common.response.Response; +import b1nd.dodamcore.common.response.ResponseData; import b1nd.dodamcore.banner.application.BannerService; import b1nd.dodamcore.banner.application.dto.req.BannerReq; import b1nd.dodamcore.banner.domain.entity.Banner; diff --git a/dodam-api/src/main/java/b1nd/dodamapi/bus/BusController.java b/dodam-api/src/main/java/b1nd/dodamapi/bus/BusController.java index 586cf9b4..f700c6c2 100644 --- a/dodam-api/src/main/java/b1nd/dodamapi/bus/BusController.java +++ b/dodam-api/src/main/java/b1nd/dodamapi/bus/BusController.java @@ -1,7 +1,7 @@ package b1nd.dodamapi.bus; -import b1nd.dodamapi.common.response.Response; -import b1nd.dodamapi.common.response.ResponseData; +import b1nd.dodamcore.common.response.Response; +import b1nd.dodamcore.common.response.ResponseData; import b1nd.dodamcore.bus.application.BusService; import b1nd.dodamcore.bus.application.dto.req.BusReq; import b1nd.dodamcore.bus.application.dto.res.BusRes; diff --git a/dodam-api/src/main/java/b1nd/dodamapi/common/exception/CustomExceptionHandler.java b/dodam-api/src/main/java/b1nd/dodamapi/common/exception/CustomExceptionHandler.java index 6ee33f19..78d95e8b 100644 --- a/dodam-api/src/main/java/b1nd/dodamapi/common/exception/CustomExceptionHandler.java +++ b/dodam-api/src/main/java/b1nd/dodamapi/common/exception/CustomExceptionHandler.java @@ -1,6 +1,6 @@ package b1nd.dodamapi.common.exception; -import b1nd.dodamcore.common.exception.ErrorResponseEntity; +import b1nd.dodamcore.common.response.ErrorResponseEntity; import b1nd.dodamcore.common.exception.ExceptionCode; import b1nd.dodamcore.common.exception.GlobalExceptionCode; import b1nd.dodamcore.common.exception.CustomException; @@ -43,14 +43,14 @@ protected ResponseEntity handleValidException(MethodArgumen log.error("Valid Fail Object : {}", e.getObjectName()); log.error("Valid Fail Message : \"{}\"", message); + ErrorResponseEntity.of(e.getStatusCode().value(), GlobalExceptionCode.PARAMETER_NOT_VALID.name(),message); return ResponseEntity .status(e.getStatusCode()) - .body(ErrorResponseEntity.builder() - .status(e.getStatusCode().value()) - .code(GlobalExceptionCode.PARAMETER_NOT_VALID.name()) - .message(message) - .build() - ); + .body(ErrorResponseEntity.of( + e.getStatusCode().value(), + GlobalExceptionCode.PARAMETER_NOT_VALID.name(), + message + )); } private String getValidExceptionMessages(List errors) { @@ -65,70 +65,70 @@ private String getValidExceptionMessages(List errors) { @ExceptionHandler(MissingServletRequestParameterException.class) protected ResponseEntity handleMissingServletRequestParameterException(MissingServletRequestParameterException e) { + return ResponseEntity .status(400) - .body(ErrorResponseEntity.builder() - .status(GlobalExceptionCode.PARAMETER_NOT_FOUND.getStatus().value()) - .code(GlobalExceptionCode.PARAMETER_NOT_FOUND.name()) - .message(GlobalExceptionCode.PARAMETER_NOT_FOUND.getMessage()) - .build()); + .body(ErrorResponseEntity.of( + GlobalExceptionCode.PARAMETER_NOT_FOUND.getStatus().value(), + GlobalExceptionCode.PARAMETER_NOT_FOUND.name(), + GlobalExceptionCode.PARAMETER_NOT_FOUND.getMessage() + )); } @ExceptionHandler(HttpMessageNotReadableException.class) protected ResponseEntity handleHttpMessageNotReadableException(HttpMessageNotReadableException e) { return ResponseEntity .status(400) - .body(ErrorResponseEntity.builder() - .status(GlobalExceptionCode.PARAMETER_NOT_FOUND.getStatus().value()) - .code(GlobalExceptionCode.PARAMETER_NOT_FOUND.name()) - .message(GlobalExceptionCode.PARAMETER_NOT_FOUND.getMessage()) - .build()); + .body(ErrorResponseEntity.of( + GlobalExceptionCode.PARAMETER_NOT_FOUND.getStatus().value(), + GlobalExceptionCode.PARAMETER_NOT_FOUND.name(), + GlobalExceptionCode.PARAMETER_NOT_FOUND.getMessage() + )); } @ExceptionHandler(HttpRequestMethodNotSupportedException.class) protected ResponseEntity handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) { return ResponseEntity .status(400) - .body(ErrorResponseEntity.builder() - .status(GlobalExceptionCode.METHOD_NOT_SUPPORTED.getStatus().value()) - .code(GlobalExceptionCode.METHOD_NOT_SUPPORTED.name()) - .message(GlobalExceptionCode.METHOD_NOT_SUPPORTED.getMessage()) - .build()); + .body(ErrorResponseEntity.of( + GlobalExceptionCode.METHOD_NOT_SUPPORTED.getStatus().value(), + GlobalExceptionCode.METHOD_NOT_SUPPORTED.name(), + GlobalExceptionCode.METHOD_NOT_SUPPORTED.getMessage() + )); } @ExceptionHandler(HttpMediaTypeNotSupportedException.class) protected ResponseEntity handleHttpMediaTypeNotSupportedException() { return ResponseEntity .status(400) - .body(ErrorResponseEntity.builder() - .status(GlobalExceptionCode.MEDIA_TYPE_NOT_SUPPORTED.getStatus().value()) - .code(GlobalExceptionCode.MEDIA_TYPE_NOT_SUPPORTED.name()) - .message(GlobalExceptionCode.MEDIA_TYPE_NOT_SUPPORTED.getMessage()) - .build()); + .body(ErrorResponseEntity.of( + GlobalExceptionCode.MEDIA_TYPE_NOT_SUPPORTED.getStatus().value(), + GlobalExceptionCode.MEDIA_TYPE_NOT_SUPPORTED.name(), + GlobalExceptionCode.MEDIA_TYPE_NOT_SUPPORTED.getMessage() + )); } @ExceptionHandler(MethodArgumentTypeMismatchException.class) protected ResponseEntity handleMethodArgumentTypeMismatchException() { return ResponseEntity .status(400) - .body(ErrorResponseEntity.builder() - .status(GlobalExceptionCode.MEDIA_TYPE_MISS_MATCHED.getStatus().value()) - .code(GlobalExceptionCode.MEDIA_TYPE_MISS_MATCHED.name()) - .message(GlobalExceptionCode.MEDIA_TYPE_MISS_MATCHED.getMessage()) - .build()); + .body(ErrorResponseEntity.of( + GlobalExceptionCode.MEDIA_TYPE_MISS_MATCHED.getStatus().value(), + GlobalExceptionCode.MEDIA_TYPE_MISS_MATCHED.name(), + GlobalExceptionCode.MEDIA_TYPE_MISS_MATCHED.getMessage() + )); } @ExceptionHandler(Exception.class) - protected ResponseEntity handleException(Exception e, HttpServletRequest request){ + protected ResponseEntity handleException(Exception e, HttpServletRequest request) { sendErrorNotice(e, request); - return ResponseEntity .status(500) - .body(ErrorResponseEntity.builder() - .status(GlobalExceptionCode.INTERNAL_SERVER.getStatus().value()) - .code(GlobalExceptionCode.INTERNAL_SERVER.name()) - .message(GlobalExceptionCode.INTERNAL_SERVER.getMessage()) - .build()); + .body(ErrorResponseEntity.of( + GlobalExceptionCode.INTERNAL_SERVER.getStatus().value(), + GlobalExceptionCode.INTERNAL_SERVER.name(), + GlobalExceptionCode.INTERNAL_SERVER.getMessage() + )); } private void sendErrorNotice(Exception e, HttpServletRequest request) { diff --git a/dodam-api/src/main/java/b1nd/dodamapi/common/util/YoutubeApiUtil.java b/dodam-api/src/main/java/b1nd/dodamapi/common/util/YoutubeApiUtil.java new file mode 100644 index 00000000..1de774e2 --- /dev/null +++ b/dodam-api/src/main/java/b1nd/dodamapi/common/util/YoutubeApiUtil.java @@ -0,0 +1,37 @@ +package b1nd.dodamapi.common.util; + +import b1nd.dodamcore.common.util.HtmlConverter; +import b1nd.dodamcore.wakeupsong.application.dto.res.YoutubeApiRes; +import b1nd.dodamcore.wakeupsong.application.dto.res.YoutubeRes; +import b1nd.dodamcore.wakeupsong.domain.exception.WakeupSongUrlMalformedException; + +import java.util.Optional; + +public final class YoutubeApiUtil { + + private YoutubeApiUtil() { + } + + static public YoutubeApiRes.Thumbnail getThumbnailUrl(YoutubeApiRes.Snippet snippet) { + Optional standard = Optional.ofNullable(snippet.getThumbnails().getStandard()); + return standard.orElseGet(() -> snippet.getThumbnails().getHigh()); + } + + static public String getVideoId(String videoUrl){ + try { + return videoUrl.split("/?v=")[1].split("&")[0]; + } catch (IndexOutOfBoundsException e) { + throw new WakeupSongUrlMalformedException(); + } + } + + static public YoutubeRes getYoutubeRes(YoutubeApiRes.SearchItem item) { + return new YoutubeRes( + HtmlConverter.of(item.getSnippet().getTitle()), + item.getId().getVideoId(), + "https://www.youtube.com/watch?v=" + item.getId().getVideoId(), + item.getSnippet().getChannelTitle(), + YoutubeApiUtil.getThumbnailUrl(item.getSnippet()).getUrl() + ); + } +} diff --git a/dodam-api/src/main/java/b1nd/dodamapi/conference/handler/ConferenceController.java b/dodam-api/src/main/java/b1nd/dodamapi/conference/handler/ConferenceController.java index 884d519f..f890c73b 100644 --- a/dodam-api/src/main/java/b1nd/dodamapi/conference/handler/ConferenceController.java +++ b/dodam-api/src/main/java/b1nd/dodamapi/conference/handler/ConferenceController.java @@ -1,6 +1,6 @@ package b1nd.dodamapi.conference.handler; -import b1nd.dodamapi.common.response.ResponseData; +import b1nd.dodamcore.common.response.ResponseData; import b1nd.dodamapi.conference.usecase.ConferenceUseCase; import b1nd.dodamcore.conference.application.dto.res.ConferenceRes; import lombok.RequiredArgsConstructor; diff --git a/dodam-api/src/main/java/b1nd/dodamapi/conference/usecase/ConferenceUseCase.java b/dodam-api/src/main/java/b1nd/dodamapi/conference/usecase/ConferenceUseCase.java index 8c15387e..54c06083 100644 --- a/dodam-api/src/main/java/b1nd/dodamapi/conference/usecase/ConferenceUseCase.java +++ b/dodam-api/src/main/java/b1nd/dodamapi/conference/usecase/ConferenceUseCase.java @@ -1,6 +1,6 @@ package b1nd.dodamapi.conference.usecase; -import b1nd.dodamapi.common.response.ResponseData; +import b1nd.dodamcore.common.response.ResponseData; import b1nd.dodamcore.conference.application.ConferenceClient; import b1nd.dodamcore.conference.application.dto.res.ConferenceRes; import lombok.RequiredArgsConstructor; diff --git a/dodam-api/src/main/java/b1nd/dodamapi/meal/MealController.java b/dodam-api/src/main/java/b1nd/dodamapi/meal/MealController.java index 94856dd9..47c4ba80 100644 --- a/dodam-api/src/main/java/b1nd/dodamapi/meal/MealController.java +++ b/dodam-api/src/main/java/b1nd/dodamapi/meal/MealController.java @@ -1,6 +1,6 @@ package b1nd.dodamapi.meal; -import b1nd.dodamapi.common.response.ResponseData; +import b1nd.dodamcore.common.response.ResponseData; import b1nd.dodamcore.meal.application.MealService; import b1nd.dodamcore.meal.application.dto.Meal; import lombok.RequiredArgsConstructor; diff --git a/dodam-api/src/main/java/b1nd/dodamapi/member/handler/MemberController.java b/dodam-api/src/main/java/b1nd/dodamapi/member/handler/MemberController.java index f6596279..c9a4c293 100644 --- a/dodam-api/src/main/java/b1nd/dodamapi/member/handler/MemberController.java +++ b/dodam-api/src/main/java/b1nd/dodamapi/member/handler/MemberController.java @@ -1,7 +1,7 @@ package b1nd.dodamapi.member.handler; -import b1nd.dodamapi.common.response.Response; -import b1nd.dodamapi.common.response.ResponseData; +import b1nd.dodamcore.common.response.Response; +import b1nd.dodamcore.common.response.ResponseData; import b1nd.dodamapi.member.usecase.MemberCommandUseCase; import b1nd.dodamapi.member.usecase.MemberQueryUseCase; import b1nd.dodamapi.member.usecase.req.*; diff --git a/dodam-api/src/main/java/b1nd/dodamapi/member/usecase/MemberCommandUseCase.java b/dodam-api/src/main/java/b1nd/dodamapi/member/usecase/MemberCommandUseCase.java index aa970eca..d4edba98 100644 --- a/dodam-api/src/main/java/b1nd/dodamapi/member/usecase/MemberCommandUseCase.java +++ b/dodam-api/src/main/java/b1nd/dodamapi/member/usecase/MemberCommandUseCase.java @@ -1,6 +1,6 @@ package b1nd.dodamapi.member.usecase; -import b1nd.dodamapi.common.response.Response; +import b1nd.dodamcore.common.response.Response; import b1nd.dodamapi.member.usecase.req.*; import b1nd.dodamcore.auth.application.PasswordEncoder; import b1nd.dodamcore.member.application.MemberService; diff --git a/dodam-api/src/main/java/b1nd/dodamapi/member/usecase/MemberQueryUseCase.java b/dodam-api/src/main/java/b1nd/dodamapi/member/usecase/MemberQueryUseCase.java index 9acfdd47..40abc769 100644 --- a/dodam-api/src/main/java/b1nd/dodamapi/member/usecase/MemberQueryUseCase.java +++ b/dodam-api/src/main/java/b1nd/dodamapi/member/usecase/MemberQueryUseCase.java @@ -1,6 +1,6 @@ package b1nd.dodamapi.member.usecase; -import b1nd.dodamapi.common.response.ResponseData; +import b1nd.dodamcore.common.response.ResponseData; import b1nd.dodamcore.member.application.MemberService; import b1nd.dodamcore.member.application.MemberSessionHolder; import b1nd.dodamcore.member.domain.entity.Member; diff --git a/dodam-api/src/main/java/b1nd/dodamapi/nightstudy/handler/NightStudyController.java b/dodam-api/src/main/java/b1nd/dodamapi/nightstudy/handler/NightStudyController.java index 400d0352..8c01d380 100644 --- a/dodam-api/src/main/java/b1nd/dodamapi/nightstudy/handler/NightStudyController.java +++ b/dodam-api/src/main/java/b1nd/dodamapi/nightstudy/handler/NightStudyController.java @@ -1,7 +1,7 @@ package b1nd.dodamapi.nightstudy.handler; -import b1nd.dodamapi.common.response.Response; -import b1nd.dodamapi.common.response.ResponseData; +import b1nd.dodamcore.common.response.Response; +import b1nd.dodamcore.common.response.ResponseData; import b1nd.dodamapi.nightstudy.usecase.NightStudyUseCase; import b1nd.dodamapi.nightstudy.usecase.dto.req.ApplyNightStudyReq; import b1nd.dodamapi.nightstudy.usecase.dto.req.RejectNightStudyReq; diff --git a/dodam-api/src/main/java/b1nd/dodamapi/nightstudy/usecase/NightStudyUseCase.java b/dodam-api/src/main/java/b1nd/dodamapi/nightstudy/usecase/NightStudyUseCase.java index 99559aa7..0e40750d 100644 --- a/dodam-api/src/main/java/b1nd/dodamapi/nightstudy/usecase/NightStudyUseCase.java +++ b/dodam-api/src/main/java/b1nd/dodamapi/nightstudy/usecase/NightStudyUseCase.java @@ -1,7 +1,7 @@ package b1nd.dodamapi.nightstudy.usecase; -import b1nd.dodamapi.common.response.Response; -import b1nd.dodamapi.common.response.ResponseData; +import b1nd.dodamcore.common.response.Response; +import b1nd.dodamcore.common.response.ResponseData; import b1nd.dodamcore.common.util.ZonedDateTimeUtil; import b1nd.dodamcore.member.application.MemberService; import b1nd.dodamcore.member.domain.entity.Student; diff --git a/dodam-api/src/main/java/b1nd/dodamapi/outgoing/handler/OutGoingController.java b/dodam-api/src/main/java/b1nd/dodamapi/outgoing/handler/OutGoingController.java index 6a0c0870..1a1958b9 100644 --- a/dodam-api/src/main/java/b1nd/dodamapi/outgoing/handler/OutGoingController.java +++ b/dodam-api/src/main/java/b1nd/dodamapi/outgoing/handler/OutGoingController.java @@ -1,7 +1,7 @@ package b1nd.dodamapi.outgoing.handler; -import b1nd.dodamapi.common.response.Response; -import b1nd.dodamapi.common.response.ResponseData; +import b1nd.dodamcore.common.response.Response; +import b1nd.dodamcore.common.response.ResponseData; import b1nd.dodamapi.outgoing.usecase.OutGoingUseCase; import b1nd.dodamapi.outgoing.usecase.dto.req.RejectOutGoingReq; import b1nd.dodamapi.outgoing.usecase.dto.res.OutGoingRes; diff --git a/dodam-api/src/main/java/b1nd/dodamapi/outgoing/usecase/OutGoingUseCase.java b/dodam-api/src/main/java/b1nd/dodamapi/outgoing/usecase/OutGoingUseCase.java index 78a767c7..19b1a52f 100644 --- a/dodam-api/src/main/java/b1nd/dodamapi/outgoing/usecase/OutGoingUseCase.java +++ b/dodam-api/src/main/java/b1nd/dodamapi/outgoing/usecase/OutGoingUseCase.java @@ -1,7 +1,7 @@ package b1nd.dodamapi.outgoing.usecase; -import b1nd.dodamapi.common.response.Response; -import b1nd.dodamapi.common.response.ResponseData; +import b1nd.dodamcore.common.response.Response; +import b1nd.dodamcore.common.response.ResponseData; import b1nd.dodamcore.common.util.ZonedDateTimeUtil; import b1nd.dodamcore.member.application.MemberService; import b1nd.dodamcore.member.domain.entity.Student; diff --git a/dodam-api/src/main/java/b1nd/dodamapi/outsleeping/handler/OutSleepingController.java b/dodam-api/src/main/java/b1nd/dodamapi/outsleeping/handler/OutSleepingController.java index ef2ed24d..f9d461da 100644 --- a/dodam-api/src/main/java/b1nd/dodamapi/outsleeping/handler/OutSleepingController.java +++ b/dodam-api/src/main/java/b1nd/dodamapi/outsleeping/handler/OutSleepingController.java @@ -1,7 +1,7 @@ package b1nd.dodamapi.outsleeping.handler; -import b1nd.dodamapi.common.response.Response; -import b1nd.dodamapi.common.response.ResponseData; +import b1nd.dodamcore.common.response.Response; +import b1nd.dodamcore.common.response.ResponseData; import b1nd.dodamapi.outsleeping.usecase.OutSleepingUseCase; import b1nd.dodamapi.outsleeping.usecase.dto.req.ApplyOutSleepingReq; import b1nd.dodamapi.outsleeping.usecase.dto.req.RejectOutSleepingReq; diff --git a/dodam-api/src/main/java/b1nd/dodamapi/outsleeping/usecase/OutSleepingUseCase.java b/dodam-api/src/main/java/b1nd/dodamapi/outsleeping/usecase/OutSleepingUseCase.java index 2c2b6293..667d206a 100644 --- a/dodam-api/src/main/java/b1nd/dodamapi/outsleeping/usecase/OutSleepingUseCase.java +++ b/dodam-api/src/main/java/b1nd/dodamapi/outsleeping/usecase/OutSleepingUseCase.java @@ -1,7 +1,7 @@ package b1nd.dodamapi.outsleeping.usecase; -import b1nd.dodamapi.common.response.Response; -import b1nd.dodamapi.common.response.ResponseData; +import b1nd.dodamcore.common.response.Response; +import b1nd.dodamcore.common.response.ResponseData; import b1nd.dodamcore.common.util.ZonedDateTimeUtil; import b1nd.dodamcore.member.application.MemberService; import b1nd.dodamcore.member.domain.entity.Student; diff --git a/dodam-api/src/main/java/b1nd/dodamapi/point/handler/PointController.java b/dodam-api/src/main/java/b1nd/dodamapi/point/handler/PointController.java index ff8a2c6f..ca0384a3 100644 --- a/dodam-api/src/main/java/b1nd/dodamapi/point/handler/PointController.java +++ b/dodam-api/src/main/java/b1nd/dodamapi/point/handler/PointController.java @@ -1,7 +1,7 @@ package b1nd.dodamapi.point.handler; -import b1nd.dodamapi.common.response.Response; -import b1nd.dodamapi.common.response.ResponseData; +import b1nd.dodamcore.common.response.Response; +import b1nd.dodamcore.common.response.ResponseData; import b1nd.dodamapi.point.usecase.PointReasonUseCase; import b1nd.dodamapi.point.usecase.PointUseCase; import b1nd.dodamapi.point.usecase.req.IssuePointReq; diff --git a/dodam-api/src/main/java/b1nd/dodamapi/point/usecase/PointReasonUseCase.java b/dodam-api/src/main/java/b1nd/dodamapi/point/usecase/PointReasonUseCase.java index d99ea0a9..72ec739e 100644 --- a/dodam-api/src/main/java/b1nd/dodamapi/point/usecase/PointReasonUseCase.java +++ b/dodam-api/src/main/java/b1nd/dodamapi/point/usecase/PointReasonUseCase.java @@ -1,7 +1,7 @@ package b1nd.dodamapi.point.usecase; -import b1nd.dodamapi.common.response.Response; -import b1nd.dodamapi.common.response.ResponseData; +import b1nd.dodamcore.common.response.Response; +import b1nd.dodamcore.common.response.ResponseData; import b1nd.dodamcore.point.application.PointReasonService; import b1nd.dodamapi.point.usecase.req.ModifyPointReasonReq; import b1nd.dodamapi.point.usecase.req.RegisterPointReasonReq; diff --git a/dodam-api/src/main/java/b1nd/dodamapi/point/usecase/PointUseCase.java b/dodam-api/src/main/java/b1nd/dodamapi/point/usecase/PointUseCase.java index 4c69eaab..b38255ab 100644 --- a/dodam-api/src/main/java/b1nd/dodamapi/point/usecase/PointUseCase.java +++ b/dodam-api/src/main/java/b1nd/dodamapi/point/usecase/PointUseCase.java @@ -1,7 +1,7 @@ package b1nd.dodamapi.point.usecase; -import b1nd.dodamapi.common.response.Response; -import b1nd.dodamapi.common.response.ResponseData; +import b1nd.dodamcore.common.response.Response; +import b1nd.dodamcore.common.response.ResponseData; import b1nd.dodamcore.member.application.MemberService; import b1nd.dodamcore.member.domain.entity.Member; import b1nd.dodamcore.member.domain.entity.Student; diff --git a/dodam-api/src/main/java/b1nd/dodamapi/recruit/RecruitController.java b/dodam-api/src/main/java/b1nd/dodamapi/recruit/RecruitController.java index 2871d886..6edee185 100644 --- a/dodam-api/src/main/java/b1nd/dodamapi/recruit/RecruitController.java +++ b/dodam-api/src/main/java/b1nd/dodamapi/recruit/RecruitController.java @@ -1,7 +1,7 @@ package b1nd.dodamapi.recruit; -import b1nd.dodamapi.common.response.Response; -import b1nd.dodamapi.common.response.ResponseData; +import b1nd.dodamcore.common.response.Response; +import b1nd.dodamcore.common.response.ResponseData; import b1nd.dodamcore.recruit.application.RecruitService; import b1nd.dodamcore.recruit.application.dto.req.RecruitReq; import b1nd.dodamcore.recruit.application.dto.res.RecruitPageRes; diff --git a/dodam-api/src/main/java/b1nd/dodamapi/schedule/ScheduleController.java b/dodam-api/src/main/java/b1nd/dodamapi/schedule/ScheduleController.java index ef5f7bd8..0c8da325 100644 --- a/dodam-api/src/main/java/b1nd/dodamapi/schedule/ScheduleController.java +++ b/dodam-api/src/main/java/b1nd/dodamapi/schedule/ScheduleController.java @@ -1,7 +1,7 @@ package b1nd.dodamapi.schedule; -import b1nd.dodamapi.common.response.Response; -import b1nd.dodamapi.common.response.ResponseData; +import b1nd.dodamcore.common.response.Response; +import b1nd.dodamcore.common.response.ResponseData; import b1nd.dodamcore.schedule.application.ScheduleService; import b1nd.dodamcore.schedule.application.dto.req.ScheduleReq; import b1nd.dodamcore.schedule.application.dto.res.ScheduleRes; diff --git a/dodam-api/src/main/java/b1nd/dodamapi/upload/UploadController.java b/dodam-api/src/main/java/b1nd/dodamapi/upload/UploadController.java index e575f581..02f57d91 100644 --- a/dodam-api/src/main/java/b1nd/dodamapi/upload/UploadController.java +++ b/dodam-api/src/main/java/b1nd/dodamapi/upload/UploadController.java @@ -1,6 +1,6 @@ package b1nd.dodamapi.upload; -import b1nd.dodamapi.common.response.ResponseData; +import b1nd.dodamcore.common.response.ResponseData; import b1nd.dodamcore.upload.application.UploadService; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.PostMapping; diff --git a/dodam-api/src/main/java/b1nd/dodamapi/wakeupsong/WakeupSongController.java b/dodam-api/src/main/java/b1nd/dodamapi/wakeupsong/WakeupSongController.java deleted file mode 100644 index c882dd18..00000000 --- a/dodam-api/src/main/java/b1nd/dodamapi/wakeupsong/WakeupSongController.java +++ /dev/null @@ -1,94 +0,0 @@ -package b1nd.dodamapi.wakeupsong; - -import b1nd.dodamapi.common.response.Response; -import b1nd.dodamapi.common.response.ResponseData; -import b1nd.dodamcore.wakeupsong.application.WakeupSongService; -import b1nd.dodamcore.wakeupsong.application.dto.req.ApplyWakeupSongBySearchReq; -import b1nd.dodamcore.wakeupsong.application.dto.req.ApplyWakeupSongReq; -import b1nd.dodamcore.wakeupsong.application.dto.res.ChartRes; -import b1nd.dodamcore.wakeupsong.application.dto.res.WakeupSongRes; -import b1nd.dodamcore.wakeupsong.application.dto.res.YoutubeRes; -import jakarta.validation.Valid; -import lombok.RequiredArgsConstructor; -import org.springframework.web.bind.annotation.*; - -import java.util.List; -import java.util.concurrent.Callable; - -@RestController -@RequestMapping("/wakeup-song") -@RequiredArgsConstructor -public class WakeupSongController { - - private final WakeupSongService wakeupSongService; - - @GetMapping("/allowed") - public ResponseData> getAllowedWakeupSongByPlayDate( - @RequestParam int year, - @RequestParam int month, - @RequestParam int day - ) { - List wakeupSongList = wakeupSongService.getAllowedWakeupSongByPlayDate(year, month, day); - return ResponseData.ok("승인된 기상송 조회 성공", wakeupSongList); - } - - @GetMapping("/pending") - public ResponseData> getPendingWakeupSong() { - List wakeupSongList = wakeupSongService.getPendingWakeupSong(); - return ResponseData.ok("승인 대기 중인 기상송 조회 성공", wakeupSongList); - } - - @GetMapping("/my") - public ResponseData> getMyWakeupSong() { - List wakeupSongList = wakeupSongService.getMyWakeupSong(); - return ResponseData.ok("자신이 신청한 기상송 조회 성공", wakeupSongList); - } - - @PostMapping - public Callable createWakeupSong(@RequestBody @Valid ApplyWakeupSongReq req) { - wakeupSongService.createWakeupSong(req.videoUrl()); - return () -> Response.created("기상송 신청 성공"); - } - - @PostMapping("/keyword") - public Callable createWakeupSongByYoutubeSearch(@RequestBody @Valid ApplyWakeupSongBySearchReq req) { - wakeupSongService.createWakeupSongByYoutubeSearch(req); - return () -> Response.created("유튜브 검색을 통한 기상송 신청 성공"); - } - - @GetMapping("/search") - public ResponseData> getYoutubeVideo(@RequestParam String keyword) { - List videoList = wakeupSongService.getYoutubeList(keyword); - return ResponseData.ok("유튜브 검색을 통한 기상송 조회 성공", videoList); - } - - @PatchMapping("/allow/{id}") - public Response allowWakeupSong(@PathVariable int id) { - wakeupSongService.allowWakeupSong(id); - return Response.ok("기상송 승인 성공"); - } - - @PatchMapping("/deny/{id}") - public Response denyWakeupSong(@PathVariable int id) { - wakeupSongService.denyWakeupSong(id); - return Response.ok("기상송 거절 성공"); - } - - @DeleteMapping("/{id}") - public Response deleteWakeupSong(@PathVariable int id) { - wakeupSongService.deleteWakeupSong(id); - return Response.ok("기상송 삭제 성공"); - } - - @DeleteMapping("/my/{id}") - public Response deleteMyWakeupSong(@PathVariable int id) { - wakeupSongService.deleteMyWakeupSong(id); - return Response.ok("기상송 신청 취소 성공"); - } - - @GetMapping("/chart") - public ResponseData> getChart() { - List chartList = wakeupSongService.getChartList(); - return ResponseData.ok("차트 조회 성공", chartList); - } -} diff --git a/dodam-api/src/main/java/b1nd/dodamapi/wakeupsong/handler/WakeupSongController.java b/dodam-api/src/main/java/b1nd/dodamapi/wakeupsong/handler/WakeupSongController.java new file mode 100644 index 00000000..fca229d5 --- /dev/null +++ b/dodam-api/src/main/java/b1nd/dodamapi/wakeupsong/handler/WakeupSongController.java @@ -0,0 +1,84 @@ +package b1nd.dodamapi.wakeupsong.handler; + +import b1nd.dodamcore.common.response.Response; +import b1nd.dodamcore.common.response.ResponseData; +import b1nd.dodamapi.wakeupsong.usecase.WakeupSongUseCase; +import b1nd.dodamcore.wakeupsong.application.dto.req.ApplyWakeupSongBySearchReq; +import b1nd.dodamcore.wakeupsong.application.dto.req.ApplyWakeupSongReq; +import b1nd.dodamcore.wakeupsong.application.dto.res.ChartRes; +import b1nd.dodamcore.wakeupsong.application.dto.res.WakeupSongRes; +import b1nd.dodamcore.wakeupsong.application.dto.res.YoutubeRes; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.concurrent.CompletableFuture; + +@RestController +@RequestMapping("/wakeup-song") +@RequiredArgsConstructor +@Slf4j +public class WakeupSongController { + private final WakeupSongUseCase wakeupSongUseCase; + + @GetMapping("/allowed") + public ResponseData> getAllowedWakeupSongByPlayDate( + @RequestParam int year, + @RequestParam int month, + @RequestParam int day + ) { + return wakeupSongUseCase.getAllowedWakeupSong(year, month, day); + } + + @GetMapping("/pending") + public ResponseData> getPendingWakeupSong() { + return wakeupSongUseCase.getPendingWakeupSong(); + } + + @GetMapping("/my") + public ResponseData> getMyWakeupSong() { + return wakeupSongUseCase.getMyWakeupSong(); + } + + @PostMapping + public CompletableFuture createWakeupSong(@RequestBody @Valid ApplyWakeupSongReq req) { + return wakeupSongUseCase.createWakeupSong(req.videoUrl()); + } + + @PostMapping("/keyword") + public CompletableFuture createWakeupSongByYoutubeSearch(@RequestBody @Valid ApplyWakeupSongBySearchReq req) { + return wakeupSongUseCase.createWakeupSongByYoutubeSearch(req); + } + + @GetMapping("/search") + public ResponseData> getYoutubeVideo(@RequestParam String keyword) { + return wakeupSongUseCase.getYoutubeList(keyword); + } + + @PatchMapping("/allow/{id}") + public Response allowWakeupSong(@PathVariable int id) { + return wakeupSongUseCase.allow(id); + } + + @PatchMapping("/deny/{id}") + public Response denyWakeupSong(@PathVariable int id) { + return wakeupSongUseCase.deny(id); + } + + @DeleteMapping("/{id}") + public Response deleteWakeupSong(@PathVariable int id) { + return wakeupSongUseCase.delete(id); + } + + @DeleteMapping("/my/{id}") + public Response deleteMyWakeupSong(@PathVariable int id) { + return wakeupSongUseCase.deleteMyWakeupSong(id); + } + + @GetMapping("/chart") + public ResponseData>> getChart() { + return wakeupSongUseCase.getChartList(); + } +} diff --git a/dodam-api/src/main/java/b1nd/dodamapi/wakeupsong/usecase/WakeupSongUseCase.java b/dodam-api/src/main/java/b1nd/dodamapi/wakeupsong/usecase/WakeupSongUseCase.java new file mode 100644 index 00000000..ea082f75 --- /dev/null +++ b/dodam-api/src/main/java/b1nd/dodamapi/wakeupsong/usecase/WakeupSongUseCase.java @@ -0,0 +1,168 @@ +package b1nd.dodamapi.wakeupsong.usecase; + +import b1nd.dodamapi.common.util.YoutubeApiUtil; +import b1nd.dodamcore.common.exception.ExceptionCode; +import b1nd.dodamcore.common.exception.GlobalExceptionCode; +import b1nd.dodamcore.common.response.ErrorResponseEntity; +import b1nd.dodamcore.common.response.Response; +import b1nd.dodamcore.common.response.ResponseData; +import b1nd.dodamcore.common.util.HtmlConverter; +import b1nd.dodamcore.member.application.MemberSessionHolder; +import b1nd.dodamcore.member.domain.entity.Member; +import b1nd.dodamcore.wakeupsong.application.MusicChartClient; +import b1nd.dodamcore.wakeupsong.application.VideoClient; +import b1nd.dodamcore.wakeupsong.application.WakeupSongService; +import b1nd.dodamcore.wakeupsong.application.dto.req.ApplyWakeupSongBySearchReq; +import b1nd.dodamcore.wakeupsong.application.dto.res.ChartRes; +import b1nd.dodamcore.wakeupsong.application.dto.res.WakeupSongRes; +import b1nd.dodamcore.wakeupsong.application.dto.res.YoutubeApiRes; +import b1nd.dodamcore.wakeupsong.application.dto.res.YoutubeRes; +import b1nd.dodamcore.wakeupsong.domain.entity.WakeupSong; +import b1nd.dodamcore.wakeupsong.domain.exception.UnsupportedVideoTypeException; +import b1nd.dodamcore.wakeupsong.domain.exception.WakeupSongAlreadyCreatedException; +import b1nd.dodamcore.wakeupsong.domain.exception.WakeupSongExceptionCode; +import b1nd.dodamcore.wakeupsong.domain.exception.WakeupSongUrlMalformedException; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; + +@Slf4j +@Component +@RequiredArgsConstructor +public class WakeupSongUseCase { + private final WakeupSongService wakeupSongService; + private final VideoClient videoClient; + private final MusicChartClient chartClient; + private final MemberSessionHolder memberSessionHolder; + + @Transactional(readOnly = true) + public ResponseData> getAllowedWakeupSong(int year, int month, int day){ + List wakeupSongList = wakeupSongService.getByPlayDate(year, month, day); + return ResponseData.ok("승인된 기상송 조회 성공", WakeupSongRes.of(wakeupSongList)); + } + + @Transactional(readOnly = true) + public ResponseData> getPendingWakeupSong(){ + List wakeupSongList = wakeupSongService.getPendingWakeupSong(); + return ResponseData.ok("승인 대기 중인 기상송 조회 성공", WakeupSongRes.of(wakeupSongList)); + } + + @Transactional(readOnly = true) + public ResponseData> getMyWakeupSong(){ + Member member = memberSessionHolder.current(); + List wakeupSongList = wakeupSongService.getMyWakeupSong(member); + return ResponseData.ok("자신이 신청한 기상송 조회 성공", WakeupSongRes.of(wakeupSongList)); + } + + @Transactional(rollbackFor = Exception.class) + public CompletableFuture createWakeupSong(String videoUrl) { + Member member = verifyAlreadyAppliedFromSession(); + return CompletableFuture.supplyAsync(() -> { + String videoId = YoutubeApiUtil.getVideoId(videoUrl); + YoutubeApiRes.Snippet snippet = videoClient.getVideo(videoId).getItems().get(0).getSnippet(); + checkValidVideoType(snippet.getTitle()); + buildAndSaveWakeupSong(snippet, videoId,videoUrl,member); + return Response.created("기상송 신청 성공"); + }).exceptionally(this::handleExceptionOnCreateWakeupSong); + } + + @Transactional(rollbackFor = Exception.class) + public CompletableFuture createWakeupSongByYoutubeSearch(ApplyWakeupSongBySearchReq req){ + Member member = verifyAlreadyAppliedFromSession(); + return CompletableFuture.supplyAsync(() -> { + YoutubeApiRes.SearchItem searchItem = videoClient.searchVideoByKeyword( + req.title() + " " + req.artist(), 1).getItems().get(0); + checkValidVideoType(searchItem.getSnippet().getTitle()); + buildAndSaveWakeupSong(searchItem.getSnippet(), searchItem.getId().getVideoId(), + "https://www.youtube.com/watch?v=" + searchItem.getId().getVideoId(), member); + return Response.created("유튜브 검색을 통한 기상송 신청 성공"); + }).exceptionally(this::handleExceptionOnCreateWakeupSong); + } + + private Response handleExceptionOnCreateWakeupSong(Throwable e) { + Throwable cause = (e instanceof CompletionException) ? e.getCause() : e; + ExceptionCode exceptionCode = mapExceptionToCodeOnCreateWakeupSong(cause); + return ErrorResponseEntity.of(exceptionCode.getHttpStatus().value(), exceptionCode.getExceptionName(), exceptionCode.getMessage()); + } + + private ExceptionCode mapExceptionToCodeOnCreateWakeupSong(Throwable cause) { + if (cause instanceof WakeupSongUrlMalformedException) { + return WakeupSongExceptionCode.URL_MALFORMED; + } else if (cause instanceof UnsupportedVideoTypeException) { + return WakeupSongExceptionCode.UNSUPPORTED_TYPE; + } else { + return GlobalExceptionCode.INTERNAL_SERVER; + } + } + + private void buildAndSaveWakeupSong(YoutubeApiRes.Snippet snippet, String videoId, String videoUrl, Member member){ + WakeupSong wakeupSong = WakeupSong.builder() + .videoId(videoId) + .videoTitle(HtmlConverter.of(snippet.getTitle())) + .videoUrl(videoUrl) + .channelTitle(snippet.getChannelTitle()) + .thumbnailUrl(YoutubeApiUtil.getThumbnailUrl(snippet).getUrl()) + .member(member) + .build(); + wakeupSongService.saveWakeupSong(wakeupSong); + } + + private void checkValidVideoType(String title){ + if(title.contains("MV")){ + throw new UnsupportedVideoTypeException(); + } + } + + private Member verifyAlreadyAppliedFromSession(){ + Member member = memberSessionHolder.current(); + if (wakeupSongService.existsByMemberAndCreatedAt(member)){ + throw new WakeupSongAlreadyCreatedException(); + } + return member; + } + + @Transactional(rollbackFor = Exception.class) + public Response allow(int id){ + WakeupSong wakeupSong = wakeupSongService.getById(id); + wakeupSong.allow(memberSessionHolder.current()); + return Response.ok("기상송 승인 성공"); + } + + @Transactional(rollbackFor = Exception.class) + public Response deny(int id){ + WakeupSong wakeupSong = wakeupSongService.getById(id); + wakeupSong.deny(); + return Response.ok("기상송 거절 성공"); + } + + @Transactional(rollbackFor = Exception.class) + public Response delete(int id){ + WakeupSong wakeupSong = wakeupSongService.getById(id); + wakeupSongService.delete(wakeupSong); + return Response.ok("기상송 삭제 성공"); + } + + @Transactional(rollbackFor = Exception.class) + public Response deleteMyWakeupSong(int id) { + WakeupSong wakeupSong = wakeupSongService.getById(id); + wakeupSong.isApplicant(memberSessionHolder.current()); + wakeupSongService.delete(wakeupSong); + return Response.ok("기상송 신청 취소 성공"); + } + + public ResponseData>> getChartList() { + return ResponseData.ok("차트 조회 성공", chartClient.getList()); + } + + public ResponseData> getYoutubeList(String keyword) { + List videoList = videoClient.searchVideoByKeyword(keyword, 5).getItems().stream() + .map(YoutubeApiUtil::getYoutubeRes).toList(); + return ResponseData.ok("유튜브 검색을 통한 기상송 조회 성공", videoList); + } +} \ No newline at end of file diff --git a/dodam-core/src/main/java/b1nd/dodamcore/common/exception/ErrorResponseEntity.java b/dodam-core/src/main/java/b1nd/dodamcore/common/exception/ErrorResponseEntity.java deleted file mode 100644 index a064094e..00000000 --- a/dodam-core/src/main/java/b1nd/dodamcore/common/exception/ErrorResponseEntity.java +++ /dev/null @@ -1,23 +0,0 @@ -package b1nd.dodamcore.common.exception; - -import lombok.Builder; -import lombok.Getter; -import org.springframework.http.ResponseEntity; - -@Getter -@Builder -public class ErrorResponseEntity { - private int status; - private String code; - private String message; - - public static ResponseEntity responseEntity(ExceptionCode e){ - return ResponseEntity - .status(e.getHttpStatus()) - .body(ErrorResponseEntity.builder() - .status(e.getHttpStatus().value()) - .code(e.getExceptionName()) - .message(e.getMessage()) - .build()); - } -} diff --git a/dodam-core/src/main/java/b1nd/dodamcore/common/response/ErrorResponseEntity.java b/dodam-core/src/main/java/b1nd/dodamcore/common/response/ErrorResponseEntity.java new file mode 100644 index 00000000..fa8afa46 --- /dev/null +++ b/dodam-core/src/main/java/b1nd/dodamcore/common/response/ErrorResponseEntity.java @@ -0,0 +1,30 @@ +package b1nd.dodamcore.common.response; + +import b1nd.dodamcore.common.exception.ExceptionCode; +import lombok.Builder; +import lombok.Getter; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; + +@Getter +public class ErrorResponseEntity extends Response { + private final String code; + + private ErrorResponseEntity(int status, String code, String message) { + super(status, message); + this.code = code; + } + + public static ResponseEntity responseEntity(ExceptionCode e){ + return ResponseEntity + .status(e.getHttpStatus()) + .body(new ErrorResponseEntity( + e.getHttpStatus().value(), + e.getExceptionName(), + e.getMessage())); + } + + public static ErrorResponseEntity of(int status, String code, String message) { + return new ErrorResponseEntity(status, code, message); + } +} diff --git a/dodam-api/src/main/java/b1nd/dodamapi/common/response/Response.java b/dodam-core/src/main/java/b1nd/dodamcore/common/response/Response.java similarity index 94% rename from dodam-api/src/main/java/b1nd/dodamapi/common/response/Response.java rename to dodam-core/src/main/java/b1nd/dodamcore/common/response/Response.java index f46f733a..c7af5aae 100644 --- a/dodam-api/src/main/java/b1nd/dodamapi/common/response/Response.java +++ b/dodam-core/src/main/java/b1nd/dodamcore/common/response/Response.java @@ -1,4 +1,4 @@ -package b1nd.dodamapi.common.response; +package b1nd.dodamcore.common.response; import lombok.Builder; import lombok.Getter; diff --git a/dodam-api/src/main/java/b1nd/dodamapi/common/response/ResponseData.java b/dodam-core/src/main/java/b1nd/dodamcore/common/response/ResponseData.java similarity index 94% rename from dodam-api/src/main/java/b1nd/dodamapi/common/response/ResponseData.java rename to dodam-core/src/main/java/b1nd/dodamcore/common/response/ResponseData.java index fb7180f0..3a044c58 100644 --- a/dodam-api/src/main/java/b1nd/dodamapi/common/response/ResponseData.java +++ b/dodam-core/src/main/java/b1nd/dodamcore/common/response/ResponseData.java @@ -1,4 +1,4 @@ -package b1nd.dodamapi.common.response; +package b1nd.dodamcore.common.response; import lombok.Getter; import org.springframework.http.HttpStatus; diff --git a/dodam-core/src/main/java/b1nd/dodamcore/wakeupsong/application/ChartClient.java b/dodam-core/src/main/java/b1nd/dodamcore/wakeupsong/application/MusicChartClient.java similarity index 86% rename from dodam-core/src/main/java/b1nd/dodamcore/wakeupsong/application/ChartClient.java rename to dodam-core/src/main/java/b1nd/dodamcore/wakeupsong/application/MusicChartClient.java index bfe1e3a9..2394c080 100644 --- a/dodam-core/src/main/java/b1nd/dodamcore/wakeupsong/application/ChartClient.java +++ b/dodam-core/src/main/java/b1nd/dodamcore/wakeupsong/application/MusicChartClient.java @@ -5,7 +5,7 @@ import java.util.List; import java.util.concurrent.CompletableFuture; -public interface ChartClient { +public interface MusicChartClient { CompletableFuture> getList(); } diff --git a/dodam-core/src/main/java/b1nd/dodamcore/wakeupsong/application/WakeupSongClient.java b/dodam-core/src/main/java/b1nd/dodamcore/wakeupsong/application/VideoClient.java similarity index 87% rename from dodam-core/src/main/java/b1nd/dodamcore/wakeupsong/application/WakeupSongClient.java rename to dodam-core/src/main/java/b1nd/dodamcore/wakeupsong/application/VideoClient.java index 78d8291c..48e13743 100644 --- a/dodam-core/src/main/java/b1nd/dodamcore/wakeupsong/application/WakeupSongClient.java +++ b/dodam-core/src/main/java/b1nd/dodamcore/wakeupsong/application/VideoClient.java @@ -2,7 +2,7 @@ import b1nd.dodamcore.wakeupsong.application.dto.res.YoutubeApiRes; -public interface WakeupSongClient { +public interface VideoClient { YoutubeApiRes.Video getVideo(String videoId); diff --git a/dodam-core/src/main/java/b1nd/dodamcore/wakeupsong/application/WakeupSongService.java b/dodam-core/src/main/java/b1nd/dodamcore/wakeupsong/application/WakeupSongService.java index 2368206a..8a9d7a86 100644 --- a/dodam-core/src/main/java/b1nd/dodamcore/wakeupsong/application/WakeupSongService.java +++ b/dodam-core/src/main/java/b1nd/dodamcore/wakeupsong/application/WakeupSongService.java @@ -1,19 +1,10 @@ package b1nd.dodamcore.wakeupsong.application; -import b1nd.dodamcore.common.util.HtmlConverter; import b1nd.dodamcore.common.util.ZonedDateTimeUtil; -import b1nd.dodamcore.member.application.MemberSessionHolder; import b1nd.dodamcore.member.domain.entity.Member; -import b1nd.dodamcore.wakeupsong.application.dto.req.ApplyWakeupSongBySearchReq; -import b1nd.dodamcore.wakeupsong.application.dto.res.ChartRes; -import b1nd.dodamcore.wakeupsong.application.dto.res.WakeupSongRes; -import b1nd.dodamcore.wakeupsong.application.dto.res.YoutubeApiRes; -import b1nd.dodamcore.wakeupsong.application.dto.res.YoutubeRes; import b1nd.dodamcore.wakeupsong.domain.entity.WakeupSong; import b1nd.dodamcore.wakeupsong.domain.enums.WakeupSongStatus; -import b1nd.dodamcore.wakeupsong.domain.exception.WakeupSongAlreadyCreatedException; import b1nd.dodamcore.wakeupsong.domain.exception.WakeupSongNotFoundException; -import b1nd.dodamcore.wakeupsong.domain.exception.WakeupSongUrlMalformedException; import b1nd.dodamcore.wakeupsong.repository.WakeupSongRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -21,138 +12,39 @@ import java.time.LocalDate; import java.util.List; -import java.util.Optional; @Service @RequiredArgsConstructor @Transactional(readOnly = true) public class WakeupSongService { - private final WakeupSongRepository wakeupSongRepository; - private final WakeupSongClient wakeupSongClient; - private final ChartClient chartClient; - private final MemberSessionHolder memberSessionHolder; - - public List getAllowedWakeupSongByPlayDate(int year, int month, int day) { - return WakeupSongRes.of( - wakeupSongRepository.findAllByPlayAt(LocalDate.of(year, month, day)) - ); - } - - public List getPendingWakeupSong() { - return WakeupSongRes.of( - wakeupSongRepository.findAllByStatus(WakeupSongStatus.PENDING) - ); - } - - public List getMyWakeupSong() { - return WakeupSongRes.of( - wakeupSongRepository.findAllByMember_IdAndStatus(memberSessionHolder.current().getId(), WakeupSongStatus.PENDING) - ); - } - - @Transactional(rollbackFor = Exception.class) - public void createWakeupSong(String videoUrl) { - Member member = verifyAlreadyApplied(); - String videoId; - try { - videoId = videoUrl.split("/?v=")[1].split("&")[0]; - } catch (IndexOutOfBoundsException e) { - throw new WakeupSongUrlMalformedException(); - } - - YoutubeApiRes.Snippet snippet = wakeupSongClient.getVideo(videoId).getItems().get(0).getSnippet(); - - buildAndSaveWakeupSong(snippet, videoId, videoUrl, member); + public List getByPlayDate(int year, int month, int day) { + return wakeupSongRepository.findAllByPlayAt(LocalDate.of(year, month, day)); } - @Transactional(rollbackFor = Exception.class) - public void createWakeupSongByYoutubeSearch(ApplyWakeupSongBySearchReq req) { - Member member = verifyAlreadyApplied(); - - YoutubeApiRes.SearchItem searchItem = wakeupSongClient.searchVideoByKeyword(req.title() + " " + req.artist(), 1).getItems().get(0); - - buildAndSaveWakeupSong(searchItem.getSnippet(), searchItem.getId().getVideoId(), - "https://www.youtube.com/watch?v=" + searchItem.getId().getVideoId(), member); + public List getPendingWakeupSong() { + return wakeupSongRepository.findAllByStatus(WakeupSongStatus.PENDING); } - private Member verifyAlreadyApplied() { - Member member = memberSessionHolder.current(); - if (wakeupSongRepository.existsByMember_IdAndCreatedAtAfter(member.getId(), ZonedDateTimeUtil.nowToLocalDateTime().minusDays(7))) { - throw new WakeupSongAlreadyCreatedException(); - } - return member; + public List getMyWakeupSong(Member member) { + return wakeupSongRepository.findAllByMember_IdAndStatus(member.getId(), WakeupSongStatus.PENDING); } - private void buildAndSaveWakeupSong(YoutubeApiRes.Snippet snippet, String videoId, String videoUrl, Member member) { - WakeupSong wakeupSong = WakeupSong.builder() - .videoId(videoId) - .videoTitle(HtmlConverter.of(snippet.getTitle())) - .videoUrl(videoUrl) - .channelTitle(snippet.getChannelTitle()) - .thumbnailUrl(getThumbnailUrl(snippet).getUrl()) - .member(member) - .build(); - + public void saveWakeupSong(WakeupSong wakeupSong){ wakeupSongRepository.save(wakeupSong); } - public List getYoutubeList(String keyword) { - return wakeupSongClient.searchVideoByKeyword(keyword, 5).getItems().stream() - .map(this::getYoutubeRes).toList(); - } - - private YoutubeRes getYoutubeRes(YoutubeApiRes.SearchItem item) { - return new YoutubeRes( - HtmlConverter.of(item.getSnippet().getTitle()), - item.getId().getVideoId(), - "https://www.youtube.com/watch?v=" + item.getId().getVideoId(), - item.getSnippet().getChannelTitle(), - getThumbnailUrl(item.getSnippet()).getUrl() - ); - } - - private YoutubeApiRes.Thumbnail getThumbnailUrl(YoutubeApiRes.Snippet snippet) { - Optional standard = Optional.ofNullable(snippet.getThumbnails().getStandard()); - return standard.orElseGet(() -> snippet.getThumbnails().getHigh()); - } - - @Transactional(rollbackFor = Exception.class) - public void allowWakeupSong(int id) { - WakeupSong wakeupSong = wakeupSongRepository.findById(id) - .orElseThrow(WakeupSongNotFoundException::new); - - wakeupSong.allow(memberSessionHolder.current()); - } - - @Transactional(rollbackFor = Exception.class) - public void denyWakeupSong(int id) { - WakeupSong wakeupSong = wakeupSongRepository.findById(id) - .orElseThrow(WakeupSongNotFoundException::new); - - wakeupSong.deny(); + public Boolean existsByMemberAndCreatedAt(Member member){ + return wakeupSongRepository.existsByMember_IdAndCreatedAtAfter(member.getId(), ZonedDateTimeUtil.nowToLocalDateTime().minusDays(7)); } - @Transactional(rollbackFor = Exception.class) - public void deleteWakeupSong(int id) { - WakeupSong wakeupSong = wakeupSongRepository.findById(id) + public WakeupSong getById(int id){ + return wakeupSongRepository.findById(id) .orElseThrow(WakeupSongNotFoundException::new); - - wakeupSongRepository.delete(wakeupSong); } - @Transactional(rollbackFor = Exception.class) - public void deleteMyWakeupSong(int id) { - WakeupSong wakeupSong = wakeupSongRepository.findById(id) - .orElseThrow(WakeupSongNotFoundException::new); - - wakeupSong.isApplicant(memberSessionHolder.current()); - + public void delete(WakeupSong wakeupSong){ wakeupSongRepository.delete(wakeupSong); } - - public List getChartList() { - return chartClient.getList().join(); - } } diff --git a/dodam-core/src/main/java/b1nd/dodamcore/wakeupsong/domain/exception/UnsupportedVideoTypeException.java b/dodam-core/src/main/java/b1nd/dodamcore/wakeupsong/domain/exception/UnsupportedVideoTypeException.java new file mode 100644 index 00000000..92bd599e --- /dev/null +++ b/dodam-core/src/main/java/b1nd/dodamcore/wakeupsong/domain/exception/UnsupportedVideoTypeException.java @@ -0,0 +1,14 @@ +package b1nd.dodamcore.wakeupsong.domain.exception; + +import b1nd.dodamcore.common.exception.CustomException; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(value = HttpStatus.UNPROCESSABLE_ENTITY) +public class UnsupportedVideoTypeException extends CustomException { + + public UnsupportedVideoTypeException() { + super(WakeupSongExceptionCode.UNSUPPORTED_TYPE); + } + +} \ No newline at end of file diff --git a/dodam-core/src/main/java/b1nd/dodamcore/wakeupsong/domain/exception/WakeupSongExceptionCode.java b/dodam-core/src/main/java/b1nd/dodamcore/wakeupsong/domain/exception/WakeupSongExceptionCode.java index 07e2d341..77d9c63f 100644 --- a/dodam-core/src/main/java/b1nd/dodamcore/wakeupsong/domain/exception/WakeupSongExceptionCode.java +++ b/dodam-core/src/main/java/b1nd/dodamcore/wakeupsong/domain/exception/WakeupSongExceptionCode.java @@ -10,7 +10,8 @@ public enum WakeupSongExceptionCode implements ExceptionCode { ALREADY_APPLIED(HttpStatus.LOCKED, "이미 이번주에 기상송을 신청함"), NOT_FOUND(HttpStatus.NOT_FOUND, "없는 기상송"), NOT_APPLICANT(HttpStatus.FORBIDDEN, "신청자가 아님"), - URL_MALFORMED(HttpStatus.BAD_REQUEST, "잘못된 유튜브 URL 형식"); + URL_MALFORMED(HttpStatus.BAD_REQUEST, "잘못된 유튜브 URL 형식"), + UNSUPPORTED_TYPE(HttpStatus.UNPROCESSABLE_ENTITY,"지원하지 않는 유형의 비디오"); private final HttpStatus status; private final String message; diff --git a/dodam-core/src/main/resources/application.yml b/dodam-core/src/main/resources/application.yml index 8b137891..e69de29b 100644 --- a/dodam-core/src/main/resources/application.yml +++ b/dodam-core/src/main/resources/application.yml @@ -1 +0,0 @@ - diff --git a/dodam-infra/src/main/java/b1nd/dodaminfra/api/melon/MelonClient.java b/dodam-infra/src/main/java/b1nd/dodaminfra/api/melon/MelonClient.java index 048717aa..950d3394 100644 --- a/dodam-infra/src/main/java/b1nd/dodaminfra/api/melon/MelonClient.java +++ b/dodam-infra/src/main/java/b1nd/dodaminfra/api/melon/MelonClient.java @@ -1,6 +1,6 @@ package b1nd.dodaminfra.api.melon; -import b1nd.dodamcore.wakeupsong.application.ChartClient; +import b1nd.dodamcore.wakeupsong.application.MusicChartClient; import b1nd.dodamcore.wakeupsong.application.dto.res.ChartRes; import b1nd.dodaminfra.webclient.WebClientSupport; import lombok.RequiredArgsConstructor; @@ -12,7 +12,7 @@ @Component @RequiredArgsConstructor -public class MelonClient implements ChartClient { +public class MelonClient implements MusicChartClient { private final MelonProperties melonProperties; private final WebClientSupport webClientSupport; diff --git a/dodam-infra/src/main/java/b1nd/dodaminfra/api/youtube/YoutubeClient.java b/dodam-infra/src/main/java/b1nd/dodaminfra/api/youtube/YoutubeClient.java index 767c6f85..699f6f2c 100644 --- a/dodam-infra/src/main/java/b1nd/dodaminfra/api/youtube/YoutubeClient.java +++ b/dodam-infra/src/main/java/b1nd/dodaminfra/api/youtube/YoutubeClient.java @@ -1,6 +1,6 @@ package b1nd.dodaminfra.api.youtube; -import b1nd.dodamcore.wakeupsong.application.WakeupSongClient; +import b1nd.dodamcore.wakeupsong.application.VideoClient; import b1nd.dodamcore.wakeupsong.application.dto.res.YoutubeApiRes; import b1nd.dodaminfra.webclient.WebClientSupport; import lombok.RequiredArgsConstructor; @@ -9,7 +9,7 @@ @Component @RequiredArgsConstructor -public class YoutubeClient implements WakeupSongClient { +public class YoutubeClient implements VideoClient { private final YoutubeProperties youtubeProperties; private final WebClientSupport webClientSupport; diff --git a/dodam-infra/src/main/java/b1nd/dodaminfra/security/MemberAuthenticationHolder.java b/dodam-infra/src/main/java/b1nd/dodaminfra/security/MemberAuthenticationHolder.java index 435fd4c5..6fb4e71e 100644 --- a/dodam-infra/src/main/java/b1nd/dodaminfra/security/MemberAuthenticationHolder.java +++ b/dodam-infra/src/main/java/b1nd/dodaminfra/security/MemberAuthenticationHolder.java @@ -3,9 +3,11 @@ import b1nd.dodamcore.member.application.MemberSessionHolder; import b1nd.dodamcore.member.domain.entity.Member; import b1nd.dodaminfra.security.common.MemberDetails; +import lombok.extern.slf4j.Slf4j; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Component; +@Slf4j @Component final class MemberAuthenticationHolder implements MemberSessionHolder { diff --git a/dodam-infra/src/main/java/b1nd/dodaminfra/security/SecurityConfig.java b/dodam-infra/src/main/java/b1nd/dodaminfra/security/SecurityConfig.java index 6251b6d5..c059fdef 100644 --- a/dodam-infra/src/main/java/b1nd/dodaminfra/security/SecurityConfig.java +++ b/dodam-infra/src/main/java/b1nd/dodaminfra/security/SecurityConfig.java @@ -11,6 +11,7 @@ import org.springframework.http.HttpStatus; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.access.intercept.AuthorizationFilter; import org.springframework.security.web.authentication.HttpStatusEntryPoint; diff --git a/dodam-infra/src/main/java/b1nd/dodaminfra/security/common/ErrorResponseSender.java b/dodam-infra/src/main/java/b1nd/dodaminfra/security/common/ErrorResponseSender.java index 8afa6f6b..42bbb1fb 100644 --- a/dodam-infra/src/main/java/b1nd/dodaminfra/security/common/ErrorResponseSender.java +++ b/dodam-infra/src/main/java/b1nd/dodaminfra/security/common/ErrorResponseSender.java @@ -1,6 +1,6 @@ package b1nd.dodaminfra.security.common; -import b1nd.dodamcore.common.exception.ErrorResponseEntity; +import b1nd.dodamcore.common.response.ErrorResponseEntity; import b1nd.dodamcore.common.exception.ExceptionCode; import com.fasterxml.jackson.databind.ObjectMapper; import jakarta.servlet.http.HttpServletResponse; @@ -29,11 +29,10 @@ public void send(HttpServletResponse response, ExceptionCode code) { } private ErrorResponseEntity getErrorResponseEntity(ExceptionCode code) { - return ErrorResponseEntity.builder() - .status(code.getHttpStatus().value()) - .code(code.getExceptionName()) - .message(code.getMessage()) - .build(); + return ErrorResponseEntity.of( + code.getHttpStatus().value(), + code.getExceptionName(), + code.getMessage()); } } diff --git a/dodam-infra/src/main/java/b1nd/dodaminfra/token/TokenFilter.java b/dodam-infra/src/main/java/b1nd/dodaminfra/token/TokenFilter.java index 76821486..ac5e9996 100644 --- a/dodam-infra/src/main/java/b1nd/dodaminfra/token/TokenFilter.java +++ b/dodam-infra/src/main/java/b1nd/dodaminfra/token/TokenFilter.java @@ -28,11 +28,9 @@ public class TokenFilter extends OncePerRequestFilter { @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { String token = TokenExtractor.extract(request, TOKEN_TYPE); - if(!token.isEmpty()) { setAuthentication(token); } - filterChain.doFilter(request, response); }