Skip to content

Commit

Permalink
(#412) notifications: update post updated event hadnler
Browse files Browse the repository at this point in the history
  • Loading branch information
SaintAngeLs committed Sep 16, 2024
1 parent 8aa77fd commit 1ef338e
Showing 1 changed file with 69 additions and 125 deletions.
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}.");
}
}
}

0 comments on commit 1ef338e

Please sign in to comment.