From 80065400967aeb222ac3c162c227e125d5fbd390 Mon Sep 17 00:00:00 2001 From: misim3 Date: Mon, 1 Apr 2024 13:50:54 +0900 Subject: [PATCH 01/21] =?UTF-8?q?refactor:=20=EA=B5=AC=EB=8F=85=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../model/Request/SubscribingRequest.java | 26 ++++++++++ .../com/misim/exception/MitubeErrorCode.java | 5 ++ .../repository/SubscriptionRepository.java | 2 + .../misim/service/SubscriptionService.java | 49 +++++++++++++++++++ 4 files changed, 82 insertions(+) create mode 100644 mitube-app/src/main/java/com/misim/controller/model/Request/SubscribingRequest.java create mode 100644 mitube-app/src/main/java/com/misim/service/SubscriptionService.java diff --git a/mitube-app/src/main/java/com/misim/controller/model/Request/SubscribingRequest.java b/mitube-app/src/main/java/com/misim/controller/model/Request/SubscribingRequest.java new file mode 100644 index 0000000..2caac0a --- /dev/null +++ b/mitube-app/src/main/java/com/misim/controller/model/Request/SubscribingRequest.java @@ -0,0 +1,26 @@ +package com.misim.controller.model.Request; + +import com.misim.controller.model.Checker; +import com.misim.exception.MitubeErrorCode; +import com.misim.exception.MitubeException; +import lombok.Data; + +@Data +public class SubscribingRequest implements Checker { + + private Long ownerId; + + private Long subscriberId; + + @Override + public void check() { + + if (ownerId == null) { + throw new MitubeException(MitubeErrorCode.INVALID_SUBSCRIPTION_OWNER); + } + + if (subscriberId == null) { + throw new MitubeException(MitubeErrorCode.INVALID_SUBSCRIPTION_SUBSCRIBER); + } + } +} diff --git a/mitube-app/src/main/java/com/misim/exception/MitubeErrorCode.java b/mitube-app/src/main/java/com/misim/exception/MitubeErrorCode.java index 2d1685a..e520076 100644 --- a/mitube-app/src/main/java/com/misim/exception/MitubeErrorCode.java +++ b/mitube-app/src/main/java/com/misim/exception/MitubeErrorCode.java @@ -58,6 +58,11 @@ public enum MitubeErrorCode implements ErrorCode{ INVALID_COMMENT_USER(HttpStatus.BAD_REQUEST, "댓글 유저 형식에 맞지 않습니다.", 10802), NOT_FOUND_COMMENT(HttpStatus.BAD_REQUEST, "댓글을 찾을 수 없습니다.", 10803), + + INVALID_SUBSCRIPTION_OWNER(HttpStatus.BAD_REQUEST, "채널 소유자 형식에 맞지 않습니다.", 10900), + INVALID_SUBSCRIPTION_SUBSCRIBER(HttpStatus.BAD_REQUEST, "구독자 형식에 맞지 않습니다.", 10901), + + UNKNOWN_EXCEPTION(HttpStatus.INTERNAL_SERVER_ERROR, "알 수 없는 에러가 발생했습니다.", 99999),; private final HttpStatus httpStatus; diff --git a/mitube-app/src/main/java/com/misim/repository/SubscriptionRepository.java b/mitube-app/src/main/java/com/misim/repository/SubscriptionRepository.java index 295400b..89a5f6b 100644 --- a/mitube-app/src/main/java/com/misim/repository/SubscriptionRepository.java +++ b/mitube-app/src/main/java/com/misim/repository/SubscriptionRepository.java @@ -8,4 +8,6 @@ public interface SubscriptionRepository extends JpaRepository { List findSubscriptionsBySubscriberId(Long subscriberId); + + void deleteByOwnerIdAndSubscriberId(Long ownerId, Long subscriberId); } diff --git a/mitube-app/src/main/java/com/misim/service/SubscriptionService.java b/mitube-app/src/main/java/com/misim/service/SubscriptionService.java new file mode 100644 index 0000000..1c902f1 --- /dev/null +++ b/mitube-app/src/main/java/com/misim/service/SubscriptionService.java @@ -0,0 +1,49 @@ +package com.misim.service; + +import com.misim.entity.Subscription; +import com.misim.exception.MitubeErrorCode; +import com.misim.exception.MitubeException; +import com.misim.repository.SubscriptionRepository; +import com.misim.repository.UserRepository; +import com.misim.repository.VideoRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class SubscriptionService { + + private final SubscriptionRepository subscriptionRepository; + private final UserRepository userRepository; + + public void subscribing(Long ownerId, Long subscriberId) { + + if (!userRepository.existsById(ownerId)) { + throw new MitubeException(MitubeErrorCode.NOT_FOUND_USER); + } + + if (!userRepository.existsById(subscriberId)) { + throw new MitubeException(MitubeErrorCode.NOT_FOUND_USER); + } + + Subscription subscription = Subscription.builder() + .ownerId(ownerId) + .subscriberId(subscriberId) + .build(); + + subscriptionRepository.save(subscription); + } + + public void unsubscribing(Long ownerId, Long subscriberId) { + + if (!userRepository.existsById(ownerId)) { + throw new MitubeException(MitubeErrorCode.NOT_FOUND_USER); + } + + if (!userRepository.existsById(subscriberId)) { + throw new MitubeException(MitubeErrorCode.NOT_FOUND_USER); + } + + subscriptionRepository.deleteByOwnerIdAndSubscriberId(ownerId, subscriberId); + } +} From e22906d8678ee66d9d2a100ab21be4e4570fdcd7 Mon Sep 17 00:00:00 2001 From: misim3 Date: Mon, 1 Apr 2024 14:36:17 +0900 Subject: [PATCH 02/21] =?UTF-8?q?refactor:=20=EA=B5=AC=EB=8F=85=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../misim/controller/ChannelController.java | 33 +++++++++++++++++++ .../repository/SubscriptionRepository.java | 2 ++ 2 files changed, 35 insertions(+) create mode 100644 mitube-app/src/main/java/com/misim/controller/ChannelController.java diff --git a/mitube-app/src/main/java/com/misim/controller/ChannelController.java b/mitube-app/src/main/java/com/misim/controller/ChannelController.java new file mode 100644 index 0000000..74cdb79 --- /dev/null +++ b/mitube-app/src/main/java/com/misim/controller/ChannelController.java @@ -0,0 +1,33 @@ +package com.misim.controller; + +import com.misim.controller.model.Request.SubscribingRequest; +import com.misim.service.SubscriptionService; +import lombok.RequiredArgsConstructor; +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; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/channels") +public class ChannelController { + + private final SubscriptionService subscriptionService; + + @PostMapping("/subscribe") + public void subscribing(@RequestBody SubscribingRequest request) { + + request.check(); + + subscriptionService.subscribing(request.getOwnerId(), request.getSubscriberId()); + } + + @PostMapping("/unsubscribe") + public void unsubscribing(@RequestBody SubscribingRequest request) { + + request.check(); + + subscriptionService.unsubscribing(request.getOwnerId(), request.getSubscriberId()); + } +} diff --git a/mitube-app/src/main/java/com/misim/repository/SubscriptionRepository.java b/mitube-app/src/main/java/com/misim/repository/SubscriptionRepository.java index 89a5f6b..1fb069c 100644 --- a/mitube-app/src/main/java/com/misim/repository/SubscriptionRepository.java +++ b/mitube-app/src/main/java/com/misim/repository/SubscriptionRepository.java @@ -2,9 +2,11 @@ import com.misim.entity.Subscription; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; import java.util.List; +@Repository public interface SubscriptionRepository extends JpaRepository { List findSubscriptionsBySubscriberId(Long subscriberId); From 70bb8f338839ecd3405f1d5ba6843ec258a3a566 Mon Sep 17 00:00:00 2001 From: misim3 Date: Mon, 1 Apr 2024 14:37:11 +0900 Subject: [PATCH 03/21] =?UTF-8?q?feat:=20=EC=A2=8B=EC=95=84=EC=9A=94=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84=20=EB=B0=8F=20=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20=EA=B8=B0=EB=8A=A5=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/misim/controller/VideoController.java | 20 +++++ .../model/Request/ReactionRequest.java | 32 ++++++++ .../main/java/com/misim/entity/Reaction.java | 37 ++++++++++ .../com/misim/exception/MitubeErrorCode.java | 5 +- .../misim/repository/ReactionRepository.java | 13 ++++ .../com/misim/service/ReactionService.java | 73 +++++++++++++++++++ 6 files changed, 179 insertions(+), 1 deletion(-) create mode 100644 mitube-app/src/main/java/com/misim/controller/model/Request/ReactionRequest.java create mode 100644 mitube-app/src/main/java/com/misim/entity/Reaction.java create mode 100644 mitube-app/src/main/java/com/misim/repository/ReactionRepository.java create mode 100644 mitube-app/src/main/java/com/misim/service/ReactionService.java diff --git a/mitube-app/src/main/java/com/misim/controller/VideoController.java b/mitube-app/src/main/java/com/misim/controller/VideoController.java index abcb07d..85c1faf 100644 --- a/mitube-app/src/main/java/com/misim/controller/VideoController.java +++ b/mitube-app/src/main/java/com/misim/controller/VideoController.java @@ -1,5 +1,6 @@ package com.misim.controller; +import com.misim.controller.model.Request.ReactionRequest; import com.misim.controller.model.Response.CommentListResponse; import com.misim.controller.model.Response.CommentResponse; import com.misim.controller.model.Response.StartWatchingVideoResponse; @@ -9,6 +10,7 @@ import com.misim.exception.MitubeErrorCode; import com.misim.exception.MitubeException; import com.misim.service.CommentService; +import com.misim.service.ReactionService; import com.misim.service.VideoService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -30,6 +32,7 @@ public class VideoController { private final VideoService videoService; private final CommentService commentService; + private final ReactionService reactionService; @Operation(summary = "동영상 업로드", description = "새로운 동영상을 업로드합니다.") @ApiResponses(value = { @@ -105,4 +108,21 @@ public void completeWatchingVideo(@PathVariable Long videoId, @RequestParam Long videoService.updateWatchingVideoInfo(videoId, userId, watchingTime); } + + @PostMapping("/check/reaction") + public void checkVideo(@RequestBody ReactionRequest request) { + + request.check(); + + reactionService.checking(request.getType(), request.getUserId(), request.getVideoId()); + } + + + @PostMapping("/uncheck/reaction") + public void uncheckVideo(@RequestBody ReactionRequest request) { + + request.check(); + + reactionService.unchecking(request.getType(), request.getUserId(), request.getVideoId()); + } } diff --git a/mitube-app/src/main/java/com/misim/controller/model/Request/ReactionRequest.java b/mitube-app/src/main/java/com/misim/controller/model/Request/ReactionRequest.java new file mode 100644 index 0000000..df4093c --- /dev/null +++ b/mitube-app/src/main/java/com/misim/controller/model/Request/ReactionRequest.java @@ -0,0 +1,32 @@ +package com.misim.controller.model.Request; + +import com.misim.controller.model.Checker; +import com.misim.exception.MitubeErrorCode; +import com.misim.exception.MitubeException; +import lombok.Data; + +@Data +public class ReactionRequest implements Checker { + + private String type; + + private Long userId; + + private Long videoId; + + @Override + public void check() { + + if (type == null || type.isBlank()) { + throw new MitubeException(MitubeErrorCode.INVALID_REACTION_TYPE); + } + + if (userId == null) { + throw new MitubeException(MitubeErrorCode.INVALID_REACTION_USER); + } + + if (videoId == null) { + throw new MitubeException(MitubeErrorCode.INVALID_REACTION_VIDEO); + } + } +} diff --git a/mitube-app/src/main/java/com/misim/entity/Reaction.java b/mitube-app/src/main/java/com/misim/entity/Reaction.java new file mode 100644 index 0000000..456a6ac --- /dev/null +++ b/mitube-app/src/main/java/com/misim/entity/Reaction.java @@ -0,0 +1,37 @@ +package com.misim.entity; + + +import jakarta.persistence.*; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Entity +@Getter +@Table(name = "reactions") +@NoArgsConstructor +public class Reaction { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Setter + private String type; + + @Setter + private Boolean isActive; + + private Long userId; + + private Long videoId; + + @Builder + public Reaction(String type, Boolean isActive, Long userId, Long videoId) { + this.type = type; + this.isActive = isActive; + this.userId = userId; + this.videoId = videoId; + } +} diff --git a/mitube-app/src/main/java/com/misim/exception/MitubeErrorCode.java b/mitube-app/src/main/java/com/misim/exception/MitubeErrorCode.java index e520076..99fc1c6 100644 --- a/mitube-app/src/main/java/com/misim/exception/MitubeErrorCode.java +++ b/mitube-app/src/main/java/com/misim/exception/MitubeErrorCode.java @@ -58,10 +58,13 @@ public enum MitubeErrorCode implements ErrorCode{ INVALID_COMMENT_USER(HttpStatus.BAD_REQUEST, "댓글 유저 형식에 맞지 않습니다.", 10802), NOT_FOUND_COMMENT(HttpStatus.BAD_REQUEST, "댓글을 찾을 수 없습니다.", 10803), - INVALID_SUBSCRIPTION_OWNER(HttpStatus.BAD_REQUEST, "채널 소유자 형식에 맞지 않습니다.", 10900), INVALID_SUBSCRIPTION_SUBSCRIBER(HttpStatus.BAD_REQUEST, "구독자 형식에 맞지 않습니다.", 10901), + INVALID_REACTION_UNCHECK(HttpStatus.BAD_REQUEST, "체크되지 않은 타입을 해제하려 합니다.", 11000), + INVALID_REACTION_TYPE(HttpStatus.BAD_REQUEST, "리액션 타입 형식에 맞지 않습니다.", 11001), + INVALID_REACTION_VIDEO(HttpStatus.BAD_REQUEST, "리액션 동영상 형식에 맞지 않습니다.", 11002), + INVALID_REACTION_USER(HttpStatus.BAD_REQUEST, "리액션 유저 형식에 맞지 않습니다.", 11003), UNKNOWN_EXCEPTION(HttpStatus.INTERNAL_SERVER_ERROR, "알 수 없는 에러가 발생했습니다.", 99999),; diff --git a/mitube-app/src/main/java/com/misim/repository/ReactionRepository.java b/mitube-app/src/main/java/com/misim/repository/ReactionRepository.java new file mode 100644 index 0000000..fe075b7 --- /dev/null +++ b/mitube-app/src/main/java/com/misim/repository/ReactionRepository.java @@ -0,0 +1,13 @@ +package com.misim.repository; + +import com.misim.entity.Reaction; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface ReactionRepository extends JpaRepository { + + Boolean existsReactionByUserIdAndVideoId(Long userId, Long videoId); + + Reaction findByUserIdAndVideoId(Long userId, Long videoId); +} diff --git a/mitube-app/src/main/java/com/misim/service/ReactionService.java b/mitube-app/src/main/java/com/misim/service/ReactionService.java new file mode 100644 index 0000000..96c8330 --- /dev/null +++ b/mitube-app/src/main/java/com/misim/service/ReactionService.java @@ -0,0 +1,73 @@ +package com.misim.service; + +import com.misim.entity.Reaction; +import com.misim.exception.MitubeErrorCode; +import com.misim.exception.MitubeException; +import com.misim.repository.ReactionRepository; +import com.misim.repository.UserRepository; +import com.misim.repository.VideoRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class ReactionService { + + private final ReactionRepository reactionRepository; + private final UserRepository userRepository; + private final VideoRepository videoRepository; + + public void checking(String type, Long userId, Long videoId) { + + if (!userRepository.existsById(userId)) { + throw new MitubeException(MitubeErrorCode.NOT_FOUND_USER); + } + + if (!videoRepository.existsById(videoId)) { + throw new MitubeException(MitubeErrorCode.NOT_FOUND_VIDEO); + } + + Reaction reaction; + + if (reactionRepository.existsReactionByUserIdAndVideoId(userId, videoId)) { + + reaction = reactionRepository.findByUserIdAndVideoId(userId, videoId); + + reaction.setType(type); + reaction.setIsActive(true); + + } else { + + reaction = Reaction.builder() + .type(type) + .isActive(true) + .userId(userId) + .videoId(videoId) + .build(); + } + + reactionRepository.save(reaction); + } + + public void unchecking(String type, Long userId, Long videoId) { + + if (!userRepository.existsById(userId)) { + throw new MitubeException(MitubeErrorCode.NOT_FOUND_USER); + } + + if (!videoRepository.existsById(videoId)) { + throw new MitubeException(MitubeErrorCode.NOT_FOUND_VIDEO); + } + + if (!reactionRepository.existsReactionByUserIdAndVideoId(userId, videoId)) { + throw new MitubeException(MitubeErrorCode.INVALID_REACTION_UNCHECK); + } + + Reaction reaction = reactionRepository.findByUserIdAndVideoId(userId, videoId); + + reaction.setType(type); + reaction.setIsActive(false); + + reactionRepository.save(reaction); + } +} From be9a49c168ffd9e1ae865bf035e0f361dad80c22 Mon Sep 17 00:00:00 2001 From: misim3 Date: Mon, 1 Apr 2024 14:37:48 +0900 Subject: [PATCH 04/21] =?UTF-8?q?refactor:=20=EB=8C=93=EA=B8=80=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EB=82=B4=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EC=BD=94=EB=93=9C=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/misim/repository/CommentRepository.java | 1 - mitube-app/src/main/java/com/misim/service/CommentService.java | 1 - 2 files changed, 2 deletions(-) diff --git a/mitube-app/src/main/java/com/misim/repository/CommentRepository.java b/mitube-app/src/main/java/com/misim/repository/CommentRepository.java index 2254636..e1858b5 100644 --- a/mitube-app/src/main/java/com/misim/repository/CommentRepository.java +++ b/mitube-app/src/main/java/com/misim/repository/CommentRepository.java @@ -1,7 +1,6 @@ package com.misim.repository; import com.misim.entity.Comment; -import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; import org.springframework.data.jpa.repository.JpaRepository; diff --git a/mitube-app/src/main/java/com/misim/service/CommentService.java b/mitube-app/src/main/java/com/misim/service/CommentService.java index b55ab68..d0485b7 100644 --- a/mitube-app/src/main/java/com/misim/service/CommentService.java +++ b/mitube-app/src/main/java/com/misim/service/CommentService.java @@ -13,7 +13,6 @@ import com.misim.repository.UserRepository; import com.misim.repository.VideoRepository; import lombok.RequiredArgsConstructor; -import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; From eb0c442e036b68a9cb841820aa34777b6c53d07c Mon Sep 17 00:00:00 2001 From: misim3 Date: Wed, 3 Apr 2024 14:22:51 +0900 Subject: [PATCH 05/21] =?UTF-8?q?refactor:=20=EB=8C=93=EA=B8=80=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=ED=8E=98=EC=9D=B4=EC=A7=95=20=EB=B0=A9?= =?UTF-8?q?=EC=8B=9D=20JPA=20pageable=EC=97=90=EC=84=9C=20JPQL=EB=A1=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD,=20=EC=8A=A4=ED=81=AC=EB=A1=A4=20=EB=B0=A9?= =?UTF-8?q?=ED=96=A5=EC=97=90=20=EB=94=B0=EB=A5=B8=20=EB=8C=93=EA=B8=80=20?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EC=A0=84=EB=8B=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../misim/controller/CommentController.java | 17 +++++-- .../com/misim/controller/VideoController.java | 2 +- .../model/Response/CommentListResponse.java | 4 +- .../misim/repository/CommentRepository.java | 16 +++++++ .../com/misim/service/CommentService.java | 45 ++++++++++++------- 5 files changed, 62 insertions(+), 22 deletions(-) diff --git a/mitube-app/src/main/java/com/misim/controller/CommentController.java b/mitube-app/src/main/java/com/misim/controller/CommentController.java index 5d05b85..2236329 100644 --- a/mitube-app/src/main/java/com/misim/controller/CommentController.java +++ b/mitube-app/src/main/java/com/misim/controller/CommentController.java @@ -21,20 +21,29 @@ public class CommentController { private final CommentService commentService; + // idx, sort, scroll direction + // 1th way - idx and scroll direction -> 'idx' + // 2th way - scroll direction ~ idx -> 'idx' : scroll down lowest idx or scroll up highest idx + // scroll down + // select * from comments where parentCommentId is null and videoId = 'videoId' and idx < 'idx' order by sort DESC limit 'pageSize'; + // scroll up + // select * from comments where parentCommentId is null and videoId = 'videoId' and idx > 'idx' order by sort ACS limit 'pageSize'; + // 1 / '2' 3 4 / '5' 6 7 / '8' 9 10 @GetMapping("/{videoId}") - public CommonResponse getParentComments(@PathVariable Long videoId, @RequestParam int page) { + public CommonResponse getParentComments(@PathVariable Long videoId, @RequestParam Long idx, @RequestParam String scrollDirection) { - CommentListResponse comments = commentService.getParentComments(videoId, page); + CommentListResponse comments = commentService.getParentComments(videoId, idx, scrollDirection); return CommonResponse.builder() .body(comments) .build(); } + // @GetMapping("/{videoId}/{parentCommentId}") - public CommonResponse getChildComments(@PathVariable Long videoId, @PathVariable Long parentCommentId, @RequestParam int page) { + public CommonResponse getChildComments(@PathVariable Long videoId, @PathVariable Long parentCommentId, @RequestParam Long idx, @RequestParam String scrollDirection) { - CommentListResponse comments = commentService.getChildComments(videoId, parentCommentId, page); + CommentListResponse comments = commentService.getChildComments(videoId, parentCommentId, idx, scrollDirection); return CommonResponse.builder() .body(comments) diff --git a/mitube-app/src/main/java/com/misim/controller/VideoController.java b/mitube-app/src/main/java/com/misim/controller/VideoController.java index 85c1faf..71bb7aa 100644 --- a/mitube-app/src/main/java/com/misim/controller/VideoController.java +++ b/mitube-app/src/main/java/com/misim/controller/VideoController.java @@ -85,7 +85,7 @@ public CommonResponse startWatchingVideo(@PathVariab StartWatchingVideoResponse response = videoService.startWatchingVideo(videoId, userId); - CommentListResponse commentListResponse = commentService.getParentComments(videoId, 0); + CommentListResponse commentListResponse = commentService.getParentComments(videoId, null, "down"); response.setCommentListResponse(commentListResponse); diff --git a/mitube-app/src/main/java/com/misim/controller/model/Response/CommentListResponse.java b/mitube-app/src/main/java/com/misim/controller/model/Response/CommentListResponse.java index 21eda18..25cb3bc 100644 --- a/mitube-app/src/main/java/com/misim/controller/model/Response/CommentListResponse.java +++ b/mitube-app/src/main/java/com/misim/controller/model/Response/CommentListResponse.java @@ -5,10 +5,12 @@ import lombok.Data; import org.springframework.data.domain.Slice; +import java.util.List; + @Data @Builder public class CommentListResponse { @Schema(name = "commentResponses", description = "댓글 목록 10개", example = "재밌네요!, 좋아요!, ...", requiredMode = Schema.RequiredMode.REQUIRED) - private Slice commentResponses; + private List commentResponses; } diff --git a/mitube-app/src/main/java/com/misim/repository/CommentRepository.java b/mitube-app/src/main/java/com/misim/repository/CommentRepository.java index e1858b5..3cf9ab5 100644 --- a/mitube-app/src/main/java/com/misim/repository/CommentRepository.java +++ b/mitube-app/src/main/java/com/misim/repository/CommentRepository.java @@ -1,15 +1,31 @@ package com.misim.repository; import com.misim.entity.Comment; +import io.lettuce.core.dynamic.annotation.Param; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; +import java.util.List; + @Repository public interface CommentRepository extends JpaRepository { Slice findByVideoIdAndParentCommentIdIsNull(Long videoId, Pageable pageable); Slice findCommentsByVideoIdAndParentCommentId(Long videoId, Long parentCommentId, Pageable pageable); + + @Query("SELECT c1 from Comment c1 WHERE c1.parentCommentId IS NULL AND c1.video.id = :videoId AND c1.id < :id ORDER BY c1.createdDate DESC LIMIT 10") + List findDownCommentByVideoIdAndId(@Param("videoId") Long videoId,@Param("id") Long id); + + @Query("SELECT c1 from Comment c1 WHERE c1.parentCommentId IS NULL AND c1.video.id = :videoId AND c1.id > :id ORDER BY c1.createdDate ASC LIMIT 10") + List findUpCommentByVideoIdAndId(@Param("videoId") Long videoId,@Param("id") Long id); + + @Query("SELECT c1 from Comment c1 WHERE c1.parentCommentId = :parentCommentId AND c1.video.id = :videoId AND c1.id < :id ORDER BY c1.createdDate DESC LIMIT 10") + List findDownCommentByVideoIdAndIdAndParentCommentId(@Param("parentCommentId") Long parentCommentId, @Param("videoId") Long videoId, @Param("id") Long id); + + @Query("SELECT c1 from Comment c1 WHERE c1.parentCommentId = :parentCommentId AND c1.video.id = :videoId AND c1.id > :id ORDER BY c1.createdDate ASC LIMIT 10") + List findUpCommentByVideoIdAndIdAndParentCommentId(@Param("parentCommentId") Long parentCommentId, @Param("videoId") Long videoId, @Param("id") Long id); } diff --git a/mitube-app/src/main/java/com/misim/service/CommentService.java b/mitube-app/src/main/java/com/misim/service/CommentService.java index d0485b7..a0947b0 100644 --- a/mitube-app/src/main/java/com/misim/service/CommentService.java +++ b/mitube-app/src/main/java/com/misim/service/CommentService.java @@ -18,6 +18,9 @@ import org.springframework.data.domain.Slice; import org.springframework.stereotype.Service; +import java.util.ArrayList; +import java.util.List; + @Service @RequiredArgsConstructor @@ -27,41 +30,51 @@ public class CommentService { private final VideoRepository videoRepository; private final UserRepository userRepository; - public CommentListResponse getParentComments(Long videoId, int page) { + public CommentListResponse getParentComments(Long videoId, Long idx, String scrollDirection) { if (!videoRepository.existsById(videoId)) { throw new MitubeException(MitubeErrorCode.NOT_FOUND_VIDEO); } - // 댓글 검색 - Pageable pageable = PageRequest.of(page, 10); + List comments = new ArrayList<>(); - Slice pages = commentRepository.findByVideoIdAndParentCommentIdIsNull(videoId, pageable); + if (scrollDirection.equals("up")) { + comments = commentRepository.findUpCommentByVideoIdAndId(videoId, idx); + } else if (scrollDirection.equals("down")) { + comments = commentRepository.findDownCommentByVideoIdAndId(videoId, idx); + } return CommentListResponse.builder() - .commentResponses(pages.map(p -> CommentResponse.builder() - .content(p.getContent()) - .writerNickname(p.getUser().getNickname()) - .build())) + .commentResponses(comments.stream() + .map(c -> CommentResponse.builder() + .content(c.getContent()) + .writerNickname(c.getUser().getNickname()) + .build()) + .toList()) .build(); } - public CommentListResponse getChildComments(Long videoId, Long parentCommentId, int page) { + public CommentListResponse getChildComments(Long videoId, Long parentCommentId, Long idx, String scrollDirection) { if (!videoRepository.existsById(videoId)) { throw new MitubeException(MitubeErrorCode.NOT_FOUND_VIDEO); } - // 댓글 검색 - Pageable pageable = PageRequest.of(page, 10); + List comments = new ArrayList<>(); - Slice pages = commentRepository.findCommentsByVideoIdAndParentCommentId(videoId, parentCommentId, pageable); + if (scrollDirection.equals("up")) { + comments = commentRepository.findUpCommentByVideoIdAndIdAndParentCommentId(parentCommentId, videoId, idx); + } else if (scrollDirection.equals("down")) { + comments = commentRepository.findDownCommentByVideoIdAndIdAndParentCommentId(parentCommentId, videoId, idx); + } return CommentListResponse.builder() - .commentResponses(pages.map(p -> CommentResponse.builder() - .content(p.getContent()) - .writerNickname(p.getUser().getNickname()) - .build())) + .commentResponses(comments.stream() + .map(c -> CommentResponse.builder() + .content(c.getContent()) + .writerNickname(c.getUser().getNickname()) + .build()) + .toList()) .build(); } From 20018df2a491b6677a9a7855ca3db71da5fb453f Mon Sep 17 00:00:00 2001 From: misim3 Date: Thu, 4 Apr 2024 13:16:26 +0900 Subject: [PATCH 06/21] =?UTF-8?q?refactor:=20CommentListResponse=EC=97=90?= =?UTF-8?q?=20=EB=8B=A4=EC=9D=8C=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EC=A1=B4?= =?UTF-8?q?=EC=9E=AC=20=EC=97=AC=EB=B6=80=20=EC=B6=94=EA=B0=80=20=EB=B0=8F?= =?UTF-8?q?=20=EA=B4=80=EB=A0=A8=20=EA=B8=B0=EB=8A=A5=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../model/Response/CommentListResponse.java | 3 +++ .../java/com/misim/repository/CommentRepository.java | 4 ++-- .../main/java/com/misim/service/CommentService.java | 12 +++++++++++- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/mitube-app/src/main/java/com/misim/controller/model/Response/CommentListResponse.java b/mitube-app/src/main/java/com/misim/controller/model/Response/CommentListResponse.java index 25cb3bc..9bd2591 100644 --- a/mitube-app/src/main/java/com/misim/controller/model/Response/CommentListResponse.java +++ b/mitube-app/src/main/java/com/misim/controller/model/Response/CommentListResponse.java @@ -13,4 +13,7 @@ public class CommentListResponse { @Schema(name = "commentResponses", description = "댓글 목록 10개", example = "재밌네요!, 좋아요!, ...", requiredMode = Schema.RequiredMode.REQUIRED) private List commentResponses; + + @Schema(name = "hasNext", description = "다음 페이지가 존재하는지 true or false", example = "true", requiredMode = Schema.RequiredMode.REQUIRED) + private Boolean hasNext; } diff --git a/mitube-app/src/main/java/com/misim/repository/CommentRepository.java b/mitube-app/src/main/java/com/misim/repository/CommentRepository.java index 3cf9ab5..ffd650a 100644 --- a/mitube-app/src/main/java/com/misim/repository/CommentRepository.java +++ b/mitube-app/src/main/java/com/misim/repository/CommentRepository.java @@ -17,13 +17,13 @@ public interface CommentRepository extends JpaRepository { Slice findCommentsByVideoIdAndParentCommentId(Long videoId, Long parentCommentId, Pageable pageable); - @Query("SELECT c1 from Comment c1 WHERE c1.parentCommentId IS NULL AND c1.video.id = :videoId AND c1.id < :id ORDER BY c1.createdDate DESC LIMIT 10") + @Query("SELECT c1 from Comment c1 WHERE c1.parentCommentId IS NULL AND c1.video.id = :videoId AND c1.id < :id ORDER BY c1.createdDate DESC LIMIT 11") List findDownCommentByVideoIdAndId(@Param("videoId") Long videoId,@Param("id") Long id); @Query("SELECT c1 from Comment c1 WHERE c1.parentCommentId IS NULL AND c1.video.id = :videoId AND c1.id > :id ORDER BY c1.createdDate ASC LIMIT 10") List findUpCommentByVideoIdAndId(@Param("videoId") Long videoId,@Param("id") Long id); - @Query("SELECT c1 from Comment c1 WHERE c1.parentCommentId = :parentCommentId AND c1.video.id = :videoId AND c1.id < :id ORDER BY c1.createdDate DESC LIMIT 10") + @Query("SELECT c1 from Comment c1 WHERE c1.parentCommentId = :parentCommentId AND c1.video.id = :videoId AND c1.id < :id ORDER BY c1.createdDate DESC LIMIT 11") List findDownCommentByVideoIdAndIdAndParentCommentId(@Param("parentCommentId") Long parentCommentId, @Param("videoId") Long videoId, @Param("id") Long id); @Query("SELECT c1 from Comment c1 WHERE c1.parentCommentId = :parentCommentId AND c1.video.id = :videoId AND c1.id > :id ORDER BY c1.createdDate ASC LIMIT 10") diff --git a/mitube-app/src/main/java/com/misim/service/CommentService.java b/mitube-app/src/main/java/com/misim/service/CommentService.java index a0947b0..6337282 100644 --- a/mitube-app/src/main/java/com/misim/service/CommentService.java +++ b/mitube-app/src/main/java/com/misim/service/CommentService.java @@ -30,6 +30,7 @@ public class CommentService { private final VideoRepository videoRepository; private final UserRepository userRepository; + // 스크롤 다운의 경우만 다음 페이지가 존재하는지 미리 확인 public CommentListResponse getParentComments(Long videoId, Long idx, String scrollDirection) { if (!videoRepository.existsById(videoId)) { @@ -44,7 +45,7 @@ public CommentListResponse getParentComments(Long videoId, Long idx, String scro comments = commentRepository.findDownCommentByVideoIdAndId(videoId, idx); } - return CommentListResponse.builder() + CommentListResponse commentListResponse = CommentListResponse.builder() .commentResponses(comments.stream() .map(c -> CommentResponse.builder() .content(c.getContent()) @@ -52,6 +53,15 @@ public CommentListResponse getParentComments(Long videoId, Long idx, String scro .build()) .toList()) .build(); + + if (comments.size() == 11) { + commentListResponse.setHasNext(true); + commentListResponse.setCommentResponses(commentListResponse.getCommentResponses().subList(0, 9)); + } else { + commentListResponse.setHasNext(false); + } + + return commentListResponse; } public CommentListResponse getChildComments(Long videoId, Long parentCommentId, Long idx, String scrollDirection) { From 192213f6d6c52bd3f9fcd59f22fb4fbafb7ca0d6 Mon Sep 17 00:00:00 2001 From: misim3 Date: Thu, 4 Apr 2024 13:31:17 +0900 Subject: [PATCH 07/21] =?UTF-8?q?refactor:=20getComments=20=EB=82=B4=20?= =?UTF-8?q?=ED=8C=8C=EB=9D=BC=EB=AF=B8=ED=84=B0=20=EA=B2=80=EC=82=AC=20?= =?UTF-8?q?=EB=A9=94=EC=86=8C=EB=93=9C=20=EC=83=9D=EC=84=B1=20=EB=B0=8F=20?= =?UTF-8?q?=EC=97=90=EB=9F=AC=20=EB=A9=94=EC=8B=9C=EC=A7=80=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../misim/controller/CommentController.java | 22 ++++++++++++++++++- .../com/misim/exception/MitubeErrorCode.java | 2 ++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/mitube-app/src/main/java/com/misim/controller/CommentController.java b/mitube-app/src/main/java/com/misim/controller/CommentController.java index 2236329..a98ae1f 100644 --- a/mitube-app/src/main/java/com/misim/controller/CommentController.java +++ b/mitube-app/src/main/java/com/misim/controller/CommentController.java @@ -5,12 +5,17 @@ import com.misim.controller.model.Response.CommentResponse; import com.misim.controller.model.Response.CreateCommentResponse; import com.misim.exception.CommonResponse; +import com.misim.exception.MitubeErrorCode; +import com.misim.exception.MitubeException; import com.misim.service.CommentService; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Slice; import org.springframework.web.bind.annotation.*; +import java.util.Arrays; +import java.util.List; + @Tag(name = "댓글 API", description = "댓글 정보 관련 API") @RestController @@ -20,6 +25,7 @@ public class CommentController { private final CommentService commentService; + private final List scroll = Arrays.asList("up", "down"); // idx, sort, scroll direction // 1th way - idx and scroll direction -> 'idx' @@ -29,9 +35,12 @@ public class CommentController { // scroll up // select * from comments where parentCommentId is null and videoId = 'videoId' and idx > 'idx' order by sort ACS limit 'pageSize'; // 1 / '2' 3 4 / '5' 6 7 / '8' 9 10 + // commentService 메소드 호출 전, scrollDirection 데이터 검사 @GetMapping("/{videoId}") public CommonResponse getParentComments(@PathVariable Long videoId, @RequestParam Long idx, @RequestParam String scrollDirection) { + checkRequests(idx, scrollDirection); + CommentListResponse comments = commentService.getParentComments(videoId, idx, scrollDirection); return CommonResponse.builder() @@ -39,10 +48,11 @@ public CommonResponse getParentComments(@PathVariable Long .build(); } - // @GetMapping("/{videoId}/{parentCommentId}") public CommonResponse getChildComments(@PathVariable Long videoId, @PathVariable Long parentCommentId, @RequestParam Long idx, @RequestParam String scrollDirection) { + checkRequests(idx, scrollDirection); + CommentListResponse comments = commentService.getChildComments(videoId, parentCommentId, idx, scrollDirection); return CommonResponse.builder() @@ -70,4 +80,14 @@ public void deleteComments(@PathVariable Long commentId) { commentService.deleteComments(commentId); } + private void checkRequests(Long idx, String scrollDirection) { + + if (idx < 1) { + throw new MitubeException(MitubeErrorCode.INVALID_COMMENT_INDEX); + } + + if (scrollDirection.isBlank() || !scroll.contains(scrollDirection)) { + throw new MitubeException(MitubeErrorCode.INVALID_COMMENT_SCROLL_DIRECTION); + } + } } diff --git a/mitube-app/src/main/java/com/misim/exception/MitubeErrorCode.java b/mitube-app/src/main/java/com/misim/exception/MitubeErrorCode.java index 99fc1c6..6a16941 100644 --- a/mitube-app/src/main/java/com/misim/exception/MitubeErrorCode.java +++ b/mitube-app/src/main/java/com/misim/exception/MitubeErrorCode.java @@ -57,6 +57,8 @@ public enum MitubeErrorCode implements ErrorCode{ INVALID_COMMENT_VIDEO(HttpStatus.BAD_REQUEST, "댓글 비디오 형식에 맞지 않습니다.", 10801), INVALID_COMMENT_USER(HttpStatus.BAD_REQUEST, "댓글 유저 형식에 맞지 않습니다.", 10802), NOT_FOUND_COMMENT(HttpStatus.BAD_REQUEST, "댓글을 찾을 수 없습니다.", 10803), + INVALID_COMMENT_INDEX(HttpStatus.BAD_REQUEST, "댓글 인덱스 형식에 맞지 않습니다.", 10804), + INVALID_COMMENT_SCROLL_DIRECTION(HttpStatus.BAD_REQUEST, "댓글 스크롤 방향 형식에 맞지 않습니다.", 10805), INVALID_SUBSCRIPTION_OWNER(HttpStatus.BAD_REQUEST, "채널 소유자 형식에 맞지 않습니다.", 10900), INVALID_SUBSCRIPTION_SUBSCRIBER(HttpStatus.BAD_REQUEST, "구독자 형식에 맞지 않습니다.", 10901), From 596b8d304664779cfcc3a078bc8c5f3d469bfb10 Mon Sep 17 00:00:00 2001 From: misim3 Date: Thu, 4 Apr 2024 14:49:09 +0900 Subject: [PATCH 08/21] =?UTF-8?q?chore:=20=EC=BB=A8=ED=8A=B8=EB=A1=A4?= =?UTF-8?q?=EB=9F=AC,=20=EC=9A=94=EC=B2=AD=20=EB=B0=8F=20=EC=9D=91?= =?UTF-8?q?=EB=8B=B5=20=EA=B4=80=EB=A0=A8=20Swagger=20api=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../misim/controller/ChannelController.java | 21 ++++++++++ .../com/misim/controller/MainController.java | 15 +++++++- .../com/misim/controller/VideoController.java | 38 +++++++++++++++---- .../model/Request/CreateCommentRequest.java | 2 + .../model/Request/CreateVideoRequest.java | 1 + .../model/Request/FindNicknameRequest.java | 1 + .../model/Request/ReactionRequest.java | 5 +++ .../model/Request/ResetPasswordRequest.java | 1 + .../model/Request/SendSMSRequest.java | 1 + .../model/Request/SignUpUserRequest.java | 2 +- .../model/Request/SubscribingRequest.java | 5 +++ .../model/Request/UpdateCommentRequest.java | 30 +++++++++++++++ .../model/Request/VerifySMSRequest.java | 1 + .../model/Response/CommentListResponse.java | 1 + .../model/Response/CommentResponse.java | 4 ++ .../model/Response/CreateCommentResponse.java | 1 + .../model/Response/FindNicknameResponse.java | 1 + .../model/Response/HomeResponse.java | 1 + .../Response/StartWatchingVideoResponse.java | 4 ++ .../model/Response/UploadVideosResponse.java | 1 + .../model/Response/VerifySMSResponse.java | 1 + .../model/Response/VideoResponse.java | 1 + .../com/misim/exception/MitubeErrorCode.java | 1 + 23 files changed, 129 insertions(+), 10 deletions(-) create mode 100644 mitube-app/src/main/java/com/misim/controller/model/Request/UpdateCommentRequest.java diff --git a/mitube-app/src/main/java/com/misim/controller/ChannelController.java b/mitube-app/src/main/java/com/misim/controller/ChannelController.java index 74cdb79..a190f42 100644 --- a/mitube-app/src/main/java/com/misim/controller/ChannelController.java +++ b/mitube-app/src/main/java/com/misim/controller/ChannelController.java @@ -1,13 +1,22 @@ package com.misim.controller; import com.misim.controller.model.Request.SubscribingRequest; +import com.misim.exception.CommonResponse; import com.misim.service.SubscriptionService; +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.tags.Tag; import lombok.RequiredArgsConstructor; 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; +@Tag(name = "채널 API", description = "채널 정보 관련 API") @RestController @RequiredArgsConstructor @RequestMapping("/channels") @@ -15,6 +24,12 @@ public class ChannelController { private final SubscriptionService subscriptionService; + @Operation(summary = "채널 구독", description = "채널을 구독합니다.") + @Parameter(name = "SubscribingRequest", description = "채널 구독 요청을 위한 정보", required = true) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "채널 구독 성공"), + @ApiResponse(responseCode = "400", description = "요청이 올바르지 않습니다.", content = @Content(schema = @Schema(implementation = CommonResponse.class))) + }) @PostMapping("/subscribe") public void subscribing(@RequestBody SubscribingRequest request) { @@ -23,6 +38,12 @@ public void subscribing(@RequestBody SubscribingRequest request) { subscriptionService.subscribing(request.getOwnerId(), request.getSubscriberId()); } + @Operation(summary = "채널 구독 취소", description = "채널 구독을 취소합니다.") + @Parameter(name = "SubscribingRequest", description = "채널 구독 취소 요청을 위한 정보", required = true) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "채널 구독 취소 성공"), + @ApiResponse(responseCode = "400", description = "요청이 올바르지 않습니다.", content = @Content(schema = @Schema(implementation = CommonResponse.class))) + }) @PostMapping("/unsubscribe") public void unsubscribing(@RequestBody SubscribingRequest request) { diff --git a/mitube-app/src/main/java/com/misim/controller/MainController.java b/mitube-app/src/main/java/com/misim/controller/MainController.java index f8bcc47..78ad2f3 100644 --- a/mitube-app/src/main/java/com/misim/controller/MainController.java +++ b/mitube-app/src/main/java/com/misim/controller/MainController.java @@ -5,6 +5,12 @@ import com.misim.exception.CommonResponse; import com.misim.service.HomeService; import com.misim.service.VideoService; +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 lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; @@ -17,9 +23,14 @@ public class MainController { private final HomeService homeService; - + + @Operation(summary = "메인 화면 데이터 전송", description = "메인 화면에 필요한 데이터 전송") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "메인 화면 데이터 전송 성공"), + @ApiResponse(responseCode = "400", description = "요청이 올바르지 않습니다.", content = @Content(schema = @Schema(implementation = CommonResponse.class))) + }) @GetMapping("/home") - public CommonResponse home(@RequestParam Long userId) { + public CommonResponse home(@RequestParam @Parameter(name = "userId", description = "Mitube에 접속한 유저 식별 정보로, 비로그인 사용자의 경우 null로 요청된다.") Long userId) { HomeResponse response = homeService.getHome(userId); diff --git a/mitube-app/src/main/java/com/misim/controller/VideoController.java b/mitube-app/src/main/java/com/misim/controller/VideoController.java index 71bb7aa..287c8d0 100644 --- a/mitube-app/src/main/java/com/misim/controller/VideoController.java +++ b/mitube-app/src/main/java/com/misim/controller/VideoController.java @@ -35,6 +35,7 @@ public class VideoController { private final ReactionService reactionService; @Operation(summary = "동영상 업로드", description = "새로운 동영상을 업로드합니다.") + @Parameter(name = "MultipartFile", description = "MultipartFile 형식의 동영상 데이터") @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "동영상 업로드 성공"), @ApiResponse(responseCode = "400", description = "요청 형식이 올바르지 않습니다.", content = @Content(schema = @Schema(implementation = CommonResponse.class))) @@ -79,9 +80,14 @@ public void createVideos(@RequestBody CreateVideoRequest createVideoRequest) { // 비디오 생성 videoService.createVideos(createVideoRequest); } - + + @Operation(summary = "동영상 시청 시작", description = "동영상 시청을 시작합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "동영상 시청 시작 요청 성공"), + @ApiResponse(responseCode = "400", description = "요청 형식이 올바르지 않습니다.", content = @Content(schema = @Schema(implementation = CommonResponse.class))) + }) @GetMapping("/watch/{videoId}") - public CommonResponse startWatchingVideo(@PathVariable Long videoId, @RequestParam Long userId) { + public CommonResponse startWatchingVideo(@PathVariable @Parameter(name = "videoId", description = "시청할 동영상 식별 정보", required = true) Long videoId, @RequestParam @Parameter(name = "userId", description = "동영상을 시청할 유저의 식별 정보") Long userId) { StartWatchingVideoResponse response = videoService.startWatchingVideo(videoId, userId); @@ -94,21 +100,35 @@ public CommonResponse startWatchingVideo(@PathVariab .body(response) .build(); } - - + + @Operation(summary = "동영상 시청 중", description = "유저가 동영상을 계속 시청 중인지 확인하여 동영상 시청 정보를 업데이트합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "동영상 시청 정보 업데이트 성공"), + @ApiResponse(responseCode = "400", description = "요청 형식이 올바르지 않습니다.", content = @Content(schema = @Schema(implementation = CommonResponse.class))) + }) @PostMapping("/watch/{videoId}") - public void watchingVideo(@PathVariable Long videoId, @RequestParam Long userId, @RequestParam Long watchingTime) { + public void watchingVideo(@PathVariable @Parameter(name = "videoId", description = "시청할 동영상 식별 정보", required = true) Long videoId, @RequestParam @Parameter(name = "userId", description = "동영상을 시청할 유저의 식별 정보") Long userId, @RequestParam Long watchingTime) { videoService.updateWatchingVideoInfo(videoId, userId, watchingTime); } // 99999 에러 발생 + @Operation(summary = "동영상 시청 완료", description = "동영상 시청 완료로 시청 정보를 업데이트합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "동영상 시청 정보 업데이트 성공"), + @ApiResponse(responseCode = "400", description = "요청 형식이 올바르지 않습니다.", content = @Content(schema = @Schema(implementation = CommonResponse.class))) + }) @PostMapping("/watch/{videoId}/complete") - public void completeWatchingVideo(@PathVariable Long videoId, @RequestParam Long userId, @RequestParam Long watchingTime) { + public void completeWatchingVideo(@PathVariable @Parameter(name = "videoId", description = "시청할 동영상 식별 정보", required = true) Long videoId, @RequestParam @Parameter(name = "userId", description = "동영상을 시청할 유저의 식별 정보") Long userId, @RequestParam Long watchingTime) { videoService.updateWatchingVideoInfo(videoId, userId, watchingTime); } + @Operation(summary = "동영상에 대한 유저의 반응 선택", description = "동영상에 대한 유저의 반응. 좋아요, 싫어요 선택 정보를 저장합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "동영상 반응 정보 업데이트 성공"), + @ApiResponse(responseCode = "400", description = "요청 형식이 올바르지 않습니다.", content = @Content(schema = @Schema(implementation = CommonResponse.class))) + }) @PostMapping("/check/reaction") public void checkVideo(@RequestBody ReactionRequest request) { @@ -117,7 +137,11 @@ public void checkVideo(@RequestBody ReactionRequest request) { reactionService.checking(request.getType(), request.getUserId(), request.getVideoId()); } - + @Operation(summary = "동영상에 대한 유저의 반응 선택 취소", description = "동영상에 대한 유저의 반응. 좋아요, 싫어요 선택 취소 정보를 저장합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "동영상 반응 정보 업데이트 성공"), + @ApiResponse(responseCode = "400", description = "요청 형식이 올바르지 않습니다.", content = @Content(schema = @Schema(implementation = CommonResponse.class))) + }) @PostMapping("/uncheck/reaction") public void uncheckVideo(@RequestBody ReactionRequest request) { diff --git a/mitube-app/src/main/java/com/misim/controller/model/Request/CreateCommentRequest.java b/mitube-app/src/main/java/com/misim/controller/model/Request/CreateCommentRequest.java index 65421f0..1031061 100644 --- a/mitube-app/src/main/java/com/misim/controller/model/Request/CreateCommentRequest.java +++ b/mitube-app/src/main/java/com/misim/controller/model/Request/CreateCommentRequest.java @@ -1,12 +1,14 @@ package com.misim.controller.model.Request; import com.misim.controller.model.Checker; +import com.misim.controller.model.CommentDto; import com.misim.exception.MitubeErrorCode; import com.misim.exception.MitubeException; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @Data +@Schema(name = "댓글 생성 요청 DTO") public class CreateCommentRequest implements Checker { @Schema(name = "content", description = "댓글 내용", example = "프로그래밍 공부에 도움이 됩니다!", requiredMode = Schema.RequiredMode.REQUIRED) diff --git a/mitube-app/src/main/java/com/misim/controller/model/Request/CreateVideoRequest.java b/mitube-app/src/main/java/com/misim/controller/model/Request/CreateVideoRequest.java index 485a109..a0933d6 100644 --- a/mitube-app/src/main/java/com/misim/controller/model/Request/CreateVideoRequest.java +++ b/mitube-app/src/main/java/com/misim/controller/model/Request/CreateVideoRequest.java @@ -9,6 +9,7 @@ @Getter @Setter +@Schema(name = "새로운 동영상 생성 요청 DTO") public class CreateVideoRequest implements Checker { @Schema(name = "title", description = "동영상 제목", example = "Hello world!", requiredMode = Schema.RequiredMode.REQUIRED) diff --git a/mitube-app/src/main/java/com/misim/controller/model/Request/FindNicknameRequest.java b/mitube-app/src/main/java/com/misim/controller/model/Request/FindNicknameRequest.java index aecf599..34da927 100644 --- a/mitube-app/src/main/java/com/misim/controller/model/Request/FindNicknameRequest.java +++ b/mitube-app/src/main/java/com/misim/controller/model/Request/FindNicknameRequest.java @@ -10,6 +10,7 @@ @Getter @Setter +@Schema(name = "닉네임 찾기 요청 DTO") public class FindNicknameRequest implements Checker { @Schema(name = "token", description = "토큰", example = "AIHR==", requiredMode = Schema.RequiredMode.REQUIRED) diff --git a/mitube-app/src/main/java/com/misim/controller/model/Request/ReactionRequest.java b/mitube-app/src/main/java/com/misim/controller/model/Request/ReactionRequest.java index df4093c..102b42a 100644 --- a/mitube-app/src/main/java/com/misim/controller/model/Request/ReactionRequest.java +++ b/mitube-app/src/main/java/com/misim/controller/model/Request/ReactionRequest.java @@ -3,15 +3,20 @@ import com.misim.controller.model.Checker; import com.misim.exception.MitubeErrorCode; import com.misim.exception.MitubeException; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @Data +@Schema(name = "반응 요청 DTO") public class ReactionRequest implements Checker { + @Schema(name = "type", description = "동영상에 대한 유저의 반응 타입으로 like, dislike가 가능합니다.", requiredMode = Schema.RequiredMode.REQUIRED) private String type; + @Schema(name = "userId", description = "동영상에 반응한 유저 식별 정보", requiredMode = Schema.RequiredMode.REQUIRED) private Long userId; + @Schema(name = "videoId", description = "유저가 반응한 동영상 식별 정보", requiredMode = Schema.RequiredMode.REQUIRED) private Long videoId; @Override diff --git a/mitube-app/src/main/java/com/misim/controller/model/Request/ResetPasswordRequest.java b/mitube-app/src/main/java/com/misim/controller/model/Request/ResetPasswordRequest.java index 7765138..0000eb1 100644 --- a/mitube-app/src/main/java/com/misim/controller/model/Request/ResetPasswordRequest.java +++ b/mitube-app/src/main/java/com/misim/controller/model/Request/ResetPasswordRequest.java @@ -9,6 +9,7 @@ @Getter @Setter +@Schema(name = "비밀번호 초기화 요청 DTO") public class ResetPasswordRequest extends VerificationDto { @Schema(name = "nickname", description = "닉네임", example = "hongkildong", requiredMode = Schema.RequiredMode.REQUIRED) diff --git a/mitube-app/src/main/java/com/misim/controller/model/Request/SendSMSRequest.java b/mitube-app/src/main/java/com/misim/controller/model/Request/SendSMSRequest.java index 63a94b9..7e02aa3 100644 --- a/mitube-app/src/main/java/com/misim/controller/model/Request/SendSMSRequest.java +++ b/mitube-app/src/main/java/com/misim/controller/model/Request/SendSMSRequest.java @@ -4,6 +4,7 @@ import lombok.Data; @Data +@Schema(name = "SMS 본인 인증 메세지 요청 DTO") public class SendSMSRequest { @Schema(name = "phoneNumber", description = "전화번호", example = "01012345678", requiredMode = Schema.RequiredMode.REQUIRED) diff --git a/mitube-app/src/main/java/com/misim/controller/model/Request/SignUpUserRequest.java b/mitube-app/src/main/java/com/misim/controller/model/Request/SignUpUserRequest.java index c07a6c7..0a3a02f 100644 --- a/mitube-app/src/main/java/com/misim/controller/model/Request/SignUpUserRequest.java +++ b/mitube-app/src/main/java/com/misim/controller/model/Request/SignUpUserRequest.java @@ -11,7 +11,7 @@ @Getter @Setter -@Schema(description = "유저 DTO") +@Schema(description = "유저 등록 요청 DTO") public class SignUpUserRequest implements Checker { @Schema(name = "email", description = "User 이메일", example = "hongkildong@example.com", requiredMode = Schema.RequiredMode.REQUIRED) diff --git a/mitube-app/src/main/java/com/misim/controller/model/Request/SubscribingRequest.java b/mitube-app/src/main/java/com/misim/controller/model/Request/SubscribingRequest.java index 2caac0a..ec884d3 100644 --- a/mitube-app/src/main/java/com/misim/controller/model/Request/SubscribingRequest.java +++ b/mitube-app/src/main/java/com/misim/controller/model/Request/SubscribingRequest.java @@ -3,13 +3,18 @@ import com.misim.controller.model.Checker; import com.misim.exception.MitubeErrorCode; import com.misim.exception.MitubeException; +import io.netty.channel.ChannelHandler; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @Data +@Schema(name = "구독 요청 DTO") public class SubscribingRequest implements Checker { + @Schema(name = "ownerId", description = "채널 소유주의 유저 식별 정보", requiredMode = Schema.RequiredMode.REQUIRED) private Long ownerId; + @Schema(name = "subscriberId", description = "채널 구독자의 유저 식별 정보", requiredMode = Schema.RequiredMode.REQUIRED) private Long subscriberId; @Override diff --git a/mitube-app/src/main/java/com/misim/controller/model/Request/UpdateCommentRequest.java b/mitube-app/src/main/java/com/misim/controller/model/Request/UpdateCommentRequest.java new file mode 100644 index 0000000..ec9aa83 --- /dev/null +++ b/mitube-app/src/main/java/com/misim/controller/model/Request/UpdateCommentRequest.java @@ -0,0 +1,30 @@ +package com.misim.controller.model.Request; + +import com.misim.controller.model.Checker; +import com.misim.exception.MitubeErrorCode; +import com.misim.exception.MitubeException; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +@Schema(name = "댓글 수정 요청 DTO") +public class UpdateCommentRequest implements Checker { + + @Schema(name = "commentId", description = "댓글 식별 정보", requiredMode = Schema.RequiredMode.REQUIRED) + private Long commentId; + + @Schema(name = "content", description = "수정할 댓글 내용", requiredMode = Schema.RequiredMode.REQUIRED) + private String content; + + @Override + public void check() { + + if (commentId == null) { + throw new MitubeException(MitubeErrorCode.INVALID_COMMENT_ID); + } + + if (content.isBlank()) { + throw new MitubeException(MitubeErrorCode.INVALID_COMMENT_CONTENT); + } + } +} diff --git a/mitube-app/src/main/java/com/misim/controller/model/Request/VerifySMSRequest.java b/mitube-app/src/main/java/com/misim/controller/model/Request/VerifySMSRequest.java index cab1cdc..4af6b29 100644 --- a/mitube-app/src/main/java/com/misim/controller/model/Request/VerifySMSRequest.java +++ b/mitube-app/src/main/java/com/misim/controller/model/Request/VerifySMSRequest.java @@ -10,6 +10,7 @@ @Getter @Setter +@Schema(name = "SMS 본인 인증 검증 요청 DTO") public class VerifySMSRequest extends VerificationDto { @Schema(name = "phoneNumber", description = "전화번호", example = "01012345678", requiredMode = Schema.RequiredMode.REQUIRED) diff --git a/mitube-app/src/main/java/com/misim/controller/model/Response/CommentListResponse.java b/mitube-app/src/main/java/com/misim/controller/model/Response/CommentListResponse.java index 9bd2591..1915351 100644 --- a/mitube-app/src/main/java/com/misim/controller/model/Response/CommentListResponse.java +++ b/mitube-app/src/main/java/com/misim/controller/model/Response/CommentListResponse.java @@ -9,6 +9,7 @@ @Data @Builder +@Schema(name = "댓글 목록 정보 응답 DTO") public class CommentListResponse { @Schema(name = "commentResponses", description = "댓글 목록 10개", example = "재밌네요!, 좋아요!, ...", requiredMode = Schema.RequiredMode.REQUIRED) diff --git a/mitube-app/src/main/java/com/misim/controller/model/Response/CommentResponse.java b/mitube-app/src/main/java/com/misim/controller/model/Response/CommentResponse.java index 6a632f9..559c20c 100644 --- a/mitube-app/src/main/java/com/misim/controller/model/Response/CommentResponse.java +++ b/mitube-app/src/main/java/com/misim/controller/model/Response/CommentResponse.java @@ -6,8 +6,12 @@ @Data @Builder +@Schema(name = "댓글 정보 응답 DTO") public class CommentResponse { + @Schema(name = "commentId", description = "댓글 식별 정보", example = "1", requiredMode = Schema.RequiredMode.REQUIRED) + private Long commentId; + @Schema(name = "content", description = "댓글 내용", example = "재밌네요!", requiredMode = Schema.RequiredMode.REQUIRED) private String content; diff --git a/mitube-app/src/main/java/com/misim/controller/model/Response/CreateCommentResponse.java b/mitube-app/src/main/java/com/misim/controller/model/Response/CreateCommentResponse.java index 91d4ef9..b68f74c 100644 --- a/mitube-app/src/main/java/com/misim/controller/model/Response/CreateCommentResponse.java +++ b/mitube-app/src/main/java/com/misim/controller/model/Response/CreateCommentResponse.java @@ -6,6 +6,7 @@ @Data @Builder +@Schema(name = "댓글 생성 응답 DTO") public class CreateCommentResponse { @Schema(name = "commentId", description = "생성된 댓글 식별 정보 반환", example = "1", requiredMode = Schema.RequiredMode.REQUIRED) diff --git a/mitube-app/src/main/java/com/misim/controller/model/Response/FindNicknameResponse.java b/mitube-app/src/main/java/com/misim/controller/model/Response/FindNicknameResponse.java index 72c986f..5296f8f 100644 --- a/mitube-app/src/main/java/com/misim/controller/model/Response/FindNicknameResponse.java +++ b/mitube-app/src/main/java/com/misim/controller/model/Response/FindNicknameResponse.java @@ -4,6 +4,7 @@ import lombok.Data; @Data +@Schema(name = "닉네임 찾기 응답 DTO") public class FindNicknameResponse { @Schema(name = "nickname", description = "닉네임 찾기 결과인 닉네임", example = "hongkildong", requiredMode = Schema.RequiredMode.REQUIRED) diff --git a/mitube-app/src/main/java/com/misim/controller/model/Response/HomeResponse.java b/mitube-app/src/main/java/com/misim/controller/model/Response/HomeResponse.java index 742888f..57a4d13 100644 --- a/mitube-app/src/main/java/com/misim/controller/model/Response/HomeResponse.java +++ b/mitube-app/src/main/java/com/misim/controller/model/Response/HomeResponse.java @@ -8,6 +8,7 @@ @Data @Builder +@Schema(name = "메인 페이지 정보 응답 DTO") public class HomeResponse { @Schema(name = "categoryList", description = "전체 동영상 카테고리 목록", example = "영화, 음악, ...", requiredMode = Schema.RequiredMode.REQUIRED) diff --git a/mitube-app/src/main/java/com/misim/controller/model/Response/StartWatchingVideoResponse.java b/mitube-app/src/main/java/com/misim/controller/model/Response/StartWatchingVideoResponse.java index a8903bf..3c818c4 100644 --- a/mitube-app/src/main/java/com/misim/controller/model/Response/StartWatchingVideoResponse.java +++ b/mitube-app/src/main/java/com/misim/controller/model/Response/StartWatchingVideoResponse.java @@ -6,8 +6,12 @@ @Data @Builder +@Schema(name = "동영상 시청 시작 정보 응답 DTO") public class StartWatchingVideoResponse { + @Schema(name = "videoId", description = "동영상 식별 정보", example = "1", requiredMode = Schema.RequiredMode.REQUIRED) + private Long videoId; + @Schema(name = "watchingTime", description = "동영상 시청 시각. 동영상 시청한 기록이 없다면, 0. 있다면, 시청 시각 반환", example = "1234", requiredMode = Schema.RequiredMode.REQUIRED) private Long watchingTime; diff --git a/mitube-app/src/main/java/com/misim/controller/model/Response/UploadVideosResponse.java b/mitube-app/src/main/java/com/misim/controller/model/Response/UploadVideosResponse.java index 0f0208b..c7a061e 100644 --- a/mitube-app/src/main/java/com/misim/controller/model/Response/UploadVideosResponse.java +++ b/mitube-app/src/main/java/com/misim/controller/model/Response/UploadVideosResponse.java @@ -4,6 +4,7 @@ import lombok.Data; @Data +@Schema(name = "동영상 업로드 결과 응답 DTO") public class UploadVideosResponse { @Schema(name = "id", description = "동영상 업로드 식별 정보", example = "AHKW+==", requiredMode = Schema.RequiredMode.REQUIRED) diff --git a/mitube-app/src/main/java/com/misim/controller/model/Response/VerifySMSResponse.java b/mitube-app/src/main/java/com/misim/controller/model/Response/VerifySMSResponse.java index eeb377e..01e8a63 100644 --- a/mitube-app/src/main/java/com/misim/controller/model/Response/VerifySMSResponse.java +++ b/mitube-app/src/main/java/com/misim/controller/model/Response/VerifySMSResponse.java @@ -5,6 +5,7 @@ import lombok.Data; @Data +@Schema(name = "SMS 본인 인증 검증 결과 응답 DTO") public class VerifySMSResponse { @Schema(name = "token", description = "SMS 인증 토큰", example = "AHKW+==", requiredMode = Schema.RequiredMode.REQUIRED) diff --git a/mitube-app/src/main/java/com/misim/controller/model/Response/VideoResponse.java b/mitube-app/src/main/java/com/misim/controller/model/Response/VideoResponse.java index f4e65ad..d63d59f 100644 --- a/mitube-app/src/main/java/com/misim/controller/model/Response/VideoResponse.java +++ b/mitube-app/src/main/java/com/misim/controller/model/Response/VideoResponse.java @@ -10,6 +10,7 @@ @Data @Builder +@Schema(name = "동영상 정보 응답 DTO") public class VideoResponse { @Schema(name = "videoId", description = "동영상 식별 정보", example = "1", requiredMode = Schema.RequiredMode.REQUIRED) diff --git a/mitube-app/src/main/java/com/misim/exception/MitubeErrorCode.java b/mitube-app/src/main/java/com/misim/exception/MitubeErrorCode.java index 6a16941..c8a69e9 100644 --- a/mitube-app/src/main/java/com/misim/exception/MitubeErrorCode.java +++ b/mitube-app/src/main/java/com/misim/exception/MitubeErrorCode.java @@ -59,6 +59,7 @@ public enum MitubeErrorCode implements ErrorCode{ NOT_FOUND_COMMENT(HttpStatus.BAD_REQUEST, "댓글을 찾을 수 없습니다.", 10803), INVALID_COMMENT_INDEX(HttpStatus.BAD_REQUEST, "댓글 인덱스 형식에 맞지 않습니다.", 10804), INVALID_COMMENT_SCROLL_DIRECTION(HttpStatus.BAD_REQUEST, "댓글 스크롤 방향 형식에 맞지 않습니다.", 10805), + INVALID_COMMENT_ID(HttpStatus.BAD_REQUEST, "댓글 식별 정보 형식에 맞지 않습니다.", 10806), INVALID_SUBSCRIPTION_OWNER(HttpStatus.BAD_REQUEST, "채널 소유자 형식에 맞지 않습니다.", 10900), INVALID_SUBSCRIPTION_SUBSCRIBER(HttpStatus.BAD_REQUEST, "구독자 형식에 맞지 않습니다.", 10901), From 3daa7776e9f3e4fb364b5cf54c8c5d7df43c4601 Mon Sep 17 00:00:00 2001 From: misim3 Date: Thu, 4 Apr 2024 14:50:17 +0900 Subject: [PATCH 09/21] =?UTF-8?q?refactor:=20=EB=8C=93=EA=B8=80=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EC=A4=91=20=EB=8C=93=EA=B8=80=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../misim/controller/CommentController.java | 59 ++++++++++++++++--- .../misim/controller/model/CommentDto.java | 21 +++++++ .../main/java/com/misim/entity/Comment.java | 5 ++ .../com/misim/service/CommentService.java | 16 ++++- 4 files changed, 90 insertions(+), 11 deletions(-) create mode 100644 mitube-app/src/main/java/com/misim/controller/model/CommentDto.java diff --git a/mitube-app/src/main/java/com/misim/controller/CommentController.java b/mitube-app/src/main/java/com/misim/controller/CommentController.java index a98ae1f..85dd23e 100644 --- a/mitube-app/src/main/java/com/misim/controller/CommentController.java +++ b/mitube-app/src/main/java/com/misim/controller/CommentController.java @@ -1,6 +1,8 @@ package com.misim.controller; +import com.misim.controller.model.CommentDto; import com.misim.controller.model.Request.CreateCommentRequest; +import com.misim.controller.model.Request.UpdateCommentRequest; import com.misim.controller.model.Response.CommentListResponse; import com.misim.controller.model.Response.CommentResponse; import com.misim.controller.model.Response.CreateCommentResponse; @@ -8,9 +10,17 @@ import com.misim.exception.MitubeErrorCode; import com.misim.exception.MitubeException; import com.misim.service.CommentService; +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.tags.Tag; import lombok.RequiredArgsConstructor; +import org.hibernate.sql.Update; import org.springframework.data.domain.Slice; +import org.springframework.security.core.parameters.P; import org.springframework.web.bind.annotation.*; import java.util.Arrays; @@ -36,8 +46,13 @@ public class CommentController { // select * from comments where parentCommentId is null and videoId = 'videoId' and idx > 'idx' order by sort ACS limit 'pageSize'; // 1 / '2' 3 4 / '5' 6 7 / '8' 9 10 // commentService 메소드 호출 전, scrollDirection 데이터 검사 + @Operation(summary = "댓글 목록 요청", description = "동영상의 댓글 목록 10개 전달") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "댓글 목록 요청 성공"), + @ApiResponse(responseCode = "400", description = "요청이 올바르지 않습니다.", content = @Content(schema = @Schema(implementation = CommonResponse.class))) + }) @GetMapping("/{videoId}") - public CommonResponse getParentComments(@PathVariable Long videoId, @RequestParam Long idx, @RequestParam String scrollDirection) { + public CommonResponse getParentComments(@PathVariable @Parameter(name = "videoId", description = "시청할 동영상 식별 정보", required = true) Long videoId, @RequestParam @Parameter(name = "idx", description = "댓글의 인덱스 정보") Long idx, @RequestParam @Parameter(name = "scrollDirection", description = "댓글 목록 스크롤 방향으로 up, down만 가능하다.") String scrollDirection) { checkRequests(idx, scrollDirection); @@ -48,8 +63,13 @@ public CommonResponse getParentComments(@PathVariable Long .build(); } + @Operation(summary = "대댓글 목록 요청", description = "동영상 댓글의 대댓글 목록 10개 전달") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "대댓글 목록 요청 성공"), + @ApiResponse(responseCode = "400", description = "요청이 올바르지 않습니다.", content = @Content(schema = @Schema(implementation = CommonResponse.class))) + }) @GetMapping("/{videoId}/{parentCommentId}") - public CommonResponse getChildComments(@PathVariable Long videoId, @PathVariable Long parentCommentId, @RequestParam Long idx, @RequestParam String scrollDirection) { + public CommonResponse getChildComments(@PathVariable @Parameter(name = "videoId", description = "시청할 동영상 식별 정보", required = true) Long videoId, @PathVariable @Parameter(name = "parentCommentId", description = "대댓글이 달린 댓글의 식별 정보") Long parentCommentId, @RequestParam @Parameter(name = "idx", description = "댓글의 인덱스 정보") Long idx, @RequestParam @Parameter(name = "scrollDirection", description = "댓글 목록 스크롤 방향으로 up, down만 가능하다.") String scrollDirection) { checkRequests(idx, scrollDirection); @@ -60,8 +80,14 @@ public CommonResponse getChildComments(@PathVariable Long v .build(); } + @Operation(summary = "댓글 생성", description = "동영상 댓글을 생성합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "댓글 생성 성공"), + @ApiResponse(responseCode = "400", description = "요청이 올바르지 않습니다.", content = @Content(schema = @Schema(implementation = CommonResponse.class))) + }) @PostMapping("/create") public CommonResponse createComments(@RequestBody CreateCommentRequest request) { + request.check(); CreateCommentResponse response = commentService.createComments(request); @@ -69,15 +95,30 @@ public CommonResponse createComments(@RequestBody CreateC return CommonResponse.builder().body(response).build(); } - @PostMapping("/{commentId}") - public void updateComments(@PathVariable Long commentId, @RequestParam String content) { - commentService.updateComments(commentId, content); + @Operation(summary = "댓글 수정", description = "동영상 댓글을 수정합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "댓글 수정 성공"), + @ApiResponse(responseCode = "400", description = "요청이 올바르지 않습니다.", content = @Content(schema = @Schema(implementation = CommonResponse.class))) + }) + @PostMapping("/update") + public void updateComments(@RequestBody UpdateCommentRequest request) { + + request.check(); + + commentService.updateComments(request.getCommentId(), request.getContent()); } - // 댓글 삭제 요청을 post, delete 중에 선택 - @DeleteMapping("/{commentId}") - public void deleteComments(@PathVariable Long commentId) { - commentService.deleteComments(commentId); + @Operation(summary = "댓글 삭제", description = "동영상 댓글을 삭제합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "댓글 삭제 성공"), + @ApiResponse(responseCode = "400", description = "요청이 올바르지 않습니다.", content = @Content(schema = @Schema(implementation = CommonResponse.class))) + }) + @PostMapping("/delete") + public void deleteComments(@RequestBody CommentDto request) { + + request.check(); + + commentService.deleteComments(request.getCommentId()); } private void checkRequests(Long idx, String scrollDirection) { diff --git a/mitube-app/src/main/java/com/misim/controller/model/CommentDto.java b/mitube-app/src/main/java/com/misim/controller/model/CommentDto.java new file mode 100644 index 0000000..cbd7a98 --- /dev/null +++ b/mitube-app/src/main/java/com/misim/controller/model/CommentDto.java @@ -0,0 +1,21 @@ +package com.misim.controller.model; + +import com.misim.exception.MitubeErrorCode; +import com.misim.exception.MitubeException; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class CommentDto implements Checker{ + + @Schema(name = "commentId", description = "댓글 식별 정보", example = "1", requiredMode = Schema.RequiredMode.REQUIRED) + private Long commentId; + + @Override + public void check() { + + if (commentId == null) { + throw new MitubeException(MitubeErrorCode.INVALID_COMMENT_ID); + } + } +} diff --git a/mitube-app/src/main/java/com/misim/entity/Comment.java b/mitube-app/src/main/java/com/misim/entity/Comment.java index 5e64991..3da2e89 100644 --- a/mitube-app/src/main/java/com/misim/entity/Comment.java +++ b/mitube-app/src/main/java/com/misim/entity/Comment.java @@ -26,13 +26,18 @@ public class Comment extends BaseTimeEntity { private Long parentCommentId; @ManyToOne + @Setter private User user; + @Setter + private Boolean isActive; + @Builder public Comment(String content, Video video, Long parentCommentId, User user) { this.content = content; this.video = video; this.parentCommentId = parentCommentId; this.user = user; + this.isActive = true; } } diff --git a/mitube-app/src/main/java/com/misim/service/CommentService.java b/mitube-app/src/main/java/com/misim/service/CommentService.java index 6337282..1f805a1 100644 --- a/mitube-app/src/main/java/com/misim/service/CommentService.java +++ b/mitube-app/src/main/java/com/misim/service/CommentService.java @@ -48,6 +48,7 @@ public CommentListResponse getParentComments(Long videoId, Long idx, String scro CommentListResponse commentListResponse = CommentListResponse.builder() .commentResponses(comments.stream() .map(c -> CommentResponse.builder() + .commentId(c.getId()) .content(c.getContent()) .writerNickname(c.getUser().getNickname()) .build()) @@ -81,6 +82,7 @@ public CommentListResponse getChildComments(Long videoId, Long parentCommentId, return CommentListResponse.builder() .commentResponses(comments.stream() .map(c -> CommentResponse.builder() + .commentId(c.getId()) .content(c.getContent()) .writerNickname(c.getUser().getNickname()) .build()) @@ -135,13 +137,23 @@ public void updateComments(Long commentId, String content) { commentRepository.save(comment); } - + public void deleteComments(Long commentId) { if (commentId == null || !commentRepository.existsById(commentId)) { throw new MitubeException(MitubeErrorCode.NOT_FOUND_COMMENT); } - commentRepository.deleteById(commentId); + Comment comment = commentRepository.findById(commentId) + .orElseThrow(() -> new MitubeException(MitubeErrorCode.NOT_FOUND_COMMENT)); + + comment.setContent("삭제된 댓글입니다."); + // 아래와 같은 코드가 가능한지 테스트가 필요하다. + // 만약 불가능하다면, 댓글 목록을 가져올 때, 댓글이 활성화 상태인지 확인해서 댓글 작성자의 닉네임을 가져와야 한다. + // 만약 가능하다면, 댓글이 활성화 상태인지 여부를 담는 isActive 필드는 필요하지 않다. + comment.setUser(null); + comment.setIsActive(false); + + commentRepository.save(comment); } } From d5e71df7eef63e97a22c8e44ba09f052adbf431a Mon Sep 17 00:00:00 2001 From: misim3 Date: Mon, 8 Apr 2024 13:38:56 +0900 Subject: [PATCH 10/21] =?UTF-8?q?refactor:=20=EA=B5=AC=EB=8F=85=EC=9D=84?= =?UTF-8?q?=20=EC=9C=84=ED=95=9C=20=EC=B1=84=EB=84=90=20=EC=97=94=ED=8B=B0?= =?UTF-8?q?=ED=8B=B0=20=EC=83=9D=EC=84=B1=20=EB=B0=8F=20=EA=B4=80=EB=A0=A8?= =?UTF-8?q?=20=EA=B8=B0=EB=8A=A5=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../misim/controller/ChannelController.java | 4 +- .../model/Request/SubscribingRequest.java | 8 ++-- .../main/java/com/misim/entity/Channel.java | 38 +++++++++++++++++++ .../java/com/misim/entity/Subscription.java | 16 +++++--- .../src/main/java/com/misim/entity/User.java | 8 +++- .../com/misim/exception/MitubeErrorCode.java | 4 +- .../misim/repository/ChannelRepository.java | 9 +++++ .../repository/SubscriptionRepository.java | 2 +- .../misim/service/SubscriptionService.java | 31 +++++++-------- 9 files changed, 90 insertions(+), 30 deletions(-) create mode 100644 mitube-app/src/main/java/com/misim/entity/Channel.java create mode 100644 mitube-app/src/main/java/com/misim/repository/ChannelRepository.java diff --git a/mitube-app/src/main/java/com/misim/controller/ChannelController.java b/mitube-app/src/main/java/com/misim/controller/ChannelController.java index a190f42..cc67dd8 100644 --- a/mitube-app/src/main/java/com/misim/controller/ChannelController.java +++ b/mitube-app/src/main/java/com/misim/controller/ChannelController.java @@ -35,7 +35,7 @@ public void subscribing(@RequestBody SubscribingRequest request) { request.check(); - subscriptionService.subscribing(request.getOwnerId(), request.getSubscriberId()); + subscriptionService.subscribing(request.getChannelId(), request.getSubscriberId()); } @Operation(summary = "채널 구독 취소", description = "채널 구독을 취소합니다.") @@ -49,6 +49,6 @@ public void unsubscribing(@RequestBody SubscribingRequest request) { request.check(); - subscriptionService.unsubscribing(request.getOwnerId(), request.getSubscriberId()); + subscriptionService.unsubscribing(request.getChannelId(), request.getSubscriberId()); } } diff --git a/mitube-app/src/main/java/com/misim/controller/model/Request/SubscribingRequest.java b/mitube-app/src/main/java/com/misim/controller/model/Request/SubscribingRequest.java index ec884d3..58302ab 100644 --- a/mitube-app/src/main/java/com/misim/controller/model/Request/SubscribingRequest.java +++ b/mitube-app/src/main/java/com/misim/controller/model/Request/SubscribingRequest.java @@ -11,8 +11,8 @@ @Schema(name = "구독 요청 DTO") public class SubscribingRequest implements Checker { - @Schema(name = "ownerId", description = "채널 소유주의 유저 식별 정보", requiredMode = Schema.RequiredMode.REQUIRED) - private Long ownerId; + @Schema(name = "channelId", description = "채널 식별 정보", requiredMode = Schema.RequiredMode.REQUIRED) + private Long channelId; @Schema(name = "subscriberId", description = "채널 구독자의 유저 식별 정보", requiredMode = Schema.RequiredMode.REQUIRED) private Long subscriberId; @@ -20,8 +20,8 @@ public class SubscribingRequest implements Checker { @Override public void check() { - if (ownerId == null) { - throw new MitubeException(MitubeErrorCode.INVALID_SUBSCRIPTION_OWNER); + if (channelId == null) { + throw new MitubeException(MitubeErrorCode.INVALID_SUBSCRIPTION_CHANNEL); } if (subscriberId == null) { diff --git a/mitube-app/src/main/java/com/misim/entity/Channel.java b/mitube-app/src/main/java/com/misim/entity/Channel.java new file mode 100644 index 0000000..b850b37 --- /dev/null +++ b/mitube-app/src/main/java/com/misim/entity/Channel.java @@ -0,0 +1,38 @@ +package com.misim.entity; + +import jakarta.persistence.*; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.util.ArrayList; +import java.util.List; + +@Entity +@Getter +@Table(name = "channels") +@NoArgsConstructor +public class Channel extends BaseTimeEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private String title; + + private String description; + + @ManyToOne + @JoinColumn(name = "USER_ID") + private User owner; + + @Setter + @OneToMany + private List subscriptionList = new ArrayList<>(); + + public Channel(String title, String description, User owner) { + this.title = title; + this.description = description; + this.owner = owner; + } +} diff --git a/mitube-app/src/main/java/com/misim/entity/Subscription.java b/mitube-app/src/main/java/com/misim/entity/Subscription.java index 49ddaf7..ebdd1ed 100644 --- a/mitube-app/src/main/java/com/misim/entity/Subscription.java +++ b/mitube-app/src/main/java/com/misim/entity/Subscription.java @@ -5,6 +5,8 @@ import lombok.Getter; import lombok.NoArgsConstructor; +import java.util.List; + @Entity @Getter @Table(name = "subscriptions") @@ -15,13 +17,17 @@ public class Subscription { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long Id; - private Long ownerId; + @ManyToOne + @JoinColumn(name = "CHANNEL_ID") + private Channel channel; - private Long subscriberId; + @ManyToOne + @JoinColumn(name = "USER_ID") + private User subscriber; @Builder - public Subscription(Long ownerId, Long subscriberId) { - this.ownerId = ownerId; - this.subscriberId = subscriberId; + public Subscription(Channel channel, User subscriber) { + this.channel = channel; + this.subscriber = subscriber; } } diff --git a/mitube-app/src/main/java/com/misim/entity/User.java b/mitube-app/src/main/java/com/misim/entity/User.java index c056850..b02418a 100644 --- a/mitube-app/src/main/java/com/misim/entity/User.java +++ b/mitube-app/src/main/java/com/misim/entity/User.java @@ -30,14 +30,18 @@ public class User extends BaseTimeEntity{ private boolean isEnabled; - @OneToMany(mappedBy = "user", cascade = CascadeType.PERSIST) + @OneToMany(mappedBy = "users", cascade = CascadeType.PERSIST) @Setter private List termAgreements = new ArrayList<>(); - @OneToOne(mappedBy = "user", cascade = CascadeType.PERSIST) + @OneToOne(mappedBy = "users", cascade = CascadeType.PERSIST) @Setter private VerificationToken verificationToken; + @OneToMany(mappedBy = "users") + @Setter + private List subscribingList = new ArrayList<>(); + @Builder public User(String email, String password, String nickname, String phoneNumber) { this.email = email; diff --git a/mitube-app/src/main/java/com/misim/exception/MitubeErrorCode.java b/mitube-app/src/main/java/com/misim/exception/MitubeErrorCode.java index c8a69e9..fd2ce7e 100644 --- a/mitube-app/src/main/java/com/misim/exception/MitubeErrorCode.java +++ b/mitube-app/src/main/java/com/misim/exception/MitubeErrorCode.java @@ -61,8 +61,10 @@ public enum MitubeErrorCode implements ErrorCode{ INVALID_COMMENT_SCROLL_DIRECTION(HttpStatus.BAD_REQUEST, "댓글 스크롤 방향 형식에 맞지 않습니다.", 10805), INVALID_COMMENT_ID(HttpStatus.BAD_REQUEST, "댓글 식별 정보 형식에 맞지 않습니다.", 10806), - INVALID_SUBSCRIPTION_OWNER(HttpStatus.BAD_REQUEST, "채널 소유자 형식에 맞지 않습니다.", 10900), + INVALID_SUBSCRIPTION_CHANNEL(HttpStatus.BAD_REQUEST, "채널 형식에 맞지 않습니다.", 10900), INVALID_SUBSCRIPTION_SUBSCRIBER(HttpStatus.BAD_REQUEST, "구독자 형식에 맞지 않습니다.", 10901), + NOT_FOUND_CHANNEL(HttpStatus.BAD_REQUEST, "채널을 찾을 수 없습니다.", 10902), + NOT_FOUND_SUBSCRIBER(HttpStatus.BAD_REQUEST, "채널 구독자를 찾을 수 없습니다.", 10903), INVALID_REACTION_UNCHECK(HttpStatus.BAD_REQUEST, "체크되지 않은 타입을 해제하려 합니다.", 11000), INVALID_REACTION_TYPE(HttpStatus.BAD_REQUEST, "리액션 타입 형식에 맞지 않습니다.", 11001), diff --git a/mitube-app/src/main/java/com/misim/repository/ChannelRepository.java b/mitube-app/src/main/java/com/misim/repository/ChannelRepository.java new file mode 100644 index 0000000..bd50bbc --- /dev/null +++ b/mitube-app/src/main/java/com/misim/repository/ChannelRepository.java @@ -0,0 +1,9 @@ +package com.misim.repository; + +import com.misim.entity.Channel; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface ChannelRepository extends JpaRepository { +} diff --git a/mitube-app/src/main/java/com/misim/repository/SubscriptionRepository.java b/mitube-app/src/main/java/com/misim/repository/SubscriptionRepository.java index 1fb069c..d1e14a8 100644 --- a/mitube-app/src/main/java/com/misim/repository/SubscriptionRepository.java +++ b/mitube-app/src/main/java/com/misim/repository/SubscriptionRepository.java @@ -11,5 +11,5 @@ public interface SubscriptionRepository extends JpaRepository findSubscriptionsBySubscriberId(Long subscriberId); - void deleteByOwnerIdAndSubscriberId(Long ownerId, Long subscriberId); + void deleteByChannelIdAndSubscriberId(Long channelId, Long subscriberId); } diff --git a/mitube-app/src/main/java/com/misim/service/SubscriptionService.java b/mitube-app/src/main/java/com/misim/service/SubscriptionService.java index 1c902f1..a1abf21 100644 --- a/mitube-app/src/main/java/com/misim/service/SubscriptionService.java +++ b/mitube-app/src/main/java/com/misim/service/SubscriptionService.java @@ -1,11 +1,13 @@ package com.misim.service; +import com.misim.entity.Channel; import com.misim.entity.Subscription; +import com.misim.entity.User; import com.misim.exception.MitubeErrorCode; import com.misim.exception.MitubeException; +import com.misim.repository.ChannelRepository; import com.misim.repository.SubscriptionRepository; import com.misim.repository.UserRepository; -import com.misim.repository.VideoRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -15,35 +17,34 @@ public class SubscriptionService { private final SubscriptionRepository subscriptionRepository; private final UserRepository userRepository; + private final ChannelRepository channelRepository; - public void subscribing(Long ownerId, Long subscriberId) { + public void subscribing(Long channelId, Long subscriberId) { - if (!userRepository.existsById(ownerId)) { - throw new MitubeException(MitubeErrorCode.NOT_FOUND_USER); - } + Channel channel = channelRepository.findById(channelId) + .orElseThrow(() -> new MitubeException(MitubeErrorCode.NOT_FOUND_CHANNEL)); - if (!userRepository.existsById(subscriberId)) { - throw new MitubeException(MitubeErrorCode.NOT_FOUND_USER); - } + User subscriber = userRepository.findById(subscriberId) + .orElseThrow(() -> new MitubeException(MitubeErrorCode.NOT_FOUND_SUBSCRIBER)); Subscription subscription = Subscription.builder() - .ownerId(ownerId) - .subscriberId(subscriberId) + .channel(channel) + .subscriber(subscriber) .build(); subscriptionRepository.save(subscription); } - public void unsubscribing(Long ownerId, Long subscriberId) { + public void unsubscribing(Long channelId, Long subscriberId) { - if (!userRepository.existsById(ownerId)) { - throw new MitubeException(MitubeErrorCode.NOT_FOUND_USER); + if (!channelRepository.existsById(channelId)) { + throw new MitubeException(MitubeErrorCode.NOT_FOUND_CHANNEL); } if (!userRepository.existsById(subscriberId)) { - throw new MitubeException(MitubeErrorCode.NOT_FOUND_USER); + throw new MitubeException(MitubeErrorCode.NOT_FOUND_SUBSCRIBER); } - subscriptionRepository.deleteByOwnerIdAndSubscriberId(ownerId, subscriberId); + subscriptionRepository.deleteByChannelIdAndSubscriberId(channelId, subscriberId); } } From 5bc93c7fd0876a946c351a80b2e2a2bc94cad422 Mon Sep 17 00:00:00 2001 From: misim3 Date: Mon, 8 Apr 2024 13:40:03 +0900 Subject: [PATCH 11/21] =?UTF-8?q?chore:=20=EB=B0=B0=ED=8F=AC=EB=A5=BC=20?= =?UTF-8?q?=EC=9C=84=ED=95=B4=20bootJar=20=EC=83=9D=EC=84=B1=ED=95=98?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20gradle=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build.gradle b/build.gradle index 192ec89..e4eba91 100644 --- a/build.gradle +++ b/build.gradle @@ -52,3 +52,5 @@ tasks.named('bootBuildImage') { tasks.named('test') { useJUnitPlatform() } + +bootJar.mainClass = 'com.misim.MitubeAppApplication' \ No newline at end of file From 2425cab1390d7392677251d660893f3e66fbba9b Mon Sep 17 00:00:00 2001 From: misim3 Date: Mon, 8 Apr 2024 14:07:49 +0900 Subject: [PATCH 12/21] =?UTF-8?q?refactor:=20=EC=9C=A0=EC=A0=80=EC=9D=98?= =?UTF-8?q?=20=EB=B0=98=EC=9D=91=20=EC=97=94=ED=8B=B0=ED=8B=B0=EC=97=90=20?= =?UTF-8?q?=EC=97=B0=EA=B4=80=EA=B4=80=EA=B3=84=20=EC=84=A4=EC=A0=95=20?= =?UTF-8?q?=EB=B0=8F=20=EA=B4=80=EB=A0=A8=20=EA=B8=B0=EB=8A=A5=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/misim/entity/Reaction.java | 14 +++++++++----- .../com/misim/exception/MitubeErrorCode.java | 1 + .../com/misim/repository/ReactionRepository.java | 4 +++- .../java/com/misim/service/ReactionService.java | 16 +++++++++------- 4 files changed, 22 insertions(+), 13 deletions(-) diff --git a/mitube-app/src/main/java/com/misim/entity/Reaction.java b/mitube-app/src/main/java/com/misim/entity/Reaction.java index 456a6ac..8755eb0 100644 --- a/mitube-app/src/main/java/com/misim/entity/Reaction.java +++ b/mitube-app/src/main/java/com/misim/entity/Reaction.java @@ -23,15 +23,19 @@ public class Reaction { @Setter private Boolean isActive; - private Long userId; + @ManyToOne + @JoinColumn(name = "USER_ID") + private User user; - private Long videoId; + @ManyToOne + @JoinColumn(name = "VIDEO_ID") + private Video video; @Builder - public Reaction(String type, Boolean isActive, Long userId, Long videoId) { + public Reaction(String type, Boolean isActive, User user, Video video) { this.type = type; this.isActive = isActive; - this.userId = userId; - this.videoId = videoId; + this.user = user; + this.video = video; } } diff --git a/mitube-app/src/main/java/com/misim/exception/MitubeErrorCode.java b/mitube-app/src/main/java/com/misim/exception/MitubeErrorCode.java index fd2ce7e..36ad4a4 100644 --- a/mitube-app/src/main/java/com/misim/exception/MitubeErrorCode.java +++ b/mitube-app/src/main/java/com/misim/exception/MitubeErrorCode.java @@ -70,6 +70,7 @@ public enum MitubeErrorCode implements ErrorCode{ INVALID_REACTION_TYPE(HttpStatus.BAD_REQUEST, "리액션 타입 형식에 맞지 않습니다.", 11001), INVALID_REACTION_VIDEO(HttpStatus.BAD_REQUEST, "리액션 동영상 형식에 맞지 않습니다.", 11002), INVALID_REACTION_USER(HttpStatus.BAD_REQUEST, "리액션 유저 형식에 맞지 않습니다.", 11003), + NOT_FOUND_REACTION(HttpStatus.BAD_REQUEST, "리액션을 찾을 수 없습니다.", 11004), UNKNOWN_EXCEPTION(HttpStatus.INTERNAL_SERVER_ERROR, "알 수 없는 에러가 발생했습니다.", 99999),; diff --git a/mitube-app/src/main/java/com/misim/repository/ReactionRepository.java b/mitube-app/src/main/java/com/misim/repository/ReactionRepository.java index fe075b7..a4d87ec 100644 --- a/mitube-app/src/main/java/com/misim/repository/ReactionRepository.java +++ b/mitube-app/src/main/java/com/misim/repository/ReactionRepository.java @@ -4,10 +4,12 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; +import java.util.Optional; + @Repository public interface ReactionRepository extends JpaRepository { Boolean existsReactionByUserIdAndVideoId(Long userId, Long videoId); - Reaction findByUserIdAndVideoId(Long userId, Long videoId); + Optional findByUserIdAndVideoId(Long userId, Long videoId); } diff --git a/mitube-app/src/main/java/com/misim/service/ReactionService.java b/mitube-app/src/main/java/com/misim/service/ReactionService.java index 96c8330..bb7ed7f 100644 --- a/mitube-app/src/main/java/com/misim/service/ReactionService.java +++ b/mitube-app/src/main/java/com/misim/service/ReactionService.java @@ -27,11 +27,10 @@ public void checking(String type, Long userId, Long videoId) { throw new MitubeException(MitubeErrorCode.NOT_FOUND_VIDEO); } - Reaction reaction; + Reaction reaction = reactionRepository.findByUserIdAndVideoId(userId, videoId) + .orElse(null); - if (reactionRepository.existsReactionByUserIdAndVideoId(userId, videoId)) { - - reaction = reactionRepository.findByUserIdAndVideoId(userId, videoId); + if (reaction != null) { reaction.setType(type); reaction.setIsActive(true); @@ -41,8 +40,10 @@ public void checking(String type, Long userId, Long videoId) { reaction = Reaction.builder() .type(type) .isActive(true) - .userId(userId) - .videoId(videoId) + .user(userRepository.findById(userId) + .orElseThrow(() -> new MitubeException(MitubeErrorCode.NOT_FOUND_USER))) + .video(videoRepository.findById(videoId) + .orElseThrow(() -> new MitubeException(MitubeErrorCode.NOT_FOUND_VIDEO))) .build(); } @@ -63,7 +64,8 @@ public void unchecking(String type, Long userId, Long videoId) { throw new MitubeException(MitubeErrorCode.INVALID_REACTION_UNCHECK); } - Reaction reaction = reactionRepository.findByUserIdAndVideoId(userId, videoId); + Reaction reaction = reactionRepository.findByUserIdAndVideoId(userId, videoId) + .orElseThrow(() -> new MitubeException(MitubeErrorCode.NOT_FOUND_REACTION)); reaction.setType(type); reaction.setIsActive(false); From c923caaf092921606651fd74419f2571b9ddd92a Mon Sep 17 00:00:00 2001 From: misim3 Date: Mon, 8 Apr 2024 14:40:31 +0900 Subject: [PATCH 13/21] =?UTF-8?q?refactor:=20=EB=8F=99=EC=98=81=EC=83=81?= =?UTF-8?q?=20=EC=8B=9C=EC=B2=AD=20=EC=8B=9C=20=EC=9C=A0=EC=A0=80=EC=9D=98?= =?UTF-8?q?=20=ED=95=B4=EB=8B=B9=20=EB=8F=99=EC=98=81=EC=83=81=EC=97=90=20?= =?UTF-8?q?=EB=8C=80=ED=95=9C=20=EB=B0=98=EC=9D=91=20=EC=A0=95=EB=B3=B4=20?= =?UTF-8?q?=EC=A0=84=EB=8B=AC=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../model/Response/ReactionResponse.java | 14 ++++++++++ .../Response/StartWatchingVideoResponse.java | 3 ++ .../com/misim/service/ReactionService.java | 22 +++++++++++++++ .../java/com/misim/service/VideoService.java | 28 +++++++++++-------- 4 files changed, 55 insertions(+), 12 deletions(-) create mode 100644 mitube-app/src/main/java/com/misim/controller/model/Response/ReactionResponse.java diff --git a/mitube-app/src/main/java/com/misim/controller/model/Response/ReactionResponse.java b/mitube-app/src/main/java/com/misim/controller/model/Response/ReactionResponse.java new file mode 100644 index 0000000..5a8b9d2 --- /dev/null +++ b/mitube-app/src/main/java/com/misim/controller/model/Response/ReactionResponse.java @@ -0,0 +1,14 @@ +package com.misim.controller.model.Response; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; +import lombok.Data; + +@Data +@Builder +@Schema(name = "유저의 동영상에 대한 반응 응답 DTO") +public class ReactionResponse { + + @Schema(name = "type", description = "유저의 반응으로 like, dislike, null 값이 가능하다.", example = "like", requiredMode = Schema.RequiredMode.REQUIRED) + private String type; +} diff --git a/mitube-app/src/main/java/com/misim/controller/model/Response/StartWatchingVideoResponse.java b/mitube-app/src/main/java/com/misim/controller/model/Response/StartWatchingVideoResponse.java index 3c818c4..453b943 100644 --- a/mitube-app/src/main/java/com/misim/controller/model/Response/StartWatchingVideoResponse.java +++ b/mitube-app/src/main/java/com/misim/controller/model/Response/StartWatchingVideoResponse.java @@ -23,4 +23,7 @@ public class StartWatchingVideoResponse { // 비디오 전용 스토리지 private String videoLink; + + @Schema(name = "reactionResponse", description = "유저의 동영상에 대한 반응으로 로그인 상태가 아닐 시 null 값을 가진다.", example = "null", requiredMode = Schema.RequiredMode.REQUIRED) + private ReactionResponse reactionResponse; } diff --git a/mitube-app/src/main/java/com/misim/service/ReactionService.java b/mitube-app/src/main/java/com/misim/service/ReactionService.java index bb7ed7f..e88bec0 100644 --- a/mitube-app/src/main/java/com/misim/service/ReactionService.java +++ b/mitube-app/src/main/java/com/misim/service/ReactionService.java @@ -1,5 +1,6 @@ package com.misim.service; +import com.misim.controller.model.Response.ReactionResponse; import com.misim.entity.Reaction; import com.misim.exception.MitubeErrorCode; import com.misim.exception.MitubeException; @@ -9,6 +10,9 @@ import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import javax.swing.text.html.Option; +import java.util.Optional; + @Service @RequiredArgsConstructor public class ReactionService { @@ -17,6 +21,24 @@ public class ReactionService { private final UserRepository userRepository; private final VideoRepository videoRepository; + public ReactionResponse getReaction(Long userId, Long videoId) { + + if (!userRepository.existsById(userId)) { + throw new MitubeException(MitubeErrorCode.NOT_FOUND_USER); + } + + if (!videoRepository.existsById(videoId)) { + throw new MitubeException(MitubeErrorCode.NOT_FOUND_VIDEO); + } + + Optional reaction = reactionRepository.findById(userId); + + return reaction.map(r -> ReactionResponse.builder() + .type(r.getType()) + .build()) + .orElse(null); + } + public void checking(String type, Long userId, Long videoId) { if (!userRepository.existsById(userId)) { diff --git a/mitube-app/src/main/java/com/misim/service/VideoService.java b/mitube-app/src/main/java/com/misim/service/VideoService.java index bbac351..8427351 100644 --- a/mitube-app/src/main/java/com/misim/service/VideoService.java +++ b/mitube-app/src/main/java/com/misim/service/VideoService.java @@ -1,6 +1,7 @@ package com.misim.service; import com.misim.controller.model.Request.CreateVideoRequest; +import com.misim.controller.model.Response.ReactionResponse; import com.misim.controller.model.Response.StartWatchingVideoResponse; import com.misim.controller.model.Response.VideoResponse; import com.misim.entity.*; @@ -36,6 +37,7 @@ public class VideoService { private final WatchingInfoRepository watchingInfoRepository; private final SubscriptionRepository subscriptionRepository; private final ViewRepository viewRepository; + private final ReactionService reactionService; public String uploadVideos(MultipartFile file) { @@ -136,22 +138,19 @@ public StartWatchingVideoResponse startWatchingVideo (Long videoId, Long userId) videoRepository.save(video); viewRepository.save(view, video.getViews()); + WatchingInfo watchingInfo; + if (watchingInfoRepository.existsByUserIdAndVideoId(userId, videoId)) { - WatchingInfo watchingInfo = watchingInfoRepository.findByUserIdAndVideoId(userId, videoId); + watchingInfo = watchingInfoRepository.findByUserIdAndVideoId(userId, videoId); if (watchingInfo == null) { throw new MitubeException(MitubeErrorCode.NOT_FOUND_WATCHING_INFO); } - return StartWatchingVideoResponse.builder() - .watchingTime(watchingInfo.getWatchingTime()) - .views(video.getViews()) - .build(); - } else { - WatchingInfo watchingInfo = WatchingInfo.builder() + watchingInfo = WatchingInfo.builder() .videoId(videoId) .userId(userId) .watchingTime(0L) @@ -159,11 +158,16 @@ public StartWatchingVideoResponse startWatchingVideo (Long videoId, Long userId) watchingInfoRepository.save(watchingInfo); - return StartWatchingVideoResponse.builder() - .watchingTime(watchingInfo.getWatchingTime()) - .views(video.getViews()) - .build(); } + + // 로그인 상태라면, 해당 유저가 해당 동영상에 대한 반응 정보를 불러온다. + ReactionResponse reactionResponse = reactionService.getReaction(userId, videoId); + + return StartWatchingVideoResponse.builder() + .watchingTime(watchingInfo.getWatchingTime()) + .views(video.getViews()) + .reactionResponse(reactionResponse) + .build(); } public void updateWatchingVideoInfo(Long videoId, Long userId, Long watchingTime) { @@ -241,7 +245,7 @@ public List getSubscribingChannelNewVideos(Long userId) { List