캐릭터 챗봇 #338
| @@ -5,6 +5,7 @@ import kr.co.vividnext.sodalive.common.SodaException | |||||||
| import kr.co.vividnext.sodalive.member.Member | import kr.co.vividnext.sodalive.member.Member | ||||||
| import org.springframework.beans.factory.annotation.Value | import org.springframework.beans.factory.annotation.Value | ||||||
| import org.springframework.security.core.annotation.AuthenticationPrincipal | import org.springframework.security.core.annotation.AuthenticationPrincipal | ||||||
|  | import org.springframework.web.bind.annotation.DeleteMapping | ||||||
| import org.springframework.web.bind.annotation.GetMapping | import org.springframework.web.bind.annotation.GetMapping | ||||||
| import org.springframework.web.bind.annotation.PathVariable | import org.springframework.web.bind.annotation.PathVariable | ||||||
| import org.springframework.web.bind.annotation.PostMapping | import org.springframework.web.bind.annotation.PostMapping | ||||||
| @@ -79,4 +80,29 @@ class CharacterCommentController( | |||||||
|         val data = service.getReplies(imageHost, commentId, cursor, limit) |         val data = service.getReplies(imageHost, commentId, cursor, limit) | ||||||
|         ApiResponse.ok(data) |         ApiResponse.ok(data) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     @DeleteMapping("/{characterId}/comments/{commentId}") | ||||||
|  |     fun deleteComment( | ||||||
|  |         @PathVariable characterId: Long, | ||||||
|  |         @PathVariable commentId: Long, | ||||||
|  |         @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? | ||||||
|  |     ) = run { | ||||||
|  |         if (member == null) throw SodaException("로그인 정보를 확인해주세요.") | ||||||
|  |         if (member.auth == null) throw SodaException("본인인증을 하셔야 합니다.") | ||||||
|  |         service.deleteComment(characterId, commentId, member) | ||||||
|  |         ApiResponse.ok(true, "댓글이 삭제되었습니다.") | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @PostMapping("/{characterId}/comments/{commentId}/reports") | ||||||
|  |     fun reportComment( | ||||||
|  |         @PathVariable characterId: Long, | ||||||
|  |         @PathVariable commentId: Long, | ||||||
|  |         @RequestBody request: ReportCharacterCommentRequest, | ||||||
|  |         @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? | ||||||
|  |     ) = run { | ||||||
|  |         if (member == null) throw SodaException("로그인 정보를 확인해주세요.") | ||||||
|  |         if (member.auth == null) throw SodaException("본인인증을 하셔야 합니다.") | ||||||
|  |         service.reportComment(characterId, commentId, member, request.content) | ||||||
|  |         ApiResponse.ok(true, "신고가 접수되었습니다.") | ||||||
|  |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -54,3 +54,8 @@ data class CharacterCommentListResponse( | |||||||
|     val comments: List<CharacterCommentResponse>, |     val comments: List<CharacterCommentResponse>, | ||||||
|     val cursor: Long? |     val cursor: Long? | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | // 신고 Request | ||||||
|  | data class ReportCharacterCommentRequest( | ||||||
|  |     val content: String | ||||||
|  | ) | ||||||
|   | |||||||
| @@ -0,0 +1,25 @@ | |||||||
|  | package kr.co.vividnext.sodalive.chat.character.comment | ||||||
|  |  | ||||||
|  | import kr.co.vividnext.sodalive.common.BaseEntity | ||||||
|  | import kr.co.vividnext.sodalive.member.Member | ||||||
|  | import javax.persistence.Column | ||||||
|  | import javax.persistence.Entity | ||||||
|  | import javax.persistence.FetchType | ||||||
|  | import javax.persistence.JoinColumn | ||||||
|  | import javax.persistence.ManyToOne | ||||||
|  | import javax.persistence.Table | ||||||
|  |  | ||||||
|  | @Entity | ||||||
|  | @Table(name = "character_comment_report") | ||||||
|  | data class CharacterCommentReport( | ||||||
|  |     @Column(columnDefinition = "TEXT", nullable = false) | ||||||
|  |     val content: String | ||||||
|  | ) : BaseEntity() { | ||||||
|  |     @ManyToOne(fetch = FetchType.LAZY) | ||||||
|  |     @JoinColumn(name = "comment_id", nullable = false) | ||||||
|  |     var comment: CharacterComment? = null | ||||||
|  |  | ||||||
|  |     @ManyToOne(fetch = FetchType.LAZY) | ||||||
|  |     @JoinColumn(name = "member_id", nullable = false) | ||||||
|  |     var member: Member? = null | ||||||
|  | } | ||||||
| @@ -0,0 +1,5 @@ | |||||||
|  | package kr.co.vividnext.sodalive.chat.character.comment | ||||||
|  |  | ||||||
|  | import org.springframework.data.jpa.repository.JpaRepository | ||||||
|  |  | ||||||
|  | interface CharacterCommentReportRepository : JpaRepository<CharacterCommentReport, Long> | ||||||
| @@ -11,7 +11,8 @@ import java.time.ZoneId | |||||||
| @Service | @Service | ||||||
| class CharacterCommentService( | class CharacterCommentService( | ||||||
|     private val chatCharacterRepository: ChatCharacterRepository, |     private val chatCharacterRepository: ChatCharacterRepository, | ||||||
|     private val commentRepository: CharacterCommentRepository |     private val commentRepository: CharacterCommentRepository, | ||||||
|  |     private val reportRepository: CharacterCommentReportRepository | ||||||
| ) { | ) { | ||||||
|  |  | ||||||
|     private fun profileUrl(imageHost: String, profileImage: String?): String { |     private fun profileUrl(imageHost: String, profileImage: String?): String { | ||||||
| @@ -157,4 +158,27 @@ class CharacterCommentService( | |||||||
|     fun getTotalCommentCount(characterId: Long): Int { |     fun getTotalCommentCount(characterId: Long): Int { | ||||||
|         return commentRepository.countByChatCharacter_IdAndIsActiveTrue(characterId) |         return commentRepository.countByChatCharacter_IdAndIsActiveTrue(characterId) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     @Transactional | ||||||
|  |     fun deleteComment(characterId: Long, commentId: Long, member: Member) { | ||||||
|  |         val comment = commentRepository.findById(commentId).orElseThrow { SodaException("댓글을 찾을 수 없습니다.") } | ||||||
|  |         if (comment.chatCharacter?.id != characterId) throw SodaException("잘못된 요청입니다.") | ||||||
|  |         if (!comment.isActive) return | ||||||
|  |         val ownerId = comment.member?.id ?: throw SodaException("유효하지 않은 댓글입니다.") | ||||||
|  |         if (ownerId != member.id) throw SodaException("삭제 권한이 없습니다.") | ||||||
|  |         comment.isActive = false | ||||||
|  |         commentRepository.save(comment) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Transactional | ||||||
|  |     fun reportComment(characterId: Long, commentId: Long, member: Member, content: String) { | ||||||
|  |         val comment = commentRepository.findById(commentId).orElseThrow { SodaException("댓글을 찾을 수 없습니다.") } | ||||||
|  |         if (comment.chatCharacter?.id != characterId) throw SodaException("잘못된 요청입니다.") | ||||||
|  |         if (content.isBlank()) throw SodaException("신고 내용을 입력해주세요.") | ||||||
|  |  | ||||||
|  |         val report = CharacterCommentReport(content = content) | ||||||
|  |         report.comment = comment | ||||||
|  |         report.member = member | ||||||
|  |         reportRepository.save(report) | ||||||
|  |     } | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user