diff --git a/DysonNetwork.Pass/Account/AccountController.cs b/DysonNetwork.Pass/Account/AccountController.cs index f556598..07b0909 100644 --- a/DysonNetwork.Pass/Account/AccountController.cs +++ b/DysonNetwork.Pass/Account/AccountController.cs @@ -1,5 +1,6 @@ using System.ComponentModel.DataAnnotations; using DysonNetwork.Pass.Auth; +using DysonNetwork.Pass.Credit; using DysonNetwork.Pass.Wallet; using DysonNetwork.Shared.Error; using Microsoft.AspNetCore.Mvc; @@ -15,7 +16,8 @@ public class AccountController( AuthService auth, AccountService accounts, SubscriptionService subscriptions, - AccountEventService events + AccountEventService events, + SocialCreditService socialCreditService ) : ControllerBase { [HttpGet("{name}")] @@ -48,6 +50,25 @@ public class AccountController( .FirstOrDefaultAsync(); return account is null ? NotFound(ApiError.NotFound(name, traceId: HttpContext.TraceIdentifier)) : account.Badges.ToList(); } + + [HttpGet("{name}/credits")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + public async Task> GetSocialCredits(string name) + { + var account = await db.Accounts + .Where(a => a.Name == name) + .Select(a => new { a.Id }) + .FirstOrDefaultAsync(); + + if (account is null) + { + return NotFound(ApiError.NotFound(name, traceId: HttpContext.TraceIdentifier)); + } + + var credits = await socialCreditService.GetSocialCredit(account.Id); + return credits; + } public class AccountCreateRequest { diff --git a/DysonNetwork.Pass/Credit/SocialCreditRecord.cs b/DysonNetwork.Pass/Credit/SocialCreditRecord.cs index 1815c64..de56891 100644 --- a/DysonNetwork.Pass/Credit/SocialCreditRecord.cs +++ b/DysonNetwork.Pass/Credit/SocialCreditRecord.cs @@ -4,6 +4,8 @@ using NodaTime; namespace DysonNetwork.Pass.Credit; +using Google.Protobuf.WellKnownTypes; + public class SocialCreditRecord : ModelBase { public Guid Id { get; set; } @@ -14,4 +16,20 @@ public class SocialCreditRecord : ModelBase public Guid AccountId { get; set; } public Account.Account Account { get; set; } = null!; + + public Shared.Proto.SocialCreditRecord ToProto() + { + var proto = new Shared.Proto.SocialCreditRecord + { + Id = Id.ToString(), + ReasonType = ReasonType, + Reason = Reason, + Delta = Delta, + AccountId = AccountId.ToString(), + CreatedAt = Timestamp.FromDateTimeOffset(CreatedAt.ToDateTimeOffset()), + UpdatedAt = Timestamp.FromDateTimeOffset(UpdatedAt.ToDateTimeOffset()) + }; + + return proto; + } } \ No newline at end of file diff --git a/DysonNetwork.Pass/Credit/SocialCreditServiceGrpc.cs b/DysonNetwork.Pass/Credit/SocialCreditServiceGrpc.cs new file mode 100644 index 0000000..c5d13b8 --- /dev/null +++ b/DysonNetwork.Pass/Credit/SocialCreditServiceGrpc.cs @@ -0,0 +1,27 @@ +using DysonNetwork.Shared.Proto; +using Grpc.Core; + +namespace DysonNetwork.Pass.Credit; + +public class SocialCreditServiceGrpc(SocialCreditService creditService) : Shared.Proto.SocialCreditService.SocialCreditServiceBase +{ + public override async Task AddRecord(AddSocialCreditRecordRequest request, ServerCallContext context) + { + var accountId = Guid.Parse(request.AccountId); + var record = await creditService.AddRecord( + request.ReasonType, + request.Reason, + request.Delta, + accountId); + + return record.ToProto(); + } + + public override async Task GetSocialCredit(GetSocialCreditRequest request, ServerCallContext context) + { + var accountId = Guid.Parse(request.AccountId); + var amount = await creditService.GetSocialCredit(accountId); + + return new SocialCreditResponse { Amount = amount }; + } +} \ No newline at end of file diff --git a/DysonNetwork.Pass/Leveling/ExperienceRecord.cs b/DysonNetwork.Pass/Leveling/ExperienceRecord.cs index f33429a..267a6b4 100644 --- a/DysonNetwork.Pass/Leveling/ExperienceRecord.cs +++ b/DysonNetwork.Pass/Leveling/ExperienceRecord.cs @@ -3,6 +3,8 @@ using DysonNetwork.Shared.Data; namespace DysonNetwork.Pass.Leveling; +using Google.Protobuf.WellKnownTypes; + public class ExperienceRecord : ModelBase { public Guid Id { get; set; } = Guid.NewGuid(); @@ -13,4 +15,21 @@ public class ExperienceRecord : ModelBase public Guid AccountId { get; set; } public Account.Account Account { get; set; } = null!; + + public Shared.Proto.ExperienceRecord ToProto() + { + var proto = new Shared.Proto.ExperienceRecord + { + Id = Id.ToString(), + ReasonType = ReasonType, + Reason = Reason, + Delta = Delta, + BonusMultiplier = BonusMultiplier, + AccountId = AccountId.ToString(), + CreatedAt = Timestamp.FromDateTimeOffset(CreatedAt.ToDateTimeOffset()), + UpdatedAt = Timestamp.FromDateTimeOffset(UpdatedAt.ToDateTimeOffset()) + }; + + return proto; + } } \ No newline at end of file diff --git a/DysonNetwork.Pass/Leveling/ExperienceServiceGrpc.cs b/DysonNetwork.Pass/Leveling/ExperienceServiceGrpc.cs new file mode 100644 index 0000000..89ec84e --- /dev/null +++ b/DysonNetwork.Pass/Leveling/ExperienceServiceGrpc.cs @@ -0,0 +1,19 @@ +using DysonNetwork.Shared.Proto; +using Grpc.Core; + +namespace DysonNetwork.Pass.Leveling; + +public class ExperienceServiceGrpc(ExperienceService experienceService) : Shared.Proto.ExperienceService.ExperienceServiceBase +{ + public override async Task AddRecord(AddExperienceRecordRequest request, ServerCallContext context) + { + var accountId = Guid.Parse(request.AccountId); + var record = await experienceService.AddRecord( + request.ReasonType, + request.Reason, + request.Delta, + accountId); + + return record.ToProto(); + } +} \ No newline at end of file diff --git a/DysonNetwork.Pass/Startup/ApplicationConfiguration.cs b/DysonNetwork.Pass/Startup/ApplicationConfiguration.cs index 38d299c..94f475a 100644 --- a/DysonNetwork.Pass/Startup/ApplicationConfiguration.cs +++ b/DysonNetwork.Pass/Startup/ApplicationConfiguration.cs @@ -1,6 +1,8 @@ using System.Net; using DysonNetwork.Pass.Account; using DysonNetwork.Pass.Auth; +using DysonNetwork.Pass.Credit; +using DysonNetwork.Pass.Leveling; using DysonNetwork.Pass.Permission; using Microsoft.AspNetCore.HttpOverrides; using Microsoft.Extensions.FileProviders; @@ -76,6 +78,8 @@ public static class ApplicationConfiguration app.MapGrpcService(); app.MapGrpcService(); app.MapGrpcService(); + app.MapGrpcService(); + app.MapGrpcService(); app.MapGrpcService(); return app; diff --git a/DysonNetwork.Shared/Proto/leveling.proto b/DysonNetwork.Shared/Proto/leveling.proto new file mode 100644 index 0000000..ea413f2 --- /dev/null +++ b/DysonNetwork.Shared/Proto/leveling.proto @@ -0,0 +1,83 @@ +syntax = "proto3"; + +package proto; + +option csharp_namespace = "DysonNetwork.Shared.Proto"; + +import "google/protobuf/timestamp.proto"; +import "google/protobuf/empty.proto"; +import "google/protobuf/field_mask.proto"; + +// ==================================== +// Message Definitions +// ==================================== + +// SocialCreditRecord represents a record of social credit changes for an account +message SocialCreditRecord { + string id = 1; // UUID string + string reason_type = 2; + string reason = 3; + double delta = 4; + string account_id = 5; // UUID string + google.protobuf.Timestamp created_at = 6; + google.protobuf.Timestamp updated_at = 7; +} + +// ExperienceRecord represents a record of experience points gained by an account +message ExperienceRecord { + string id = 1; // UUID string + string reason_type = 2; + string reason = 3; + int64 delta = 4; + double bonus_multiplier = 5; + string account_id = 6; // UUID string + google.protobuf.Timestamp created_at = 7; + google.protobuf.Timestamp updated_at = 8; +} + +// ==================================== +// Request/Response Messages +// ==================================== + +// Social Credit Requests/Responses +message AddSocialCreditRecordRequest { + string reason_type = 1; + string reason = 2; + double delta = 3; + string account_id = 4; // UUID string +} + +message GetSocialCreditRequest { + string account_id = 1; // UUID string +} + +message SocialCreditResponse { + double amount = 1; +} + +// Experience Requests/Responses +message AddExperienceRecordRequest { + string reason_type = 1; + string reason = 2; + int64 delta = 3; + string account_id = 4; // UUID string +} + +// ==================================== +// Service Definitions +// ==================================== + +// SocialCreditService provides operations for managing social credit scores +service SocialCreditService { + // Adds a new social credit record for an account + rpc AddRecord(AddSocialCreditRecordRequest) returns (SocialCreditRecord); + + // Gets the current social credit score for an account + rpc GetSocialCredit(GetSocialCreditRequest) returns (SocialCreditResponse); +} + +// ExperienceService provides operations for managing experience points +service ExperienceService { + // Adds a new experience record for an account + rpc AddRecord(AddExperienceRecordRequest) returns (ExperienceRecord); +}