From fc6cee17d7e0a5f9b2c6a83dfe6997813348440f Mon Sep 17 00:00:00 2001 From: LittleSheep Date: Tue, 19 Aug 2025 19:06:08 +0800 Subject: [PATCH] :sparkles: Add notification to friend request --- .../Account/RelationshipService.cs | 59 +++++++++++++------ DysonNetwork.Pass/DysonNetwork.Pass.csproj | 19 ++---- .../Localization/NotificationResource.resx | 6 ++ .../NotificationResource.zh-hans.resx | 6 ++ DysonNetwork.sln.DotSettings.user | 8 ++- 5 files changed, 65 insertions(+), 33 deletions(-) diff --git a/DysonNetwork.Pass/Account/RelationshipService.cs b/DysonNetwork.Pass/Account/RelationshipService.cs index 0b2bc03..f64086d 100644 --- a/DysonNetwork.Pass/Account/RelationshipService.cs +++ b/DysonNetwork.Pass/Account/RelationshipService.cs @@ -1,14 +1,22 @@ +using DysonNetwork.Pass.Localization; using DysonNetwork.Shared.Cache; +using DysonNetwork.Shared.Proto; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Localization; using NodaTime; namespace DysonNetwork.Pass.Account; -public class RelationshipService(AppDatabase db, ICacheService cache) +public class RelationshipService( + AppDatabase db, + ICacheService cache, + PusherService.PusherServiceClient pusher, + IStringLocalizer localizer +) { private const string UserFriendsCacheKeyPrefix = "accounts:friends:"; private const string UserBlockedCacheKeyPrefix = "accounts:blocked:"; - + public async Task HasExistingRelationship(Guid accountId, Guid relatedId) { var count = await db.AccountRelationships @@ -51,7 +59,7 @@ public class RelationshipService(AppDatabase db, ICacheService cache) db.AccountRelationships.Add(relationship); await db.SaveChangesAsync(); - + await PurgeRelationshipCache(sender.Id, target.Id); return relationship; @@ -63,16 +71,16 @@ public class RelationshipService(AppDatabase db, ICacheService cache) return await UpdateRelationship(sender.Id, target.Id, RelationshipStatus.Blocked); return await CreateRelationship(sender, target, RelationshipStatus.Blocked); } - + public async Task UnblockAccount(Account sender, Account target) { var relationship = await GetRelationship(sender.Id, target.Id, RelationshipStatus.Blocked); if (relationship is null) throw new ArgumentException("There is no relationship between you and the user."); db.Remove(relationship); await db.SaveChangesAsync(); - + await PurgeRelationshipCache(sender.Id, target.Id); - + return relationship; } @@ -92,21 +100,34 @@ public class RelationshipService(AppDatabase db, ICacheService cache) db.AccountRelationships.Add(relationship); await db.SaveChangesAsync(); + await pusher.SendPushNotificationToUserAsync(new SendPushNotificationToUserRequest + { + UserId = target.Id.ToString(), + Notification = new PushNotification + { + Topic = "relationships.friends.request", + Title = localizer["FriendRequestTitle", sender.Nick], + Body = localizer["FriendRequestBody"], + ActionUri = "/account/relationships", + IsSavable = true + } + }); + return relationship; } - + public async Task DeleteFriendRequest(Guid accountId, Guid relatedId) { var relationship = await GetRelationship(accountId, relatedId, RelationshipStatus.Pending); if (relationship is null) throw new ArgumentException("Friend request was not found."); - + await db.AccountRelationships .Where(r => r.AccountId == accountId && r.RelatedId == relatedId && r.Status == RelationshipStatus.Pending) .ExecuteDeleteAsync(); - + await PurgeRelationshipCache(relationship.AccountId, relationship.RelatedId); } - + public async Task AcceptFriendRelationship( Relationship relationship, RelationshipStatus status = RelationshipStatus.Friends @@ -146,9 +167,9 @@ public class RelationshipService(AppDatabase db, ICacheService cache) relationship.Status = status; db.Update(relationship); await db.SaveChangesAsync(); - + await PurgeRelationshipCache(accountId, relatedId); - + return relationship; } @@ -161,7 +182,7 @@ public class RelationshipService(AppDatabase db, ICacheService cache) { var cacheKey = $"{UserFriendsCacheKeyPrefix}{accountId}"; var friends = await cache.GetAsync>(cacheKey); - + if (friends == null) { friends = await db.AccountRelationships @@ -169,23 +190,23 @@ public class RelationshipService(AppDatabase db, ICacheService cache) .Where(r => r.Status == RelationshipStatus.Friends) .Select(r => r.AccountId) .ToListAsync(); - + await cache.SetAsync(cacheKey, friends, TimeSpan.FromHours(1)); } return friends ?? []; } - + public async Task> ListAccountBlocked(Account account) { return await ListAccountBlocked(account.Id); } - + public async Task> ListAccountBlocked(Guid accountId) { var cacheKey = $"{UserBlockedCacheKeyPrefix}{accountId}"; var blocked = await cache.GetAsync>(cacheKey); - + if (blocked == null) { blocked = await db.AccountRelationships @@ -193,7 +214,7 @@ public class RelationshipService(AppDatabase db, ICacheService cache) .Where(r => r.Status == RelationshipStatus.Blocked) .Select(r => r.AccountId) .ToListAsync(); - + await cache.SetAsync(cacheKey, blocked, TimeSpan.FromHours(1)); } @@ -206,7 +227,7 @@ public class RelationshipService(AppDatabase db, ICacheService cache) var relationship = await GetRelationship(accountId, relatedId, status); return relationship is not null; } - + private async Task PurgeRelationshipCache(Guid accountId, Guid relatedId) { await cache.RemoveAsync($"{UserFriendsCacheKeyPrefix}{accountId}"); diff --git a/DysonNetwork.Pass/DysonNetwork.Pass.csproj b/DysonNetwork.Pass/DysonNetwork.Pass.csproj index fc73b38..f2e889c 100644 --- a/DysonNetwork.Pass/DysonNetwork.Pass.csproj +++ b/DysonNetwork.Pass/DysonNetwork.Pass.csproj @@ -136,19 +136,12 @@ - - - - - - - - - - - - - + + + + + + diff --git a/DysonNetwork.Pass/Resources/Localization/NotificationResource.resx b/DysonNetwork.Pass/Resources/Localization/NotificationResource.resx index 218a4d5..dfbe7ef 100644 --- a/DysonNetwork.Pass/Resources/Localization/NotificationResource.resx +++ b/DysonNetwork.Pass/Resources/Localization/NotificationResource.resx @@ -86,4 +86,10 @@ Your account logged on to a device named {0} at {1} + + {0} requested to be your friend + + + You can go to relationships page and decide accept their request or not. + \ No newline at end of file diff --git a/DysonNetwork.Pass/Resources/Localization/NotificationResource.zh-hans.resx b/DysonNetwork.Pass/Resources/Localization/NotificationResource.zh-hans.resx index d6346f7..10546f1 100644 --- a/DysonNetwork.Pass/Resources/Localization/NotificationResource.zh-hans.resx +++ b/DysonNetwork.Pass/Resources/Localization/NotificationResource.zh-hans.resx @@ -78,4 +78,10 @@ 您的帐号在位于 {1} 的设备 {0} 上刚刚登陆了 + + {0} 请求成为您的好友 + + + 您可以前往人际关系页面来决定时候要接受他们的邀请。 + \ No newline at end of file diff --git a/DysonNetwork.sln.DotSettings.user b/DysonNetwork.sln.DotSettings.user index e5c3a1b..8b151a9 100644 --- a/DysonNetwork.sln.DotSettings.user +++ b/DysonNetwork.sln.DotSettings.user @@ -149,8 +149,14 @@ <AssemblyExplorer> <Assembly Path="/opt/homebrew/Cellar/dotnet/9.0.6/libexec/packs/Microsoft.AspNetCore.App.Ref/9.0.6/ref/net9.0/Microsoft.AspNetCore.RateLimiting.dll" /> </AssemblyExplorer> - True + False + + False + True + + False + False True False