♻️ Moving to MagicOnion

This commit is contained in:
2025-07-07 21:54:51 +08:00
parent 1672d46038
commit 8d2f4a4c47
41 changed files with 790 additions and 530 deletions

View File

@ -1,29 +1,29 @@
using System.Text;
using System.Text.Json;
using DysonNetwork.Shared.Models;
using EFCore.BulkExtensions;
using Microsoft.EntityFrameworkCore;
using NodaTime;
using DysonNetwork.Shared.Services;
using EFCore.BulkExtensions;
using MagicOnion.Server;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using System.Net.Http;
namespace DysonNetwork.Pass.Account;
public class NotificationService(
AppDatabase db
// WebSocketService ws,
// IHttpClientFactory httpFactory,
// IConfiguration config
)
AppDatabase db,
IConfiguration config,
IHttpClientFactory httpFactory
) : ServiceBase<INotificationService>, INotificationService
{
// private readonly string _notifyTopic = config["Notifications:Topic"]!;
// private readonly Uri _notifyEndpoint = new(config["Notifications:Endpoint"]!);
private readonly string _notifyTopic = config["Notifications:Topic"]!;
private readonly Uri _notifyEndpoint = new(config["Notifications:Endpoint"]!);
public async Task UnsubscribePushNotifications(string deviceId)
{
// await db.NotificationPushSubscriptions
// .Where(s => s.DeviceId == deviceId)
// .ExecuteDeleteAsync();
await db.NotificationPushSubscriptions
.Where(s => s.DeviceId == deviceId)
.ExecuteDeleteAsync();
}
public async Task<NotificationPushSubscription> SubscribePushNotification(
@ -34,29 +34,29 @@ public class NotificationService(
)
{
var now = SystemClock.Instance.GetCurrentInstant();
// First check if a matching subscription exists
// var existingSubscription = await db.NotificationPushSubscriptions
// .Where(s => s.AccountId == account.Id)
// .Where(s => s.DeviceId == deviceId || s.DeviceToken == deviceToken)
// .FirstOrDefaultAsync();
var existingSubscription = await db.NotificationPushSubscriptions
.Where(s => s.AccountId == account.Id)
.Where(s => s.DeviceId == deviceId || s.DeviceToken == deviceToken)
.FirstOrDefaultAsync();
// if (existingSubscription is not null)
// {
// // Update the existing subscription directly in the database
// await db.NotificationPushSubscriptions
// .Where(s => s.Id == existingSubscription.Id)
// .ExecuteUpdateAsync(setters => setters
// .SetProperty(s => s.DeviceId, deviceId)
// .SetProperty(s => s.DeviceToken, deviceToken)
// .SetProperty(s => s.UpdatedAt, now));
if (existingSubscription is not null)
{
// Update the existing subscription directly in the database
await db.NotificationPushSubscriptions
.Where(s => s.Id == existingSubscription.Id)
.ExecuteUpdateAsync(setters => setters
.SetProperty(s => s.DeviceId, deviceId)
.SetProperty(s => s.DeviceToken, deviceToken)
.SetProperty(s => s.UpdatedAt, now));
// // Return the updated subscription
// existingSubscription.DeviceId = deviceId;
// existingSubscription.DeviceToken = deviceToken;
// existingSubscription.UpdatedAt = now;
// return existingSubscription;
// }
// Return the updated subscription
existingSubscription.DeviceId = deviceId;
existingSubscription.DeviceToken = deviceToken;
existingSubscription.UpdatedAt = now;
return existingSubscription;
}
var subscription = new NotificationPushSubscription
{
@ -102,11 +102,12 @@ public class NotificationService(
if (save)
{
// db.Add(notification);
// await db.SaveChangesAsync();
db.Add(notification);
await db.SaveChangesAsync();
}
if (!isSilent) Console.WriteLine("Simulating notification delivery."); // _ = DeliveryNotification(notification);
if (!isSilent)
Console.WriteLine("Simulating notification delivery."); // _ = DeliveryNotification(notification);
return notification;
}
@ -120,11 +121,11 @@ public class NotificationService(
// });
// Pushing the notification
// var subscribers = await db.NotificationPushSubscriptions
// .Where(s => s.AccountId == notification.AccountId)
// .ToListAsync();
var subscribers = await db.NotificationPushSubscriptions
.Where(s => s.AccountId == notification.AccountId)
.ToListAsync();
// await _PushNotification(notification, subscribers);
await _PushNotification(notification, subscribers);
}
public async Task MarkNotificationsViewed(ICollection<Notification> notifications)
@ -174,12 +175,13 @@ public class NotificationService(
// });
}
// var subscribers = await db.NotificationPushSubscriptions
// .ToListAsync();
// await _PushNotification(notification, subscribers);
var subscribers = await db.NotificationPushSubscriptions
.ToListAsync();
await _PushNotification(notification, subscribers);
}
public async Task SendNotificationBatch(Notification notification, List<Shared.Models.Account> accounts, bool save = false)
public async Task SendNotificationBatch(Notification notification, List<Shared.Models.Account> accounts,
bool save = false)
{
if (save)
{
@ -198,7 +200,7 @@ public class NotificationService(
};
return newNotification;
}).ToList();
// await db.BulkInsertAsync(notifications);
await db.BulkInsertAsync(notifications);
}
foreach (var account in accounts)
@ -219,93 +221,93 @@ public class NotificationService(
// await _PushNotification(notification, subscribers);
}
// private List<Dictionary<string, object>> _BuildNotificationPayload(Notification notification,
// IEnumerable<NotificationPushSubscription> subscriptions)
// {
// var subDict = subscriptions
// .GroupBy(x => x.Provider)
// .ToDictionary(x => x.Key, x => x.ToList());
private List<Dictionary<string, object>> _BuildNotificationPayload(Notification notification,
IEnumerable<NotificationPushSubscription> subscriptions)
{
var subDict = subscriptions
.GroupBy(x => x.Provider)
.ToDictionary(x => x.Key, x => x.ToList());
// var notifications = subDict.Select(value =>
// {
// var platformCode = value.Key switch
// {
// NotificationPushProvider.Apple => 1,
// NotificationPushProvider.Google => 2,
// _ => throw new InvalidOperationException($"Unknown push provider: {value.Key}")
// };
var notifications = subDict.Select(value =>
{
var platformCode = value.Key switch
{
NotificationPushProvider.Apple => 1,
NotificationPushProvider.Google => 2,
_ => throw new InvalidOperationException($"Unknown push provider: {value.Key}")
};
// var tokens = value.Value.Select(x => x.DeviceToken).ToList();
// return _BuildNotificationPayload(notification, platformCode, tokens);
// }).ToList();
var tokens = value.Value.Select(x => x.DeviceToken).ToList();
return _BuildNotificationPayload(notification, platformCode, tokens);
}).ToList();
// return notifications.ToList();
// }
return notifications.ToList();
}
// private Dictionary<string, object> _BuildNotificationPayload(Notification notification, int platformCode,
// IEnumerable<string> deviceTokens)
// {
// var alertDict = new Dictionary<string, object>();
// var dict = new Dictionary<string, object>
// {
// ["notif_id"] = notification.Id.ToString(),
// ["apns_id"] = notification.Id.ToString(),
// ["topic"] = _notifyTopic,
// ["tokens"] = deviceTokens,
// ["data"] = new Dictionary<string, object>
// {
// ["type"] = notification.Topic,
// ["meta"] = notification.Meta ?? new Dictionary<string, object>(),
// },
// ["mutable_content"] = true,
// ["priority"] = notification.Priority >= 5 ? "high" : "normal",
// };
private Dictionary<string, object> _BuildNotificationPayload(Notification notification, int platformCode,
IEnumerable<string> deviceTokens)
{
var alertDict = new Dictionary<string, object>();
var dict = new Dictionary<string, object>
{
["notif_id"] = notification.Id.ToString(),
["apns_id"] = notification.Id.ToString(),
["topic"] = _notifyTopic,
["tokens"] = deviceTokens,
["data"] = new Dictionary<string, object>
{
["type"] = notification.Topic,
["meta"] = notification.Meta ?? new Dictionary<string, object>(),
},
["mutable_content"] = true,
["priority"] = notification.Priority >= 5 ? "high" : "normal",
};
// if (!string.IsNullOrWhiteSpace(notification.Title))
// {
// dict["title"] = notification.Title;
// alertDict["title"] = notification.Title;
// }
if (!string.IsNullOrWhiteSpace(notification.Title))
{
dict["title"] = notification.Title;
alertDict["title"] = notification.Title;
}
// if (!string.IsNullOrWhiteSpace(notification.Content))
// {
// dict["message"] = notification.Content;
// alertDict["body"] = notification.Content;
// }
if (!string.IsNullOrWhiteSpace(notification.Content))
{
dict["message"] = notification.Content;
alertDict["body"] = notification.Content;
}
// if (!string.IsNullOrWhiteSpace(notification.Subtitle))
// {
// dict["message"] = $"{notification.Subtitle}\n{dict["message"]}";
// alertDict["subtitle"] = notification.Subtitle;
// }
if (!string.IsNullOrWhiteSpace(notification.Subtitle))
{
dict["message"] = $"{notification.Subtitle}\n{dict["message"]}";
alertDict["subtitle"] = notification.Subtitle;
}
// if (notification.Priority >= 5)
// dict["name"] = "default";
if (notification.Priority >= 5)
dict["name"] = "default";
// dict["platform"] = platformCode;
// dict["alert"] = alertDict;
dict["platform"] = platformCode;
dict["alert"] = alertDict;
// return dict;
// }
return dict;
}
// private async Task _PushNotification(Notification notification,
// IEnumerable<NotificationPushSubscription> subscriptions)
// {
// var subList = subscriptions.ToList();
// if (subList.Count == 0) return;
private async Task _PushNotification(Notification notification,
IEnumerable<NotificationPushSubscription> subscriptions)
{
var subList = subscriptions.ToList();
if (subList.Count == 0) return;
// var requestDict = new Dictionary<string, object>
// {
// ["notifications"] = _BuildNotificationPayload(notification, subList)
// };
var requestDict = new Dictionary<string, object>
{
["notifications"] = _BuildNotificationPayload(notification, subList)
};
// var client = httpFactory.CreateClient();
// client.BaseAddress = _notifyEndpoint;
// var request = await client.PostAsync("/push", new StringContent(
// JsonSerializer.Serialize(requestDict),
// Encoding.UTF8,
// "application/json"
// ));
// request.EnsureSuccessStatusCode();
// }
var client = httpFactory.CreateClient();
client.BaseAddress = _notifyEndpoint;
var request = await client.PostAsync("/push", new StringContent(
JsonSerializer.Serialize(requestDict),
Encoding.UTF8,
"application/json"
));
request.EnsureSuccessStatusCode();
}
}