| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105 |
- using Application.Abstractions.Data;
- using Application.Abstractions.Messaging;
- using Application.Abstractions.Notification;
- using Domain.Entities.Notifications.ValueObject;
- using Microsoft.EntityFrameworkCore;
- using SharedKernel.Results;
- namespace Application.Features.Api.Note.GetDetail;
- internal sealed class Handler(
- IAppDbContext db,
- INotificationService notification
- ) : IQueryHandler<Query, Result<Response>>
- {
- public async Task<Result<Response>> Handle(Query r, CancellationToken ct)
- {
- // 받은쪽지(receiver 본인) 또는 보낸쪽지(sender 본인) 둘 다 조회 허용
- var note = await db.Note
- .Where(n => n.ID == r.NoteID && (
- (n.ReceiverMemberID == r.CurrentMemberID && !n.IsDeletedByReceiver) ||
- (n.SenderMemberID == r.CurrentMemberID && !n.IsDeletedBySender)
- ))
- .FirstOrDefaultAsync(ct);
- if (note is null)
- {
- return Result.Failure<Response>(Error.NotFound("Note.NotFound", "쪽지를 찾을 수 없습니다."));
- }
- var isReceiverView = note.ReceiverMemberID == r.CurrentMemberID;
- var wasUnread = !note.IsRead;
- // receiver 본인이 처음 조회한 경우만 읽음 처리
- if (isReceiverView && wasUnread)
- {
- note.MarkRead();
- await db.SaveChangesAsync(ct);
- }
- // 발신자 정보 + 채널 (시스템 쪽지면 sender=0 → null)
- var sender = note.SenderMemberID > 0
- ? await db.Member.AsNoTracking()
- .Where(m => m.ID == note.SenderMemberID)
- .Select(m => new {
- m.Name, m.Thumb, m.SID,
- ChannelName = m.Channel != null ? m.Channel.Name : null,
- ChannelHandle = m.Channel != null ? m.Channel.Handle : null
- })
- .FirstOrDefaultAsync(ct)
- : null;
- // 수신자 정보 + 채널
- var receiver = await db.Member.AsNoTracking()
- .Where(m => m.ID == note.ReceiverMemberID)
- .Select(m => new {
- m.Name, m.Thumb, m.SID,
- ChannelName = m.Channel != null ? m.Channel.Name : null,
- ChannelHandle = m.Channel != null ? m.Channel.Handle : null
- })
- .FirstOrDefaultAsync(ct);
- // 처음 읽었고 일반 쪽지면 발신자에게 NoteRead 알림 (receiver 본인 조회 시에만)
- if (isReceiverView && wasUnread && !note.IsSystem && note.SenderMemberID > 0)
- {
- // 채널명 > 회원 별명, 보조 @handle / #sid
- var primary = receiver?.ChannelName ?? receiver?.Name ?? "알 수 없는 회원";
- var secondary = !string.IsNullOrEmpty(receiver?.ChannelHandle)
- ? $"@{receiver.ChannelHandle}"
- : (!string.IsNullOrEmpty(receiver?.SID) ? $"#{receiver.SID}" : null);
- var receiverDisplay = secondary is null ? primary : $"{primary} ({secondary})";
- await notification.SendAsync(
- note.SenderMemberID,
- NotificationType.NoteRead,
- "쪽지를 읽었습니다",
- $"{receiverDisplay}님이 \"{note.Title}\" 쪽지를 읽었습니다.",
- actionUrl: null,
- relatedType: "Note",
- relatedID: note.ID,
- ct: ct
- );
- }
- return Result.Success(new Response(
- note.ID,
- note.IsSystem ? null : note.SenderMemberID,
- note.IsSystem ? "시스템" : sender?.Name,
- note.IsSystem ? null : sender?.Thumb,
- note.IsSystem ? null : sender?.SID,
- note.IsSystem ? null : sender?.ChannelName,
- note.IsSystem ? null : sender?.ChannelHandle,
- note.ReceiverMemberID,
- receiver?.Name,
- receiver?.Thumb,
- receiver?.SID,
- receiver?.ChannelName,
- receiver?.ChannelHandle,
- note.Title,
- note.Content,
- note.IsSystem,
- note.IsRead,
- note.CreatedAt
- ));
- }
- }
|