Send.cs 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. using Application.Abstractions.Hub;
  2. using Infrastructure.Hubs;
  3. using Web.Api.Common;
  4. using Web.Api.Extensions;
  5. using MediatR;
  6. using Microsoft.AspNetCore.SignalR;
  7. using Microsoft.EntityFrameworkCore;
  8. using System.Security.Claims;
  9. namespace Web.Api.Endpoints.Donation;
  10. /// <summary>후원 전송</summary>
  11. internal sealed class Send : IEndpoint
  12. {
  13. public void MapEndpoint(IEndpointRouteBuilder app)
  14. {
  15. /// 후원 전송 (지갑 차감 → Donation 생성 → 알림 큐 → SignalR 브로드캐스트)
  16. app.MapPost("api/donation/send", async (
  17. Application.Features.Api.Donation.Send.Command body,
  18. ClaimsPrincipal user,
  19. ISender sender,
  20. IHubContext<AppHub, IAppHubClient> appHub,
  21. IHubContext<DonationHub, IDonationHubClient> donationHub,
  22. Application.Abstractions.Data.IAppDbContext db,
  23. CancellationToken ct
  24. ) => {
  25. var memberID = user.GetRequiredMemberID();
  26. var command = body with { SponsorMemberID = memberID };
  27. var data = await sender.Send(command, ct);
  28. // 크루 세션 후원인 경우 추가 브로드캐스트
  29. if (body.CrewSessionID.HasValue && body.CrewMemberID.HasValue)
  30. {
  31. // 크루 순위 업데이트 → DonationHub (OBS 위젯)
  32. var rankData = await sender.Send(
  33. new Application.Features.Api.Crew.GetCrewRanking.Query(body.CrewSessionID.Value), ct
  34. );
  35. // 채널의 widgetToken 조회
  36. var channelID = body.ChannelID > 0 ? body.ChannelID :
  37. (body.ChannelSID != null ?
  38. await db.Channel.AsNoTracking().Where(c => c.SID == body.ChannelSID).Select(c => c.ID).FirstOrDefaultAsync(ct) : 0);
  39. var widgetToken = await db.Channel.AsNoTracking()
  40. .Where(c => c.ID == channelID).Select(c => c.WidgetToken).FirstOrDefaultAsync(ct);
  41. if (!string.IsNullOrEmpty(widgetToken))
  42. {
  43. await donationHub.Clients.Group(widgetToken).ReceiveCrewUpdate(new
  44. {
  45. rankData.List,
  46. rankData.TotalAmount
  47. });
  48. }
  49. // 크루원에게 토스트 알림 → AppHub
  50. var crewMember = await db.CrewMember.AsNoTracking()
  51. .Where(m => m.ID == body.CrewMemberID.Value).FirstOrDefaultAsync(ct);
  52. if (crewMember is not null)
  53. {
  54. await appHub.Clients.Group($"member:{crewMember.MemberID}").ReceiveCrewToast(new
  55. {
  56. SendName = body.SendName,
  57. Amount = body.Amount,
  58. Message = body.Message,
  59. CrewMemberNickname = crewMember.Nickname
  60. });
  61. }
  62. }
  63. return ApiResponse.Ok(data);
  64. })
  65. .WithTags("Donation")
  66. .RequireAuthorization();
  67. }
  68. }