|  |  | @@ -7,6 +7,7 @@ namespace DysonNetwork.Sphere.Account; | 
			
		
	
		
		
			
				
					
					|  |  |  | public class RelationshipService(AppDatabase db, ICacheService cache) |  |  |  | public class RelationshipService(AppDatabase db, ICacheService cache) | 
			
		
	
		
		
			
				
					
					|  |  |  | { |  |  |  | { | 
			
		
	
		
		
			
				
					
					|  |  |  |     private const string UserFriendsCacheKeyPrefix = "accounts:friends:"; |  |  |  |     private const string UserFriendsCacheKeyPrefix = "accounts:friends:"; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     private const string UserBlockedCacheKeyPrefix = "accounts:blocked:"; | 
			
		
	
		
		
			
				
					
					|  |  |  |      |  |  |  |      | 
			
		
	
		
		
			
				
					
					|  |  |  |     public async Task<bool> HasExistingRelationship(Guid accountId, Guid relatedId) |  |  |  |     public async Task<bool> HasExistingRelationship(Guid accountId, Guid relatedId) | 
			
		
	
		
		
			
				
					
					|  |  |  |     { |  |  |  |     { | 
			
		
	
	
		
		
			
				
					
					|  |  | @@ -50,9 +51,8 @@ public class RelationshipService(AppDatabase db, ICacheService cache) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         db.AccountRelationships.Add(relationship); |  |  |  |         db.AccountRelationships.Add(relationship); | 
			
		
	
		
		
			
				
					
					|  |  |  |         await db.SaveChangesAsync(); |  |  |  |         await db.SaveChangesAsync(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |          | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         await cache.RemoveAsync($"{UserFriendsCacheKeyPrefix}{relationship.AccountId}"); |  |  |  |         await PurgeRelationshipCache(sender.Id, target.Id); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         await cache.RemoveAsync($"{UserFriendsCacheKeyPrefix}{relationship.RelatedId}"); |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         return relationship; |  |  |  |         return relationship; | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
	
		
		
			
				
					
					|  |  | @@ -63,6 +63,18 @@ public class RelationshipService(AppDatabase db, ICacheService cache) | 
			
		
	
		
		
			
				
					
					|  |  |  |             return await UpdateRelationship(sender.Id, target.Id, RelationshipStatus.Blocked); |  |  |  |             return await UpdateRelationship(sender.Id, target.Id, RelationshipStatus.Blocked); | 
			
		
	
		
		
			
				
					
					|  |  |  |         return await CreateRelationship(sender, target, RelationshipStatus.Blocked); |  |  |  |         return await CreateRelationship(sender, target, RelationshipStatus.Blocked); | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     public async Task<Relationship> 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; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     public async Task<Relationship> SendFriendRequest(Account sender, Account target) |  |  |  |     public async Task<Relationship> SendFriendRequest(Account sender, Account target) | 
			
		
	
		
		
			
				
					
					|  |  |  |     { |  |  |  |     { | 
			
		
	
	
		
		
			
				
					
					|  |  | @@ -92,8 +104,7 @@ public class RelationshipService(AppDatabase db, ICacheService cache) | 
			
		
	
		
		
			
				
					
					|  |  |  |             .Where(r => r.AccountId == accountId && r.RelatedId == relatedId && r.Status == RelationshipStatus.Pending) |  |  |  |             .Where(r => r.AccountId == accountId && r.RelatedId == relatedId && r.Status == RelationshipStatus.Pending) | 
			
		
	
		
		
			
				
					
					|  |  |  |             .ExecuteDeleteAsync(); |  |  |  |             .ExecuteDeleteAsync(); | 
			
		
	
		
		
			
				
					
					|  |  |  |          |  |  |  |          | 
			
		
	
		
		
			
				
					
					|  |  |  |         await cache.RemoveAsync($"{UserFriendsCacheKeyPrefix}{accountId}"); |  |  |  |         await PurgeRelationshipCache(relationship.AccountId, relationship.RelatedId); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         await cache.RemoveAsync($"{UserFriendsCacheKeyPrefix}{relatedId}"); |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |      |  |  |  |      | 
			
		
	
		
		
			
				
					
					|  |  |  |     public async Task<Relationship> AcceptFriendRelationship( |  |  |  |     public async Task<Relationship> AcceptFriendRelationship( | 
			
		
	
	
		
		
			
				
					
					|  |  | @@ -122,8 +133,7 @@ public class RelationshipService(AppDatabase db, ICacheService cache) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         await db.SaveChangesAsync(); |  |  |  |         await db.SaveChangesAsync(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         await cache.RemoveAsync($"{UserFriendsCacheKeyPrefix}{relationship.AccountId}"); |  |  |  |         await PurgeRelationshipCache(relationship.AccountId, relationship.RelatedId); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         await cache.RemoveAsync($"{UserFriendsCacheKeyPrefix}{relationship.RelatedId}"); |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         return relationshipBackward; |  |  |  |         return relationshipBackward; | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
	
		
		
			
				
					
					|  |  | @@ -137,15 +147,14 @@ public class RelationshipService(AppDatabase db, ICacheService cache) | 
			
		
	
		
		
			
				
					
					|  |  |  |         db.Update(relationship); |  |  |  |         db.Update(relationship); | 
			
		
	
		
		
			
				
					
					|  |  |  |         await db.SaveChangesAsync(); |  |  |  |         await db.SaveChangesAsync(); | 
			
		
	
		
		
			
				
					
					|  |  |  |          |  |  |  |          | 
			
		
	
		
		
			
				
					
					|  |  |  |         await cache.RemoveAsync($"{UserFriendsCacheKeyPrefix}{accountId}"); |  |  |  |         await PurgeRelationshipCache(accountId, relatedId); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         await cache.RemoveAsync($"{UserFriendsCacheKeyPrefix}{relatedId}"); |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |          |  |  |  |          | 
			
		
	
		
		
			
				
					
					|  |  |  |         return relationship; |  |  |  |         return relationship; | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     public async Task<List<Guid>> ListAccountFriends(Account account) |  |  |  |     public async Task<List<Guid>> ListAccountFriends(Account account) | 
			
		
	
		
		
			
				
					
					|  |  |  |     { |  |  |  |     { | 
			
		
	
		
		
			
				
					
					|  |  |  |         string cacheKey = $"{UserFriendsCacheKeyPrefix}{account.Id}"; |  |  |  |         var cacheKey = $"{UserFriendsCacheKeyPrefix}{account.Id}"; | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         var friends = await cache.GetAsync<List<Guid>>(cacheKey); |  |  |  |         var friends = await cache.GetAsync<List<Guid>>(cacheKey); | 
			
		
	
		
		
			
				
					
					|  |  |  |          |  |  |  |          | 
			
		
	
		
		
			
				
					
					|  |  |  |         if (friends == null) |  |  |  |         if (friends == null) | 
			
		
	
	
		
		
			
				
					
					|  |  | @@ -161,6 +170,25 @@ public class RelationshipService(AppDatabase db, ICacheService cache) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         return friends ?? []; |  |  |  |         return friends ?? []; | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     public async Task<List<Guid>> ListAccountBlocked(Account account) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         var cacheKey = $"{UserBlockedCacheKeyPrefix}{account.Id}"; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         var blocked = await cache.GetAsync<List<Guid>>(cacheKey); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |          | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         if (blocked == null) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             blocked = await db.AccountRelationships | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 .Where(r => r.RelatedId == account.Id) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 .Where(r => r.Status == RelationshipStatus.Blocked) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 .Select(r => r.AccountId) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 .ToListAsync(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                  | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             await cache.SetAsync(cacheKey, blocked, TimeSpan.FromHours(1)); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         return blocked ?? []; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     public async Task<bool> HasRelationshipWithStatus(Guid accountId, Guid relatedId, |  |  |  |     public async Task<bool> HasRelationshipWithStatus(Guid accountId, Guid relatedId, | 
			
		
	
		
		
			
				
					
					|  |  |  |         RelationshipStatus status = RelationshipStatus.Friends) |  |  |  |         RelationshipStatus status = RelationshipStatus.Friends) | 
			
		
	
	
		
		
			
				
					
					|  |  | @@ -168,4 +196,12 @@ public class RelationshipService(AppDatabase db, ICacheService cache) | 
			
		
	
		
		
			
				
					
					|  |  |  |         var relationship = await GetRelationship(accountId, relatedId, status); |  |  |  |         var relationship = await GetRelationship(accountId, relatedId, status); | 
			
		
	
		
		
			
				
					
					|  |  |  |         return relationship is not null; |  |  |  |         return relationship is not null; | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |      | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     private async Task PurgeRelationshipCache(Guid accountId, Guid relatedId) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         await cache.RemoveAsync($"{UserFriendsCacheKeyPrefix}{accountId}"); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         await cache.RemoveAsync($"{UserFriendsCacheKeyPrefix}{relatedId}"); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         await cache.RemoveAsync($"{UserBlockedCacheKeyPrefix}{accountId}"); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         await cache.RemoveAsync($"{UserBlockedCacheKeyPrefix}{relatedId}"); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } |