-
-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
(#412) notifications: update post updated event hadnler
- Loading branch information
1 parent
8aa77fd
commit 1ef338e
Showing
1 changed file
with
69 additions
and
125 deletions.
There are no files selected for viewing
194 changes: 69 additions & 125 deletions
194
...e.Services.Notifications.Application/Events/External/Posts/Handlers/PostUpdatedHandler.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,202 +1,146 @@ | ||
using System; | ||
using System.Linq; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using Convey.CQRS.Events; | ||
using Microsoft.AspNetCore.SignalR; | ||
using Microsoft.Extensions.Logging; | ||
using MiniSpace.Services.Notifications.Application.Dto; | ||
using MiniSpace.Services.Notifications.Application.Hubs; | ||
using MiniSpace.Services.Notifications.Application.Services.Clients; | ||
using MiniSpace.Services.Notifications.Core.Entities; | ||
using MiniSpace.Services.Notifications.Core.Repositories; | ||
using MiniSpace.Services.Notifications.Application.Services; | ||
using MiniSpace.Services.Notifications.Core.Entities; | ||
using MiniSpace.Services.Notifications.Application.Dto; | ||
using MiniSpace.Services.Notifications.Application.Dto.Events; | ||
using MiniSpace.Services.Notifications.Application.Dto.Posts; | ||
using MiniSpace.Services.Notifications.Application.Services; | ||
using Microsoft.AspNetCore.SignalR; | ||
using MiniSpace.Services.Notifications.Application.Hubs; | ||
using Microsoft.Extensions.Logging; | ||
|
||
namespace MiniSpace.Services.Notifications.Application.Events.External.Handlers | ||
{ | ||
public class PostUpdatedHandler : IEventHandler<PostUpdated> | ||
{ | ||
private readonly IMessageBroker _messageBroker; | ||
private readonly IUserNotificationsRepository _studentNotificationsRepository; | ||
private readonly IEventsServiceClient _eventsServiceClient; | ||
private readonly IPostsServiceClient _postsServiceClient; | ||
private readonly IStudentsServiceClient _studentsServiceClient; | ||
private readonly IFriendsServiceClient _friendsServiceClient; | ||
private readonly IOrganizationsServiceClient _organizationsServiceClient; | ||
private readonly IUserNotificationsRepository _userNotificationsRepository; | ||
private readonly IHubContext<NotificationHub> _hubContext; | ||
private readonly ILogger<PostUpdatedHandler> _logger; | ||
|
||
public PostUpdatedHandler( | ||
IMessageBroker messageBroker, | ||
IUserNotificationsRepository studentNotificationsRepository, | ||
IEventsServiceClient eventsServiceClient, | ||
IPostsServiceClient postsServiceClient, | ||
IStudentsServiceClient studentsServiceClient, | ||
IFriendsServiceClient friendsServiceClient, | ||
IOrganizationsServiceClient organizationsServiceClient, | ||
IUserNotificationsRepository userNotificationsRepository, | ||
IHubContext<NotificationHub> hubContext, | ||
ILogger<PostUpdatedHandler> logger) | ||
{ | ||
_messageBroker = messageBroker; | ||
_studentNotificationsRepository = studentNotificationsRepository; | ||
_eventsServiceClient = eventsServiceClient; | ||
_postsServiceClient = postsServiceClient; | ||
_studentsServiceClient = studentsServiceClient; | ||
_friendsServiceClient = friendsServiceClient; | ||
_organizationsServiceClient = organizationsServiceClient; | ||
_userNotificationsRepository = userNotificationsRepository; | ||
_hubContext = hubContext; | ||
_logger = logger; | ||
} | ||
|
||
public async Task HandleAsync(PostUpdated eventArgs, CancellationToken cancellationToken) | ||
{ | ||
var post = await _postsServiceClient.GetPostAsync(eventArgs.PostId); | ||
if (post == null) | ||
if (!eventArgs.ShouldNotify) | ||
{ | ||
_logger.LogError("Post not found."); | ||
_logger.LogInformation("PostUpdated event received, but notifications are disabled."); | ||
return; | ||
} | ||
|
||
var eventDetails = await _eventsServiceClient.GetEventAsync(post.EventId); | ||
if (eventDetails == null) | ||
if (eventArgs.UserId.HasValue) | ||
{ | ||
_logger.LogError("Event not found for the post."); | ||
return; | ||
await NotifyFriendsAndFollowersAsync(eventArgs); | ||
} | ||
|
||
var eventParticipants = await _eventsServiceClient.GetParticipantsAsync(post.EventId); | ||
if (eventParticipants == null) | ||
else if (eventArgs.OrganizationId.HasValue) | ||
{ | ||
_logger.LogError("No participants found for the event."); | ||
return; | ||
await NotifyOrganizationMembersAsync(eventArgs); | ||
} | ||
} | ||
|
||
foreach (var studentParticipant in eventParticipants.InterestedStudents) | ||
private async Task NotifyFriendsAndFollowersAsync(PostUpdated eventArgs) | ||
{ | ||
try | ||
{ | ||
var student = await _studentsServiceClient.GetAsync(studentParticipant.StudentId); | ||
if (student != null) | ||
// Get the user's friends | ||
var friends = await _friendsServiceClient.GetFriendsAsync(eventArgs.UserId.Value); | ||
var friendIds = friends.Select(f => f.FriendId).ToList(); | ||
|
||
// Get the user's followers | ||
var followers = await _friendsServiceClient.GetRequestsAsync(eventArgs.UserId.Value); | ||
var followerIds = followers.Select(f => f.InviterId).ToList(); | ||
|
||
// Combine friends and followers into one list of user IDs to notify | ||
var userIdsToNotify = friendIds.Concat(followerIds).Distinct().ToList(); | ||
|
||
foreach (var userId in userIdsToNotify) | ||
{ | ||
await NotifyStudent(student, eventDetails, post); | ||
var notificationMessage = $"An updated post has been created by your friend or someone you follow (Post ID: {eventArgs.PostId})."; | ||
await CreateAndSendNotification(userId, eventArgs, notificationMessage); | ||
} | ||
} | ||
|
||
foreach (var studentParticipant in eventParticipants.SignedUpStudents) | ||
catch (Exception ex) | ||
{ | ||
var student = await _studentsServiceClient.GetAsync(studentParticipant.StudentId); | ||
if (student != null) | ||
{ | ||
await NotifyStudent(student, eventDetails, post); | ||
} | ||
_logger.LogError($"Failed to notify user's friends and followers: {ex.Message}"); | ||
} | ||
|
||
// Notify the organizer | ||
await NotifyOrganizer(eventDetails.Organizer, eventDetails, post); | ||
} | ||
|
||
private async Task NotifyStudent(UserDto student, EventDto eventDetails, PostDto post) | ||
private async Task NotifyOrganizationMembersAsync(PostUpdated eventArgs) | ||
{ | ||
var notificationMessage = $"An updated post is available for an event you are interested in: '{eventDetails.Name}'."; | ||
var detailsHtml = $"<p>{notificationMessage} Check out the updated post details here: {post.TextContent}</p>"; | ||
|
||
var notification = new Notification( | ||
notificationId: Guid.NewGuid(), | ||
userId: student.Id, | ||
message: notificationMessage, | ||
status: NotificationStatus.Unread, | ||
createdAt: DateTime.UtcNow, | ||
updatedAt: null, | ||
relatedEntityId: post.EventId ?? post.OrganizationId ?? post.UserId ?? post.Id, | ||
eventType: NotificationEventType.PostUpdated, | ||
details: detailsHtml | ||
); | ||
|
||
_logger.LogInformation($"Creating post update notification for user: {student.Id}"); | ||
|
||
var studentNotifications = await _studentNotificationsRepository.GetByUserIdAsync(student.Id); | ||
if (studentNotifications == null) | ||
try | ||
{ | ||
studentNotifications = new UserNotifications(student.Id); | ||
} | ||
|
||
studentNotifications.AddNotification(notification); | ||
await _studentNotificationsRepository.AddOrUpdateAsync(studentNotifications); | ||
|
||
var notificationCreatedEvent = new NotificationCreated( | ||
notification.NotificationId, | ||
student.Id, | ||
notificationMessage, | ||
DateTime.UtcNow, | ||
NotificationEventType.PostUpdated.ToString(), | ||
relatedEntityId: post.EventId ?? post.OrganizationId ?? post.UserId ?? post.Id, | ||
detailsHtml | ||
); | ||
|
||
await _messageBroker.PublishAsync(notificationCreatedEvent); | ||
var organizationMembers = await _organizationsServiceClient.GetOrganizationMembersAsync(eventArgs.OrganizationId.Value); | ||
|
||
var notificationDto = new NotificationDto | ||
if (organizationMembers != null && organizationMembers.Users != null) | ||
{ | ||
foreach (var member in organizationMembers.Users) | ||
{ | ||
var notificationMessage = $"An updated post has been created by your organization (Post ID: {eventArgs.PostId})."; | ||
await CreateAndSendNotification(member.Id, eventArgs, notificationMessage); | ||
} | ||
} | ||
} | ||
catch (Exception ex) | ||
{ | ||
UserId = student.Id, | ||
Message = notificationMessage, | ||
CreatedAt = DateTime.UtcNow, | ||
EventType = NotificationEventType.PostUpdated, | ||
RelatedEntityId = post.EventId, | ||
Details = detailsHtml | ||
}; | ||
|
||
// Broadcast SignalR notification | ||
await NotificationHub.BroadcastNotification(_hubContext, notificationDto, _logger); | ||
_logger.LogInformation($"Broadcasted SignalR notification to student with ID {student.Id}."); | ||
_logger.LogError($"Failed to notify organization members: {ex.Message}"); | ||
} | ||
} | ||
|
||
private async Task NotifyOrganizer(OrganizerDto organizer, EventDto eventDetails, PostDto post) | ||
private async Task CreateAndSendNotification(Guid userId, PostUpdated eventArgs, string notificationMessage) | ||
{ | ||
var notificationMessage = $"An updated post is available for your event '{eventDetails.Name}'."; | ||
var detailsHtml = $"<p>{notificationMessage} View the updated post here: {post.TextContent}</p>"; | ||
var detailsHtml = $"<p>{notificationMessage} Check out the updated post details here: {eventArgs.TextContent}</p>"; | ||
|
||
var notification = new Notification( | ||
notificationId: Guid.NewGuid(), | ||
userId: organizer.Id, | ||
userId: userId, | ||
message: notificationMessage, | ||
status: NotificationStatus.Unread, | ||
createdAt: DateTime.UtcNow, | ||
updatedAt: null, | ||
relatedEntityId: post.EventId ?? post.OrganizationId ?? post.UserId ?? post.Id, | ||
relatedEntityId: eventArgs.PostId, | ||
eventType: NotificationEventType.PostUpdated, | ||
details: detailsHtml | ||
); | ||
|
||
_logger.LogInformation($"Creating post update notification for organizer: {organizer.Id}"); | ||
_logger.LogInformation($"Creating post update notification for user: {userId}"); | ||
|
||
var organizerNotifications = await _studentNotificationsRepository.GetByUserIdAsync(organizer.Id); | ||
if (organizerNotifications == null) | ||
var userNotifications = await _userNotificationsRepository.GetByUserIdAsync(userId); | ||
if (userNotifications == null) | ||
{ | ||
organizerNotifications = new UserNotifications(organizer.Id); | ||
userNotifications = new UserNotifications(userId); | ||
} | ||
|
||
organizerNotifications.AddNotification(notification); | ||
await _studentNotificationsRepository.AddOrUpdateAsync(organizerNotifications); | ||
|
||
var notificationCreatedEvent = new NotificationCreated( | ||
notification.NotificationId, | ||
organizer.Id, | ||
notificationMessage, | ||
DateTime.UtcNow, | ||
NotificationEventType.PostUpdated.ToString(), | ||
post.EventId ?? post.OrganizationId ?? post.UserId ?? post.Id, | ||
detailsHtml | ||
); | ||
|
||
await _messageBroker.PublishAsync(notificationCreatedEvent); | ||
userNotifications.AddNotification(notification); | ||
await _userNotificationsRepository.AddOrUpdateAsync(userNotifications); | ||
|
||
var notificationDto = new NotificationDto | ||
{ | ||
UserId = organizer.Id, | ||
UserId = userId, | ||
Message = notificationMessage, | ||
CreatedAt = DateTime.UtcNow, | ||
EventType = NotificationEventType.PostUpdated, | ||
RelatedEntityId = post.EventId ?? post.OrganizationId ?? post.UserId ?? post.Id, | ||
RelatedEntityId = eventArgs.PostId, | ||
Details = detailsHtml | ||
}; | ||
|
||
// Broadcast SignalR notification | ||
await NotificationHub.BroadcastNotification(_hubContext, notificationDto, _logger); | ||
_logger.LogInformation($"Broadcasted SignalR notification to organizer with ID {organizer.Id}."); | ||
_logger.LogInformation($"Broadcasted SignalR notification to user with ID {userId}."); | ||
} | ||
} | ||
} |