33import com .devkor .ifive .nadab .domain .comment .application .event .CommentCreatedEvent ;
44import com .devkor .ifive .nadab .domain .comment .application .event .SubCommentCreatedEvent ;
55import com .devkor .ifive .nadab .domain .comment .core .repository .CommentRepository ;
6+ import com .devkor .ifive .nadab .domain .moderation .core .repository .UserBlockRepository ;
67import com .devkor .ifive .nadab .domain .notification .application .NotificationCommandService ;
78import com .devkor .ifive .nadab .domain .notification .core .entity .NotificationType ;
89import com .devkor .ifive .nadab .domain .user .core .entity .User ;
1718
1819import java .util .List ;
1920import java .util .Map ;
21+ import java .util .Set ;
2022
2123@ Component
2224@ RequiredArgsConstructor
@@ -25,6 +27,7 @@ public class CommentNotificationEventListener {
2527
2628 private final UserRepository userRepository ;
2729 private final CommentRepository commentRepository ;
30+ private final UserBlockRepository userBlockRepository ;
2831 private final NotificationMessageFactory messageFactory ;
2932 private final NotificationCommandService notificationCommandService ;
3033
@@ -87,8 +90,12 @@ public void handleSubCommentCreated(SubCommentCreatedEvent event) {
8790 "commentContent" , truncate (event .getContent ())
8891 );
8992
90- // 1. 부모 댓글 작성자 알림 (author 제외, 역할 무관 최우선)
91- if (!event .getAuthorId ().equals (event .getParentCommentAuthorId ())) {
93+ Set <Long > blockedByAuthor = Set .copyOf (
94+ userBlockRepository .findBlockedUserIdsBidirectional (event .getAuthorId ()));
95+
96+ // 1. 부모 댓글 작성자 알림 (author 제외, 역할 무관 최우선,차단 관계이면 skip)
97+ if (!event .getAuthorId ().equals (event .getParentCommentAuthorId ())
98+ && !blockedByAuthor .contains (event .getParentCommentAuthorId ())) {
9299 User parentCommentAuthor = userRepository .findById (event .getParentCommentAuthorId ()).orElse (null );
93100 if (parentCommentAuthor == null || parentCommentAuthor .getDeletedAt () != null ) {
94101 log .debug ("Parent comment author not found or deleted, skip notification: parentCommentAuthorId={}" , event .getParentCommentAuthorId ());
@@ -141,20 +148,49 @@ public void handleSubCommentCreated(SubCommentCreatedEvent event) {
141148 }
142149 }
143150
144- NotificationContent participantContent = messageFactory .createMessage (
145- NotificationType .REPLY_ON_PARTICIPATED_COMMENT , params );
146- for (Long participantId : participantIds ) {
147- notificationCommandService .sendNotification (
148- participantId ,
149- NotificationType .REPLY_ON_PARTICIPATED_COMMENT ,
150- participantContent .title (),
151- participantContent .body (),
152- participantContent .inboxMessage (),
153- event .getDailyReportId ().toString (),
154- String .format ("COMMENT_%d_PARTICIPANT_%d" , event .getSubCommentId (), participantId )
155- );
151+ // 4. 참여자 알림
152+ if (!participantIds .isEmpty ()) {
153+ if (!event .isSecret () || event .isParentSecret ()) {
154+ // 공개 대댓글 or 비밀 부모 아래 대댓글: 참여자들 열람 가능 — 차단 관계 제외
155+ List <Long > notifiableParticipantIds = participantIds .stream ()
156+ .filter (id -> !blockedByAuthor .contains (id ))
157+ .toList ();
158+ if (!notifiableParticipantIds .isEmpty ()) {
159+ NotificationContent participantContent = messageFactory .createMessage (
160+ NotificationType .REPLY_ON_PARTICIPATED_COMMENT , params );
161+ for (Long participantId : notifiableParticipantIds ) {
162+ notificationCommandService .sendNotification (
163+ participantId ,
164+ NotificationType .REPLY_ON_PARTICIPATED_COMMENT ,
165+ participantContent .title (),
166+ participantContent .body (),
167+ participantContent .inboxMessage (),
168+ event .getDailyReportId ().toString (),
169+ String .format ("COMMENT_%d_PARTICIPANT_%d" , event .getSubCommentId (), participantId )
170+ );
171+ }
172+ log .debug ("Sub-comment notifications sent: subCommentId={}, participantCount={}" , event .getSubCommentId (), notifiableParticipantIds .size ());
173+ }
174+ } else if (reportOwnerIsParticipant && !reportOwnerIsAuthor
175+ && !blockedByAuthor .contains (event .getReportOwnerId ())) {
176+ // 공개 부모 댓글에 달린 비밀 대댓글 : 일반 참여자는 열람 불가하지만 리포트 당사자는 가능
177+ User reportOwner = userRepository .findById (event .getReportOwnerId ()).orElse (null );
178+ if (reportOwner != null && reportOwner .getDeletedAt () == null ) {
179+ NotificationContent participantContent = messageFactory .createMessage (
180+ NotificationType .REPLY_ON_PARTICIPATED_COMMENT , params );
181+ notificationCommandService .sendNotification (
182+ event .getReportOwnerId (),
183+ NotificationType .REPLY_ON_PARTICIPATED_COMMENT ,
184+ participantContent .title (),
185+ participantContent .body (),
186+ participantContent .inboxMessage (),
187+ event .getDailyReportId ().toString (),
188+ String .format ("COMMENT_%d_PARTICIPANT_%d" , event .getSubCommentId (), event .getReportOwnerId ())
189+ );
190+ log .debug ("Sub-comment notification sent to report owner (participant): subCommentId={}" , event .getSubCommentId ());
191+ }
192+ }
156193 }
157- log .debug ("Sub-comment notifications sent: subCommentId={}, participantCount={}" , event .getSubCommentId (), participantIds .size ());
158194 } catch (Exception e ) {
159195 log .error ("Failed to handle SubCommentCreatedEvent: subCommentId={}, error={}" ,
160196 event .getSubCommentId (), e .getMessage (), e );
0 commit comments