♻️ Finish centerlizing the data models
This commit is contained in:
@@ -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,
|
||||
|
@@ -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;
|
||||
|
@@ -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",
|
||||
|
@@ -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)
|
||||
|
@@ -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();
|
||||
})];
|
||||
}
|
||||
}
|
@@ -1,6 +1,3 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using DysonNetwork.Shared.Proto;
|
||||
|
||||
namespace DysonNetwork.Sphere.Chat.Realtime;
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using NodaTime;
|
||||
|
||||
#nullable disable
|
||||
|
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using DysonNetwork.Shared.Models;
|
||||
using DysonNetwork.Shared.Models;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using NodaTime;
|
||||
|
||||
|
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using NodaTime;
|
||||
|
||||
#nullable disable
|
||||
|
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
|
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using NodaTime;
|
||||
|
||||
#nullable disable
|
||||
|
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using NodaTime;
|
||||
|
||||
#nullable disable
|
||||
|
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using NodaTime;
|
||||
|
||||
#nullable disable
|
||||
|
@@ -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);
|
||||
|
@@ -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
|
||||
{
|
||||
|
@@ -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)
|
||||
|
@@ -1,4 +1,3 @@
|
||||
using DysonNetwork.Shared.Data;
|
||||
using DysonNetwork.Shared.Models;
|
||||
using DysonNetwork.Shared.Proto;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
|
@@ -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;
|
||||
|
@@ -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,
|
||||
|
@@ -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();
|
||||
})];
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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();
|
||||
|
||||
|
@@ -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,
|
||||
|
@@ -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();
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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,
|
||||
|
@@ -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}");
|
||||
|
@@ -1,6 +1,4 @@
|
||||
using System.Reflection;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using DysonNetwork.Shared.Proto;
|
||||
|
||||
namespace DysonNetwork.Sphere.WebReader;
|
||||
|
@@ -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;
|
||||
|
@@ -1,5 +1,4 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Quartz;
|
||||
|
||||
namespace DysonNetwork.Sphere.WebReader;
|
||||
|
@@ -1,5 +1,3 @@
|
||||
using System;
|
||||
|
||||
namespace DysonNetwork.Sphere.WebReader;
|
||||
|
||||
/// <summary>
|
||||
|
Reference in New Issue
Block a user