♻️ Finish centerlizing the data models

This commit is contained in:
2025-09-27 15:14:05 +08:00
parent e70d8371f8
commit 9ce31c4dd8
167 changed files with 780 additions and 42880 deletions

View File

@@ -1,3 +1,4 @@
using DysonNetwork.Shared.Models;
using DysonNetwork.Shared.Proto;
using Microsoft.AspNetCore.Mvc;
using NodaTime;
@@ -23,7 +24,7 @@ public class ActivityController(
/// Besides, when users are logged in, it will also mix the other kinds of data and who're plying to them.
/// </summary>
[HttpGet]
public async Task<ActionResult<List<Activity>>> ListActivities(
public async Task<ActionResult<List<SnActivity>>> ListActivities(
[FromQuery] string? cursor,
[FromQuery] string? filter,
[FromQuery] int take = 20,

View File

@@ -31,12 +31,12 @@ public class ActivityService(
return performanceWeight / Math.Pow(normalizedTime + 1.0, 1.2);
}
public async Task<List<Activity>> GetActivitiesForAnyone(
public async Task<List<SnActivity>> GetActivitiesForAnyone(
int take,
Instant? cursor,
HashSet<string>? debugInclude = null)
{
var activities = new List<Activity>();
var activities = new List<SnActivity>();
debugInclude ??= new HashSet<string>();
// Get and process posts
@@ -55,7 +55,7 @@ public class ActivityService(
var posts = await GetAndProcessPosts(postsQuery);
posts = RankPosts(posts, take);
var interleaved = new List<Activity>();
var interleaved = new List<SnActivity>();
var random = new Random();
foreach (var post in posts)
{
@@ -73,19 +73,19 @@ public class ActivityService(
activities.AddRange(interleaved);
if (activities.Count == 0)
activities.Add(Activity.Empty());
activities.Add(SnActivity.Empty());
return activities;
}
public async Task<List<Activity>> GetActivities(
public async Task<List<SnActivity>> GetActivities(
int take,
Instant? cursor,
Account currentUser,
string? filter = null,
HashSet<string>? debugInclude = null)
{
var activities = new List<Activity>();
var activities = new List<SnActivity>();
debugInclude ??= new HashSet<string>();
// Get user's friends and publishers
@@ -124,7 +124,7 @@ public class ActivityService(
posts = RankPosts(posts, take);
var interleaved = new List<Activity>();
var interleaved = new List<SnActivity>();
var random = new Random();
foreach (var post in posts)
{
@@ -141,15 +141,15 @@ public class ActivityService(
activities.AddRange(interleaved);
if (activities.Count == 0)
activities.Add(Activity.Empty());
activities.Add(SnActivity.Empty());
return activities;
}
private async Task<Activity?> MaybeGetDiscoveryActivity(HashSet<string> debugInclude, Instant? cursor)
private async Task<SnActivity?> MaybeGetDiscoveryActivity(HashSet<string> debugInclude, Instant? cursor)
{
if (cursor != null) return null;
var options = new List<Func<Task<Activity?>>>();
var options = new List<Func<Task<SnActivity?>>>();
if (debugInclude.Contains("realms") || Random.Shared.NextDouble() < 0.2)
options.Add(() => GetRealmDiscoveryActivity());
if (debugInclude.Contains("publishers") || Random.Shared.NextDouble() < 0.2)
@@ -200,7 +200,7 @@ public class ActivityService(
.ToList();
}
private async Task<Activity?> GetRealmDiscoveryActivity(int count = 5)
private async Task<SnActivity?> GetRealmDiscoveryActivity(int count = 5)
{
var realms = await ds.GetCommunityRealmAsync(null, count, 0, true);
return realms.Count > 0
@@ -208,7 +208,7 @@ public class ActivityService(
: null;
}
private async Task<Activity?> GetPublisherDiscoveryActivity(int count = 5)
private async Task<SnActivity?> GetPublisherDiscoveryActivity(int count = 5)
{
var popularPublishers = await GetPopularPublishers(count);
return popularPublishers.Count > 0
@@ -217,7 +217,7 @@ public class ActivityService(
: null;
}
private async Task<Activity?> GetShuffledPostsActivity(int count = 5)
private async Task<SnActivity?> GetShuffledPostsActivity(int count = 5)
{
var postsQuery = db.Posts
.Include(p => p.Categories)
@@ -234,7 +234,7 @@ public class ActivityService(
: new DiscoveryActivity(posts.Select(x => new DiscoveryItem("post", x)).ToList()).ToActivity();
}
private async Task<Activity?> GetArticleDiscoveryActivity(int count = 5, int feedSampleSize = 10)
private async Task<SnActivity?> GetArticleDiscoveryActivity(int count = 5, int feedSampleSize = 10)
{
var now = SystemClock.Instance.GetCurrentInstant();
var today = now.InZone(DateTimeZone.Utc).Date;

View File

@@ -1,5 +1,3 @@
using System;
using System.Collections.Generic;
using DysonNetwork.Shared.Models;
using NodaTime;
@@ -9,10 +7,10 @@ public class DiscoveryActivity(List<DiscoveryItem> items) : IActivity
{
public List<DiscoveryItem> Items { get; set; } = items;
public Activity ToActivity()
public SnActivity ToActivity()
{
var now = SystemClock.Instance.GetCurrentInstant();
return new Activity
return new SnActivity
{
Id = Guid.NewGuid(),
Type = "discovery",

View File

@@ -1,6 +1,5 @@
using System.Linq.Expressions;
using System.Reflection;
using DysonNetwork.Shared.Data;
using DysonNetwork.Shared.Models;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
@@ -20,10 +19,10 @@ public class AppDatabase(
IConfiguration configuration
) : DbContext(options)
{
public DbSet<Shared.Models.SnPublisher> Publishers { get; set; } = null!;
public DbSet<PublisherMember> PublisherMembers { get; set; } = null!;
public DbSet<PublisherSubscription> PublisherSubscriptions { get; set; } = null!;
public DbSet<PublisherFeature> PublisherFeatures { get; set; } = null!;
public DbSet<SnPublisher> Publishers { get; set; } = null!;
public DbSet<SnPublisherMember> PublisherMembers { get; set; } = null!;
public DbSet<SnPublisherSubscription> PublisherSubscriptions { get; set; } = null!;
public DbSet<SnPublisherFeature> PublisherFeatures { get; set; } = null!;
public DbSet<SnPost> Posts { get; set; } = null!;
public DbSet<SnPostReaction> PostReactions { get; set; } = null!;
@@ -72,14 +71,14 @@ public class AppDatabase(
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<PublisherMember>()
modelBuilder.Entity<SnPublisherMember>()
.HasKey(pm => new { pm.PublisherId, pm.AccountId });
modelBuilder.Entity<PublisherMember>()
modelBuilder.Entity<SnPublisherMember>()
.HasOne(pm => pm.Publisher)
.WithMany(p => p.Members)
.HasForeignKey(pm => pm.PublisherId)
.OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity<PublisherSubscription>()
modelBuilder.Entity<SnPublisherSubscription>()
.HasOne(ps => ps.Publisher)
.WithMany(p => p.Subscriptions)
.HasForeignKey(ps => ps.PublisherId)

View File

@@ -3,7 +3,6 @@ using DysonNetwork.Shared.Models;
using DysonNetwork.Shared.Registry;
using Microsoft.EntityFrameworkCore;
using NodaTime;
using Account = DysonNetwork.Shared.Data.SnAccount;
namespace DysonNetwork.Sphere.Chat;
@@ -147,7 +146,7 @@ public class ChatRoomService(
public async Task<SnChatMember> LoadMemberAccount(SnChatMember member)
{
var account = await accountsHelper.GetAccount(member.AccountId);
member.Account = Account.FromProtoValue(account);
member.Account = SnAccount.FromProtoValue(account);
return member;
}
@@ -156,11 +155,11 @@ public class ChatRoomService(
var accountIds = members.Select(m => m.AccountId).ToList();
var accounts = (await accountsHelper.GetAccountBatch(accountIds)).ToDictionary(a => Guid.Parse(a.Id), a => a);
return members.Select(m =>
return [.. members.Select(m =>
{
if (accounts.TryGetValue(m.AccountId, out var account))
m.Account = Account.FromProtoValue(account);
m.Account = SnAccount.FromProtoValue(account);
return m;
}).ToList();
})];
}
}

View File

@@ -1,6 +1,3 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using DysonNetwork.Shared.Proto;
namespace DysonNetwork.Sphere.Chat.Realtime;

View File

@@ -1,7 +1,6 @@
using DysonNetwork.Shared.Models;
using DysonNetwork.Shared.Proto;
using DysonNetwork.Sphere.Chat.Realtime;
using Livekit.Server.Sdk.Dotnet;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;

View File

@@ -1,6 +1,4 @@
using System;
using System.Collections.Generic;
using DysonNetwork.Shared.Models;
using DysonNetwork.Shared.Models;
using DysonNetwork.Sphere.WebReader;
using Microsoft.EntityFrameworkCore.Migrations;
using NodaTime;

View File

@@ -1,6 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json;
using DysonNetwork.Shared.Models;
using Microsoft.EntityFrameworkCore.Migrations;
using NodaTime;

View File

@@ -1,5 +1,4 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Migrations;
using NodaTime;
#nullable disable

View File

@@ -1,5 +1,4 @@
using System;
using DysonNetwork.Shared.Models;
using DysonNetwork.Shared.Models;
using Microsoft.EntityFrameworkCore.Migrations;
using NodaTime;

View File

@@ -1,5 +1,4 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Migrations;
using NodaTime;
#nullable disable

View File

@@ -1,5 +1,4 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable

View File

@@ -1,5 +1,4 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Migrations;
using NodaTime;
#nullable disable

View File

@@ -1,5 +1,4 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Migrations;
using NodaTime;
#nullable disable

View File

@@ -1,5 +1,4 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Migrations;
using NodaTime;
#nullable disable

View File

@@ -1,6 +1,5 @@
using System.ComponentModel.DataAnnotations;
using System.Text.Json;
using DysonNetwork.Shared.Data;
using DysonNetwork.Shared.Models;
using DysonNetwork.Shared.Proto;
using DysonNetwork.Shared.Registry;
@@ -127,7 +126,7 @@ public class PollController(
[HttpGet("me")]
[Authorize]
public async Task<ActionResult<List<Poll>>> ListPolls(
public async Task<ActionResult<List<SnPoll>>> ListPolls(
[FromQuery(Name = "pub")] string? pubName,
[FromQuery] bool active = false,
[FromQuery] int offset = 0,
@@ -199,7 +198,7 @@ public class PollController(
[HttpPost]
[Authorize]
public async Task<ActionResult<Poll>> CreatePoll([FromBody] PollRequest request,
public async Task<ActionResult<SnPoll>> CreatePoll([FromBody] PollRequest request,
[FromQuery(Name = "pub")] string pubName)
{
if (request.Questions is null) return BadRequest("Questions are required.");
@@ -211,7 +210,7 @@ public class PollController(
if (!await pub.IsMemberWithRole(publisher.Id, accountId, Shared.Models.PublisherMemberRole.Editor))
return StatusCode(403, "You need at least be an editor to create polls as this publisher.");
var poll = new Poll
var poll = new SnPoll
{
Title = request.Title,
Description = request.Description,
@@ -237,7 +236,7 @@ public class PollController(
[HttpPatch("{id:guid}")]
[Authorize]
public async Task<ActionResult<Poll>> UpdatePoll(Guid id, [FromBody] PollRequest request)
public async Task<ActionResult<SnPoll>> UpdatePoll(Guid id, [FromBody] PollRequest request)
{
if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized();
var accountId = Guid.Parse(currentUser.Id);

View File

@@ -3,12 +3,12 @@ using DysonNetwork.Sphere.WebReader;
namespace DysonNetwork.Sphere.Poll;
public class PollWithStats : Poll
public class PollWithStats : SnPoll
{
public SnPollAnswer? UserAnswer { get; set; }
public Dictionary<Guid, Dictionary<string, int>> Stats { get; set; } = new(); // question id -> (option id -> count)
public static PollWithStats FromPoll(Poll poll, SnPollAnswer? userAnswer = null)
public static PollWithStats FromPoll(SnPoll poll, SnPollAnswer? userAnswer = null)
{
return new PollWithStats
{

View File

@@ -8,7 +8,7 @@ namespace DysonNetwork.Sphere.Poll;
public class PollService(AppDatabase db, ICacheService cache)
{
public void ValidatePoll(Poll poll)
public void ValidatePoll(SnPoll poll)
{
if (poll.Questions.Count == 0)
throw new Exception("Poll must have at least one question");
@@ -32,7 +32,7 @@ public class PollService(AppDatabase db, ICacheService cache)
}
}
public async Task<Poll?> GetPoll(Guid id)
public async Task<SnPoll?> GetPoll(Guid id)
{
var poll = await db.Polls
.Where(e => e.Id == id)
@@ -307,9 +307,7 @@ public class PollService(AppDatabase db, ICacheService cache)
public async Task<PollEmbed> LoadPollEmbed(Guid pollId, Guid? accountId)
{
var poll = await GetPoll(pollId);
if (poll is null)
throw new Exception("Poll not found");
var poll = await GetPoll(pollId) ?? throw new Exception("Poll not found");
var pollWithStats = PollWithStats.FromPoll(poll);
pollWithStats.Stats = await GetPollStats(poll.Id);
if (accountId is not null)

View File

@@ -1,4 +1,3 @@
using DysonNetwork.Shared.Data;
using DysonNetwork.Shared.Models;
using DysonNetwork.Shared.Proto;
using Microsoft.AspNetCore.Authorization;

View File

@@ -2,7 +2,6 @@ using System.ComponentModel.DataAnnotations;
using System.Globalization;
using DysonNetwork.Shared.Auth;
using DysonNetwork.Shared.Content;
using DysonNetwork.Shared.Data;
using DysonNetwork.Shared.Models;
using DysonNetwork.Shared.Proto;
using DysonNetwork.Sphere.Poll;

View File

@@ -93,7 +93,7 @@ public class PublisherController(
public class PublisherMemberRequest
{
[Required] public long RelatedUserId { get; set; }
[Required] public PublisherMemberRole Role { get; set; }
[Required] public Shared.Models.PublisherMemberRole Role { get; set; }
}
[HttpPost("invites/{name}")]
@@ -226,7 +226,7 @@ public class PublisherController(
.FirstOrDefaultAsync();
var accountId = Guid.Parse(currentUser.Id);
if (member is null) return NotFound("Member was not found");
if (!await ps.IsMemberWithRole(publisher.Id, accountId, PublisherMemberRole.Manager))
if (!await ps.IsMemberWithRole(publisher.Id, accountId, Shared.Models.PublisherMemberRole.Manager))
return StatusCode(403, "You need at least be a manager to remove members from this publisher.");
db.PublisherMembers.Remove(member);
@@ -428,7 +428,7 @@ public class PublisherController(
.Where(m => m.PublisherId == publisher.Id)
.FirstOrDefaultAsync();
if (member is null) return StatusCode(403, "You are not even a member of the targeted publisher.");
if (member.Role < PublisherMemberRole.Manager)
if (member.Role < Shared.Models.PublisherMemberRole.Manager)
return StatusCode(403, "You need at least be the manager to update the publisher profile.");
if (request.Name is not null) publisher.Name = request.Name;
@@ -532,7 +532,7 @@ public class PublisherController(
.Where(m => m.PublisherId == publisher.Id)
.FirstOrDefaultAsync();
if (member is null) return StatusCode(403, "You are not even a member of the targeted publisher.");
if (member.Role < PublisherMemberRole.Owner)
if (member.Role < Shared.Models.PublisherMemberRole.Owner)
return StatusCode(403, "You need to be the owner to delete the publisher.");
var publisherResourceId = $"publisher:{publisher.Id}";
@@ -659,7 +659,7 @@ public class PublisherController(
.FirstOrDefaultAsync();
if (publisher is null) return NotFound();
var feature = new PublisherFeature
var feature = new SnPublisherFeature
{
PublisherId = publisher.Id,
Flag = request.Flag,

View File

@@ -160,7 +160,7 @@ public class PublisherService(
{
var publisher = new SnPublisher
{
Type = PublisherType.Individual,
Type = Shared.Models.PublisherType.Individual,
Name = name ?? account.Name,
Nick = nick ?? account.Nick,
Bio = bio ?? account.Profile.Bio,
@@ -171,15 +171,15 @@ public class PublisherService(
? null
: SnCloudFileReferenceObject.FromProtoValue(account.Profile.Background)),
AccountId = Guid.Parse(account.Id),
Members = new List<SnPublisherMember>
{
Members =
[
new()
{
AccountId = Guid.Parse(account.Id),
Role = PublisherMemberRole.Owner,
Role = Shared.Models.PublisherMemberRole.Owner,
JoinedAt = Instant.FromDateTimeUtc(DateTime.UtcNow)
}
}
]
};
db.Publishers.Add(publisher);
@@ -224,7 +224,7 @@ public class PublisherService(
{
var publisher = new SnPublisher
{
Type = PublisherType.Organizational,
Type = Shared.Models.PublisherType.Organizational,
Name = name ?? realm.Slug,
Nick = nick ?? realm.Name,
Bio = bio ?? realm.Description,
@@ -236,7 +236,7 @@ public class PublisherService(
new()
{
AccountId = Guid.Parse(account.Id),
Role = PublisherMemberRole.Owner,
Role = Shared.Models.PublisherMemberRole.Owner,
JoinedAt = Instant.FromDateTimeUtc(DateTime.UtcNow)
}
}
@@ -332,7 +332,7 @@ public class PublisherService(
if (featureFlag == null)
{
featureFlag = new PublisherFeature
featureFlag = new SnPublisherFeature
{
PublisherId = publisherId,
Flag = flag,
@@ -368,7 +368,7 @@ public class PublisherService(
return isEnabled.Value;
}
public async Task<bool> IsMemberWithRole(Guid publisherId, Guid accountId, PublisherMemberRole requiredRole)
public async Task<bool> IsMemberWithRole(Guid publisherId, Guid accountId, Shared.Models.PublisherMemberRole requiredRole)
{
var member = await db.Publishers
.Where(p => p.Id == publisherId)
@@ -377,7 +377,7 @@ public class PublisherService(
return member != null && member.Role >= requiredRole;
}
public async Task<SnPublisherMember> LoadMemberAccount(SnPublisherMember member)
{
var account = await accountsHelper.GetAccount(member.AccountId);
@@ -390,11 +390,11 @@ public class PublisherService(
var accountIds = members.Select(m => m.AccountId).ToList();
var accounts = (await accountsHelper.GetAccountBatch(accountIds)).ToDictionary(a => Guid.Parse(a.Id), a => a);
return members.Select(m =>
return [.. members.Select(m =>
{
if (accounts.TryGetValue(m.AccountId, out var account))
m.Account = SnAccount.FromProtoValue(account);
return m;
}).ToList();
})];
}
}

View File

@@ -2,6 +2,7 @@ using DysonNetwork.Shared.Models;
using DysonNetwork.Shared.Proto;
using Grpc.Core;
using Microsoft.EntityFrameworkCore;
using PublisherMemberRole = DysonNetwork.Shared.Models.PublisherMemberRole;
namespace DysonNetwork.Sphere.Publisher;
@@ -27,7 +28,7 @@ public class PublisherServiceGrpc(PublisherService service, AppDatabase db)
}
if (p is null) throw new RpcException(new Status(StatusCode.NotFound, "Publisher not found"));
return new GetPublisherResponse { Publisher = p.ToProto(db) };
return new GetPublisherResponse { Publisher = p.ToProto() };
}
public override async Task<ListPublishersResponse> GetPublisherBatch(
@@ -42,7 +43,7 @@ public class PublisherServiceGrpc(PublisherService service, AppDatabase db)
if (ids.Count == 0) return new ListPublishersResponse();
var list = await db.Publishers.Where(p => ids.Contains(p.Id)).ToListAsync();
var resp = new ListPublishersResponse();
resp.Publishers.AddRange(list.Select(p => p.ToProto(db)));
resp.Publishers.AddRange(list.Select(p => p.ToProto()));
return resp;
}
@@ -63,7 +64,7 @@ public class PublisherServiceGrpc(PublisherService service, AppDatabase db)
var list = await query.ToListAsync();
var resp = new ListPublishersResponse();
resp.Publishers.AddRange(list.Select(p => p.ToProto(db)));
resp.Publishers.AddRange(list.Select(p => p.ToProto()));
return resp;
}

View File

@@ -1,6 +1,5 @@
using DysonNetwork.Shared.Models;
using DysonNetwork.Shared.Proto;
using DysonNetwork.Sphere.Post;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
@@ -51,7 +50,7 @@ public class PublisherSubscriptionController(
[HttpPost("{name}/subscribe")]
[Authorize]
public async Task<ActionResult<PublisherSubscription>> Subscribe(
public async Task<ActionResult<SnPublisherSubscription>> Subscribe(
string name,
[FromBody] SubscribeRequest request)
{
@@ -104,7 +103,7 @@ public class PublisherSubscriptionController(
/// <returns>List of active subscriptions</returns>
[HttpGet("subscriptions")]
[Authorize]
public async Task<ActionResult<List<PublisherSubscription>>> GetCurrentSubscriptions()
public async Task<ActionResult<List<SnPublisherSubscription>>> GetCurrentSubscriptions()
{
if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized();

View File

@@ -38,7 +38,7 @@ public class PublisherSubscriptionService(
/// <param name="accountId">The account ID</param>
/// <param name="publisherId">The publisher ID</param>
/// <returns>The subscription or null if not found</returns>
public async Task<PublisherSubscription?> GetSubscriptionAsync(Guid accountId, Guid publisherId)
public async Task<SnPublisherSubscription?> GetSubscriptionAsync(Guid accountId, Guid publisherId)
{
return await db.PublisherSubscriptions
.Include(ps => ps.Publisher)
@@ -137,7 +137,7 @@ public class PublisherSubscriptionService(
/// </summary>
/// <param name="accountId">The account ID</param>
/// <returns>A list of active subscriptions</returns>
public async Task<List<PublisherSubscription>> GetAccountSubscriptionsAsync(Guid accountId)
public async Task<List<SnPublisherSubscription>> GetAccountSubscriptionsAsync(Guid accountId)
{
return await db.PublisherSubscriptions
.Include(ps => ps.Publisher)
@@ -150,7 +150,7 @@ public class PublisherSubscriptionService(
/// </summary>
/// <param name="publisherId">The publisher ID</param>
/// <returns>A list of active subscriptions</returns>
public async Task<List<PublisherSubscription>> GetPublisherSubscribersAsync(Guid publisherId)
public async Task<List<SnPublisherSubscription>> GetPublisherSubscribersAsync(Guid publisherId)
{
return await db.PublisherSubscriptions
.Where(ps => ps.PublisherId == publisherId && ps.Status == PublisherSubscriptionStatus.Active)
@@ -164,7 +164,7 @@ public class PublisherSubscriptionService(
/// <param name="publisherId">The publisher ID</param>
/// <param name="tier">Optional subscription tier</param>
/// <returns>The created subscription</returns>
public async Task<PublisherSubscription> CreateSubscriptionAsync(
public async Task<SnPublisherSubscription> CreateSubscriptionAsync(
Guid accountId,
Guid publisherId,
int tier = 0
@@ -187,7 +187,7 @@ public class PublisherSubscriptionService(
}
// Create a new subscription
var subscription = new PublisherSubscription
var subscription = new SnPublisherSubscription
{
AccountId = accountId,
PublisherId = publisherId,

View File

@@ -23,7 +23,7 @@ public class RealmController(
) : Controller
{
[HttpGet("{slug}")]
public async Task<ActionResult<Realm>> GetRealm(string slug)
public async Task<ActionResult<SnRealm>> GetRealm(string slug)
{
var realm = await db.Realms
.Where(e => e.Slug == slug)
@@ -35,7 +35,7 @@ public class RealmController(
[HttpGet]
[Authorize]
public async Task<ActionResult<List<Realm>>> ListJoinedRealms()
public async Task<ActionResult<List<SnRealm>>> ListJoinedRealms()
{
if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized();
var accountId = Guid.Parse(currentUser.Id);
@@ -143,7 +143,7 @@ public class RealmController(
[HttpPost("invites/{slug}/accept")]
[Authorize]
public async Task<ActionResult<Realm>> AcceptMemberInvite(string slug)
public async Task<ActionResult<SnRealm>> AcceptMemberInvite(string slug)
{
if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized();
var accountId = Guid.Parse(currentUser.Id);
@@ -345,7 +345,7 @@ public class RealmController(
[HttpPost]
[Authorize]
public async Task<ActionResult<Realm>> CreateRealm(RealmRequest request)
public async Task<ActionResult<SnRealm>> CreateRealm(RealmRequest request)
{
if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized();
if (string.IsNullOrWhiteSpace(request.Name)) return BadRequest("You cannot create a realm without a name.");
@@ -354,7 +354,7 @@ public class RealmController(
var slugExists = await db.Realms.AnyAsync(r => r.Slug == request.Slug);
if (slugExists) return BadRequest("Realm with this slug already exists.");
var realm = new Realm
var realm = new SnRealm
{
Name = request.Name!,
Slug = request.Slug!,
@@ -433,7 +433,7 @@ public class RealmController(
[HttpPatch("{slug}")]
[Authorize]
public async Task<ActionResult<Realm>> Update(string slug, [FromBody] RealmRequest request)
public async Task<ActionResult<SnRealm>> Update(string slug, [FromBody] RealmRequest request)
{
if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized();

View File

@@ -1,6 +1,5 @@
using DysonNetwork.Shared;
using DysonNetwork.Shared.Cache;
using DysonNetwork.Shared.Data;
using DysonNetwork.Shared.Models;
using DysonNetwork.Shared.Proto;
using DysonNetwork.Shared.Registry;

View File

@@ -5,7 +5,6 @@ using DysonNetwork.Shared.Proto;
using DysonNetwork.Shared.Stream;
using DysonNetwork.Sphere.Chat;
using DysonNetwork.Sphere.Post;
using DysonNetwork.Sphere.Realm;
using Microsoft.EntityFrameworkCore;
using NATS.Client.Core;
using NATS.Client.JetStream.Models;

View File

@@ -8,10 +8,8 @@ using DysonNetwork.Sphere.Publisher;
using DysonNetwork.Sphere.Realm;
using DysonNetwork.Sphere.Sticker;
using Microsoft.AspNetCore.RateLimiting;
using Microsoft.OpenApi.Models;
using NodaTime;
using NodaTime.Serialization.SystemTextJson;
using StackExchange.Redis;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading.RateLimiting;

View File

@@ -208,7 +208,7 @@ public class StickerController(
}
[HttpGet("{packId:guid}/content")]
public async Task<ActionResult<List<Sticker>>> ListStickers(Guid packId)
public async Task<ActionResult<List<SnSticker>>> ListStickers(Guid packId)
{
var stickers = await db.Stickers
.Where(s => s.Pack.Id == packId)
@@ -220,7 +220,7 @@ public class StickerController(
}
[HttpGet("lookup/{identifier}")]
public async Task<ActionResult<Sticker>> GetStickerByIdentifier(string identifier)
public async Task<ActionResult<SnSticker>> GetStickerByIdentifier(string identifier)
{
var sticker = await st.LookupStickerByIdentifierAsync(identifier);
@@ -229,7 +229,7 @@ public class StickerController(
}
[HttpGet("lookup/{identifier}/open")]
public async Task<ActionResult<Sticker>> OpenStickerByIdentifier(string identifier)
public async Task<ActionResult<SnSticker>> OpenStickerByIdentifier(string identifier)
{
var sticker = await st.LookupStickerByIdentifierAsync(identifier);
@@ -238,7 +238,7 @@ public class StickerController(
}
[HttpGet("{packId:guid}/content/{id:guid}")]
public async Task<ActionResult<Sticker>> GetSticker(Guid packId, Guid id)
public async Task<ActionResult<SnSticker>> GetSticker(Guid packId, Guid id)
{
var sticker = await db.Stickers
.Where(s => s.PackId == packId && s.Id == id)
@@ -347,7 +347,7 @@ public class StickerController(
if (file is null)
return BadRequest("Image not found.");
var sticker = new Sticker
var sticker = new SnSticker
{
Slug = request.Slug,
ImageId = file.Id,

View File

@@ -7,7 +7,6 @@ namespace DysonNetwork.Sphere.Sticker;
public class StickerService(
AppDatabase db,
FileService.FileServiceClient files,
FileReferenceService.FileReferenceServiceClient fileRefs,
ICacheService cache
)
@@ -16,7 +15,7 @@ public class StickerService(
private static readonly TimeSpan CacheDuration = TimeSpan.FromMinutes(15);
public async Task<Sticker> CreateStickerAsync(Sticker sticker)
public async Task<SnSticker> CreateStickerAsync(SnSticker sticker)
{
if (sticker.Image is null) throw new ArgumentNullException(nameof(sticker.Image));
@@ -33,7 +32,7 @@ public class StickerService(
return sticker;
}
public async Task<Sticker> UpdateStickerAsync(Sticker sticker, SnCloudFileReferenceObject? newImage)
public async Task<SnSticker> UpdateStickerAsync(SnSticker sticker, SnCloudFileReferenceObject? newImage)
{
if (newImage is not null)
{
@@ -59,7 +58,7 @@ public class StickerService(
return sticker;
}
public async Task DeleteStickerAsync(Sticker sticker)
public async Task DeleteStickerAsync(SnSticker sticker)
{
var stickerResourceId = $"sticker:{sticker.Id}";
@@ -98,17 +97,17 @@ public class StickerService(
await PurgeStickerCache(sticker);
}
public async Task<Sticker?> LookupStickerByIdentifierAsync(string identifier)
public async Task<SnSticker?> LookupStickerByIdentifierAsync(string identifier)
{
identifier = identifier.ToLower();
// Try to get from the cache first
var cacheKey = $"sticker:lookup:{identifier}";
var cachedSticker = await cache.GetAsync<Sticker>(cacheKey);
var cachedSticker = await cache.GetAsync<SnSticker>(cacheKey);
if (cachedSticker is not null)
return cachedSticker;
// If not in cache, fetch from the database
IQueryable<Sticker> query = db.Stickers
IQueryable<SnSticker> query = db.Stickers
.Include(e => e.Pack);
query = Guid.TryParse(identifier, out var guid)
? query.Where(e => e.Id == guid)
@@ -123,7 +122,7 @@ public class StickerService(
return sticker;
}
private async Task PurgeStickerCache(Sticker sticker)
private async Task PurgeStickerCache(SnSticker sticker)
{
// Remove both possible cache entries
await cache.RemoveAsync($"sticker:lookup:{sticker.Id}");

View File

@@ -1,6 +1,4 @@
using System.Reflection;
using System.Text.Json;
using System.Text.Json.Serialization;
using DysonNetwork.Shared.Proto;
namespace DysonNetwork.Sphere.WebReader;

View File

@@ -1,7 +1,6 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text.Json.Serialization;
using DysonNetwork.Shared.Data;
using DysonNetwork.Shared.Models;
namespace DysonNetwork.Sphere.WebReader;

View File

@@ -1,5 +1,4 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Quartz;
namespace DysonNetwork.Sphere.WebReader;

View File

@@ -1,5 +1,3 @@
using System;
namespace DysonNetwork.Sphere.WebReader;
/// <summary>