Skip to content

Commit

Permalink
[feat] 운영서버 3차 스프린트 반영
Browse files Browse the repository at this point in the history
  • Loading branch information
bo-ram-bo-ram committed May 30, 2024
2 parents f2a36b1 + 04246c7 commit f0f5c5a
Show file tree
Hide file tree
Showing 18 changed files with 561 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,66 +14,97 @@
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.security.Principal;
import org.springframework.web.multipart.MultipartFile;

import static com.dontbe.www.DontBeServer.common.response.SuccessStatus.*;

@RestController
@RequestMapping("/api/v1/")
@RequestMapping("/api/")
@RequiredArgsConstructor
@SecurityRequirement(name = "JWT Auth")
@Tag(name="답글 관련",description = "Comment Api Document")
public class CommentController {
private final CommentCommendService commentCommendService;
private final CommentQueryService commentQueryService;

@PostMapping("content/{contentId}/comment")
@PostMapping("v1/content/{contentId}/comment")
@Operation(summary = "답글 작성 API입니다.", description = "CommentPost")
public ResponseEntity<ApiResponse<Object>> postComment(Principal principal, @PathVariable Long contentId, @Valid @RequestBody CommentPostRequestDto commentPostRequestDto) {
commentCommendService.postComment(MemberUtil.getMemberId(principal),contentId, commentPostRequestDto);
return ApiResponse.success(POST_COMMENT_SUCCESS);
}
@DeleteMapping("comment/{commentId}")

@PostMapping("v2/content/{contentId}/comment")
@Operation(summary = "사진 첨부 기능이 추가된 답글 작성 API입니다.", description = "Comment Post +CommentImage")
public ResponseEntity<ApiResponse<Object>> postComment2(Principal principal, @PathVariable Long contentId,
@RequestPart(value = "image", required = false) MultipartFile commentImage,
@Valid @RequestPart(value="text") CommentPostRequestDto commentPostRequestDto) {
commentCommendService.postCommentVer2(MemberUtil.getMemberId(principal),contentId, commentImage, commentPostRequestDto);
return ApiResponse.success(POST_COMMENT_SUCCESS);
}

@DeleteMapping("v1/comment/{commentId}")
@Operation(summary = "답글 삭제 API입니다.", description = "CommentDelete")
public ResponseEntity<ApiResponse<Object>> deleteComment(Principal principal, @PathVariable Long commentId){ //작성자ID와 댓글ID가 같아야 함
commentCommendService.deleteComment(MemberUtil.getMemberId(principal),commentId);
return ApiResponse.success(DELETE_COMMENT_SUCCESS);
}
@PostMapping("comment/{commentId}/liked")

@PostMapping("v1/comment/{commentId}/liked")
@Operation(summary = "답글 좋아요 API입니다.", description = "CommentLiked")
public ResponseEntity<ApiResponse<Object>> likeComment(Principal principal, @PathVariable Long commentId, @Valid @RequestBody CommentLikedRequestDto commentLikedRequestDto) {
Long memberId = MemberUtil.getMemberId(principal);
commentCommendService.likeComment(memberId, commentId, commentLikedRequestDto);
return ApiResponse.success(COMMENT_LIKE_SUCCESS);
}
@DeleteMapping("comment/{commentId}/unliked")

@DeleteMapping("v1/comment/{commentId}/unliked")
@Operation(summary = "답글 좋아요 취소 API 입니다.", description = "CommentUnlike")
public ResponseEntity<ApiResponse<Object>> unlikeComment(Principal principal,@PathVariable Long commentId) {
Long memberId = MemberUtil.getMemberId(principal);
commentCommendService.unlikeComment(memberId, commentId);
return ApiResponse.success(COMMENT_UNLIKE_SUCCESS);
}
@GetMapping("content/{contentId}/comment/all") //페이지네이션 적용 후 지우기

@GetMapping("v1/content/{contentId}/comment/all") //페이지네이션 적용 후 지우기
@Operation(summary = "게시물에 해당하는 답글 리스트 조회 API 입니다.", description = "CommentByContent")
public ResponseEntity<ApiResponse<Object>> getCommentAll(Principal principal, @PathVariable Long contentId){
Long memberId = MemberUtil.getMemberId(principal);
return ApiResponse.success(GET_COMMENT_ALL_SUCCESS, commentQueryService.getCommentAll(memberId, contentId));
}
@GetMapping("member/{memberId}/comments") //페이지네이션 적용 후 지우기

@GetMapping("v1/member/{memberId}/comments") //페이지네이션 적용 후 지우기
@Operation(summary = "멤버에 해당하는 답글 리스트 조회 API 입니다.", description = "CommentByMember")
public ResponseEntity<ApiResponse<Object>> getMemberComment(Principal principal, @PathVariable Long memberId){
Long usingMemberId = MemberUtil.getMemberId(principal);
return ApiResponse.success(GET_MEMBER_COMMENT_SECCESS, commentQueryService.getMemberComment(usingMemberId,memberId));
}

@Operation(summary = "페이지네이션이 적용된 게시물에 해당하는 답글 리스트 조회 API 입니다.", description = "CommentByContentPagination")
@GetMapping("content/{contentId}/comments")
@GetMapping("v1/content/{contentId}/comments")
public ResponseEntity<ApiResponse<Object>> getCommentAllPagination(Principal principal, @PathVariable Long contentId, @RequestParam(value = "cursor") Long cursor){ //cursor= last commentId
Long memberId = MemberUtil.getMemberId(principal);
return ApiResponse.success(GET_COMMENT_ALL_SUCCESS, commentQueryService.getCommentAllPagination(memberId, contentId, cursor));
}

@Operation(summary = "게시물에 해당하는 답글 리스트 조회 API(+페이지네이션+이미지) 입니다.", description = "Comments By Content With Image")
@GetMapping("v2/content/{contentId}/comments")
public ResponseEntity<ApiResponse<Object>> getCommentAllWithImage(Principal principal, @PathVariable Long contentId, @RequestParam(value = "cursor") Long cursor){ //cursor= last commentId
Long memberId = MemberUtil.getMemberId(principal);
return ApiResponse.success(GET_COMMENT_ALL_SUCCESS, commentQueryService.getCommentAllWithImage(memberId, contentId, cursor));
}

@Operation(summary = "페이지네이션이 적용된 멤버에 해당하는 답글 리스트 조회 API 입니다.", description = "CommentByMemberPagination")
@GetMapping("member/{memberId}/member-comments")
@GetMapping("v1/member/{memberId}/member-comments")
public ResponseEntity<ApiResponse<Object>> getMemberCommentPagination(Principal principal, @PathVariable Long memberId, @RequestParam(value = "cursor") Long cursor){
Long usingMemberId = MemberUtil.getMemberId(principal);
return ApiResponse.success(GET_MEMBER_COMMENT_SECCESS, commentQueryService.getMemberCommentPagination(usingMemberId,memberId,cursor));
}

@Operation(summary = "멤버에 해당하는 답글 리스트 조회 API(+페이지네이션+이미지) 입니다.", description = "Comments By Member With Image")
@GetMapping("v2/member/{memberId}/comments")
public ResponseEntity<ApiResponse<Object>> getCommentAllByMemberWithImage(Principal principal, @PathVariable Long memberId, @RequestParam(value = "cursor") Long cursor){
Long usingMemberId = MemberUtil.getMemberId(principal);
return ApiResponse.success(GET_MEMBER_COMMENT_SECCESS, commentQueryService.getCommentAllByMemberWithImage(usingMemberId,memberId,cursor));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ public class Comment extends BaseTimeEntity {

private String commentText;

@Column(columnDefinition = "NULL")
private String commentImage;

@Column(name = "is_deleted", columnDefinition = "BOOLEAN DEFAULT false")
private boolean isDeleted;

Expand All @@ -49,6 +52,9 @@ public Comment(Member member, Content content, String commentText) {
this.content = content;
this.commentText = commentText;
}
public void setCommentImage(String commentImageUrl) {
this.commentImage = commentImageUrl;
}

public void softDelete() {
this.isDeleted = true;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.dontbe.www.DontBeServer.api.comment.dto.response;

import com.dontbe.www.DontBeServer.api.comment.domain.Comment;
import com.dontbe.www.DontBeServer.api.member.domain.Member;
import com.dontbe.www.DontBeServer.common.util.TimeUtilCustom;

public record CommentAllByMemberResponseDtoVer2(
long memberId, // 답글 작성자 Id
String memberProfileUrl, // 작성자 프로필 사진url
String memberNickname, // 답글 작성자 닉네임
Boolean isLiked, // 유저가 답글에 대해 좋아요를 눌렀는지
Boolean isGhost, //답글 작성자를 투명도 처리 했는지
int memberGhost, // 답글 작성자의 전체 투명도
int commentLikedNumber, // 답글 좋아요 개수
String commentText, // 답글 내용
String time, //답글이 작성된 시간 (년-월-일 시:분:초)
long commentId, //댓글 Id
long contentId , // 해당 댓글이 적힌 게시물 Id
String commentImageUrl
) {
public static CommentAllByMemberResponseDtoVer2 of(Member writerMember, boolean isLiked, boolean isGhost,
int memberGhost, int commentLikedNumber, Comment comment){
return new CommentAllByMemberResponseDtoVer2(
writerMember.getId() ,
writerMember.getProfileUrl(),
writerMember.getNickname(),
isLiked,
isGhost,
memberGhost,
commentLikedNumber,
comment.getCommentText(),
TimeUtilCustom.refineTime(comment.getCreatedAt()),
comment.getId(),
comment.getContent().getId(),
comment.getCommentImage()
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.dontbe.www.DontBeServer.api.comment.dto.response;

import com.dontbe.www.DontBeServer.api.member.domain.Member;

public record CommentAllResponseDtoVer3(
Long commentId, //답글 고유 id
Long memberId, // 댓글 작성자 Id
String memberProfileUrl, //작성자 프로필 사진url
String memberNickname, //댓글 작성자 닉네임
Boolean isGhost, //현재 유저가 작성자에 대해 투명도 처리를 했는지
int memberGhost, //작성자의 전체 투명도
Boolean isLiked, //유저가 게시물에 대해 좋아요를 눌렀는지
int commentLikedNumber, //댓글의 좋아요 개수
String commentText, //댓글 내용
String time, //답글이 작성된 시간을 (년-월-일 시:분:초)
Boolean isDeleted, // 댓글 작성자가 탈퇴한 회원인지 아닌지
String commentImageUrl
) {
public static CommentAllResponseDtoVer3 of(Long commentId, Member writerMember, boolean isGhost, int memberGhost
, boolean isLiked, String time, int likedNumber, String commentText, String commentImageUrl){
return new CommentAllResponseDtoVer3(
commentId,
writerMember.getId(),
writerMember.getProfileUrl(),
writerMember.getNickname(),
isGhost,
memberGhost,
isLiked,
likedNumber,
commentText,
time,
writerMember.isDeleted(),
commentImageUrl
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,12 @@
import com.dontbe.www.DontBeServer.common.exception.BadRequestException;
import com.dontbe.www.DontBeServer.common.response.ErrorStatus;
import com.dontbe.www.DontBeServer.common.util.GhostUtil;
import com.dontbe.www.DontBeServer.external.s3.service.S3Service;
import java.io.IOException;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

@Service
@RequiredArgsConstructor
Expand All @@ -28,6 +31,8 @@ public class CommentCommendService {
private final MemberRepository memberRepository;
private final CommentLikedRepository commentLikedRepository;
private final NotificationRepository notificationRepository;
private final S3Service s3Service;
private static final String POST_IMAGE_FOLDER_NAME = "contents/";

public void postComment(Long memberId, Long contentId, CommentPostRequestDto commentPostRequestDto){
Content content = contentRepository.findContentByIdOrThrow(contentId); // 게시물id 잘못됐을 때 에러
Expand Down Expand Up @@ -59,6 +64,46 @@ public void postComment(Long memberId, Long contentId, CommentPostRequestDto com
}
}

public void postCommentVer2(Long memberId, Long contentId, MultipartFile commentImage, CommentPostRequestDto commentPostRequestDto){
Content content = contentRepository.findContentByIdOrThrow(contentId);
Member usingMember = memberRepository.findMemberByIdOrThrow(memberId);

GhostUtil.isGhostMember(usingMember.getMemberGhost());

Comment comment = Comment.builder()
.member(usingMember)
.content(content)
.commentText(commentPostRequestDto.commentText())
.build();
Comment savedComment = commentRepository.save(comment);

if(commentImage != null){ //이미지를 업로드 했다면
try {
final String commentImageUrl = s3Service.uploadImage2(POST_IMAGE_FOLDER_NAME+contentId.toString()
+"/comments/"+comment.getId().toString()+"/", commentImage);
comment.setCommentImage(commentImageUrl);
} catch (IOException e) {
throw new RuntimeException(e.getMessage());
}
}

//답글 작성 시 게시물 작상자에게 알림 발생
Member contentWritingMember = memberRepository.findMemberByIdOrThrow(content.getMember().getId());

if(usingMember != contentWritingMember){ ////자신 게시물에 대한 좋아요 누르면 알림 발생 x
//노티 엔티티와 연결
Notification notification = Notification.builder()
.notificationTargetMember(contentWritingMember)
.notificationTriggerMemberId(usingMember.getId())
.notificationTriggerType(commentPostRequestDto.notificationTriggerType())
.notificationTriggerId(comment.getId()) //에러수정을 위한 notificationTriggerId에 답글id 저장, 알림 조회시 답글id로 게시글id 반환하도록하기
.isNotificationChecked(false)
.notificationText(comment.getCommentText())
.build();
Notification savedNotification = notificationRepository.save(notification);
}
}

public void deleteComment(Long memberId, Long commentId) {
deleteValidate(memberId, commentId);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

import com.dontbe.www.DontBeServer.api.comment.domain.Comment;
import com.dontbe.www.DontBeServer.api.comment.dto.response.CommentAllByMemberResponseDto;
import com.dontbe.www.DontBeServer.api.comment.dto.response.CommentAllByMemberResponseDtoVer2;
import com.dontbe.www.DontBeServer.api.comment.dto.response.CommentAllResponseDto;
import com.dontbe.www.DontBeServer.api.comment.dto.response.CommentAllResponseDtoVer2;
import com.dontbe.www.DontBeServer.api.comment.dto.response.CommentAllResponseDtoVer3;
import com.dontbe.www.DontBeServer.api.comment.repository.CommentLikedRepository;
import com.dontbe.www.DontBeServer.api.comment.repository.CommentRepository;
import com.dontbe.www.DontBeServer.api.content.repository.ContentRepository;
Expand Down Expand Up @@ -85,6 +87,27 @@ public List<CommentAllResponseDtoVer2> getCommentAllPagination(Long memberId, Lo
.collect(Collectors.toList());
}

public List<CommentAllResponseDtoVer3> getCommentAllWithImage(Long memberId, Long contentId, Long cursor) {
contentRepository.findContentByIdOrThrow(contentId);
PageRequest pageRequest = PageRequest.of(0, COMMENT_DEFAULT_PAGE_SIZE);
Slice<Comment> commentList;

commentList = commentRepository.findCommentsByContentNextPage(cursor, contentId, pageRequest);

return commentList.stream()
.map(oneComment -> CommentAllResponseDtoVer3.of(
oneComment.getId(),
memberRepository.findMemberByIdOrThrow(oneComment.getMember().getId()),
checkGhost(memberId, oneComment.getId()),
checkMemberGhost(oneComment.getId()),
checkLikedComment(memberId,oneComment.getId()),
TimeUtilCustom.refineTime(oneComment.getCreatedAt()),
likedNumber(oneComment.getId()),
oneComment.getCommentText(),
oneComment.getCommentImage()))
.collect(Collectors.toList());
}

public List<CommentAllByMemberResponseDto> getMemberCommentPagination(Long principalId, Long memberId, Long cursor) {
memberRepository.findMemberByIdOrThrow(memberId);

Expand All @@ -108,6 +131,29 @@ public List<CommentAllByMemberResponseDto> getMemberCommentPagination(Long princ
).collect(Collectors.toList());
}

public List<CommentAllByMemberResponseDtoVer2> getCommentAllByMemberWithImage(Long principalId, Long memberId, Long cursor) {
memberRepository.findMemberByIdOrThrow(memberId);

PageRequest pageRequest = PageRequest.of(0, COMMENT_DEFAULT_PAGE_SIZE);
Slice<Comment> commentList;

if (cursor==-1) {
commentList = commentRepository.findCommentsTop15ByMemberIdOrderByCreatedAtDesc(memberId, pageRequest);
} else {
commentList = commentRepository.findCommentsByMemberNextPage(cursor, memberId, pageRequest);
}

return commentList.stream()
.map(oneComment -> CommentAllByMemberResponseDtoVer2.of(
memberRepository.findMemberByIdOrThrow(memberId),
checkLikedComment(principalId, oneComment.getId()),
checkGhost(principalId, oneComment.getId()),
checkMemberGhost(oneComment.getId()),
likedNumber(oneComment.getId()),
oneComment)
).collect(Collectors.toList());
}

private boolean checkGhost(Long usingMemberId, Long commentId) {
Member writerMember = commentRepository.findCommentByIdOrThrow(commentId).getMember();
return ghostRepository.existsByGhostTargetMemberIdAndGhostTriggerMemberId(writerMember.getId(), usingMemberId);
Expand Down
Loading

0 comments on commit f0f5c5a

Please sign in to comment.