using RadicadeServer.API.Notifications; using Microsoft.EntityFrameworkCore; using RadicadeServer.DB; using RadicadeServer.RecNet.Enums.Messages; using RadicadeServer.RecNet.Notifications; namespace RadicadeServer.RecNet.Events { public static class PlayerEventNotifications { public static async Task PushToEventInstancesAsync(RecDBContext db, PlayerEventDB ev) { var audienceIds = await ( from presence in db.Presences.AsNoTracking() join instance in db.RoomInstances.AsNoTracking() on presence.roomInstance equals (long?)instance.roomInstanceId where presence.isOnline && instance.eventId == ev.PlayerEventId select presence.playerId).ToListAsync(); var update = Updated(ev); foreach (var recipientId in audienceIds.Append(ev.CreatorPlayerId).Distinct()) await PushAsync(recipientId, update); } public static Notification Created(PlayerEventDB ev) => new() { Id = NotificationType.PlayerEventCreated, Msg = Payload(ev) }; public static Notification Updated(PlayerEventDB ev) => new() { Id = NotificationType.PlayerEventUpdated, Msg = Payload(ev) }; public static Notification Deleted(long playerEventId) => new() { Id = NotificationType.PlayerEventDeleted, Msg = new Dictionary { ["playerEventId"] = playerEventId, ["PlayerEventId"] = playerEventId } }; public static Notification ResponseChanged(PlayerEventDB ev, PlayerEventResponse response) => new() { Id = NotificationType.PlayerEventResponseChanged, Msg = new Dictionary { ["PlayerEvent"] = Payload(ev), ["PlayerEventResponse"] = new Dictionary { ["PlayerEventResponseId"] = response.PlayerEventResponseId, ["PlayerEventId"] = response.PlayerEventId, ["PlayerId"] = response.PlayerId, ["CreatedAt"] = response.CreatedAt, ["Type"] = (int)response.Type } } }; public static Dictionary Payload(PlayerEventDB ev) { var tags = ParseTags(ev.TagsJson); return new Dictionary { ["tags"] = tags.Select(tag => new Dictionary { ["tag"] = tag.Tag, ["type"] = tag.Type }).ToArray(), ["playerEventId"] = ev.PlayerEventId, ["creatorPlayerId"] = ev.CreatorPlayerId, ["roomId"] = ev.RoomId, ["subRoomId"] = ev.SubRoomId, ["clubId"] = ev.ClubId, ["name"] = ev.Name, ["description"] = ev.Description, ["imageName"] = string.IsNullOrWhiteSpace(ev.ImageName) ? DefaultImageName : ev.ImageName, ["startTime"] = EventClock.ToWire(ev.StartTime), ["endTime"] = EventClock.ToWire(ev.EndTime), ["attendeeCount"] = ev.AttendeeCount, ["accessibility"] = (int)ev.Accessibility, ["isMultiInstance"] = ev.IsMultiInstance, ["supportMultiInstanceRoomChat"] = ev.SupportMultiInstanceRoomChat, ["defaultBroadcastPermissions"] = ev.DefaultBroadcastPermissions, ["canRequestBroadcastPermissions"] = ev.CanRequestBroadcastPermissions, ["broadcastingRoomInstanceId"] = ev.BroadcastingRoomInstanceId }; } public static async Task PushAsync(long accountId, Notification frame) { try { await Notify.SendNotify(accountId, frame); } catch (Exception ex) { Console.WriteLine($"[Events] pushing {Notify.WireId(frame.Id)} to account {accountId} failed: {ex.Message}"); } } private const string DefaultImageName = "default"; private static List ParseTags(string? tagsJson) { if (string.IsNullOrWhiteSpace(tagsJson)) return []; try { return System.Text.Json.JsonSerializer.Deserialize>(tagsJson) ?? []; } catch { return []; } } } }