281 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			281 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| using DysonNetwork.Pass.Wallet;
 | |
| using DysonNetwork.Shared.Proto;
 | |
| using Google.Protobuf.WellKnownTypes;
 | |
| using Grpc.Core;
 | |
| using Microsoft.EntityFrameworkCore;
 | |
| using NodaTime;
 | |
| 
 | |
| namespace DysonNetwork.Pass.Account;
 | |
| 
 | |
| public class AccountServiceGrpc(
 | |
|     AppDatabase db,
 | |
|     AccountEventService accountEvents,
 | |
|     RelationshipService relationships,
 | |
|     SubscriptionService subscriptions,
 | |
|     ILogger<AccountServiceGrpc> logger
 | |
| )
 | |
|     : Shared.Proto.AccountService.AccountServiceBase
 | |
| {
 | |
|     private readonly AppDatabase _db = db ?? throw new ArgumentNullException(nameof(db));
 | |
| 
 | |
|     private readonly ILogger<AccountServiceGrpc>
 | |
|         _logger = logger ?? throw new ArgumentNullException(nameof(logger));
 | |
| 
 | |
|     public override async Task<Shared.Proto.Account> GetAccount(GetAccountRequest request, ServerCallContext context)
 | |
|     {
 | |
|         if (!Guid.TryParse(request.Id, out var accountId))
 | |
|             throw new RpcException(new Grpc.Core.Status(StatusCode.InvalidArgument, "Invalid account ID format"));
 | |
| 
 | |
|         var account = await _db.Accounts
 | |
|             .AsNoTracking()
 | |
|             .Include(a => a.Profile)
 | |
|             .FirstOrDefaultAsync(a => a.Id == accountId);
 | |
| 
 | |
|         if (account == null)
 | |
|             throw new RpcException(new Grpc.Core.Status(StatusCode.NotFound, $"Account {request.Id} not found"));
 | |
| 
 | |
|         var perk = await subscriptions.GetPerkSubscriptionAsync(account.Id);
 | |
|         account.PerkSubscription = perk?.ToReference();
 | |
| 
 | |
|         return account.ToProtoValue();
 | |
|     }
 | |
| 
 | |
|     public override async Task<Shared.Proto.Account> GetBotAccount(GetBotAccountRequest request,
 | |
|         ServerCallContext context)
 | |
|     {
 | |
|         if (!Guid.TryParse(request.AutomatedId, out var automatedId))
 | |
|             throw new RpcException(new Grpc.Core.Status(StatusCode.InvalidArgument, "Invalid automated ID format"));
 | |
| 
 | |
|         var account = await _db.Accounts
 | |
|             .AsNoTracking()
 | |
|             .Include(a => a.Profile)
 | |
|             .FirstOrDefaultAsync(a => a.AutomatedId == automatedId);
 | |
| 
 | |
|         if (account == null)
 | |
|             throw new RpcException(new Grpc.Core.Status(StatusCode.NotFound, $"Account with automated ID {request.AutomatedId} not found"));
 | |
| 
 | |
|         var perk = await subscriptions.GetPerkSubscriptionAsync(account.Id);
 | |
|         account.PerkSubscription = perk?.ToReference();
 | |
| 
 | |
|         return account.ToProtoValue();
 | |
|     }
 | |
| 
 | |
|     public override async Task<GetAccountBatchResponse> GetAccountBatch(GetAccountBatchRequest request,
 | |
|         ServerCallContext context)
 | |
|     {
 | |
|         var accountIds = request.Id
 | |
|             .Select(id => Guid.TryParse(id, out var accountId) ? accountId : (Guid?)null)
 | |
|             .Where(id => id.HasValue)
 | |
|             .Select(id => id!.Value)
 | |
|             .ToList();
 | |
| 
 | |
|         var accounts = await _db.Accounts
 | |
|             .AsNoTracking()
 | |
|             .Where(a => accountIds.Contains(a.Id))
 | |
|             .Include(a => a.Profile)
 | |
|             .ToListAsync();
 | |
| 
 | |
|         var perks = await subscriptions.GetPerkSubscriptionsAsync(
 | |
|             accounts.Select(x => x.Id).ToList()
 | |
|         );
 | |
|         foreach (var account in accounts)
 | |
|             if (perks.TryGetValue(account.Id, out var perk))
 | |
|                 account.PerkSubscription = perk?.ToReference();
 | |
| 
 | |
|         var response = new GetAccountBatchResponse();
 | |
|         response.Accounts.AddRange(accounts.Select(a => a.ToProtoValue()));
 | |
|         return response;
 | |
|     }
 | |
|     
 | |
|     
 | |
|     public override async Task<GetAccountBatchResponse> GetBotAccountBatch(GetBotAccountBatchRequest request,
 | |
|         ServerCallContext context)
 | |
|     {
 | |
|         var automatedIds = request.AutomatedId
 | |
|             .Select(id => Guid.TryParse(id, out var automatedId) ? automatedId : (Guid?)null)
 | |
|             .Where(id => id.HasValue)
 | |
|             .Select(id => id!.Value)
 | |
|             .ToList();
 | |
| 
 | |
|         var accounts = await _db.Accounts
 | |
|             .AsNoTracking()
 | |
|             .Where(a => a.AutomatedId != null && automatedIds.Contains(a.AutomatedId.Value))
 | |
|             .Include(a => a.Profile)
 | |
|             .ToListAsync();
 | |
| 
 | |
|         var perks = await subscriptions.GetPerkSubscriptionsAsync(
 | |
|             accounts.Select(x => x.Id).ToList()
 | |
|         );
 | |
|         foreach (var account in accounts)
 | |
|             if (perks.TryGetValue(account.Id, out var perk))
 | |
|                 account.PerkSubscription = perk?.ToReference();
 | |
| 
 | |
|         var response = new GetAccountBatchResponse();
 | |
|         response.Accounts.AddRange(accounts.Select(a => a.ToProtoValue()));
 | |
|         return response;
 | |
|     }
 | |
| 
 | |
|     public override async Task<AccountStatus> GetAccountStatus(GetAccountRequest request, ServerCallContext context)
 | |
|     {
 | |
|         var accountId = Guid.Parse(request.Id);
 | |
|         var status = await accountEvents.GetStatus(accountId);
 | |
|         return status.ToProtoValue();
 | |
|     }
 | |
| 
 | |
|     public override async Task<GetAccountStatusBatchResponse> GetAccountStatusBatch(GetAccountBatchRequest request,
 | |
|         ServerCallContext context)
 | |
|     {
 | |
|         var accountIds = request.Id
 | |
|             .Select(id => Guid.TryParse(id, out var accountId) ? accountId : (Guid?)null)
 | |
|             .Where(id => id.HasValue)
 | |
|             .Select(id => id!.Value)
 | |
|             .ToList();
 | |
|         var statuses = await accountEvents.GetStatuses(accountIds);
 | |
|         var response = new GetAccountStatusBatchResponse();
 | |
|         response.Statuses.AddRange(statuses.Select(s => s.Value.ToProtoValue()));
 | |
|         return response;
 | |
|     }
 | |
| 
 | |
|     public override async Task<GetAccountBatchResponse> LookupAccountBatch(LookupAccountBatchRequest request,
 | |
|         ServerCallContext context)
 | |
|     {
 | |
|         var accountNames = request.Names.ToList();
 | |
|         var accounts = await _db.Accounts
 | |
|             .AsNoTracking()
 | |
|             .Where(a => accountNames.Contains(a.Name))
 | |
|             .Include(a => a.Profile)
 | |
|             .ToListAsync();
 | |
| 
 | |
|         var perks = await subscriptions.GetPerkSubscriptionsAsync(
 | |
|             accounts.Select(x => x.Id).ToList()
 | |
|         );
 | |
|         foreach (var account in accounts)
 | |
|             if (perks.TryGetValue(account.Id, out var perk))
 | |
|                 account.PerkSubscription = perk?.ToReference();
 | |
| 
 | |
|         var response = new GetAccountBatchResponse();
 | |
|         response.Accounts.AddRange(accounts.Select(a => a.ToProtoValue()));
 | |
|         return response;
 | |
|     }
 | |
| 
 | |
|     public override async Task<GetAccountBatchResponse> SearchAccount(SearchAccountRequest request, ServerCallContext context)
 | |
|     {
 | |
|         var accounts = await _db.Accounts
 | |
|             .AsNoTracking()
 | |
|             .Where(a => EF.Functions.ILike(a.Name, $"%{request.Query}%"))
 | |
|             .Include(a => a.Profile)
 | |
|             .ToListAsync();
 | |
| 
 | |
|         var perks = await subscriptions.GetPerkSubscriptionsAsync(
 | |
|             accounts.Select(x => x.Id).ToList()
 | |
|         );
 | |
|         foreach (var account in accounts)
 | |
|             if (perks.TryGetValue(account.Id, out var perk))
 | |
|                 account.PerkSubscription = perk?.ToReference();
 | |
| 
 | |
|         var response = new GetAccountBatchResponse();
 | |
|         response.Accounts.AddRange(accounts.Select(a => a.ToProtoValue()));
 | |
|         return response;
 | |
|     }
 | |
| 
 | |
|     public override async Task<ListAccountsResponse> ListAccounts(ListAccountsRequest request,
 | |
|         ServerCallContext context)
 | |
|     {
 | |
|         var query = _db.Accounts.AsNoTracking();
 | |
| 
 | |
|         // Apply filters if provided
 | |
|         if (!string.IsNullOrEmpty(request.Filter))
 | |
|         {
 | |
|             // Implement filtering logic based on request.Filter
 | |
|             // This is a simplified example
 | |
|             query = query.Where(a => a.Name.Contains(request.Filter) || a.Nick.Contains(request.Filter));
 | |
|         }
 | |
| 
 | |
|         // Apply ordering
 | |
|         query = request.OrderBy switch
 | |
|         {
 | |
|             "name" => query.OrderBy(a => a.Name),
 | |
|             "name_desc" => query.OrderByDescending(a => a.Name),
 | |
|             _ => query.OrderBy(a => a.Id)
 | |
|         };
 | |
| 
 | |
|         // Get total count for pagination
 | |
|         var totalCount = await query.CountAsync();
 | |
| 
 | |
|         // Apply pagination
 | |
|         var accounts = await query
 | |
|             .Skip(request.PageSize * (request.PageToken != null ? int.Parse(request.PageToken) : 0))
 | |
|             .Take(request.PageSize)
 | |
|             .Include(a => a.Profile)
 | |
|             .ToListAsync();
 | |
| 
 | |
|         var perks = await subscriptions.GetPerkSubscriptionsAsync(
 | |
|             accounts.Select(x => x.Id).ToList()
 | |
|         );
 | |
|         foreach (var account in accounts)
 | |
|             if (perks.TryGetValue(account.Id, out var perk))
 | |
|                 account.PerkSubscription = perk?.ToReference();
 | |
| 
 | |
|         var response = new ListAccountsResponse
 | |
|         {
 | |
|             TotalSize = totalCount,
 | |
|             NextPageToken = (accounts.Count == request.PageSize)
 | |
|                 ? ((request.PageToken != null ? int.Parse(request.PageToken) : 0) + 1).ToString()
 | |
|                 : ""
 | |
|         };
 | |
| 
 | |
|         response.Accounts.AddRange(accounts.Select(x => x.ToProtoValue()));
 | |
|         return response;
 | |
|     }
 | |
| 
 | |
|     public override async Task<ListRelationshipSimpleResponse> ListFriends(
 | |
|         ListRelationshipSimpleRequest request, ServerCallContext context)
 | |
|     {
 | |
|         var accountId = Guid.Parse(request.AccountId);
 | |
|         var relationship = await relationships.ListAccountFriends(accountId);
 | |
|         var resp = new ListRelationshipSimpleResponse();
 | |
|         resp.AccountsId.AddRange(relationship.Select(x => x.ToString()));
 | |
|         return resp;
 | |
|     }
 | |
| 
 | |
|     public override async Task<ListRelationshipSimpleResponse> ListBlocked(
 | |
|         ListRelationshipSimpleRequest request, ServerCallContext context)
 | |
|     {
 | |
|         var accountId = Guid.Parse(request.AccountId);
 | |
|         var relationship = await relationships.ListAccountBlocked(accountId);
 | |
|         var resp = new ListRelationshipSimpleResponse();
 | |
|         resp.AccountsId.AddRange(relationship.Select(x => x.ToString()));
 | |
|         return resp;
 | |
|     }
 | |
| 
 | |
|     public override async Task<GetRelationshipResponse> GetRelationship(GetRelationshipRequest request,
 | |
|         ServerCallContext context)
 | |
|     {
 | |
|         var relationship = await relationships.GetRelationship(
 | |
|             Guid.Parse(request.AccountId),
 | |
|             Guid.Parse(request.RelatedId),
 | |
|             status: (Shared.Models.RelationshipStatus?)request.Status
 | |
|         );
 | |
|         return new GetRelationshipResponse
 | |
|         {
 | |
|             Relationship = relationship?.ToProtoValue()
 | |
|         };
 | |
|     }
 | |
| 
 | |
|     public override async Task<BoolValue> HasRelationship(GetRelationshipRequest request, ServerCallContext context)
 | |
|     {
 | |
|         bool hasRelationship;
 | |
|         if (!request.HasStatus)
 | |
|             hasRelationship = await relationships.HasExistingRelationship(
 | |
|                 Guid.Parse(request.AccountId),
 | |
|                 Guid.Parse(request.RelatedId)
 | |
|             );
 | |
|         else
 | |
|             hasRelationship = await relationships.HasRelationshipWithStatus(
 | |
|                 Guid.Parse(request.AccountId),
 | |
|                 Guid.Parse(request.RelatedId),
 | |
|                 (Shared.Models.RelationshipStatus)request.Status
 | |
|             );
 | |
|         return new BoolValue { Value = hasRelationship };
 | |
|     }
 | |
| } |