✨ Rewind service basis and sphere service rewind
This commit is contained in:
@@ -0,0 +1,6 @@
|
|||||||
|
namespace DysonNetwork.Pass.Account.Rewind;
|
||||||
|
|
||||||
|
public class AccountRewindController
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
6
DysonNetwork.Pass/Account/Rewind/AccountRewindService.cs
Normal file
6
DysonNetwork.Pass/Account/Rewind/AccountRewindService.cs
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
namespace DysonNetwork.Pass.Account.Rewind;
|
||||||
|
|
||||||
|
public class AccountRewindService(AppDatabase db)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
@@ -63,6 +63,8 @@ public class AppDatabase(
|
|||||||
|
|
||||||
public DbSet<SnAffiliationSpell> AffiliationSpells { get; set; } = null!;
|
public DbSet<SnAffiliationSpell> AffiliationSpells { get; set; } = null!;
|
||||||
public DbSet<SnAffiliationResult> AffiliationResults { get; set; } = null!;
|
public DbSet<SnAffiliationResult> AffiliationResults { get; set; } = null!;
|
||||||
|
|
||||||
|
public DbSet<SnRewindPoint> RewindPoints { get; set; }
|
||||||
|
|
||||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||||
{
|
{
|
||||||
|
|||||||
14
DysonNetwork.Shared/Models/SnRewindPoint.cs
Normal file
14
DysonNetwork.Shared/Models/SnRewindPoint.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
|
||||||
|
namespace DysonNetwork.Shared.Models;
|
||||||
|
|
||||||
|
public class SnRewindPoint
|
||||||
|
{
|
||||||
|
public Guid Id { get; set; } = Guid.NewGuid();
|
||||||
|
public int Year { get; set; } = DateTime.UtcNow.Year;
|
||||||
|
|
||||||
|
[Column(TypeName = "jsonb")] public Dictionary<string, string> Data { get; set; } = new();
|
||||||
|
|
||||||
|
public Guid AccountId { get; set; }
|
||||||
|
public SnAccount Account { get; set; } = null!;
|
||||||
|
}
|
||||||
19
DysonNetwork.Shared/Proto/rewind.proto
Normal file
19
DysonNetwork.Shared/Proto/rewind.proto
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package proto;
|
||||||
|
|
||||||
|
option csharp_namespace = "DysonNetwork.Shared.Proto";
|
||||||
|
|
||||||
|
message RewindEvent {
|
||||||
|
string account_id = 1;
|
||||||
|
optional bytes data = 2;
|
||||||
|
string service_id = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message RequestRewindEvent {
|
||||||
|
string account_id = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
service RewindService {
|
||||||
|
rpc GetRewindEvent(RequestRewindEvent) returns (RewindEvent) {}
|
||||||
|
}
|
||||||
@@ -20,6 +20,14 @@ public class PublisherService(
|
|||||||
RemoteAccountService remoteAccounts
|
RemoteAccountService remoteAccounts
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
public async Task<SnPublisher?> GetPublisherLoaded(Guid id)
|
||||||
|
{
|
||||||
|
var publisher = await db.Publishers
|
||||||
|
.Where(p => p.Id == id)
|
||||||
|
.FirstOrDefaultAsync();
|
||||||
|
return publisher is null ? null : (await LoadIndividualPublisherAccounts([publisher])).First();
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<SnPublisher?> GetPublisherByName(string name)
|
public async Task<SnPublisher?> GetPublisherByName(string name)
|
||||||
{
|
{
|
||||||
return await db.Publishers
|
return await db.Publishers
|
||||||
@@ -453,7 +461,7 @@ public class PublisherService(
|
|||||||
public async Task<List<SnPublisher>> LoadIndividualPublisherAccounts(ICollection<SnPublisher> publishers)
|
public async Task<List<SnPublisher>> LoadIndividualPublisherAccounts(ICollection<SnPublisher> publishers)
|
||||||
{
|
{
|
||||||
var accountIds = publishers
|
var accountIds = publishers
|
||||||
.Where(p => p.AccountId.HasValue && p.Type == PublisherType.Individual)
|
.Where(p => p is { AccountId: not null, Type: PublisherType.Individual })
|
||||||
.Select(p => p.AccountId!.Value)
|
.Select(p => p.AccountId!.Value)
|
||||||
.ToList();
|
.ToList();
|
||||||
if (accountIds.Count == 0) return publishers.ToList();
|
if (accountIds.Count == 0) return publishers.ToList();
|
||||||
@@ -638,7 +646,7 @@ public class PublisherService(
|
|||||||
|
|
||||||
if (!publisherAccounts.TryGetValue(publisherId, out var receivers) || receivers.Count == 0)
|
if (!publisherAccounts.TryGetValue(publisherId, out var receivers) || receivers.Count == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var publisherName = publishers.TryGetValue(publisherId, out var pub) ? pub.Name : "unknown";
|
var publisherName = publishers.TryGetValue(publisherId, out var pub) ? pub.Name : "unknown";
|
||||||
|
|
||||||
// Set social credit for receivers, expired before next settle
|
// Set social credit for receivers, expired before next settle
|
||||||
|
|||||||
97
DysonNetwork.Sphere/Rewind/SphereRewindServiceGrpc.cs
Normal file
97
DysonNetwork.Sphere/Rewind/SphereRewindServiceGrpc.cs
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
using System.Globalization;
|
||||||
|
using DysonNetwork.Shared.Proto;
|
||||||
|
using DysonNetwork.Shared.Registry;
|
||||||
|
using Grpc.Core;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace DysonNetwork.Sphere.Rewind;
|
||||||
|
|
||||||
|
public class SphereRewindServiceGrpc(
|
||||||
|
AppDatabase db,
|
||||||
|
RemoteAccountService remoteAccounts,
|
||||||
|
Publisher.PublisherService ps
|
||||||
|
) : RewindService.RewindServiceBase
|
||||||
|
{
|
||||||
|
public override async Task<RewindEvent> GetRewindEvent(RequestRewindEvent request, ServerCallContext context)
|
||||||
|
{
|
||||||
|
var accountId = Guid.Parse(request.AccountId);
|
||||||
|
|
||||||
|
// Audience data
|
||||||
|
var mostLovedPublisherClue =
|
||||||
|
await db.PostReactions
|
||||||
|
.Where(p => p.AccountId == accountId && p.Attitude == Shared.Models.PostReactionAttitude.Positive)
|
||||||
|
.GroupBy(p => p.Post.PublisherId)
|
||||||
|
.OrderByDescending(g => g.Count())
|
||||||
|
.Select(g => new { PublisherId = g.Key, ReactionCount = g.Count() })
|
||||||
|
.FirstOrDefaultAsync();
|
||||||
|
var mostLovedPublisher = mostLovedPublisherClue is not null
|
||||||
|
? ps.GetPublisherLoaded(mostLovedPublisherClue.PublisherId)
|
||||||
|
: null;
|
||||||
|
|
||||||
|
// Creator data
|
||||||
|
var publishers = await db.PublisherMembers
|
||||||
|
.Where(pm => pm.AccountId == accountId)
|
||||||
|
.Select(pm => pm.PublisherId)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
var mostLovedAudienceClue =
|
||||||
|
await db.PostReactions
|
||||||
|
.Where(pr =>
|
||||||
|
pr.Attitude == Shared.Models.PostReactionAttitude.Positive &&
|
||||||
|
publishers.Contains(pr.Post.PublisherId))
|
||||||
|
.GroupBy(pr => pr.AccountId)
|
||||||
|
.OrderByDescending(g => g.Count())
|
||||||
|
.Select(g => new { AccountId = g.Key, ReactionCount = g.Count() })
|
||||||
|
.FirstOrDefaultAsync();
|
||||||
|
var mostLovedAudience = mostLovedAudienceClue is not null
|
||||||
|
? await remoteAccounts.GetAccount(mostLovedAudienceClue.AccountId)
|
||||||
|
: null;
|
||||||
|
|
||||||
|
var posts = await db.Posts
|
||||||
|
.Where(p => publishers.Contains(p.PublisherId))
|
||||||
|
.ToListAsync();
|
||||||
|
var postTotalCount = posts.Count;
|
||||||
|
var mostPopularPost = posts
|
||||||
|
.OrderByDescending(p => p.Upvotes - p.Downvotes)
|
||||||
|
.FirstOrDefault();
|
||||||
|
var mostProductiveDay = posts
|
||||||
|
.GroupBy(p => p.CreatedAt.ToDateTimeUtc().Date)
|
||||||
|
.OrderByDescending(g => g.Count())
|
||||||
|
.Select(g => new { Date = g.Key, PostCount = g.Count() })
|
||||||
|
.FirstOrDefault();
|
||||||
|
|
||||||
|
var data = new Dictionary<string, object?>
|
||||||
|
{
|
||||||
|
["total_count"] = postTotalCount,
|
||||||
|
["most_popular_post"] = mostPopularPost,
|
||||||
|
["most_productive_day"] = mostProductiveDay is not null
|
||||||
|
? new Dictionary<string, object?>
|
||||||
|
{
|
||||||
|
["date"] = mostProductiveDay.Date.ToString(CultureInfo.InvariantCulture),
|
||||||
|
["post_count"] = mostProductiveDay.PostCount,
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
["most_loved_publisher"] = mostLovedPublisherClue is not null
|
||||||
|
? new Dictionary<string, object?>
|
||||||
|
{
|
||||||
|
["publisher"] = mostLovedPublisher,
|
||||||
|
["upvote_counts"] = mostLovedPublisherClue.ReactionCount,
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
["most_loved_audience"] = mostLovedAudienceClue is not null
|
||||||
|
? new Dictionary<string, object?>
|
||||||
|
{
|
||||||
|
["account"] = mostLovedAudience,
|
||||||
|
["upvote_counts"] = mostLovedAudienceClue.ReactionCount,
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
return new RewindEvent
|
||||||
|
{
|
||||||
|
ServiceId = "sphere",
|
||||||
|
AccountId = request.AccountId,
|
||||||
|
Data = GrpcTypeHelper.ConvertObjectToByteString(data)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@ using DysonNetwork.Shared.Auth;
|
|||||||
using DysonNetwork.Shared.Http;
|
using DysonNetwork.Shared.Http;
|
||||||
using DysonNetwork.Sphere.Post;
|
using DysonNetwork.Sphere.Post;
|
||||||
using DysonNetwork.Sphere.Publisher;
|
using DysonNetwork.Sphere.Publisher;
|
||||||
|
using DysonNetwork.Sphere.Rewind;
|
||||||
|
|
||||||
namespace DysonNetwork.Sphere.Startup;
|
namespace DysonNetwork.Sphere.Startup;
|
||||||
|
|
||||||
@@ -23,6 +24,7 @@ public static class ApplicationConfiguration
|
|||||||
// Map gRPC services
|
// Map gRPC services
|
||||||
app.MapGrpcService<PostServiceGrpc>();
|
app.MapGrpcService<PostServiceGrpc>();
|
||||||
app.MapGrpcService<PublisherServiceGrpc>();
|
app.MapGrpcService<PublisherServiceGrpc>();
|
||||||
|
app.MapGrpcService<SphereRewindServiceGrpc>();
|
||||||
app.MapGrpcReflectionService();
|
app.MapGrpcReflectionService();
|
||||||
|
|
||||||
return app;
|
return app;
|
||||||
|
|||||||
Reference in New Issue
Block a user