♻️ Centralized data models (wip)

This commit is contained in:
2025-09-27 14:09:28 +08:00
parent 51b6f7309e
commit e70d8371f8
206 changed files with 1352 additions and 2128 deletions

View File

@@ -1,38 +0,0 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using DysonNetwork.Shared.Data;
using NodaTime;
namespace DysonNetwork.Sphere.Activity;
public interface IActivity
{
public Activity ToActivity();
}
[NotMapped]
public class Activity : ModelBase
{
public Guid Id { get; set; }
[MaxLength(1024)] public string Type { get; set; } = null!;
[MaxLength(4096)] public string ResourceIdentifier { get; set; } = null!;
[Column(TypeName = "jsonb")] public Dictionary<string, object> Meta { get; set; } = new();
public object? Data { get; set; }
// Outdated fields, for backward compability
public int Visibility => 0;
public static Activity Empty()
{
var now = SystemClock.Instance.GetCurrentInstant();
return new Activity
{
CreatedAt = now,
UpdatedAt = now,
Id = Guid.NewGuid(),
Type = "empty",
ResourceIdentifier = "none"
};
}
}

View File

@@ -1,3 +1,4 @@
using DysonNetwork.Shared.Models;
using DysonNetwork.Shared.Proto;
using DysonNetwork.Sphere.Discovery;
using DysonNetwork.Sphere.Post;
@@ -17,7 +18,7 @@ public class ActivityService(
AccountService.AccountServiceClient accounts
)
{
private static double CalculateHotRank(Post.Post post, Instant now)
private static double CalculateHotRank(SnPost post, Instant now)
{
var performanceScore = post.Upvotes - post.Downvotes + post.RepliesCount + (int)post.AwardedScore / 10;
var postTime = post.PublishedAt ?? post.CreatedAt;
@@ -163,7 +164,7 @@ public class ActivityService(
return await pick();
}
private static List<Post.Post> RankPosts(List<Post.Post> posts, int take)
private static List<SnPost> RankPosts(List<SnPost> posts, int take)
{
var now = SystemClock.Instance.GetCurrentInstant();
return posts
@@ -175,7 +176,7 @@ public class ActivityService(
// return posts.Take(take).ToList();
}
private async Task<List<Publisher.Publisher>> GetPopularPublishers(int take)
private async Task<List<Shared.Models.SnPublisher>> GetPopularPublishers(int take)
{
var now = SystemClock.Instance.GetCurrentInstant();
var recent = now.Minus(Duration.FromDays(7));
@@ -268,11 +269,11 @@ public class ActivityService(
: null;
}
private async Task<List<Post.Post>> GetAndProcessPosts(
IQueryable<Post.Post> baseQuery,
private async Task<List<SnPost>> GetAndProcessPosts(
IQueryable<SnPost> baseQuery,
Account? currentUser = null,
List<Guid>? userFriends = null,
List<Publisher.Publisher>? userPublishers = null,
List<Shared.Models.SnPublisher>? userPublishers = null,
bool trackViews = true)
{
var posts = await baseQuery.ToListAsync();
@@ -294,7 +295,7 @@ public class ActivityService(
return posts;
}
private IQueryable<Post.Post> BuildPostsQuery(
private IQueryable<SnPost> BuildPostsQuery(
Instant? cursor,
List<Guid>? filteredPublishersId = null,
List<Guid>? userRealms = null
@@ -322,7 +323,7 @@ public class ActivityService(
return query;
}
private async Task<List<Publisher.Publisher>?> GetFilteredPublishers(
private async Task<List<Shared.Models.SnPublisher>?> GetFilteredPublishers(
string? filter,
Account currentUser,
List<Guid> userFriends)
@@ -338,7 +339,7 @@ public class ActivityService(
};
}
private static double CalculatePopularity(List<Post.Post> posts)
private static double CalculatePopularity(List<SnPost> posts)
{
var score = posts.Sum(p => p.Upvotes - p.Downvotes);
var postCount = posts.Count;

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using DysonNetwork.Shared.Models;
using NodaTime;
namespace DysonNetwork.Sphere.Activity;

View File

@@ -1,11 +1,7 @@
using System.Linq.Expressions;
using System.Reflection;
using DysonNetwork.Shared.Data;
using DysonNetwork.Sphere.Chat;
using DysonNetwork.Sphere.Post;
using DysonNetwork.Sphere.Publisher;
using DysonNetwork.Sphere.Realm;
using DysonNetwork.Sphere.Sticker;
using DysonNetwork.Shared.Models;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
using Microsoft.EntityFrameworkCore.Query;
@@ -24,34 +20,34 @@ public class AppDatabase(
IConfiguration configuration
) : DbContext(options)
{
public DbSet<Publisher.Publisher> Publishers { get; set; } = null!;
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<Post.Post> Posts { get; set; } = null!;
public DbSet<PostReaction> PostReactions { get; set; } = null!;
public DbSet<PostAward> PostAwards { get; set; } = null!;
public DbSet<PostTag> PostTags { get; set; } = null!;
public DbSet<PostCategory> PostCategories { get; set; } = null!;
public DbSet<PostCollection> PostCollections { get; set; } = null!;
public DbSet<PostFeaturedRecord> PostFeaturedRecords { get; set; } = null!;
public DbSet<PostCategorySubscription> PostCategorySubscriptions { get; set; } = null!;
public DbSet<SnPost> Posts { get; set; } = null!;
public DbSet<SnPostReaction> PostReactions { get; set; } = null!;
public DbSet<SnPostAward> PostAwards { get; set; } = null!;
public DbSet<SnPostTag> PostTags { get; set; } = null!;
public DbSet<SnPostCategory> PostCategories { get; set; } = null!;
public DbSet<SnPostCollection> PostCollections { get; set; } = null!;
public DbSet<SnPostFeaturedRecord> PostFeaturedRecords { get; set; } = null!;
public DbSet<SnPostCategorySubscription> PostCategorySubscriptions { get; set; } = null!;
public DbSet<Poll.Poll> Polls { get; set; } = null!;
public DbSet<Poll.PollQuestion> PollQuestions { get; set; } = null!;
public DbSet<Poll.PollAnswer> PollAnswers { get; set; } = null!;
public DbSet<Shared.Models.SnPoll> Polls { get; set; } = null!;
public DbSet<SnPollQuestion> PollQuestions { get; set; } = null!;
public DbSet<SnPollAnswer> PollAnswers { get; set; } = null!;
public DbSet<Realm.Realm> Realms { get; set; } = null!;
public DbSet<RealmMember> RealmMembers { get; set; } = null!;
public DbSet<Shared.Models.SnRealm> Realms { get; set; } = null!;
public DbSet<SnRealmMember> RealmMembers { get; set; } = null!;
public DbSet<ChatRoom> ChatRooms { get; set; } = null!;
public DbSet<ChatMember> ChatMembers { get; set; } = null!;
public DbSet<Message> ChatMessages { get; set; } = null!;
public DbSet<RealtimeCall> ChatRealtimeCall { get; set; } = null!;
public DbSet<MessageReaction> ChatReactions { get; set; } = null!;
public DbSet<SnChatRoom> ChatRooms { get; set; } = null!;
public DbSet<SnChatMember> ChatMembers { get; set; } = null!;
public DbSet<SnChatMessage> ChatMessages { get; set; } = null!;
public DbSet<SnRealtimeCall> ChatRealtimeCall { get; set; } = null!;
public DbSet<SnChatMessageReaction> ChatReactions { get; set; } = null!;
public DbSet<Sticker.Sticker> Stickers { get; set; } = null!;
public DbSet<Shared.Models.SnSticker> Stickers { get; set; } = null!;
public DbSet<StickerPack> StickerPacks { get; set; } = null!;
public DbSet<StickerPackOwnership> StickerPackOwnerships { get; set; } = null!;
@@ -89,67 +85,67 @@ public class AppDatabase(
.HasForeignKey(ps => ps.PublisherId)
.OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity<Post.Post>()
modelBuilder.Entity<SnPost>()
.HasGeneratedTsVectorColumn(p => p.SearchVector, "simple", p => new { p.Title, p.Description, p.Content })
.HasIndex(p => p.SearchVector)
.HasMethod("GIN");
modelBuilder.Entity<Post.Post>()
modelBuilder.Entity<SnPost>()
.HasOne(p => p.RepliedPost)
.WithMany()
.HasForeignKey(p => p.RepliedPostId)
.OnDelete(DeleteBehavior.Restrict);
modelBuilder.Entity<Post.Post>()
modelBuilder.Entity<SnPost>()
.HasOne(p => p.ForwardedPost)
.WithMany()
.HasForeignKey(p => p.ForwardedPostId)
.OnDelete(DeleteBehavior.Restrict);
modelBuilder.Entity<Post.Post>()
modelBuilder.Entity<SnPost>()
.HasMany(p => p.Tags)
.WithMany(t => t.Posts)
.UsingEntity(j => j.ToTable("post_tag_links"));
modelBuilder.Entity<Post.Post>()
modelBuilder.Entity<SnPost>()
.HasMany(p => p.Categories)
.WithMany(c => c.Posts)
.UsingEntity(j => j.ToTable("post_category_links"));
modelBuilder.Entity<Post.Post>()
modelBuilder.Entity<SnPost>()
.HasMany(p => p.Collections)
.WithMany(c => c.Posts)
.UsingEntity(j => j.ToTable("post_collection_links"));
modelBuilder.Entity<RealmMember>()
modelBuilder.Entity<SnRealmMember>()
.HasKey(pm => new { pm.RealmId, pm.AccountId });
modelBuilder.Entity<RealmMember>()
modelBuilder.Entity<SnRealmMember>()
.HasOne(pm => pm.Realm)
.WithMany(p => p.Members)
.HasForeignKey(pm => pm.RealmId)
.OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity<ChatMember>()
modelBuilder.Entity<SnChatMember>()
.HasKey(pm => new { pm.Id });
modelBuilder.Entity<ChatMember>()
modelBuilder.Entity<SnChatMember>()
.HasAlternateKey(pm => new { pm.ChatRoomId, pm.AccountId });
modelBuilder.Entity<ChatMember>()
modelBuilder.Entity<SnChatMember>()
.HasOne(pm => pm.ChatRoom)
.WithMany(p => p.Members)
.HasForeignKey(pm => pm.ChatRoomId)
.OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity<Message>()
modelBuilder.Entity<SnChatMessage>()
.HasOne(m => m.ForwardedMessage)
.WithMany()
.HasForeignKey(m => m.ForwardedMessageId)
.OnDelete(DeleteBehavior.Restrict);
modelBuilder.Entity<Message>()
modelBuilder.Entity<SnChatMessage>()
.HasOne(m => m.RepliedMessage)
.WithMany()
.HasForeignKey(m => m.RepliedMessageId)
.OnDelete(DeleteBehavior.Restrict);
modelBuilder.Entity<RealtimeCall>()
modelBuilder.Entity<SnRealtimeCall>()
.HasOne(m => m.Room)
.WithMany()
.HasForeignKey(m => m.RoomId)
.OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity<RealtimeCall>()
modelBuilder.Entity<SnRealtimeCall>()
.HasOne(m => m.Sender)
.WithMany()
.HasForeignKey(m => m.SenderId)

View File

@@ -2,7 +2,7 @@ using System.ComponentModel.DataAnnotations;
using System.Text.RegularExpressions;
using DysonNetwork.Shared.Auth;
using DysonNetwork.Shared.Content;
using DysonNetwork.Shared.Data;
using DysonNetwork.Shared.Models;
using DysonNetwork.Shared.Proto;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
@@ -33,7 +33,7 @@ public partial class ChatController(
public class ChatSummaryResponse
{
public int UnreadCount { get; set; }
public Message? LastMessage { get; set; }
public SnChatMessage? LastMessage { get; set; }
}
[HttpGet("summary")]
@@ -71,7 +71,7 @@ public partial class ChatController(
}
[HttpGet("{roomId:guid}/messages")]
public async Task<ActionResult<List<Message>>> ListMessages(Guid roomId, [FromQuery] int offset,
public async Task<ActionResult<List<SnChatMessage>>> ListMessages(Guid roomId, [FromQuery] int offset,
[FromQuery] int take = 20)
{
var currentUser = HttpContext.Items["CurrentUser"] as Account;
@@ -114,7 +114,7 @@ public partial class ChatController(
}
[HttpGet("{roomId:guid}/messages/{messageId:guid}")]
public async Task<ActionResult<Message>> GetMessage(Guid roomId, Guid messageId)
public async Task<ActionResult<SnChatMessage>> GetMessage(Guid roomId, Guid messageId)
{
var currentUser = HttpContext.Items["CurrentUser"] as Account;
@@ -165,7 +165,7 @@ public partial class ChatController(
if (member == null || member.Role < ChatMemberRole.Member)
return StatusCode(403, "You need to be a normal member to send messages here.");
var message = new Message
var message = new SnChatMessage
{
Type = "text",
SenderId = member.Id,
@@ -182,7 +182,7 @@ public partial class ChatController(
var queryResponse = await files.GetFileBatchAsync(queryRequest);
message.Attachments = queryResponse.Files
.OrderBy(f => request.AttachmentsId.IndexOf(f.Id))
.Select(CloudFileReferenceObject.FromProtoValue)
.Select(SnCloudFileReferenceObject.FromProtoValue)
.ToList();
}

View File

@@ -1,145 +0,0 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text.Json.Serialization;
using DysonNetwork.Shared.Data;
using NodaTime;
namespace DysonNetwork.Sphere.Chat;
public enum ChatRoomType
{
Group,
DirectMessage
}
public class ChatRoom : ModelBase, IIdentifiedResource
{
public Guid Id { get; set; }
[MaxLength(1024)] public string? Name { get; set; }
[MaxLength(4096)] public string? Description { get; set; }
public ChatRoomType Type { get; set; }
public bool IsCommunity { get; set; }
public bool IsPublic { get; set; }
// Outdated fields, for backward compability
[MaxLength(32)] public string? PictureId { get; set; }
[MaxLength(32)] public string? BackgroundId { get; set; }
[Column(TypeName = "jsonb")] public CloudFileReferenceObject? Picture { get; set; }
[Column(TypeName = "jsonb")] public CloudFileReferenceObject? Background { get; set; }
[JsonIgnore] public ICollection<ChatMember> Members { get; set; } = new List<ChatMember>();
public Guid? RealmId { get; set; }
public Realm.Realm? Realm { get; set; }
[NotMapped]
[JsonPropertyName("members")]
public ICollection<ChatMemberTransmissionObject> DirectMembers { get; set; } =
new List<ChatMemberTransmissionObject>();
public string ResourceIdentifier => $"chatroom:{Id}";
}
public abstract class ChatMemberRole
{
public const int Owner = 100;
public const int Moderator = 50;
public const int Member = 0;
}
public enum ChatMemberNotify
{
All,
Mentions,
None
}
public enum ChatTimeoutCauseType
{
ByModerator = 0,
BySlowMode = 1,
}
public class ChatTimeoutCause
{
public ChatTimeoutCauseType Type { get; set; }
public Guid? SenderId { get; set; }
}
public class ChatMember : ModelBase
{
public Guid Id { get; set; }
public Guid ChatRoomId { get; set; }
public ChatRoom ChatRoom { get; set; } = null!;
public Guid AccountId { get; set; }
[NotMapped] public AccountReference? Account { get; set; }
[NotMapped] public AccountStatusReference? Status { get; set; }
[MaxLength(1024)] public string? Nick { get; set; }
public int Role { get; set; } = ChatMemberRole.Member;
public ChatMemberNotify Notify { get; set; } = ChatMemberNotify.All;
public Instant? LastReadAt { get; set; }
public Instant? JoinedAt { get; set; }
public Instant? LeaveAt { get; set; }
public bool IsBot { get; set; } = false;
/// <summary>
/// The break time is the user doesn't receive any message from this member for a while.
/// Expect mentioned him or her.
/// </summary>
public Instant? BreakUntil { get; set; }
/// <summary>
/// The timeout is the user can't send any message.
/// Set by the moderator of the chat room.
/// </summary>
public Instant? TimeoutUntil { get; set; }
/// <summary>
/// The timeout cause is the reason why the user is timeout.
/// </summary>
[Column(TypeName = "jsonb")] public ChatTimeoutCause? TimeoutCause { get; set; }
}
public class ChatMemberTransmissionObject : ModelBase
{
public Guid Id { get; set; }
public Guid ChatRoomId { get; set; }
public Guid AccountId { get; set; }
[NotMapped] public AccountReference Account { get; set; } = null!;
[MaxLength(1024)] public string? Nick { get; set; }
public int Role { get; set; } = ChatMemberRole.Member;
public ChatMemberNotify Notify { get; set; } = ChatMemberNotify.All;
public Instant? JoinedAt { get; set; }
public Instant? LeaveAt { get; set; }
public bool IsBot { get; set; } = false;
public Instant? BreakUntil { get; set; }
public Instant? TimeoutUntil { get; set; }
public ChatTimeoutCause? TimeoutCause { get; set; }
public static ChatMemberTransmissionObject FromEntity(ChatMember member)
{
return new ChatMemberTransmissionObject
{
Id = member.Id,
ChatRoomId = member.ChatRoomId,
AccountId = member.AccountId,
Account = member.Account!,
Nick = member.Nick,
Role = member.Role,
Notify = member.Notify,
JoinedAt = member.JoinedAt,
LeaveAt = member.LeaveAt,
IsBot = member.IsBot,
BreakUntil = member.BreakUntil,
TimeoutUntil = member.TimeoutUntil,
TimeoutCause = member.TimeoutCause,
CreatedAt = member.CreatedAt,
UpdatedAt = member.UpdatedAt,
DeletedAt = member.DeletedAt
};
}
}

View File

@@ -3,7 +3,6 @@ using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations;
using DysonNetwork.Shared;
using DysonNetwork.Shared.Auth;
using DysonNetwork.Shared.Data;
using DysonNetwork.Shared.Proto;
using DysonNetwork.Shared.Registry;
using DysonNetwork.Sphere.Localization;
@@ -12,6 +11,7 @@ using Grpc.Core;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Localization;
using NodaTime;
using DysonNetwork.Shared.Models;
namespace DysonNetwork.Sphere.Chat;
@@ -31,7 +31,7 @@ public class ChatRoomController(
) : ControllerBase
{
[HttpGet("{id:guid}")]
public async Task<ActionResult<ChatRoom>> GetChatRoom(Guid id)
public async Task<ActionResult<SnChatRoom>> GetChatRoom(Guid id)
{
var chatRoom = await db.ChatRooms
.Where(c => c.Id == id)
@@ -48,7 +48,7 @@ public class ChatRoomController(
[HttpGet]
[Authorize]
public async Task<ActionResult<List<ChatRoom>>> ListJoinedChatRooms()
public async Task<ActionResult<List<SnChatRoom>>> ListJoinedChatRooms()
{
if (HttpContext.Items["CurrentUser"] is not Account currentUser)
return Unauthorized();
@@ -74,7 +74,7 @@ public class ChatRoomController(
[HttpPost("direct")]
[Authorize]
public async Task<ActionResult<ChatRoom>> CreateDirectMessage([FromBody] DirectMessageRequest request)
public async Task<ActionResult<SnChatRoom>> CreateDirectMessage([FromBody] DirectMessageRequest request)
{
if (HttpContext.Items["CurrentUser"] is not Account currentUser)
return Unauthorized();
@@ -106,11 +106,11 @@ public class ChatRoomController(
return BadRequest("You already have a DM with this user.");
// Create new DM chat room
var dmRoom = new ChatRoom
var dmRoom = new SnChatRoom
{
Type = ChatRoomType.DirectMessage,
IsPublic = false,
Members = new List<ChatMember>
Members = new List<SnChatMember>
{
new()
{
@@ -148,7 +148,7 @@ public class ChatRoomController(
[HttpGet("direct/{accountId:guid}")]
[Authorize]
public async Task<ActionResult<ChatRoom>> GetDirectChatRoom(Guid accountId)
public async Task<ActionResult<SnChatRoom>> GetDirectChatRoom(Guid accountId)
{
if (HttpContext.Items["CurrentUser"] is not Account currentUser)
return Unauthorized();
@@ -178,19 +178,19 @@ public class ChatRoomController(
[HttpPost]
[Authorize]
[RequiredPermission("global", "chat.create")]
public async Task<ActionResult<ChatRoom>> CreateChatRoom(ChatRoomRequest request)
public async Task<ActionResult<SnChatRoom>> CreateChatRoom(ChatRoomRequest request)
{
if (HttpContext.Items["CurrentUser"] is not Shared.Proto.Account currentUser) return Unauthorized();
if (request.Name is null) return BadRequest("You cannot create a chat room without a name.");
var chatRoom = new ChatRoom
var chatRoom = new SnChatRoom
{
Name = request.Name,
Description = request.Description ?? string.Empty,
IsCommunity = request.IsCommunity ?? false,
IsPublic = request.IsPublic ?? false,
Type = ChatRoomType.Group,
Members = new List<ChatMember>
Members = new List<SnChatMember>
{
new()
{
@@ -215,7 +215,7 @@ public class ChatRoomController(
{
var fileResponse = await files.GetFileAsync(new GetFileRequest { Id = request.PictureId });
if (fileResponse == null) return BadRequest("Invalid picture id, unable to find the file on cloud.");
chatRoom.Picture = CloudFileReferenceObject.FromProtoValue(fileResponse);
chatRoom.Picture = SnCloudFileReferenceObject.FromProtoValue(fileResponse);
await fileRefs.CreateReferenceAsync(new CreateReferenceRequest
{
@@ -236,7 +236,7 @@ public class ChatRoomController(
{
var fileResponse = await files.GetFileAsync(new GetFileRequest { Id = request.BackgroundId });
if (fileResponse == null) return BadRequest("Invalid background id, unable to find the file on cloud.");
chatRoom.Background = CloudFileReferenceObject.FromProtoValue(fileResponse);
chatRoom.Background = SnCloudFileReferenceObject.FromProtoValue(fileResponse);
await fileRefs.CreateReferenceAsync(new CreateReferenceRequest
{
@@ -290,7 +290,7 @@ public class ChatRoomController(
[HttpPatch("{id:guid}")]
public async Task<ActionResult<ChatRoom>> UpdateChatRoom(Guid id, [FromBody] ChatRoomRequest request)
public async Task<ActionResult<SnChatRoom>> UpdateChatRoom(Guid id, [FromBody] ChatRoomRequest request)
{
if (HttpContext.Items["CurrentUser"] is not Shared.Proto.Account currentUser) return Unauthorized();
@@ -341,7 +341,7 @@ public class ChatRoomController(
ResourceId = chatRoom.ResourceIdentifier
});
chatRoom.Picture = CloudFileReferenceObject.FromProtoValue(fileResponse);
chatRoom.Picture = SnCloudFileReferenceObject.FromProtoValue(fileResponse);
}
catch (RpcException ex) when (ex.StatusCode == Grpc.Core.StatusCode.NotFound)
{
@@ -371,7 +371,7 @@ public class ChatRoomController(
ResourceId = chatRoom.ResourceIdentifier
});
chatRoom.Background = CloudFileReferenceObject.FromProtoValue(fileResponse);
chatRoom.Background = SnCloudFileReferenceObject.FromProtoValue(fileResponse);
}
catch (RpcException ex) when (ex.StatusCode == Grpc.Core.StatusCode.NotFound)
{
@@ -468,7 +468,7 @@ public class ChatRoomController(
[HttpGet("{roomId:guid}/members/me")]
[Authorize]
public async Task<ActionResult<ChatMember>> GetRoomIdentity(Guid roomId)
public async Task<ActionResult<SnChatMember>> GetRoomIdentity(Guid roomId)
{
if (HttpContext.Items["CurrentUser"] is not Shared.Proto.Account currentUser)
return Unauthorized();
@@ -484,7 +484,7 @@ public class ChatRoomController(
}
[HttpGet("{roomId:guid}/members")]
public async Task<ActionResult<List<ChatMember>>> ListMembers(Guid roomId,
public async Task<ActionResult<List<SnChatMember>>> ListMembers(Guid roomId,
[FromQuery] int take = 20,
[FromQuery] int offset = 0,
[FromQuery] bool withStatus = false
@@ -561,7 +561,7 @@ public class ChatRoomController(
[HttpPost("invites/{roomId:guid}")]
[Authorize]
public async Task<ActionResult<ChatMember>> InviteMember(Guid roomId,
public async Task<ActionResult<SnChatMember>> InviteMember(Guid roomId,
[FromBody] ChatMemberRequest request)
{
if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized();
@@ -620,7 +620,7 @@ public class ChatRoomController(
if (hasExistingMember)
return BadRequest("This user has been joined the chat cannot be invited again.");
var newMember = new ChatMember
var newMember = new SnChatMember
{
AccountId = Guid.Parse(relatedUser.Id),
ChatRoomId = roomId,
@@ -651,7 +651,7 @@ public class ChatRoomController(
[HttpGet("invites")]
[Authorize]
public async Task<ActionResult<List<ChatMember>>> ListChatInvites()
public async Task<ActionResult<List<SnChatMember>>> ListChatInvites()
{
if (HttpContext.Items["CurrentUser"] is not Shared.Proto.Account currentUser) return Unauthorized();
var accountId = Guid.Parse(currentUser.Id);
@@ -674,7 +674,7 @@ public class ChatRoomController(
[HttpPost("invites/{roomId:guid}/accept")]
[Authorize]
public async Task<ActionResult<ChatRoom>> AcceptChatInvite(Guid roomId)
public async Task<ActionResult<SnChatRoom>> AcceptChatInvite(Guid roomId)
{
if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized();
var accountId = Guid.Parse(currentUser.Id);
@@ -731,7 +731,7 @@ public class ChatRoomController(
[HttpPatch("{roomId:guid}/members/me/notify")]
[Authorize]
public async Task<ActionResult<ChatMember>> UpdateChatMemberNotify(
public async Task<ActionResult<SnChatMember>> UpdateChatMemberNotify(
Guid roomId,
[FromBody] ChatMemberNotifyRequest request
)
@@ -763,7 +763,7 @@ public class ChatRoomController(
[HttpPatch("{roomId:guid}/members/{memberId:guid}/role")]
[Authorize]
public async Task<ActionResult<ChatMember>> UpdateChatMemberRole(Guid roomId, Guid memberId, [FromBody] int newRole)
public async Task<ActionResult<SnChatMember>> UpdateChatMemberRole(Guid roomId, Guid memberId, [FromBody] int newRole)
{
if (newRole >= ChatMemberRole.Owner) return BadRequest("Unable to set chat member to owner or greater role.");
if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized();
@@ -885,7 +885,7 @@ public class ChatRoomController(
[HttpPost("{roomId:guid}/members/me")]
[Authorize]
public async Task<ActionResult<ChatRoom>> JoinChatRoom(Guid roomId)
public async Task<ActionResult<SnChatRoom>> JoinChatRoom(Guid roomId)
{
if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized();
@@ -901,7 +901,7 @@ public class ChatRoomController(
if (existingMember != null)
return BadRequest("You are already a member of this chat room.");
var newMember = new ChatMember
var newMember = new SnChatMember
{
AccountId = Guid.Parse(currentUser.Id),
ChatRoomId = roomId,
@@ -966,7 +966,7 @@ public class ChatRoomController(
return NoContent();
}
private async Task _SendInviteNotify(ChatMember member, Account sender)
private async Task _SendInviteNotify(SnChatMember member, Account sender)
{
var account = await accounts.GetAccountAsync(new GetAccountRequest { Id = member.AccountId.ToString() });
CultureService.SetCultureInfo(account);

View File

@@ -1,8 +1,9 @@
using DysonNetwork.Shared.Cache;
using DysonNetwork.Shared.Models;
using DysonNetwork.Shared.Registry;
using Microsoft.EntityFrameworkCore;
using NodaTime;
using Account = DysonNetwork.Shared.Data.AccountReference;
using Account = DysonNetwork.Shared.Data.SnAccount;
namespace DysonNetwork.Sphere.Chat;
@@ -16,10 +17,10 @@ public class ChatRoomService(
private const string RoomMembersCacheKeyPrefix = "chatroom:members:";
private const string ChatMemberCacheKey = "chatroom:{0}:member:{1}";
public async Task<List<ChatMember>> ListRoomMembers(Guid roomId)
public async Task<List<SnChatMember>> ListRoomMembers(Guid roomId)
{
var cacheKey = RoomMembersCacheKeyPrefix + roomId;
var cachedMembers = await cache.GetAsync<List<ChatMember>>(cacheKey);
var cachedMembers = await cache.GetAsync<List<SnChatMember>>(cacheKey);
if (cachedMembers != null)
return cachedMembers;
@@ -38,10 +39,10 @@ public class ChatRoomService(
return members;
}
public async Task<ChatMember?> GetRoomMember(Guid accountId, Guid chatRoomId)
public async Task<SnChatMember?> GetRoomMember(Guid accountId, Guid chatRoomId)
{
var cacheKey = string.Format(ChatMemberCacheKey, accountId, chatRoomId);
var member = await cache.GetAsync<ChatMember?>(cacheKey);
var member = await cache.GetAsync<SnChatMember?>(cacheKey);
if (member is not null) return member;
member = await db.ChatMembers
@@ -66,7 +67,7 @@ public class ChatRoomService(
await cache.RemoveGroupAsync(chatRoomGroup);
}
public async Task<List<ChatRoom>> SortChatRoomByLastMessage(List<ChatRoom> rooms)
public async Task<List<SnChatRoom>> SortChatRoomByLastMessage(List<SnChatRoom> rooms)
{
var roomIds = rooms.Select(r => r.Id).ToList();
var lastMessages = await db.ChatMessages
@@ -83,7 +84,7 @@ public class ChatRoomService(
return sortedRooms;
}
public async Task<List<ChatRoom>> LoadDirectMessageMembers(List<ChatRoom> rooms, Guid userId)
public async Task<List<SnChatRoom>> LoadDirectMessageMembers(List<SnChatRoom> rooms, Guid userId)
{
var directRoomsId = rooms
.Where(r => r.Type == ChatRoomType.DirectMessage)
@@ -91,7 +92,7 @@ public class ChatRoomService(
.ToList();
if (directRoomsId.Count == 0) return rooms;
List<ChatMember> members = directRoomsId.Count != 0
List<SnChatMember> members = directRoomsId.Count != 0
? await db.ChatMembers
.Where(m => directRoomsId.Contains(m.ChatRoomId))
.Where(m => m.AccountId != userId)
@@ -100,7 +101,7 @@ public class ChatRoomService(
: [];
members = await LoadMemberAccounts(members);
Dictionary<Guid, List<ChatMember>> directMembers = new();
Dictionary<Guid, List<SnChatMember>> directMembers = new();
foreach (var member in members)
{
if (!directMembers.ContainsKey(member.ChatRoomId))
@@ -116,7 +117,7 @@ public class ChatRoomService(
}).ToList();
}
public async Task<ChatRoom> LoadDirectMessageMembers(ChatRoom room, Guid userId)
public async Task<SnChatRoom> LoadDirectMessageMembers(SnChatRoom room, Guid userId)
{
if (room.Type != ChatRoomType.DirectMessage) return room;
var members = await db.ChatMembers
@@ -143,14 +144,14 @@ public class ChatRoomService(
return member?.Role >= maxRequiredRole;
}
public async Task<ChatMember> LoadMemberAccount(ChatMember member)
public async Task<SnChatMember> LoadMemberAccount(SnChatMember member)
{
var account = await accountsHelper.GetAccount(member.AccountId);
member.Account = Account.FromProtoValue(account);
return member;
}
public async Task<List<ChatMember>> LoadMemberAccounts(ICollection<ChatMember> members)
public async Task<List<SnChatMember>> LoadMemberAccounts(ICollection<SnChatMember> members)
{
var accountIds = members.Select(m => m.AccountId).ToList();
var accounts = (await accountsHelper.GetAccountBatch(accountIds)).ToDictionary(a => Guid.Parse(a.Id), a => a);

View File

@@ -1,5 +1,5 @@
using System.Text.RegularExpressions;
using DysonNetwork.Shared.Data;
using DysonNetwork.Shared.Models;
using DysonNetwork.Shared.Proto;
using DysonNetwork.Sphere.Chat.Realtime;
using DysonNetwork.Sphere.WebReader;
@@ -29,7 +29,7 @@ public partial class ChatService(
/// This method is designed to be called from a background task
/// </summary>
/// <param name="message">The message to process link previews for</param>
private async Task ProcessMessageLinkPreviewAsync(Message message)
private async Task ProcessMessageLinkPreviewAsync(SnChatMessage message)
{
try
{
@@ -66,7 +66,7 @@ public partial class ChatService(
logger.LogDebug($"Updated message {message.Id} with {embedsList.Count} link previews");
// Create and store sync message for link preview update
var syncMessage = new Message
var syncMessage = new SnChatMessage
{
Type = "messages.update.links",
ChatRoomId = dbMessage.ChatRoomId,
@@ -114,7 +114,7 @@ public partial class ChatService(
/// <param name="message">The message to process</param>
/// <param name="webReader">The web reader service</param>
/// <returns>The message with link previews added to its meta data</returns>
public async Task<Message> PreviewMessageLinkAsync(Message message, WebReaderService? webReader = null)
public async Task<SnChatMessage> PreviewMessageLinkAsync(SnChatMessage message, WebReaderService? webReader = null)
{
if (string.IsNullOrEmpty(message.Content))
return message;
@@ -172,9 +172,9 @@ public partial class ChatService(
}
private async Task DeliverWebSocketMessage(
Message message,
SnChatMessage message,
string type,
List<ChatMember> members,
List<SnChatMember> members,
IServiceScope scope
)
{
@@ -195,7 +195,7 @@ public partial class ChatService(
logger.LogInformation($"Delivered message to {request.UserIds.Count} accounts.");
}
public async Task<Message> SendMessageAsync(Message message, ChatMember sender, ChatRoom room)
public async Task<SnChatMessage> SendMessageAsync(SnChatMessage message, SnChatMember sender, SnChatRoom room)
{
if (string.IsNullOrWhiteSpace(message.Nonce)) message.Nonce = Guid.NewGuid().ToString();
message.CreatedAt = SystemClock.Instance.GetCurrentInstant();
@@ -230,9 +230,9 @@ public partial class ChatService(
}
private async Task DeliverMessageAsync(
Message message,
ChatMember sender,
ChatRoom room,
SnChatMessage message,
SnChatMember sender,
SnChatRoom room,
string type = WebSocketPacketType.MessageNew,
bool notify = true
)
@@ -254,11 +254,11 @@ public partial class ChatService(
}
private async Task SendPushNotificationsAsync(
Message message,
ChatMember sender,
ChatRoom room,
SnChatMessage message,
SnChatMember sender,
SnChatRoom room,
string type,
List<ChatMember> members,
List<SnChatMember> members,
IServiceScope scope
)
{
@@ -292,7 +292,7 @@ public partial class ChatService(
logger.LogInformation($"Delivered message to {accountsToNotify.Count} accounts.");
}
private PushNotification BuildNotification(Message message, ChatMember sender, ChatRoom room, string roomSubject,
private PushNotification BuildNotification(SnChatMessage message, SnChatMember sender, SnChatRoom room, string roomSubject,
string type)
{
var metaDict = new Dictionary<string, object>
@@ -325,7 +325,7 @@ public partial class ChatService(
return notification;
}
private string BuildNotificationBody(Message message, string type)
private string BuildNotificationBody(SnChatMessage message, string type)
{
if (message.DeletedAt is not null)
return "Deleted a message";
@@ -356,7 +356,7 @@ public partial class ChatService(
}
}
private List<Account> FilterAccountsForNotification(List<ChatMember> members, Message message, ChatMember sender)
private List<Account> FilterAccountsForNotification(List<SnChatMember> members, SnChatMessage message, SnChatMember sender)
{
var now = SystemClock.Instance.GetCurrentInstant();
@@ -377,7 +377,7 @@ public partial class ChatService(
return accountsToNotify.Where(a => a.Id != sender.AccountId.ToString()).ToList();
}
private async Task CreateFileReferencesForMessageAsync(Message message)
private async Task CreateFileReferencesForMessageAsync(SnChatMessage message)
{
var files = message.Attachments.Distinct().ToList();
if (files.Count == 0) return;
@@ -391,7 +391,7 @@ public partial class ChatService(
await fileRefs.CreateReferenceBatchAsync(request);
}
private async Task UpdateFileReferencesForMessageAsync(Message message, List<string> attachmentsId)
private async Task UpdateFileReferencesForMessageAsync(SnChatMessage message, List<string> attachmentsId)
{
// Delete existing references for this message
await fileRefs.DeleteResourceReferencesAsync(
@@ -411,10 +411,10 @@ public partial class ChatService(
var queryRequest = new GetFileBatchRequest();
queryRequest.Ids.AddRange(attachmentsId);
var queryResult = await filesClient.GetFileBatchAsync(queryRequest);
message.Attachments = queryResult.Files.Select(CloudFileReferenceObject.FromProtoValue).ToList();
message.Attachments = queryResult.Files.Select(SnCloudFileReferenceObject.FromProtoValue).ToList();
}
private async Task DeleteFileReferencesForMessageAsync(Message message)
private async Task DeleteFileReferencesForMessageAsync(SnChatMessage message)
{
var messageResourceId = $"message:{message.Id}";
await fileRefs.DeleteResourceReferencesAsync(
@@ -474,7 +474,7 @@ public partial class ChatService(
);
}
public async Task<Dictionary<Guid, Message?>> ListLastMessageForUser(Guid userId)
public async Task<Dictionary<Guid, SnChatMessage?>> ListLastMessageForUser(Guid userId)
{
var userRooms = await db.ChatMembers
.Where(m => m.LeaveAt == null && m.JoinedAt != null)
@@ -517,9 +517,9 @@ public partial class ChatService(
return messages;
}
public async Task<RealtimeCall> CreateCallAsync(ChatRoom room, ChatMember sender)
public async Task<SnRealtimeCall> CreateCallAsync(SnChatRoom room, SnChatMember sender)
{
var call = new RealtimeCall
var call = new SnRealtimeCall
{
RoomId = room.Id,
SenderId = sender.Id,
@@ -547,7 +547,7 @@ public partial class ChatService(
db.ChatRealtimeCall.Add(call);
await db.SaveChangesAsync();
await SendMessageAsync(new Message
await SendMessageAsync(new SnChatMessage
{
Type = "call.start",
ChatRoomId = room.Id,
@@ -561,7 +561,7 @@ public partial class ChatService(
return call;
}
public async Task EndCallAsync(Guid roomId, ChatMember sender)
public async Task EndCallAsync(Guid roomId, SnChatMember sender)
{
var call = await GetCallOngoingAsync(roomId);
if (call is null) throw new InvalidOperationException("No ongoing call was not found.");
@@ -592,7 +592,7 @@ public partial class ChatService(
db.ChatRealtimeCall.Update(call);
await db.SaveChangesAsync();
await SendMessageAsync(new Message
await SendMessageAsync(new SnChatMessage
{
Type = "call.ended",
ChatRoomId = call.RoomId,
@@ -605,7 +605,7 @@ public partial class ChatService(
}, call.Sender, call.Room);
}
public async Task<RealtimeCall?> GetCallOngoingAsync(Guid roomId)
public async Task<SnRealtimeCall?> GetCallOngoingAsync(Guid roomId)
{
return await db.ChatRealtimeCall
.Where(c => c.RoomId == roomId)
@@ -660,8 +660,8 @@ public partial class ChatService(
}
public async Task<Message> UpdateMessageAsync(
Message message,
public async Task<SnChatMessage> UpdateMessageAsync(
SnChatMessage message,
Dictionary<string, object>? meta = null,
string? content = null,
Guid? repliedMessageId = null,
@@ -705,7 +705,7 @@ public partial class ChatService(
await db.SaveChangesAsync();
// Create and store sync message for the update
var syncMessage = new Message
var syncMessage = new SnChatMessage
{
Type = "messages.update",
ChatRoomId = message.ChatRoomId,
@@ -751,7 +751,7 @@ public partial class ChatService(
/// Soft deletes a message and notifies other chat members
/// </summary>
/// <param name="message">The message to delete</param>
public async Task DeleteMessageAsync(Message message)
public async Task DeleteMessageAsync(SnChatMessage message)
{
// Only allow deleting regular text messages
if (message.Type != "text")
@@ -770,7 +770,7 @@ public partial class ChatService(
await db.SaveChangesAsync();
// Create and store sync message for the deletion
var syncMessage = new Message
var syncMessage = new SnChatMessage
{
Type = "messages.delete",
ChatRoomId = message.ChatRoomId,
@@ -805,6 +805,6 @@ public partial class ChatService(
public class SyncResponse
{
public List<Message> Messages { get; set; } = [];
public List<SnChatMessage> Messages { get; set; } = [];
public Instant CurrentTimestamp { get; set; }
}

View File

@@ -1,80 +0,0 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text.Json.Serialization;
using DysonNetwork.Shared.Data;
using NodaTime;
namespace DysonNetwork.Sphere.Chat;
public class Message : ModelBase, IIdentifiedResource
{
public Guid Id { get; set; } = Guid.NewGuid();
[MaxLength(1024)] public string Type { get; set; } = null!;
[MaxLength(4096)] public string? Content { get; set; }
[Column(TypeName = "jsonb")] public Dictionary<string, object>? Meta { get; set; }
[Column(TypeName = "jsonb")] public List<Guid>? MembersMentioned { get; set; }
[MaxLength(36)] public string Nonce { get; set; } = null!;
public Instant? EditedAt { get; set; }
[Column(TypeName = "jsonb")] public List<CloudFileReferenceObject> Attachments { get; set; } = [];
public ICollection<MessageReaction> Reactions { get; set; } = new List<MessageReaction>();
public Guid? RepliedMessageId { get; set; }
public Message? RepliedMessage { get; set; }
public Guid? ForwardedMessageId { get; set; }
public Message? ForwardedMessage { get; set; }
public Guid SenderId { get; set; }
public ChatMember Sender { get; set; } = null!;
public Guid ChatRoomId { get; set; }
[JsonIgnore] public ChatRoom ChatRoom { get; set; } = null!;
public string ResourceIdentifier => $"message:{Id}";
/// <summary>
/// Creates a shallow clone of this message for sync operations
/// </summary>
/// <returns>A new Message instance with copied properties</returns>
public Message Clone()
{
return new Message
{
Id = Id,
Type = Type,
Content = Content,
Meta = Meta,
MembersMentioned = MembersMentioned,
Nonce = Nonce,
EditedAt = EditedAt,
Attachments = Attachments,
RepliedMessageId = RepliedMessageId,
ForwardedMessageId = ForwardedMessageId,
SenderId = SenderId,
Sender = Sender,
ChatRoomId = ChatRoomId,
ChatRoom = ChatRoom,
CreatedAt = CreatedAt,
UpdatedAt = UpdatedAt
};
}
}
public enum MessageReactionAttitude
{
Positive,
Neutral,
Negative,
}
public class MessageReaction : ModelBase
{
public Guid Id { get; set; } = Guid.NewGuid();
public Guid MessageId { get; set; }
[JsonIgnore] public Message Message { get; set; } = null!;
public Guid SenderId { get; set; }
public ChatMember Sender { get; set; } = null!;
[MaxLength(256)] public string Symbol { get; set; } = null!;
public MessageReactionAttitude Attitude { get; set; }
}

View File

@@ -1,51 +0,0 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text.Json;
using System.Text.Json.Serialization;
using DysonNetwork.Shared.Data;
using DysonNetwork.Sphere.Chat.Realtime;
using NodaTime;
namespace DysonNetwork.Sphere.Chat;
public class RealtimeCall : ModelBase
{
public Guid Id { get; set; } = Guid.NewGuid();
public Instant? EndedAt { get; set; }
public Guid SenderId { get; set; }
public ChatMember Sender { get; set; } = null!;
public Guid RoomId { get; set; }
public ChatRoom Room { get; set; } = null!;
/// <summary>
/// Provider name (e.g., "cloudflare", "agora", "twilio")
/// </summary>
public string? ProviderName { get; set; }
/// <summary>
/// Service provider's session identifier
/// </summary>
public string? SessionId { get; set; }
/// <summary>
/// JSONB column containing provider-specific configuration
/// </summary>
[Column(name: "upstream", TypeName = "jsonb")]
public string? UpstreamConfigJson { get; set; }
/// <summary>
/// Deserialized upstream configuration
/// </summary>
[NotMapped]
public Dictionary<string, object> UpstreamConfig
{
get => string.IsNullOrEmpty(UpstreamConfigJson)
? new Dictionary<string, object>()
: JsonSerializer.Deserialize<Dictionary<string, object>>(UpstreamConfigJson) ?? new Dictionary<string, object>();
set => UpstreamConfigJson = value.Count > 0
? JsonSerializer.Serialize(value)
: null;
}
}

View File

@@ -1,3 +1,4 @@
using DysonNetwork.Shared.Models;
using DysonNetwork.Shared.Proto;
using DysonNetwork.Sphere.Chat.Realtime;
using Livekit.Server.Sdk.Dotnet;
@@ -46,7 +47,7 @@ public class RealtimeCallController(
[HttpGet("{roomId:guid}")]
[Authorize]
public async Task<ActionResult<RealtimeCall>> GetOngoingCall(Guid roomId)
public async Task<ActionResult<SnRealtimeCall>> GetOngoingCall(Guid roomId)
{
if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized();
@@ -145,7 +146,7 @@ public class RealtimeCallController(
[HttpPost("{roomId:guid}")]
[Authorize]
public async Task<ActionResult<RealtimeCall>> StartCall(Guid roomId)
public async Task<ActionResult<SnRealtimeCall>> StartCall(Guid roomId)
{
if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized();
@@ -165,7 +166,7 @@ public class RealtimeCallController(
[HttpDelete("{roomId:guid}")]
[Authorize]
public async Task<ActionResult<RealtimeCall>> EndCall(Guid roomId)
public async Task<ActionResult<SnRealtimeCall>> EndCall(Guid roomId)
{
if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized();
@@ -250,7 +251,7 @@ public class CallParticipant
/// <summary>
/// The participant's profile in the chat
/// </summary>
public ChatMember? Profile { get; set; }
public SnChatMember? Profile { get; set; }
/// <summary>
/// When the participant joined the call

View File

@@ -7,7 +7,7 @@ namespace DysonNetwork.Sphere.Discovery;
public class DiscoveryController(DiscoveryService discoveryService) : ControllerBase
{
[HttpGet("realms")]
public Task<List<Realm.Realm>> GetPublicRealms(
public Task<List<Shared.Models.SnRealm>> GetPublicRealms(
[FromQuery] string? query,
[FromQuery] int take = 10,
[FromQuery] int offset = 0

View File

@@ -4,7 +4,7 @@ namespace DysonNetwork.Sphere.Discovery;
public class DiscoveryService(AppDatabase appDatabase)
{
public Task<List<Realm.Realm>> GetCommunityRealmAsync(
public Task<List<Shared.Models.SnRealm>> GetCommunityRealmAsync(
string? query,
int take = 10,
int offset = 0,

View File

@@ -1,9 +1,8 @@
// <auto-generated />
using System;
using System.Collections.Generic;
using DysonNetwork.Shared.Data;
using DysonNetwork.Shared.Models;
using DysonNetwork.Sphere;
using DysonNetwork.Sphere.Chat;
using DysonNetwork.Sphere.WebReader;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
@@ -116,7 +115,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<CloudFileReferenceObject>("Background")
b.Property<SnCloudFileReferenceObject>("Background")
.HasColumnType("jsonb")
.HasColumnName("background");
@@ -151,7 +150,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("character varying(1024)")
.HasColumnName("name");
b.Property<CloudFileReferenceObject>("Picture")
b.Property<SnCloudFileReferenceObject>("Picture")
.HasColumnType("jsonb")
.HasColumnName("picture");
@@ -188,7 +187,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<List<CloudFileReferenceObject>>("Attachments")
b.Property<List<SnCloudFileReferenceObject>>("Attachments")
.IsRequired()
.HasColumnType("jsonb")
.HasColumnName("attachments");
@@ -379,7 +378,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<CloudFileReferenceObject>("Background")
b.Property<SnCloudFileReferenceObject>("Background")
.HasColumnType("jsonb")
.HasColumnName("background");
@@ -402,7 +401,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("character varying(1024)")
.HasColumnName("name");
b.Property<CloudFileReferenceObject>("Picture")
b.Property<SnCloudFileReferenceObject>("Picture")
.HasColumnType("jsonb")
.HasColumnName("picture");
@@ -424,7 +423,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("timestamp with time zone")
.HasColumnName("updated_at");
b.Property<VerificationMark>("Verification")
b.Property<SnVerificationMark>("Verification")
.HasColumnType("jsonb")
.HasColumnName("verification");
@@ -499,7 +498,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<List<CloudFileReferenceObject>>("Attachments")
b.Property<List<SnCloudFileReferenceObject>>("Attachments")
.IsRequired()
.HasColumnType("jsonb")
.HasColumnName("attachments");
@@ -792,7 +791,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("account_id");
b.Property<CloudFileReferenceObject>("Background")
b.Property<SnCloudFileReferenceObject>("Background")
.HasColumnType("jsonb")
.HasColumnName("background");
@@ -826,7 +825,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("character varying(256)")
.HasColumnName("nick");
b.Property<CloudFileReferenceObject>("Picture")
b.Property<SnCloudFileReferenceObject>("Picture")
.HasColumnType("jsonb")
.HasColumnName("picture");
@@ -847,7 +846,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("timestamp with time zone")
.HasColumnName("updated_at");
b.Property<VerificationMark>("Verification")
b.Property<SnVerificationMark>("Verification")
.HasColumnType("jsonb")
.HasColumnName("verification");
@@ -997,7 +996,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("account_id");
b.Property<CloudFileReferenceObject>("Background")
b.Property<SnCloudFileReferenceObject>("Background")
.HasColumnType("jsonb")
.HasColumnName("background");
@@ -1034,7 +1033,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("character varying(1024)")
.HasColumnName("name");
b.Property<CloudFileReferenceObject>("Picture")
b.Property<SnCloudFileReferenceObject>("Picture")
.HasColumnType("jsonb")
.HasColumnName("picture");
@@ -1053,7 +1052,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("timestamp with time zone")
.HasColumnName("updated_at");
b.Property<VerificationMark>("Verification")
b.Property<SnVerificationMark>("Verification")
.HasColumnType("jsonb")
.HasColumnName("verification");
@@ -1184,7 +1183,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("timestamp with time zone")
.HasColumnName("deleted_at");
b.Property<CloudFileReferenceObject>("Image")
b.Property<SnCloudFileReferenceObject>("Image")
.HasColumnType("jsonb")
.HasColumnName("image");

View File

@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using DysonNetwork.Shared.Data;
using DysonNetwork.Sphere.Chat;
using DysonNetwork.Shared.Models;
using DysonNetwork.Sphere.WebReader;
using Microsoft.EntityFrameworkCore.Migrations;
using NodaTime;
@@ -64,9 +63,9 @@ namespace DysonNetwork.Sphere.Migrations
is_public = table.Column<bool>(type: "boolean", nullable: false),
picture_id = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: true),
background_id = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: true),
picture = table.Column<CloudFileReferenceObject>(type: "jsonb", nullable: true),
background = table.Column<CloudFileReferenceObject>(type: "jsonb", nullable: true),
verification = table.Column<VerificationMark>(type: "jsonb", nullable: true),
picture = table.Column<SnCloudFileReferenceObject>(type: "jsonb", nullable: true),
background = table.Column<SnCloudFileReferenceObject>(type: "jsonb", nullable: true),
verification = table.Column<SnVerificationMark>(type: "jsonb", nullable: true),
account_id = table.Column<Guid>(type: "uuid", nullable: false),
created_at = table.Column<Instant>(type: "timestamp with time zone", nullable: false),
updated_at = table.Column<Instant>(type: "timestamp with time zone", nullable: false),
@@ -104,8 +103,8 @@ namespace DysonNetwork.Sphere.Migrations
is_public = table.Column<bool>(type: "boolean", nullable: false),
picture_id = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: true),
background_id = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: true),
picture = table.Column<CloudFileReferenceObject>(type: "jsonb", nullable: true),
background = table.Column<CloudFileReferenceObject>(type: "jsonb", nullable: true),
picture = table.Column<SnCloudFileReferenceObject>(type: "jsonb", nullable: true),
background = table.Column<SnCloudFileReferenceObject>(type: "jsonb", nullable: true),
realm_id = table.Column<Guid>(type: "uuid", nullable: true),
created_at = table.Column<Instant>(type: "timestamp with time zone", nullable: false),
updated_at = table.Column<Instant>(type: "timestamp with time zone", nullable: false),
@@ -132,9 +131,9 @@ namespace DysonNetwork.Sphere.Migrations
bio = table.Column<string>(type: "character varying(4096)", maxLength: 4096, nullable: true),
picture_id = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: true),
background_id = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: true),
picture = table.Column<CloudFileReferenceObject>(type: "jsonb", nullable: true),
background = table.Column<CloudFileReferenceObject>(type: "jsonb", nullable: true),
verification = table.Column<VerificationMark>(type: "jsonb", nullable: true),
picture = table.Column<SnCloudFileReferenceObject>(type: "jsonb", nullable: true),
background = table.Column<SnCloudFileReferenceObject>(type: "jsonb", nullable: true),
verification = table.Column<SnVerificationMark>(type: "jsonb", nullable: true),
account_id = table.Column<Guid>(type: "uuid", nullable: true),
realm_id = table.Column<Guid>(type: "uuid", nullable: true),
created_at = table.Column<Instant>(type: "timestamp with time zone", nullable: false),
@@ -244,9 +243,9 @@ namespace DysonNetwork.Sphere.Migrations
name = table.Column<string>(type: "character varying(1024)", maxLength: 1024, nullable: false),
description = table.Column<string>(type: "character varying(4096)", maxLength: 4096, nullable: true),
status = table.Column<int>(type: "integer", nullable: false),
picture = table.Column<CloudFileReferenceObject>(type: "jsonb", nullable: true),
background = table.Column<CloudFileReferenceObject>(type: "jsonb", nullable: true),
verification = table.Column<VerificationMark>(type: "jsonb", nullable: true),
picture = table.Column<SnCloudFileReferenceObject>(type: "jsonb", nullable: true),
background = table.Column<SnCloudFileReferenceObject>(type: "jsonb", nullable: true),
verification = table.Column<SnVerificationMark>(type: "jsonb", nullable: true),
publisher_id = table.Column<Guid>(type: "uuid", nullable: false),
created_at = table.Column<Instant>(type: "timestamp with time zone", nullable: false),
updated_at = table.Column<Instant>(type: "timestamp with time zone", nullable: false),
@@ -308,7 +307,7 @@ namespace DysonNetwork.Sphere.Migrations
downvotes = table.Column<int>(type: "integer", nullable: false),
replied_post_id = table.Column<Guid>(type: "uuid", nullable: true),
forwarded_post_id = table.Column<Guid>(type: "uuid", nullable: true),
attachments = table.Column<List<CloudFileReferenceObject>>(type: "jsonb", nullable: false),
attachments = table.Column<List<SnCloudFileReferenceObject>>(type: "jsonb", nullable: false),
search_vector = table.Column<NpgsqlTsVector>(type: "tsvector", nullable: false)
.Annotation("Npgsql:TsVectorConfig", "simple")
.Annotation("Npgsql:TsVectorProperties", new[] { "title", "description", "content" }),
@@ -471,7 +470,7 @@ namespace DysonNetwork.Sphere.Migrations
members_mentioned = table.Column<List<Guid>>(type: "jsonb", nullable: true),
nonce = table.Column<string>(type: "character varying(36)", maxLength: 36, nullable: false),
edited_at = table.Column<Instant>(type: "timestamp with time zone", nullable: true),
attachments = table.Column<List<CloudFileReferenceObject>>(type: "jsonb", nullable: false),
attachments = table.Column<List<SnCloudFileReferenceObject>>(type: "jsonb", nullable: false),
replied_message_id = table.Column<Guid>(type: "uuid", nullable: true),
forwarded_message_id = table.Column<Guid>(type: "uuid", nullable: true),
sender_id = table.Column<Guid>(type: "uuid", nullable: false),
@@ -669,7 +668,7 @@ namespace DysonNetwork.Sphere.Migrations
id = table.Column<Guid>(type: "uuid", nullable: false),
slug = table.Column<string>(type: "character varying(128)", maxLength: 128, nullable: false),
image_id = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: true),
image = table.Column<CloudFileReferenceObject>(type: "jsonb", nullable: true),
image = table.Column<SnCloudFileReferenceObject>(type: "jsonb", nullable: true),
pack_id = table.Column<Guid>(type: "uuid", nullable: false),
created_at = table.Column<Instant>(type: "timestamp with time zone", nullable: false),
updated_at = table.Column<Instant>(type: "timestamp with time zone", nullable: false),

View File

@@ -1,9 +1,8 @@
// <auto-generated />
using System;
using System.Collections.Generic;
using DysonNetwork.Shared.Data;
using DysonNetwork.Shared.Models;
using DysonNetwork.Sphere;
using DysonNetwork.Sphere.Chat;
using DysonNetwork.Sphere.WebReader;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
@@ -116,7 +115,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<CloudFileReferenceObject>("Background")
b.Property<SnCloudFileReferenceObject>("Background")
.HasColumnType("jsonb")
.HasColumnName("background");
@@ -151,7 +150,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("character varying(1024)")
.HasColumnName("name");
b.Property<CloudFileReferenceObject>("Picture")
b.Property<SnCloudFileReferenceObject>("Picture")
.HasColumnType("jsonb")
.HasColumnName("picture");
@@ -188,7 +187,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<List<CloudFileReferenceObject>>("Attachments")
b.Property<List<SnCloudFileReferenceObject>>("Attachments")
.IsRequired()
.HasColumnType("jsonb")
.HasColumnName("attachments");
@@ -379,7 +378,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<CloudFileReferenceObject>("Background")
b.Property<SnCloudFileReferenceObject>("Background")
.HasColumnType("jsonb")
.HasColumnName("background");
@@ -402,7 +401,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("character varying(1024)")
.HasColumnName("name");
b.Property<CloudFileReferenceObject>("Picture")
b.Property<SnCloudFileReferenceObject>("Picture")
.HasColumnType("jsonb")
.HasColumnName("picture");
@@ -424,7 +423,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("timestamp with time zone")
.HasColumnName("updated_at");
b.Property<VerificationMark>("Verification")
b.Property<SnVerificationMark>("Verification")
.HasColumnType("jsonb")
.HasColumnName("verification");
@@ -499,7 +498,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<List<CloudFileReferenceObject>>("Attachments")
b.Property<List<SnCloudFileReferenceObject>>("Attachments")
.IsRequired()
.HasColumnType("jsonb")
.HasColumnName("attachments");
@@ -792,7 +791,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("account_id");
b.Property<CloudFileReferenceObject>("Background")
b.Property<SnCloudFileReferenceObject>("Background")
.HasColumnType("jsonb")
.HasColumnName("background");
@@ -826,7 +825,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("character varying(256)")
.HasColumnName("nick");
b.Property<CloudFileReferenceObject>("Picture")
b.Property<SnCloudFileReferenceObject>("Picture")
.HasColumnType("jsonb")
.HasColumnName("picture");
@@ -847,7 +846,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("timestamp with time zone")
.HasColumnName("updated_at");
b.Property<VerificationMark>("Verification")
b.Property<SnVerificationMark>("Verification")
.HasColumnType("jsonb")
.HasColumnName("verification");
@@ -997,7 +996,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("account_id");
b.Property<CloudFileReferenceObject>("Background")
b.Property<SnCloudFileReferenceObject>("Background")
.HasColumnType("jsonb")
.HasColumnName("background");
@@ -1034,7 +1033,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("character varying(1024)")
.HasColumnName("name");
b.Property<CloudFileReferenceObject>("Picture")
b.Property<SnCloudFileReferenceObject>("Picture")
.HasColumnType("jsonb")
.HasColumnName("picture");
@@ -1053,7 +1052,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("timestamp with time zone")
.HasColumnName("updated_at");
b.Property<VerificationMark>("Verification")
b.Property<SnVerificationMark>("Verification")
.HasColumnType("jsonb")
.HasColumnName("verification");
@@ -1184,7 +1183,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("timestamp with time zone")
.HasColumnName("deleted_at");
b.Property<CloudFileReferenceObject>("Image")
b.Property<SnCloudFileReferenceObject>("Image")
.HasColumnType("jsonb")
.HasColumnName("image");

View File

@@ -2,10 +2,8 @@
using System;
using System.Collections.Generic;
using System.Text.Json;
using DysonNetwork.Shared.Data;
using DysonNetwork.Shared.Models;
using DysonNetwork.Sphere;
using DysonNetwork.Sphere.Chat;
using DysonNetwork.Sphere.Poll;
using DysonNetwork.Sphere.WebReader;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
@@ -118,7 +116,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<CloudFileReferenceObject>("Background")
b.Property<SnCloudFileReferenceObject>("Background")
.HasColumnType("jsonb")
.HasColumnName("background");
@@ -153,7 +151,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("character varying(1024)")
.HasColumnName("name");
b.Property<CloudFileReferenceObject>("Picture")
b.Property<SnCloudFileReferenceObject>("Picture")
.HasColumnType("jsonb")
.HasColumnName("picture");
@@ -190,7 +188,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<List<CloudFileReferenceObject>>("Attachments")
b.Property<List<SnCloudFileReferenceObject>>("Attachments")
.IsRequired()
.HasColumnType("jsonb")
.HasColumnName("attachments");
@@ -381,7 +379,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<CloudFileReferenceObject>("Background")
b.Property<SnCloudFileReferenceObject>("Background")
.HasColumnType("jsonb")
.HasColumnName("background");
@@ -404,7 +402,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("character varying(1024)")
.HasColumnName("name");
b.Property<CloudFileReferenceObject>("Picture")
b.Property<SnCloudFileReferenceObject>("Picture")
.HasColumnType("jsonb")
.HasColumnName("picture");
@@ -426,7 +424,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("timestamp with time zone")
.HasColumnName("updated_at");
b.Property<VerificationMark>("Verification")
b.Property<SnVerificationMark>("Verification")
.HasColumnType("jsonb")
.HasColumnName("verification");
@@ -605,7 +603,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("boolean")
.HasColumnName("is_required");
b.Property<List<PollOption>>("Options")
b.Property<List<SnPollOption>>("Options")
.HasColumnType("jsonb")
.HasColumnName("options");
@@ -647,7 +645,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<List<CloudFileReferenceObject>>("Attachments")
b.Property<List<SnCloudFileReferenceObject>>("Attachments")
.IsRequired()
.HasColumnType("jsonb")
.HasColumnName("attachments");
@@ -940,7 +938,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("account_id");
b.Property<CloudFileReferenceObject>("Background")
b.Property<SnCloudFileReferenceObject>("Background")
.HasColumnType("jsonb")
.HasColumnName("background");
@@ -974,7 +972,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("character varying(256)")
.HasColumnName("nick");
b.Property<CloudFileReferenceObject>("Picture")
b.Property<SnCloudFileReferenceObject>("Picture")
.HasColumnType("jsonb")
.HasColumnName("picture");
@@ -995,7 +993,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("timestamp with time zone")
.HasColumnName("updated_at");
b.Property<VerificationMark>("Verification")
b.Property<SnVerificationMark>("Verification")
.HasColumnType("jsonb")
.HasColumnName("verification");
@@ -1145,7 +1143,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("account_id");
b.Property<CloudFileReferenceObject>("Background")
b.Property<SnCloudFileReferenceObject>("Background")
.HasColumnType("jsonb")
.HasColumnName("background");
@@ -1182,7 +1180,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("character varying(1024)")
.HasColumnName("name");
b.Property<CloudFileReferenceObject>("Picture")
b.Property<SnCloudFileReferenceObject>("Picture")
.HasColumnType("jsonb")
.HasColumnName("picture");
@@ -1201,7 +1199,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("timestamp with time zone")
.HasColumnName("updated_at");
b.Property<VerificationMark>("Verification")
b.Property<SnVerificationMark>("Verification")
.HasColumnType("jsonb")
.HasColumnName("verification");
@@ -1332,7 +1330,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("timestamp with time zone")
.HasColumnName("deleted_at");
b.Property<CloudFileReferenceObject>("Image")
b.Property<SnCloudFileReferenceObject>("Image")
.HasColumnType("jsonb")
.HasColumnName("image");

View File

@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
using System.Text.Json;
using DysonNetwork.Sphere.Poll;
using DysonNetwork.Shared.Models;
using Microsoft.EntityFrameworkCore.Migrations;
using NodaTime;
@@ -68,7 +68,7 @@ namespace DysonNetwork.Sphere.Migrations
{
id = table.Column<Guid>(type: "uuid", nullable: false),
type = table.Column<int>(type: "integer", nullable: false),
options = table.Column<List<PollOption>>(type: "jsonb", nullable: true),
options = table.Column<List<SnPollOption>>(type: "jsonb", nullable: true),
title = table.Column<string>(type: "character varying(1024)", maxLength: 1024, nullable: false),
description = table.Column<string>(type: "character varying(4096)", maxLength: 4096, nullable: true),
order = table.Column<int>(type: "integer", nullable: false),

View File

@@ -2,10 +2,8 @@
using System;
using System.Collections.Generic;
using System.Text.Json;
using DysonNetwork.Shared.Data;
using DysonNetwork.Shared.Models;
using DysonNetwork.Sphere;
using DysonNetwork.Sphere.Chat;
using DysonNetwork.Sphere.Poll;
using DysonNetwork.Sphere.WebReader;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
@@ -118,7 +116,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<CloudFileReferenceObject>("Background")
b.Property<SnCloudFileReferenceObject>("Background")
.HasColumnType("jsonb")
.HasColumnName("background");
@@ -153,7 +151,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("character varying(1024)")
.HasColumnName("name");
b.Property<CloudFileReferenceObject>("Picture")
b.Property<SnCloudFileReferenceObject>("Picture")
.HasColumnType("jsonb")
.HasColumnName("picture");
@@ -190,7 +188,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<List<CloudFileReferenceObject>>("Attachments")
b.Property<List<SnCloudFileReferenceObject>>("Attachments")
.IsRequired()
.HasColumnType("jsonb")
.HasColumnName("attachments");
@@ -381,7 +379,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<CloudFileReferenceObject>("Background")
b.Property<SnCloudFileReferenceObject>("Background")
.HasColumnType("jsonb")
.HasColumnName("background");
@@ -404,7 +402,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("character varying(1024)")
.HasColumnName("name");
b.Property<CloudFileReferenceObject>("Picture")
b.Property<SnCloudFileReferenceObject>("Picture")
.HasColumnType("jsonb")
.HasColumnName("picture");
@@ -426,7 +424,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("timestamp with time zone")
.HasColumnName("updated_at");
b.Property<VerificationMark>("Verification")
b.Property<SnVerificationMark>("Verification")
.HasColumnType("jsonb")
.HasColumnName("verification");
@@ -605,7 +603,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("boolean")
.HasColumnName("is_required");
b.Property<List<PollOption>>("Options")
b.Property<List<SnPollOption>>("Options")
.HasColumnType("jsonb")
.HasColumnName("options");
@@ -647,7 +645,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<List<CloudFileReferenceObject>>("Attachments")
b.Property<List<SnCloudFileReferenceObject>>("Attachments")
.IsRequired()
.HasColumnType("jsonb")
.HasColumnName("attachments");
@@ -940,7 +938,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("account_id");
b.Property<CloudFileReferenceObject>("Background")
b.Property<SnCloudFileReferenceObject>("Background")
.HasColumnType("jsonb")
.HasColumnName("background");
@@ -974,7 +972,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("character varying(256)")
.HasColumnName("nick");
b.Property<CloudFileReferenceObject>("Picture")
b.Property<SnCloudFileReferenceObject>("Picture")
.HasColumnType("jsonb")
.HasColumnName("picture");
@@ -995,7 +993,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("timestamp with time zone")
.HasColumnName("updated_at");
b.Property<VerificationMark>("Verification")
b.Property<SnVerificationMark>("Verification")
.HasColumnType("jsonb")
.HasColumnName("verification");
@@ -1145,7 +1143,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("account_id");
b.Property<CloudFileReferenceObject>("Background")
b.Property<SnCloudFileReferenceObject>("Background")
.HasColumnType("jsonb")
.HasColumnName("background");
@@ -1182,7 +1180,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("character varying(1024)")
.HasColumnName("name");
b.Property<CloudFileReferenceObject>("Picture")
b.Property<SnCloudFileReferenceObject>("Picture")
.HasColumnType("jsonb")
.HasColumnName("picture");
@@ -1201,7 +1199,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("timestamp with time zone")
.HasColumnName("updated_at");
b.Property<VerificationMark>("Verification")
b.Property<SnVerificationMark>("Verification")
.HasColumnType("jsonb")
.HasColumnName("verification");
@@ -1332,7 +1330,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("timestamp with time zone")
.HasColumnName("deleted_at");
b.Property<CloudFileReferenceObject>("Image")
b.Property<SnCloudFileReferenceObject>("Image")
.HasColumnType("jsonb")
.HasColumnName("image");

View File

@@ -2,10 +2,8 @@
using System;
using System.Collections.Generic;
using System.Text.Json;
using DysonNetwork.Shared.Data;
using DysonNetwork.Shared.Models;
using DysonNetwork.Sphere;
using DysonNetwork.Sphere.Chat;
using DysonNetwork.Sphere.Poll;
using DysonNetwork.Sphere.WebReader;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
@@ -118,7 +116,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<CloudFileReferenceObject>("Background")
b.Property<SnCloudFileReferenceObject>("Background")
.HasColumnType("jsonb")
.HasColumnName("background");
@@ -153,7 +151,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("character varying(1024)")
.HasColumnName("name");
b.Property<CloudFileReferenceObject>("Picture")
b.Property<SnCloudFileReferenceObject>("Picture")
.HasColumnType("jsonb")
.HasColumnName("picture");
@@ -190,7 +188,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<List<CloudFileReferenceObject>>("Attachments")
b.Property<List<SnCloudFileReferenceObject>>("Attachments")
.IsRequired()
.HasColumnType("jsonb")
.HasColumnName("attachments");
@@ -485,7 +483,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("boolean")
.HasColumnName("is_required");
b.Property<List<PollOption>>("Options")
b.Property<List<SnPollOption>>("Options")
.HasColumnType("jsonb")
.HasColumnName("options");
@@ -527,7 +525,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<List<CloudFileReferenceObject>>("Attachments")
b.Property<List<SnCloudFileReferenceObject>>("Attachments")
.IsRequired()
.HasColumnType("jsonb")
.HasColumnName("attachments");
@@ -820,7 +818,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("account_id");
b.Property<CloudFileReferenceObject>("Background")
b.Property<SnCloudFileReferenceObject>("Background")
.HasColumnType("jsonb")
.HasColumnName("background");
@@ -854,7 +852,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("character varying(256)")
.HasColumnName("nick");
b.Property<CloudFileReferenceObject>("Picture")
b.Property<SnCloudFileReferenceObject>("Picture")
.HasColumnType("jsonb")
.HasColumnName("picture");
@@ -875,7 +873,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("timestamp with time zone")
.HasColumnName("updated_at");
b.Property<VerificationMark>("Verification")
b.Property<SnVerificationMark>("Verification")
.HasColumnType("jsonb")
.HasColumnName("verification");
@@ -1025,7 +1023,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("account_id");
b.Property<CloudFileReferenceObject>("Background")
b.Property<SnCloudFileReferenceObject>("Background")
.HasColumnType("jsonb")
.HasColumnName("background");
@@ -1062,7 +1060,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("character varying(1024)")
.HasColumnName("name");
b.Property<CloudFileReferenceObject>("Picture")
b.Property<SnCloudFileReferenceObject>("Picture")
.HasColumnType("jsonb")
.HasColumnName("picture");
@@ -1081,7 +1079,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("timestamp with time zone")
.HasColumnName("updated_at");
b.Property<VerificationMark>("Verification")
b.Property<SnVerificationMark>("Verification")
.HasColumnType("jsonb")
.HasColumnName("verification");
@@ -1150,7 +1148,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("timestamp with time zone")
.HasColumnName("deleted_at");
b.Property<CloudFileReferenceObject>("Image")
b.Property<SnCloudFileReferenceObject>("Image")
.HasColumnType("jsonb")
.HasColumnName("image");

View File

@@ -1,5 +1,5 @@
using System;
using DysonNetwork.Shared.Data;
using DysonNetwork.Shared.Models;
using Microsoft.EntityFrameworkCore.Migrations;
using NodaTime;
@@ -35,16 +35,16 @@ namespace DysonNetwork.Sphere.Migrations
{
id = table.Column<Guid>(type: "uuid", nullable: false),
publisher_id = table.Column<Guid>(type: "uuid", nullable: false),
background = table.Column<CloudFileReferenceObject>(type: "jsonb", nullable: true),
background = table.Column<SnCloudFileReferenceObject>(type: "jsonb", nullable: true),
created_at = table.Column<Instant>(type: "timestamp with time zone", nullable: false),
deleted_at = table.Column<Instant>(type: "timestamp with time zone", nullable: true),
description = table.Column<string>(type: "character varying(4096)", maxLength: 4096, nullable: true),
name = table.Column<string>(type: "character varying(1024)", maxLength: 1024, nullable: false),
picture = table.Column<CloudFileReferenceObject>(type: "jsonb", nullable: true),
picture = table.Column<SnCloudFileReferenceObject>(type: "jsonb", nullable: true),
slug = table.Column<string>(type: "character varying(1024)", maxLength: 1024, nullable: false),
status = table.Column<int>(type: "integer", nullable: false),
updated_at = table.Column<Instant>(type: "timestamp with time zone", nullable: false),
verification = table.Column<VerificationMark>(type: "jsonb", nullable: true)
verification = table.Column<SnVerificationMark>(type: "jsonb", nullable: true)
},
constraints: table =>
{

View File

@@ -2,10 +2,8 @@
using System;
using System.Collections.Generic;
using System.Text.Json;
using DysonNetwork.Shared.Data;
using DysonNetwork.Shared.Models;
using DysonNetwork.Sphere;
using DysonNetwork.Sphere.Chat;
using DysonNetwork.Sphere.Poll;
using DysonNetwork.Sphere.WebReader;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
@@ -118,7 +116,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<CloudFileReferenceObject>("Background")
b.Property<SnCloudFileReferenceObject>("Background")
.HasColumnType("jsonb")
.HasColumnName("background");
@@ -153,7 +151,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("character varying(1024)")
.HasColumnName("name");
b.Property<CloudFileReferenceObject>("Picture")
b.Property<SnCloudFileReferenceObject>("Picture")
.HasColumnType("jsonb")
.HasColumnName("picture");
@@ -190,7 +188,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<List<CloudFileReferenceObject>>("Attachments")
b.Property<List<SnCloudFileReferenceObject>>("Attachments")
.IsRequired()
.HasColumnType("jsonb")
.HasColumnName("attachments");
@@ -485,7 +483,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("boolean")
.HasColumnName("is_required");
b.Property<List<PollOption>>("Options")
b.Property<List<SnPollOption>>("Options")
.HasColumnType("jsonb")
.HasColumnName("options");
@@ -527,7 +525,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<List<CloudFileReferenceObject>>("Attachments")
b.Property<List<SnCloudFileReferenceObject>>("Attachments")
.IsRequired()
.HasColumnType("jsonb")
.HasColumnName("attachments");
@@ -860,7 +858,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("account_id");
b.Property<CloudFileReferenceObject>("Background")
b.Property<SnCloudFileReferenceObject>("Background")
.HasColumnType("jsonb")
.HasColumnName("background");
@@ -894,7 +892,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("character varying(256)")
.HasColumnName("nick");
b.Property<CloudFileReferenceObject>("Picture")
b.Property<SnCloudFileReferenceObject>("Picture")
.HasColumnType("jsonb")
.HasColumnName("picture");
@@ -915,7 +913,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("timestamp with time zone")
.HasColumnName("updated_at");
b.Property<VerificationMark>("Verification")
b.Property<SnVerificationMark>("Verification")
.HasColumnType("jsonb")
.HasColumnName("verification");
@@ -1065,7 +1063,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("account_id");
b.Property<CloudFileReferenceObject>("Background")
b.Property<SnCloudFileReferenceObject>("Background")
.HasColumnType("jsonb")
.HasColumnName("background");
@@ -1102,7 +1100,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("character varying(1024)")
.HasColumnName("name");
b.Property<CloudFileReferenceObject>("Picture")
b.Property<SnCloudFileReferenceObject>("Picture")
.HasColumnType("jsonb")
.HasColumnName("picture");
@@ -1121,7 +1119,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("timestamp with time zone")
.HasColumnName("updated_at");
b.Property<VerificationMark>("Verification")
b.Property<SnVerificationMark>("Verification")
.HasColumnType("jsonb")
.HasColumnName("verification");
@@ -1190,7 +1188,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("timestamp with time zone")
.HasColumnName("deleted_at");
b.Property<CloudFileReferenceObject>("Image")
b.Property<SnCloudFileReferenceObject>("Image")
.HasColumnType("jsonb")
.HasColumnName("image");

View File

@@ -2,10 +2,8 @@
using System;
using System.Collections.Generic;
using System.Text.Json;
using DysonNetwork.Shared.Data;
using DysonNetwork.Shared.Models;
using DysonNetwork.Sphere;
using DysonNetwork.Sphere.Chat;
using DysonNetwork.Sphere.Poll;
using DysonNetwork.Sphere.WebReader;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
@@ -118,7 +116,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<CloudFileReferenceObject>("Background")
b.Property<SnCloudFileReferenceObject>("Background")
.HasColumnType("jsonb")
.HasColumnName("background");
@@ -153,7 +151,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("character varying(1024)")
.HasColumnName("name");
b.Property<CloudFileReferenceObject>("Picture")
b.Property<SnCloudFileReferenceObject>("Picture")
.HasColumnType("jsonb")
.HasColumnName("picture");
@@ -190,7 +188,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<List<CloudFileReferenceObject>>("Attachments")
b.Property<List<SnCloudFileReferenceObject>>("Attachments")
.IsRequired()
.HasColumnType("jsonb")
.HasColumnName("attachments");
@@ -485,7 +483,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("boolean")
.HasColumnName("is_required");
b.Property<List<PollOption>>("Options")
b.Property<List<SnPollOption>>("Options")
.HasColumnType("jsonb")
.HasColumnName("options");
@@ -527,7 +525,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<List<CloudFileReferenceObject>>("Attachments")
b.Property<List<SnCloudFileReferenceObject>>("Attachments")
.IsRequired()
.HasColumnType("jsonb")
.HasColumnName("attachments");
@@ -867,7 +865,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("account_id");
b.Property<CloudFileReferenceObject>("Background")
b.Property<SnCloudFileReferenceObject>("Background")
.HasColumnType("jsonb")
.HasColumnName("background");
@@ -901,7 +899,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("character varying(256)")
.HasColumnName("nick");
b.Property<CloudFileReferenceObject>("Picture")
b.Property<SnCloudFileReferenceObject>("Picture")
.HasColumnType("jsonb")
.HasColumnName("picture");
@@ -922,7 +920,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("timestamp with time zone")
.HasColumnName("updated_at");
b.Property<VerificationMark>("Verification")
b.Property<SnVerificationMark>("Verification")
.HasColumnType("jsonb")
.HasColumnName("verification");
@@ -1072,7 +1070,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("account_id");
b.Property<CloudFileReferenceObject>("Background")
b.Property<SnCloudFileReferenceObject>("Background")
.HasColumnType("jsonb")
.HasColumnName("background");
@@ -1109,7 +1107,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("character varying(1024)")
.HasColumnName("name");
b.Property<CloudFileReferenceObject>("Picture")
b.Property<SnCloudFileReferenceObject>("Picture")
.HasColumnType("jsonb")
.HasColumnName("picture");
@@ -1128,7 +1126,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("timestamp with time zone")
.HasColumnName("updated_at");
b.Property<VerificationMark>("Verification")
b.Property<SnVerificationMark>("Verification")
.HasColumnType("jsonb")
.HasColumnName("verification");
@@ -1197,7 +1195,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("timestamp with time zone")
.HasColumnName("deleted_at");
b.Property<CloudFileReferenceObject>("Image")
b.Property<SnCloudFileReferenceObject>("Image")
.HasColumnType("jsonb")
.HasColumnName("image");

View File

@@ -2,10 +2,8 @@
using System;
using System.Collections.Generic;
using System.Text.Json;
using DysonNetwork.Shared.Data;
using DysonNetwork.Shared.Models;
using DysonNetwork.Sphere;
using DysonNetwork.Sphere.Chat;
using DysonNetwork.Sphere.Poll;
using DysonNetwork.Sphere.WebReader;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
@@ -118,7 +116,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<CloudFileReferenceObject>("Background")
b.Property<SnCloudFileReferenceObject>("Background")
.HasColumnType("jsonb")
.HasColumnName("background");
@@ -153,7 +151,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("character varying(1024)")
.HasColumnName("name");
b.Property<CloudFileReferenceObject>("Picture")
b.Property<SnCloudFileReferenceObject>("Picture")
.HasColumnType("jsonb")
.HasColumnName("picture");
@@ -190,7 +188,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<List<CloudFileReferenceObject>>("Attachments")
b.Property<List<SnCloudFileReferenceObject>>("Attachments")
.IsRequired()
.HasColumnType("jsonb")
.HasColumnName("attachments");
@@ -485,7 +483,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("boolean")
.HasColumnName("is_required");
b.Property<List<PollOption>>("Options")
b.Property<List<SnPollOption>>("Options")
.HasColumnType("jsonb")
.HasColumnName("options");
@@ -527,7 +525,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<List<CloudFileReferenceObject>>("Attachments")
b.Property<List<SnCloudFileReferenceObject>>("Attachments")
.IsRequired()
.HasColumnType("jsonb")
.HasColumnName("attachments");
@@ -867,7 +865,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("account_id");
b.Property<CloudFileReferenceObject>("Background")
b.Property<SnCloudFileReferenceObject>("Background")
.HasColumnType("jsonb")
.HasColumnName("background");
@@ -901,7 +899,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("character varying(256)")
.HasColumnName("nick");
b.Property<CloudFileReferenceObject>("Picture")
b.Property<SnCloudFileReferenceObject>("Picture")
.HasColumnType("jsonb")
.HasColumnName("picture");
@@ -922,7 +920,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("timestamp with time zone")
.HasColumnName("updated_at");
b.Property<VerificationMark>("Verification")
b.Property<SnVerificationMark>("Verification")
.HasColumnType("jsonb")
.HasColumnName("verification");
@@ -1072,7 +1070,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("account_id");
b.Property<CloudFileReferenceObject>("Background")
b.Property<SnCloudFileReferenceObject>("Background")
.HasColumnType("jsonb")
.HasColumnName("background");
@@ -1109,7 +1107,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("character varying(1024)")
.HasColumnName("name");
b.Property<CloudFileReferenceObject>("Picture")
b.Property<SnCloudFileReferenceObject>("Picture")
.HasColumnType("jsonb")
.HasColumnName("picture");
@@ -1128,7 +1126,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("timestamp with time zone")
.HasColumnName("updated_at");
b.Property<VerificationMark>("Verification")
b.Property<SnVerificationMark>("Verification")
.HasColumnType("jsonb")
.HasColumnName("verification");
@@ -1197,7 +1195,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("timestamp with time zone")
.HasColumnName("deleted_at");
b.Property<CloudFileReferenceObject>("Image")
b.Property<SnCloudFileReferenceObject>("Image")
.HasColumnType("jsonb")
.HasColumnName("image");

View File

@@ -2,10 +2,8 @@
using System;
using System.Collections.Generic;
using System.Text.Json;
using DysonNetwork.Shared.Data;
using DysonNetwork.Shared.Models;
using DysonNetwork.Sphere;
using DysonNetwork.Sphere.Chat;
using DysonNetwork.Sphere.Poll;
using DysonNetwork.Sphere.WebReader;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
@@ -118,7 +116,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<CloudFileReferenceObject>("Background")
b.Property<SnCloudFileReferenceObject>("Background")
.HasColumnType("jsonb")
.HasColumnName("background");
@@ -153,7 +151,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("character varying(1024)")
.HasColumnName("name");
b.Property<CloudFileReferenceObject>("Picture")
b.Property<SnCloudFileReferenceObject>("Picture")
.HasColumnType("jsonb")
.HasColumnName("picture");
@@ -190,7 +188,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<List<CloudFileReferenceObject>>("Attachments")
b.Property<List<SnCloudFileReferenceObject>>("Attachments")
.IsRequired()
.HasColumnType("jsonb")
.HasColumnName("attachments");
@@ -485,7 +483,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("boolean")
.HasColumnName("is_required");
b.Property<List<PollOption>>("Options")
b.Property<List<SnPollOption>>("Options")
.HasColumnType("jsonb")
.HasColumnName("options");
@@ -527,7 +525,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<List<CloudFileReferenceObject>>("Attachments")
b.Property<List<SnCloudFileReferenceObject>>("Attachments")
.IsRequired()
.HasColumnType("jsonb")
.HasColumnName("attachments");
@@ -875,7 +873,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("account_id");
b.Property<CloudFileReferenceObject>("Background")
b.Property<SnCloudFileReferenceObject>("Background")
.HasColumnType("jsonb")
.HasColumnName("background");
@@ -909,7 +907,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("character varying(256)")
.HasColumnName("nick");
b.Property<CloudFileReferenceObject>("Picture")
b.Property<SnCloudFileReferenceObject>("Picture")
.HasColumnType("jsonb")
.HasColumnName("picture");
@@ -930,7 +928,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("timestamp with time zone")
.HasColumnName("updated_at");
b.Property<VerificationMark>("Verification")
b.Property<SnVerificationMark>("Verification")
.HasColumnType("jsonb")
.HasColumnName("verification");
@@ -1080,7 +1078,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("account_id");
b.Property<CloudFileReferenceObject>("Background")
b.Property<SnCloudFileReferenceObject>("Background")
.HasColumnType("jsonb")
.HasColumnName("background");
@@ -1117,7 +1115,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("character varying(1024)")
.HasColumnName("name");
b.Property<CloudFileReferenceObject>("Picture")
b.Property<SnCloudFileReferenceObject>("Picture")
.HasColumnType("jsonb")
.HasColumnName("picture");
@@ -1136,7 +1134,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("timestamp with time zone")
.HasColumnName("updated_at");
b.Property<VerificationMark>("Verification")
b.Property<SnVerificationMark>("Verification")
.HasColumnType("jsonb")
.HasColumnName("verification");
@@ -1205,7 +1203,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("timestamp with time zone")
.HasColumnName("deleted_at");
b.Property<CloudFileReferenceObject>("Image")
b.Property<SnCloudFileReferenceObject>("Image")
.HasColumnType("jsonb")
.HasColumnName("image");

View File

@@ -2,10 +2,8 @@
using System;
using System.Collections.Generic;
using System.Text.Json;
using DysonNetwork.Shared.Data;
using DysonNetwork.Shared.Models;
using DysonNetwork.Sphere;
using DysonNetwork.Sphere.Chat;
using DysonNetwork.Sphere.Poll;
using DysonNetwork.Sphere.WebReader;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
@@ -118,7 +116,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<CloudFileReferenceObject>("Background")
b.Property<SnCloudFileReferenceObject>("Background")
.HasColumnType("jsonb")
.HasColumnName("background");
@@ -153,7 +151,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("character varying(1024)")
.HasColumnName("name");
b.Property<CloudFileReferenceObject>("Picture")
b.Property<SnCloudFileReferenceObject>("Picture")
.HasColumnType("jsonb")
.HasColumnName("picture");
@@ -190,7 +188,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<List<CloudFileReferenceObject>>("Attachments")
b.Property<List<SnCloudFileReferenceObject>>("Attachments")
.IsRequired()
.HasColumnType("jsonb")
.HasColumnName("attachments");
@@ -485,7 +483,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("boolean")
.HasColumnName("is_required");
b.Property<List<PollOption>>("Options")
b.Property<List<SnPollOption>>("Options")
.HasColumnType("jsonb")
.HasColumnName("options");
@@ -527,7 +525,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<List<CloudFileReferenceObject>>("Attachments")
b.Property<List<SnCloudFileReferenceObject>>("Attachments")
.IsRequired()
.HasColumnType("jsonb")
.HasColumnName("attachments");
@@ -875,7 +873,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("account_id");
b.Property<CloudFileReferenceObject>("Background")
b.Property<SnCloudFileReferenceObject>("Background")
.HasColumnType("jsonb")
.HasColumnName("background");
@@ -909,7 +907,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("character varying(256)")
.HasColumnName("nick");
b.Property<CloudFileReferenceObject>("Picture")
b.Property<SnCloudFileReferenceObject>("Picture")
.HasColumnType("jsonb")
.HasColumnName("picture");
@@ -930,7 +928,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("timestamp with time zone")
.HasColumnName("updated_at");
b.Property<VerificationMark>("Verification")
b.Property<SnVerificationMark>("Verification")
.HasColumnType("jsonb")
.HasColumnName("verification");
@@ -1080,7 +1078,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("account_id");
b.Property<CloudFileReferenceObject>("Background")
b.Property<SnCloudFileReferenceObject>("Background")
.HasColumnType("jsonb")
.HasColumnName("background");
@@ -1117,7 +1115,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("character varying(1024)")
.HasColumnName("name");
b.Property<CloudFileReferenceObject>("Picture")
b.Property<SnCloudFileReferenceObject>("Picture")
.HasColumnType("jsonb")
.HasColumnName("picture");
@@ -1136,7 +1134,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("timestamp with time zone")
.HasColumnName("updated_at");
b.Property<VerificationMark>("Verification")
b.Property<SnVerificationMark>("Verification")
.HasColumnType("jsonb")
.HasColumnName("verification");
@@ -1205,7 +1203,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("timestamp with time zone")
.HasColumnName("deleted_at");
b.Property<CloudFileReferenceObject>("Image")
b.Property<SnCloudFileReferenceObject>("Image")
.HasColumnType("jsonb")
.HasColumnName("image");

View File

@@ -2,10 +2,8 @@
using System;
using System.Collections.Generic;
using System.Text.Json;
using DysonNetwork.Shared.Data;
using DysonNetwork.Shared.Models;
using DysonNetwork.Sphere;
using DysonNetwork.Sphere.Chat;
using DysonNetwork.Sphere.Poll;
using DysonNetwork.Sphere.WebReader;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
@@ -118,7 +116,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<CloudFileReferenceObject>("Background")
b.Property<SnCloudFileReferenceObject>("Background")
.HasColumnType("jsonb")
.HasColumnName("background");
@@ -153,7 +151,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("character varying(1024)")
.HasColumnName("name");
b.Property<CloudFileReferenceObject>("Picture")
b.Property<SnCloudFileReferenceObject>("Picture")
.HasColumnType("jsonb")
.HasColumnName("picture");
@@ -190,7 +188,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<List<CloudFileReferenceObject>>("Attachments")
b.Property<List<SnCloudFileReferenceObject>>("Attachments")
.IsRequired()
.HasColumnType("jsonb")
.HasColumnName("attachments");
@@ -485,7 +483,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("boolean")
.HasColumnName("is_required");
b.Property<List<PollOption>>("Options")
b.Property<List<SnPollOption>>("Options")
.HasColumnType("jsonb")
.HasColumnName("options");
@@ -527,7 +525,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<List<CloudFileReferenceObject>>("Attachments")
b.Property<List<SnCloudFileReferenceObject>>("Attachments")
.IsRequired()
.HasColumnType("jsonb")
.HasColumnName("attachments");
@@ -879,7 +877,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("account_id");
b.Property<CloudFileReferenceObject>("Background")
b.Property<SnCloudFileReferenceObject>("Background")
.HasColumnType("jsonb")
.HasColumnName("background");
@@ -913,7 +911,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("character varying(256)")
.HasColumnName("nick");
b.Property<CloudFileReferenceObject>("Picture")
b.Property<SnCloudFileReferenceObject>("Picture")
.HasColumnType("jsonb")
.HasColumnName("picture");
@@ -934,7 +932,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("timestamp with time zone")
.HasColumnName("updated_at");
b.Property<VerificationMark>("Verification")
b.Property<SnVerificationMark>("Verification")
.HasColumnType("jsonb")
.HasColumnName("verification");
@@ -1084,7 +1082,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("account_id");
b.Property<CloudFileReferenceObject>("Background")
b.Property<SnCloudFileReferenceObject>("Background")
.HasColumnType("jsonb")
.HasColumnName("background");
@@ -1121,7 +1119,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("character varying(1024)")
.HasColumnName("name");
b.Property<CloudFileReferenceObject>("Picture")
b.Property<SnCloudFileReferenceObject>("Picture")
.HasColumnType("jsonb")
.HasColumnName("picture");
@@ -1140,7 +1138,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("timestamp with time zone")
.HasColumnName("updated_at");
b.Property<VerificationMark>("Verification")
b.Property<SnVerificationMark>("Verification")
.HasColumnType("jsonb")
.HasColumnName("verification");
@@ -1209,7 +1207,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("timestamp with time zone")
.HasColumnName("deleted_at");
b.Property<CloudFileReferenceObject>("Image")
b.Property<SnCloudFileReferenceObject>("Image")
.HasColumnType("jsonb")
.HasColumnName("image");

View File

@@ -2,10 +2,8 @@
using System;
using System.Collections.Generic;
using System.Text.Json;
using DysonNetwork.Shared.Data;
using DysonNetwork.Shared.Models;
using DysonNetwork.Sphere;
using DysonNetwork.Sphere.Chat;
using DysonNetwork.Sphere.Poll;
using DysonNetwork.Sphere.WebReader;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
@@ -118,7 +116,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<CloudFileReferenceObject>("Background")
b.Property<SnCloudFileReferenceObject>("Background")
.HasColumnType("jsonb")
.HasColumnName("background");
@@ -153,7 +151,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("character varying(1024)")
.HasColumnName("name");
b.Property<CloudFileReferenceObject>("Picture")
b.Property<SnCloudFileReferenceObject>("Picture")
.HasColumnType("jsonb")
.HasColumnName("picture");
@@ -190,7 +188,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<List<CloudFileReferenceObject>>("Attachments")
b.Property<List<SnCloudFileReferenceObject>>("Attachments")
.IsRequired()
.HasColumnType("jsonb")
.HasColumnName("attachments");
@@ -485,7 +483,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("boolean")
.HasColumnName("is_required");
b.Property<List<PollOption>>("Options")
b.Property<List<SnPollOption>>("Options")
.HasColumnType("jsonb")
.HasColumnName("options");
@@ -527,7 +525,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<List<CloudFileReferenceObject>>("Attachments")
b.Property<List<SnCloudFileReferenceObject>>("Attachments")
.IsRequired()
.HasColumnType("jsonb")
.HasColumnName("attachments");
@@ -922,7 +920,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("account_id");
b.Property<CloudFileReferenceObject>("Background")
b.Property<SnCloudFileReferenceObject>("Background")
.HasColumnType("jsonb")
.HasColumnName("background");
@@ -956,7 +954,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("character varying(256)")
.HasColumnName("nick");
b.Property<CloudFileReferenceObject>("Picture")
b.Property<SnCloudFileReferenceObject>("Picture")
.HasColumnType("jsonb")
.HasColumnName("picture");
@@ -977,7 +975,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("timestamp with time zone")
.HasColumnName("updated_at");
b.Property<VerificationMark>("Verification")
b.Property<SnVerificationMark>("Verification")
.HasColumnType("jsonb")
.HasColumnName("verification");
@@ -1127,7 +1125,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("account_id");
b.Property<CloudFileReferenceObject>("Background")
b.Property<SnCloudFileReferenceObject>("Background")
.HasColumnType("jsonb")
.HasColumnName("background");
@@ -1164,7 +1162,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("character varying(1024)")
.HasColumnName("name");
b.Property<CloudFileReferenceObject>("Picture")
b.Property<SnCloudFileReferenceObject>("Picture")
.HasColumnType("jsonb")
.HasColumnName("picture");
@@ -1183,7 +1181,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("timestamp with time zone")
.HasColumnName("updated_at");
b.Property<VerificationMark>("Verification")
b.Property<SnVerificationMark>("Verification")
.HasColumnType("jsonb")
.HasColumnName("verification");
@@ -1252,7 +1250,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("timestamp with time zone")
.HasColumnName("deleted_at");
b.Property<CloudFileReferenceObject>("Image")
b.Property<SnCloudFileReferenceObject>("Image")
.HasColumnType("jsonb")
.HasColumnName("image");

View File

@@ -2,10 +2,8 @@
using System;
using System.Collections.Generic;
using System.Text.Json;
using DysonNetwork.Shared.Data;
using DysonNetwork.Shared.Models;
using DysonNetwork.Sphere;
using DysonNetwork.Sphere.Chat;
using DysonNetwork.Sphere.Poll;
using DysonNetwork.Sphere.WebReader;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
@@ -118,7 +116,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<CloudFileReferenceObject>("Background")
b.Property<SnCloudFileReferenceObject>("Background")
.HasColumnType("jsonb")
.HasColumnName("background");
@@ -153,7 +151,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("character varying(1024)")
.HasColumnName("name");
b.Property<CloudFileReferenceObject>("Picture")
b.Property<SnCloudFileReferenceObject>("Picture")
.HasColumnType("jsonb")
.HasColumnName("picture");
@@ -190,7 +188,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<List<CloudFileReferenceObject>>("Attachments")
b.Property<List<SnCloudFileReferenceObject>>("Attachments")
.IsRequired()
.HasColumnType("jsonb")
.HasColumnName("attachments");
@@ -485,7 +483,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("boolean")
.HasColumnName("is_required");
b.Property<List<PollOption>>("Options")
b.Property<List<SnPollOption>>("Options")
.HasColumnType("jsonb")
.HasColumnName("options");
@@ -527,7 +525,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<List<CloudFileReferenceObject>>("Attachments")
b.Property<List<SnCloudFileReferenceObject>>("Attachments")
.IsRequired()
.HasColumnType("jsonb")
.HasColumnName("attachments");
@@ -975,7 +973,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("account_id");
b.Property<CloudFileReferenceObject>("Background")
b.Property<SnCloudFileReferenceObject>("Background")
.HasColumnType("jsonb")
.HasColumnName("background");
@@ -1009,7 +1007,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("character varying(256)")
.HasColumnName("nick");
b.Property<CloudFileReferenceObject>("Picture")
b.Property<SnCloudFileReferenceObject>("Picture")
.HasColumnType("jsonb")
.HasColumnName("picture");
@@ -1030,7 +1028,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("timestamp with time zone")
.HasColumnName("updated_at");
b.Property<VerificationMark>("Verification")
b.Property<SnVerificationMark>("Verification")
.HasColumnType("jsonb")
.HasColumnName("verification");
@@ -1180,7 +1178,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("account_id");
b.Property<CloudFileReferenceObject>("Background")
b.Property<SnCloudFileReferenceObject>("Background")
.HasColumnType("jsonb")
.HasColumnName("background");
@@ -1217,7 +1215,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("character varying(1024)")
.HasColumnName("name");
b.Property<CloudFileReferenceObject>("Picture")
b.Property<SnCloudFileReferenceObject>("Picture")
.HasColumnType("jsonb")
.HasColumnName("picture");
@@ -1236,7 +1234,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("timestamp with time zone")
.HasColumnName("updated_at");
b.Property<VerificationMark>("Verification")
b.Property<SnVerificationMark>("Verification")
.HasColumnType("jsonb")
.HasColumnName("verification");
@@ -1305,7 +1303,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("timestamp with time zone")
.HasColumnName("deleted_at");
b.Property<CloudFileReferenceObject>("Image")
b.Property<SnCloudFileReferenceObject>("Image")
.HasColumnType("jsonb")
.HasColumnName("image");

View File

@@ -2,10 +2,8 @@
using System;
using System.Collections.Generic;
using System.Text.Json;
using DysonNetwork.Shared.Data;
using DysonNetwork.Shared.Models;
using DysonNetwork.Sphere;
using DysonNetwork.Sphere.Chat;
using DysonNetwork.Sphere.Poll;
using DysonNetwork.Sphere.WebReader;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
@@ -117,7 +115,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<CloudFileReferenceObject>("Background")
b.Property<SnCloudFileReferenceObject>("Background")
.HasColumnType("jsonb")
.HasColumnName("background");
@@ -152,7 +150,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("character varying(1024)")
.HasColumnName("name");
b.Property<CloudFileReferenceObject>("Picture")
b.Property<SnCloudFileReferenceObject>("Picture")
.HasColumnType("jsonb")
.HasColumnName("picture");
@@ -189,7 +187,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<List<CloudFileReferenceObject>>("Attachments")
b.Property<List<SnCloudFileReferenceObject>>("Attachments")
.IsRequired()
.HasColumnType("jsonb")
.HasColumnName("attachments");
@@ -484,7 +482,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("boolean")
.HasColumnName("is_required");
b.Property<List<PollOption>>("Options")
b.Property<List<SnPollOption>>("Options")
.HasColumnType("jsonb")
.HasColumnName("options");
@@ -526,7 +524,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<List<CloudFileReferenceObject>>("Attachments")
b.Property<List<SnCloudFileReferenceObject>>("Attachments")
.IsRequired()
.HasColumnType("jsonb")
.HasColumnName("attachments");
@@ -974,7 +972,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("account_id");
b.Property<CloudFileReferenceObject>("Background")
b.Property<SnCloudFileReferenceObject>("Background")
.HasColumnType("jsonb")
.HasColumnName("background");
@@ -1008,7 +1006,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("character varying(256)")
.HasColumnName("nick");
b.Property<CloudFileReferenceObject>("Picture")
b.Property<SnCloudFileReferenceObject>("Picture")
.HasColumnType("jsonb")
.HasColumnName("picture");
@@ -1029,7 +1027,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("timestamp with time zone")
.HasColumnName("updated_at");
b.Property<VerificationMark>("Verification")
b.Property<SnVerificationMark>("Verification")
.HasColumnType("jsonb")
.HasColumnName("verification");
@@ -1179,7 +1177,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("account_id");
b.Property<CloudFileReferenceObject>("Background")
b.Property<SnCloudFileReferenceObject>("Background")
.HasColumnType("jsonb")
.HasColumnName("background");
@@ -1216,7 +1214,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("character varying(1024)")
.HasColumnName("name");
b.Property<CloudFileReferenceObject>("Picture")
b.Property<SnCloudFileReferenceObject>("Picture")
.HasColumnType("jsonb")
.HasColumnName("picture");
@@ -1235,7 +1233,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("timestamp with time zone")
.HasColumnName("updated_at");
b.Property<VerificationMark>("Verification")
b.Property<SnVerificationMark>("Verification")
.HasColumnType("jsonb")
.HasColumnName("verification");
@@ -1304,7 +1302,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("timestamp with time zone")
.HasColumnName("deleted_at");
b.Property<CloudFileReferenceObject>("Image")
b.Property<SnCloudFileReferenceObject>("Image")
.HasColumnType("jsonb")
.HasColumnName("image");

View File

@@ -2,11 +2,8 @@
using System;
using System.Collections.Generic;
using System.Text.Json;
using DysonNetwork.Shared.Data;
using DysonNetwork.Shared.Models;
using DysonNetwork.Sphere;
using DysonNetwork.Sphere.Chat;
using DysonNetwork.Sphere.Poll;
using DysonNetwork.Sphere.Post;
using DysonNetwork.Sphere.WebReader;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
@@ -118,7 +115,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<CloudFileReferenceObject>("Background")
b.Property<SnCloudFileReferenceObject>("Background")
.HasColumnType("jsonb")
.HasColumnName("background");
@@ -153,7 +150,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("character varying(1024)")
.HasColumnName("name");
b.Property<CloudFileReferenceObject>("Picture")
b.Property<SnCloudFileReferenceObject>("Picture")
.HasColumnType("jsonb")
.HasColumnName("picture");
@@ -190,7 +187,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<List<CloudFileReferenceObject>>("Attachments")
b.Property<List<SnCloudFileReferenceObject>>("Attachments")
.IsRequired()
.HasColumnType("jsonb")
.HasColumnName("attachments");
@@ -485,7 +482,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("boolean")
.HasColumnName("is_required");
b.Property<List<PollOption>>("Options")
b.Property<List<SnPollOption>>("Options")
.HasColumnType("jsonb")
.HasColumnName("options");
@@ -527,7 +524,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<List<CloudFileReferenceObject>>("Attachments")
b.Property<List<SnCloudFileReferenceObject>>("Attachments")
.IsRequired()
.HasColumnType("jsonb")
.HasColumnName("attachments");
@@ -979,7 +976,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("account_id");
b.Property<CloudFileReferenceObject>("Background")
b.Property<SnCloudFileReferenceObject>("Background")
.HasColumnType("jsonb")
.HasColumnName("background");
@@ -1013,7 +1010,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("character varying(256)")
.HasColumnName("nick");
b.Property<CloudFileReferenceObject>("Picture")
b.Property<SnCloudFileReferenceObject>("Picture")
.HasColumnType("jsonb")
.HasColumnName("picture");
@@ -1034,7 +1031,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("timestamp with time zone")
.HasColumnName("updated_at");
b.Property<VerificationMark>("Verification")
b.Property<SnVerificationMark>("Verification")
.HasColumnType("jsonb")
.HasColumnName("verification");
@@ -1184,7 +1181,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("account_id");
b.Property<CloudFileReferenceObject>("Background")
b.Property<SnCloudFileReferenceObject>("Background")
.HasColumnType("jsonb")
.HasColumnName("background");
@@ -1221,7 +1218,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("character varying(1024)")
.HasColumnName("name");
b.Property<CloudFileReferenceObject>("Picture")
b.Property<SnCloudFileReferenceObject>("Picture")
.HasColumnType("jsonb")
.HasColumnName("picture");
@@ -1240,7 +1237,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("timestamp with time zone")
.HasColumnName("updated_at");
b.Property<VerificationMark>("Verification")
b.Property<SnVerificationMark>("Verification")
.HasColumnType("jsonb")
.HasColumnName("verification");
@@ -1309,7 +1306,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("timestamp with time zone")
.HasColumnName("deleted_at");
b.Property<CloudFileReferenceObject>("Image")
b.Property<SnCloudFileReferenceObject>("Image")
.HasColumnType("jsonb")
.HasColumnName("image");

View File

@@ -1,4 +1,4 @@
using DysonNetwork.Sphere.Post;
using DysonNetwork.Shared.Models;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable

View File

@@ -2,11 +2,8 @@
using System;
using System.Collections.Generic;
using System.Text.Json;
using DysonNetwork.Shared.Data;
using DysonNetwork.Shared.Models;
using DysonNetwork.Sphere;
using DysonNetwork.Sphere.Chat;
using DysonNetwork.Sphere.Poll;
using DysonNetwork.Sphere.Post;
using DysonNetwork.Sphere.WebReader;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
@@ -118,7 +115,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<CloudFileReferenceObject>("Background")
b.Property<SnCloudFileReferenceObject>("Background")
.HasColumnType("jsonb")
.HasColumnName("background");
@@ -153,7 +150,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("character varying(1024)")
.HasColumnName("name");
b.Property<CloudFileReferenceObject>("Picture")
b.Property<SnCloudFileReferenceObject>("Picture")
.HasColumnType("jsonb")
.HasColumnName("picture");
@@ -190,7 +187,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<List<CloudFileReferenceObject>>("Attachments")
b.Property<List<SnCloudFileReferenceObject>>("Attachments")
.IsRequired()
.HasColumnType("jsonb")
.HasColumnName("attachments");
@@ -489,7 +486,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("boolean")
.HasColumnName("is_required");
b.Property<List<PollOption>>("Options")
b.Property<List<SnPollOption>>("Options")
.HasColumnType("jsonb")
.HasColumnName("options");
@@ -531,7 +528,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<List<CloudFileReferenceObject>>("Attachments")
b.Property<List<SnCloudFileReferenceObject>>("Attachments")
.IsRequired()
.HasColumnType("jsonb")
.HasColumnName("attachments");
@@ -983,7 +980,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("account_id");
b.Property<CloudFileReferenceObject>("Background")
b.Property<SnCloudFileReferenceObject>("Background")
.HasColumnType("jsonb")
.HasColumnName("background");
@@ -1017,7 +1014,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("character varying(256)")
.HasColumnName("nick");
b.Property<CloudFileReferenceObject>("Picture")
b.Property<SnCloudFileReferenceObject>("Picture")
.HasColumnType("jsonb")
.HasColumnName("picture");
@@ -1038,7 +1035,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("timestamp with time zone")
.HasColumnName("updated_at");
b.Property<VerificationMark>("Verification")
b.Property<SnVerificationMark>("Verification")
.HasColumnType("jsonb")
.HasColumnName("verification");
@@ -1188,7 +1185,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("account_id");
b.Property<CloudFileReferenceObject>("Background")
b.Property<SnCloudFileReferenceObject>("Background")
.HasColumnType("jsonb")
.HasColumnName("background");
@@ -1225,7 +1222,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("character varying(1024)")
.HasColumnName("name");
b.Property<CloudFileReferenceObject>("Picture")
b.Property<SnCloudFileReferenceObject>("Picture")
.HasColumnType("jsonb")
.HasColumnName("picture");
@@ -1244,7 +1241,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("timestamp with time zone")
.HasColumnName("updated_at");
b.Property<VerificationMark>("Verification")
b.Property<SnVerificationMark>("Verification")
.HasColumnType("jsonb")
.HasColumnName("verification");
@@ -1313,7 +1310,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("timestamp with time zone")
.HasColumnName("deleted_at");
b.Property<CloudFileReferenceObject>("Image")
b.Property<SnCloudFileReferenceObject>("Image")
.HasColumnType("jsonb")
.HasColumnName("image");

View File

@@ -2,11 +2,8 @@
using System;
using System.Collections.Generic;
using System.Text.Json;
using DysonNetwork.Shared.Data;
using DysonNetwork.Shared.Models;
using DysonNetwork.Sphere;
using DysonNetwork.Sphere.Chat;
using DysonNetwork.Sphere.Poll;
using DysonNetwork.Sphere.Post;
using DysonNetwork.Sphere.WebReader;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
@@ -115,7 +112,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<CloudFileReferenceObject>("Background")
b.Property<SnCloudFileReferenceObject>("Background")
.HasColumnType("jsonb")
.HasColumnName("background");
@@ -150,7 +147,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("character varying(1024)")
.HasColumnName("name");
b.Property<CloudFileReferenceObject>("Picture")
b.Property<SnCloudFileReferenceObject>("Picture")
.HasColumnType("jsonb")
.HasColumnName("picture");
@@ -187,7 +184,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<List<CloudFileReferenceObject>>("Attachments")
b.Property<List<SnCloudFileReferenceObject>>("Attachments")
.IsRequired()
.HasColumnType("jsonb")
.HasColumnName("attachments");
@@ -486,7 +483,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("boolean")
.HasColumnName("is_required");
b.Property<List<PollOption>>("Options")
b.Property<List<SnPollOption>>("Options")
.HasColumnType("jsonb")
.HasColumnName("options");
@@ -528,7 +525,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<List<CloudFileReferenceObject>>("Attachments")
b.Property<List<SnCloudFileReferenceObject>>("Attachments")
.IsRequired()
.HasColumnType("jsonb")
.HasColumnName("attachments");
@@ -980,7 +977,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("account_id");
b.Property<CloudFileReferenceObject>("Background")
b.Property<SnCloudFileReferenceObject>("Background")
.HasColumnType("jsonb")
.HasColumnName("background");
@@ -1014,7 +1011,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("character varying(256)")
.HasColumnName("nick");
b.Property<CloudFileReferenceObject>("Picture")
b.Property<SnCloudFileReferenceObject>("Picture")
.HasColumnType("jsonb")
.HasColumnName("picture");
@@ -1035,7 +1032,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("timestamp with time zone")
.HasColumnName("updated_at");
b.Property<VerificationMark>("Verification")
b.Property<SnVerificationMark>("Verification")
.HasColumnType("jsonb")
.HasColumnName("verification");
@@ -1185,7 +1182,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("uuid")
.HasColumnName("account_id");
b.Property<CloudFileReferenceObject>("Background")
b.Property<SnCloudFileReferenceObject>("Background")
.HasColumnType("jsonb")
.HasColumnName("background");
@@ -1222,7 +1219,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("character varying(1024)")
.HasColumnName("name");
b.Property<CloudFileReferenceObject>("Picture")
b.Property<SnCloudFileReferenceObject>("Picture")
.HasColumnType("jsonb")
.HasColumnName("picture");
@@ -1241,7 +1238,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("timestamp with time zone")
.HasColumnName("updated_at");
b.Property<VerificationMark>("Verification")
b.Property<SnVerificationMark>("Verification")
.HasColumnType("jsonb")
.HasColumnName("verification");
@@ -1310,7 +1307,7 @@ namespace DysonNetwork.Sphere.Migrations
.HasColumnType("timestamp with time zone")
.HasColumnName("deleted_at");
b.Property<CloudFileReferenceObject>("Image")
b.Property<SnCloudFileReferenceObject>("Image")
.HasColumnType("jsonb")
.HasColumnName("image");

View File

@@ -1,67 +0,0 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text.Json;
using System.Text.Json.Serialization;
using DysonNetwork.Shared.Data;
using NodaTime;
namespace DysonNetwork.Sphere.Poll;
public class Poll : ModelBase
{
public Guid Id { get; set; } = Guid.NewGuid();
public List<PollQuestion> Questions { get; set; } = new();
[MaxLength(1024)] public string? Title { get; set; }
[MaxLength(4096)] public string? Description { get; set; }
public Instant? EndedAt { get; set; }
public bool IsAnonymous { get; set; }
public Guid PublisherId { get; set; }
[JsonIgnore] public Publisher.Publisher? Publisher { get; set; }
}
public enum PollQuestionType
{
SingleChoice,
MultipleChoice,
YesNo,
Rating,
FreeText
}
public class PollQuestion : ModelBase
{
public Guid Id { get; set; } = Guid.NewGuid();
public PollQuestionType Type { get; set; }
[Column(TypeName = "jsonb")] public List<PollOption>? Options { get; set; }
[MaxLength(1024)] public string Title { get; set; } = null!;
[MaxLength(4096)] public string? Description { get; set; }
public int Order { get; set; } = 0;
public bool IsRequired { get; set; }
public Guid PollId { get; set; }
[JsonIgnore] public Poll Poll { get; set; } = null!;
}
public class PollOption
{
public Guid Id { get; set; } = Guid.NewGuid();
[Required][MaxLength(1024)] public string Label { get; set; } = null!;
[MaxLength(4096)] public string? Description { get; set; }
public int Order { get; set; } = 0;
}
public class PollAnswer : ModelBase
{
public Guid Id { get; set; } = Guid.NewGuid();
[Column(TypeName = "jsonb")] public Dictionary<string, JsonElement> Answer { get; set; } = null!;
public Guid AccountId { get; set; }
public Guid PollId { get; set; }
[JsonIgnore] public Poll? Poll { get; set; }
[NotMapped] public AccountReference? Account { get; set; }
}

View File

@@ -1,6 +1,7 @@
using System.ComponentModel.DataAnnotations;
using System.Text.Json;
using DysonNetwork.Shared.Data;
using DysonNetwork.Shared.Models;
using DysonNetwork.Shared.Proto;
using DysonNetwork.Shared.Registry;
using Microsoft.AspNetCore.Authorization;
@@ -46,7 +47,7 @@ public class PollController(
[HttpPost("{id:guid}/answer")]
[Authorize]
public async Task<ActionResult<PollAnswer>> AnswerPoll(Guid id, [FromBody] PollAnswerRequest request)
public async Task<ActionResult<SnPollAnswer>> AnswerPoll(Guid id, [FromBody] PollAnswerRequest request)
{
if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized();
var accountId = Guid.Parse(currentUser.Id);
@@ -78,7 +79,7 @@ public class PollController(
}
[HttpGet("{id:guid}/feedback")]
public async Task<ActionResult<List<PollAnswer>>> GetPollFeedback(
public async Task<ActionResult<List<SnPollAnswer>>> GetPollFeedback(
Guid id,
[FromQuery] int offset = 0,
[FromQuery] int take = 20
@@ -91,7 +92,7 @@ public class PollController(
.FirstOrDefaultAsync(p => p.Id == id);
if (poll is null) return NotFound("Poll not found");
if (!await pub.IsMemberWithRole(poll.PublisherId, accountId, Publisher.PublisherMemberRole.Viewer))
if (!await pub.IsMemberWithRole(poll.PublisherId, accountId, Shared.Models.PublisherMemberRole.Viewer))
return StatusCode(403, "You need to be a viewer to view this poll's feedback.");
var answerQuery = db.PollAnswers
@@ -117,7 +118,7 @@ public class PollController(
{
var protoValue = answeredAccounts.FirstOrDefault(a => a.Id == answer.AccountId.ToString());
if (protoValue is not null)
answer.Account = AccountReference.FromProtoValue(protoValue);
answer.Account = SnAccount.FromProtoValue(protoValue);
}
}
@@ -177,14 +178,14 @@ public class PollController(
public Guid Id { get; set; } = Guid.NewGuid();
public PollQuestionType Type { get; set; }
public List<PollOption>? Options { get; set; }
public List<SnPollOption>? Options { get; set; }
[MaxLength(1024)] public string Title { get; set; } = null!;
[MaxLength(4096)] public string? Description { get; set; }
public int Order { get; set; } = 0;
public bool IsRequired { get; set; }
public PollQuestion ToQuestion() => new()
public SnPollQuestion ToQuestion() => new()
{
Id = Id,
Type = Type,
@@ -207,7 +208,7 @@ public class PollController(
var publisher = await pub.GetPublisherByName(pubName);
if (publisher is null) return BadRequest("Publisher was not found.");
if (!await pub.IsMemberWithRole(publisher.Id, accountId, Publisher.PublisherMemberRole.Editor))
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
@@ -253,7 +254,7 @@ public class PollController(
if (poll == null) return NotFound("Poll not found");
// Check if user is an editor of the publisher that owns the poll
if (!await pub.IsMemberWithRole(poll.PublisherId, accountId, Publisher.PublisherMemberRole.Editor))
if (!await pub.IsMemberWithRole(poll.PublisherId, accountId, Shared.Models.PublisherMemberRole.Editor))
return StatusCode(403, "You need to be at least an editor to update this poll.");
// Update properties if they are provided in the request
@@ -317,7 +318,7 @@ public class PollController(
if (poll == null) return NotFound("Poll not found");
// Check if user is an editor of the publisher that owns the poll
if (!await pub.IsMemberWithRole(poll.PublisherId, accountId, Publisher.PublisherMemberRole.Editor))
if (!await pub.IsMemberWithRole(poll.PublisherId, accountId, Shared.Models.PublisherMemberRole.Editor))
return StatusCode(403, "You need to be at least an editor to delete this poll.");
// Delete all answers for this poll

View File

@@ -1,13 +1,14 @@
using DysonNetwork.Shared.Models;
using DysonNetwork.Sphere.WebReader;
namespace DysonNetwork.Sphere.Poll;
public class PollWithStats : Poll
{
public PollAnswer? UserAnswer { get; set; }
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, PollAnswer? userAnswer = null)
public static PollWithStats FromPoll(Poll poll, SnPollAnswer? userAnswer = null)
{
return new PollWithStats
{

View File

@@ -1,5 +1,6 @@
using System.Text.Json;
using DysonNetwork.Shared.Cache;
using DysonNetwork.Shared.Models;
using Microsoft.EntityFrameworkCore;
using NodaTime;
@@ -42,10 +43,10 @@ public class PollService(AppDatabase db, ICacheService cache)
private const string PollAnswerCachePrefix = "poll:answer:";
public async Task<PollAnswer?> GetPollAnswer(Guid pollId, Guid accountId)
public async Task<SnPollAnswer?> GetPollAnswer(Guid pollId, Guid accountId)
{
var cacheKey = $"{PollAnswerCachePrefix}{pollId}:{accountId}";
var cachedAnswer = await cache.GetAsync<PollAnswer?>(cacheKey);
var cachedAnswer = await cache.GetAsync<SnPollAnswer?>(cacheKey);
if (cachedAnswer is not null)
return cachedAnswer;
@@ -103,7 +104,7 @@ public class PollService(AppDatabase db, ICacheService cache)
}
}
public async Task<PollAnswer> AnswerPoll(Guid pollId, Guid accountId, Dictionary<string, JsonElement> answer)
public async Task<SnPollAnswer> AnswerPoll(Guid pollId, Guid accountId, Dictionary<string, JsonElement> answer)
{
// Validation
var poll = await db.Polls
@@ -124,7 +125,7 @@ public class PollService(AppDatabase db, ICacheService cache)
await UnAnswerPoll(pollId, accountId);
// Save the new answer
var answerRecord = new PollAnswer
var answerRecord = new SnPollAnswer
{
PollId = pollId,
AccountId = accountId,

View File

@@ -1,202 +0,0 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text.Json.Serialization;
using DysonNetwork.Shared.Data;
using DysonNetwork.Sphere.Activity;
using NodaTime;
using NpgsqlTypes;
namespace DysonNetwork.Sphere.Post;
public enum PostType
{
Moment,
Article
}
public enum PostVisibility
{
Public,
Friends,
Unlisted,
Private
}
public enum PostPinMode
{
PublisherPage,
RealmPage,
ReplyPage,
}
public class Post : ModelBase, IIdentifiedResource, IActivity
{
public Guid Id { get; set; }
[MaxLength(1024)] public string? Title { get; set; }
[MaxLength(4096)] public string? Description { get; set; }
[MaxLength(1024)] public string? Slug { get; set; }
public Instant? EditedAt { get; set; }
public Instant? PublishedAt { get; set; }
public PostVisibility Visibility { get; set; } = PostVisibility.Public;
// ReSharper disable once EntityFramework.ModelValidation.UnlimitedStringLength
public string? Content { get; set; }
public PostType Type { get; set; }
public PostPinMode? PinMode { get; set; }
[Column(TypeName = "jsonb")] public Dictionary<string, object>? Meta { get; set; }
[Column(TypeName = "jsonb")] public List<ContentSensitiveMark>? SensitiveMarks { get; set; } = [];
[Column(TypeName = "jsonb")] public PostEmbedView? EmbedView { get; set; }
public int ViewsUnique { get; set; }
public int ViewsTotal { get; set; }
public int Upvotes { get; set; }
public int Downvotes { get; set; }
public decimal AwardedScore { get; set; }
[NotMapped] public Dictionary<string, int> ReactionsCount { get; set; } = new();
[NotMapped] public int RepliesCount { get; set; }
[NotMapped] public Dictionary<string, bool>? ReactionsMade { get; set; }
public bool RepliedGone { get; set; }
public bool ForwardedGone { get; set; }
public Guid? RepliedPostId { get; set; }
public Post? RepliedPost { get; set; }
public Guid? ForwardedPostId { get; set; }
public Post? ForwardedPost { get; set; }
public Guid? RealmId { get; set; }
public Realm.Realm? Realm { get; set; }
[Column(TypeName = "jsonb")] public List<CloudFileReferenceObject> Attachments { get; set; } = [];
[JsonIgnore] public NpgsqlTsVector SearchVector { get; set; } = null!;
public Guid PublisherId { get; set; }
public Publisher.Publisher Publisher { get; set; } = null!;
public ICollection<PostAward> Awards { get; set; } = null!;
[JsonIgnore] public ICollection<PostReaction> Reactions { get; set; } = new List<PostReaction>();
public ICollection<PostTag> Tags { get; set; } = new List<PostTag>();
public ICollection<PostCategory> Categories { get; set; } = new List<PostCategory>();
[JsonIgnore] public ICollection<PostCollection> Collections { get; set; } = new List<PostCollection>();
[JsonIgnore] public bool Empty => Content == null && Attachments.Count == 0 && ForwardedPostId == null;
[NotMapped] public bool IsTruncated { get; set; } = false;
public string ResourceIdentifier => $"post:{Id}";
public Activity.Activity ToActivity()
{
return new Activity.Activity()
{
CreatedAt = PublishedAt ?? CreatedAt,
UpdatedAt = UpdatedAt,
DeletedAt = DeletedAt,
Id = Id,
Type = RepliedPostId is null ? "posts.new" : "posts.new.replies",
ResourceIdentifier = ResourceIdentifier,
Data = this
};
}
}
public class PostTag : ModelBase
{
public Guid Id { get; set; }
[MaxLength(128)] public string Slug { get; set; } = null!;
[MaxLength(256)] public string? Name { get; set; }
[JsonIgnore] public ICollection<Post> Posts { get; set; } = new List<Post>();
[NotMapped] public int? Usage { get; set; }
}
public class PostCategory : ModelBase
{
public Guid Id { get; set; }
[MaxLength(128)] public string Slug { get; set; } = null!;
[MaxLength(256)] public string? Name { get; set; }
[JsonIgnore] public ICollection<Post> Posts { get; set; } = new List<Post>();
[NotMapped] public int? Usage { get; set; }
}
public class PostCategorySubscription : ModelBase
{
public Guid Id { get; set; }
public Guid AccountId { get; set; }
public Guid? CategoryId { get; set; }
public PostCategory? Category { get; set; }
public Guid? TagId { get; set; }
public PostTag? Tag { get; set; }
}
public class PostCollection : ModelBase
{
public Guid Id { get; set; }
[MaxLength(128)] public string Slug { get; set; } = null!;
[MaxLength(256)] public string? Name { get; set; }
[MaxLength(4096)] public string? Description { get; set; }
public Publisher.Publisher Publisher { get; set; } = null!;
public ICollection<Post> Posts { get; set; } = new List<Post>();
}
public class PostFeaturedRecord : ModelBase
{
public Guid Id { get; set; }
public Guid PostId { get; set; }
public Post Post { get; set; } = null!;
public Instant? FeaturedAt { get; set; }
public int SocialCredits { get; set; }
}
public enum PostReactionAttitude
{
Positive,
Neutral,
Negative,
}
public class PostReaction : ModelBase
{
public Guid Id { get; set; }
[MaxLength(256)] public string Symbol { get; set; } = null!;
public PostReactionAttitude Attitude { get; set; }
public Guid PostId { get; set; }
[JsonIgnore] public Post Post { get; set; } = null!;
public Guid AccountId { get; set; }
}
public class PostAward : ModelBase
{
public Guid Id { get; set; }
public decimal Amount { get; set; }
public PostReactionAttitude Attitude { get; set; }
[MaxLength(4096)] public string? Message { get; set; }
public Guid PostId { get; set; }
[JsonIgnore] public Post Post { get; set; } = null!;
public Guid AccountId { get; set; }
}
/// <summary>
/// This model is used to tell the client to render a WebView / iframe
/// Usually external website and web pages
/// Used as a JSON column
/// </summary>
public class PostEmbedView
{
public string Uri { get; set; } = null!;
public double? AspectRatio { get; set; }
public PostEmbedViewRenderer Renderer { get; set; } = PostEmbedViewRenderer.WebView;
}
public enum PostEmbedViewRenderer
{
WebView
}

View File

@@ -1,4 +1,5 @@
using DysonNetwork.Shared.Data;
using DysonNetwork.Shared.Models;
using DysonNetwork.Shared.Proto;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
@@ -11,7 +12,7 @@ namespace DysonNetwork.Sphere.Post;
public class PostCategoryController(AppDatabase db) : ControllerBase
{
[HttpGet("categories")]
public async Task<ActionResult<List<PostCategory>>> ListCategories(
public async Task<ActionResult<List<SnPostCategory>>> ListCategories(
[FromQuery] string? query = null,
[FromQuery] int offset = 0,
[FromQuery] int take = 20,
@@ -59,7 +60,7 @@ public class PostCategoryController(AppDatabase db) : ControllerBase
}
[HttpGet("tags")]
public async Task<ActionResult<List<PostTag>>> ListTags(
public async Task<ActionResult<List<SnPostTag>>> ListTags(
[FromQuery] string? query = null,
[FromQuery] int offset = 0,
[FromQuery] int take = 20,
@@ -107,7 +108,7 @@ public class PostCategoryController(AppDatabase db) : ControllerBase
}
[HttpGet("categories/{slug}")]
public async Task<ActionResult<PostCategory>> GetCategory(string slug)
public async Task<ActionResult<SnPostCategory>> GetCategory(string slug)
{
var category = await db.PostCategories.FirstOrDefaultAsync(e => e.Slug == slug);
if (category is null)
@@ -116,7 +117,7 @@ public class PostCategoryController(AppDatabase db) : ControllerBase
}
[HttpGet("tags/{slug}")]
public async Task<ActionResult<PostTag>> GetTag(string slug)
public async Task<ActionResult<SnPostTag>> GetTag(string slug)
{
var tag = await db.PostTags.FirstOrDefaultAsync(e => e.Slug == slug);
if (tag is null)
@@ -126,7 +127,7 @@ public class PostCategoryController(AppDatabase db) : ControllerBase
[HttpPost("categories/{slug}/subscribe")]
[Authorize]
public async Task<ActionResult<PostCategorySubscription>> SubscribeCategory(string slug)
public async Task<ActionResult<SnPostCategorySubscription>> SubscribeCategory(string slug)
{
if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized();
var accountId = Guid.Parse(currentUser.Id);
@@ -143,7 +144,7 @@ public class PostCategoryController(AppDatabase db) : ControllerBase
if (existingSubscription != null)
return Ok(existingSubscription);
var subscription = new PostCategorySubscription
var subscription = new SnPostCategorySubscription
{
AccountId = accountId,
CategoryId = category.Id
@@ -180,7 +181,7 @@ public class PostCategoryController(AppDatabase db) : ControllerBase
[HttpGet("categories/{slug}/subscription")]
[Authorize]
public async Task<ActionResult<PostCategorySubscription>> GetCategorySubscription(string slug)
public async Task<ActionResult<SnPostCategorySubscription>> GetCategorySubscription(string slug)
{
if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized();
var accountId = Guid.Parse(currentUser.Id);
@@ -200,7 +201,7 @@ public class PostCategoryController(AppDatabase db) : ControllerBase
[HttpPost("tags/{slug}/subscribe")]
[Authorize]
public async Task<ActionResult<PostCategorySubscription>> SubscribeTag(string slug)
public async Task<ActionResult<SnPostCategorySubscription>> SubscribeTag(string slug)
{
if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized();
var accountId = Guid.Parse(currentUser.Id);
@@ -219,7 +220,7 @@ public class PostCategoryController(AppDatabase db) : ControllerBase
return Ok(existingSubscription);
}
var subscription = new PostCategorySubscription
var subscription = new SnPostCategorySubscription
{
AccountId = accountId,
TagId = tag.Id
@@ -260,7 +261,7 @@ public class PostCategoryController(AppDatabase db) : ControllerBase
[HttpGet("tags/{slug}/subscription")]
[Authorize]
public async Task<ActionResult<PostCategorySubscription>> GetTagSubscription(string slug)
public async Task<ActionResult<SnPostCategorySubscription>> GetTagSubscription(string slug)
{
if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized();
var accountId = Guid.Parse(currentUser.Id);

View File

@@ -3,6 +3,7 @@ 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;
using DysonNetwork.Sphere.Realm;
@@ -12,7 +13,7 @@ using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using NodaTime;
using Swashbuckle.AspNetCore.Annotations;
using PublisherMemberRole = DysonNetwork.Sphere.Publisher.PublisherMemberRole;
using PublisherMemberRole = DysonNetwork.Shared.Models.PublisherMemberRole;
using PublisherService = DysonNetwork.Sphere.Publisher.PublisherService;
namespace DysonNetwork.Sphere.Post;
@@ -32,7 +33,7 @@ public class PostController(
: ControllerBase
{
[HttpGet("featured")]
public async Task<ActionResult<List<Post>>> ListFeaturedPosts()
public async Task<ActionResult<List<SnPost>>> ListFeaturedPosts()
{
HttpContext.Items.TryGetValue("CurrentUser", out var currentUserValue);
var currentUser = currentUserValue as Account;
@@ -63,7 +64,7 @@ public class PostController(
/// </returns>
/// <response code="200">Returns the list of posts matching the criteria.</response>
[HttpGet]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(List<Post>))]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(List<SnPost>))]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[SwaggerOperation(
Summary = "Retrieves a paginated list of posts",
@@ -72,9 +73,9 @@ public class PostController(
OperationId = "ListPosts",
Tags = ["Posts"]
)]
[SwaggerResponse(StatusCodes.Status200OK, "Successfully retrieved the list of posts", typeof(List<Post>))]
[SwaggerResponse(StatusCodes.Status200OK, "Successfully retrieved the list of posts", typeof(List<SnPost>))]
[SwaggerResponse(StatusCodes.Status400BadRequest, "Invalid request parameters")]
public async Task<ActionResult<List<Post>>> ListPosts(
public async Task<ActionResult<List<SnPost>>> ListPosts(
[FromQuery] int offset = 0,
[FromQuery] int take = 20,
[FromQuery(Name = "pub")] string? pubName = null,
@@ -189,7 +190,7 @@ public class PostController(
}
[HttpGet("{publisherName}/{slug}")]
public async Task<ActionResult<Post>> GetPost(string publisherName, string slug)
public async Task<ActionResult<SnPost>> GetPost(string publisherName, string slug)
{
HttpContext.Items.TryGetValue("CurrentUser", out var currentUserValue);
var currentUser = currentUserValue as Account;
@@ -220,7 +221,7 @@ public class PostController(
}
[HttpGet("{id:guid}")]
public async Task<ActionResult<Post>> GetPost(Guid id)
public async Task<ActionResult<SnPost>> GetPost(Guid id)
{
HttpContext.Items.TryGetValue("CurrentUser", out var currentUserValue);
var currentUser = currentUserValue as Account;
@@ -251,7 +252,7 @@ public class PostController(
}
[HttpGet("{id:guid}/reactions")]
public async Task<ActionResult<List<PostReaction>>> GetReactions(
public async Task<ActionResult<List<SnPostReaction>>> GetReactions(
Guid id,
[FromQuery] string? symbol = null,
[FromQuery] int offset = 0,
@@ -275,7 +276,7 @@ public class PostController(
}
[HttpGet("{id:guid}/replies/featured")]
public async Task<ActionResult<Post>> GetFeaturedReply(Guid id)
public async Task<ActionResult<SnPost>> GetFeaturedReply(Guid id)
{
HttpContext.Items.TryGetValue("CurrentUser", out var currentUserValue);
var currentUser = currentUserValue as Account;
@@ -306,7 +307,7 @@ public class PostController(
}
[HttpGet("{id:guid}/replies/pinned")]
public async Task<ActionResult<List<Post>>> ListPinnedReplies(Guid id)
public async Task<ActionResult<List<SnPost>>> ListPinnedReplies(Guid id)
{
HttpContext.Items.TryGetValue("CurrentUser", out var currentUserValue);
var currentUser = currentUserValue as Account;
@@ -332,7 +333,7 @@ public class PostController(
}
[HttpGet("{id:guid}/replies")]
public async Task<ActionResult<List<Post>>> ListReplies(Guid id, [FromQuery] int offset = 0,
public async Task<ActionResult<List<SnPost>>> ListReplies(Guid id, [FromQuery] int offset = 0,
[FromQuery] int take = 20)
{
HttpContext.Items.TryGetValue("CurrentUser", out var currentUserValue);
@@ -403,7 +404,7 @@ public class PostController(
[HttpPost]
[RequiredPermission("global", "posts.create")]
public async Task<ActionResult<Post>> CreatePost(
public async Task<ActionResult<SnPost>> CreatePost(
[FromBody] PostRequest request,
[FromQuery(Name = "pub")] string? pubName
)
@@ -415,12 +416,12 @@ public class PostController(
var accountId = Guid.Parse(currentUser.Id);
Publisher.Publisher? publisher;
Shared.Models.SnPublisher? publisher;
if (pubName is null)
{
// Use the first personal publisher
publisher = await db.Publishers.FirstOrDefaultAsync(e =>
e.AccountId == accountId && e.Type == Publisher.PublisherType.Individual);
e.AccountId == accountId && e.Type == Shared.Models.PublisherType.Individual);
}
else
{
@@ -432,7 +433,7 @@ public class PostController(
if (publisher is null) return BadRequest("Publisher was not found.");
var post = new Post
var post = new SnPost
{
Title = request.Title,
Description = request.Description,
@@ -525,7 +526,7 @@ public class PostController(
[HttpPost("{id:guid}/reactions")]
[Authorize]
[RequiredPermission("global", "posts.react")]
public async Task<ActionResult<PostReaction>> ReactPost(Guid id, [FromBody] PostReactionRequest request)
public async Task<ActionResult<SnPostReaction>> ReactPost(Guid id, [FromBody] PostReactionRequest request)
{
if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized();
@@ -549,7 +550,7 @@ public class PostController(
.AnyAsync(r => r.PostId == post.Id &&
r.Symbol == request.Symbol &&
r.AccountId == accountId);
var reaction = new PostReaction
var reaction = new SnPostReaction
{
Symbol = request.Symbol,
Attitude = request.Attitude,
@@ -590,7 +591,7 @@ public class PostController(
}
[HttpGet("{id:guid}/awards")]
public async Task<ActionResult<PostAward>> GetPostAwards(Guid id, [FromQuery] int offset = 0,
public async Task<ActionResult<SnPostAward>> GetPostAwards(Guid id, [FromQuery] int offset = 0,
[FromQuery] int take = 20)
{
var queryable = db.PostAwards
@@ -666,7 +667,7 @@ public class PostController(
[HttpPost("{id:guid}/pin")]
[Authorize]
public async Task<ActionResult<Post>> PinPost(Guid id, [FromBody] PostPinRequest request)
public async Task<ActionResult<SnPost>> PinPost(Guid id, [FromBody] PostPinRequest request)
{
if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized();
@@ -714,7 +715,7 @@ public class PostController(
[HttpDelete("{id:guid}/pin")]
[Authorize]
public async Task<ActionResult<Post>> UnpinPost(Guid id)
public async Task<ActionResult<SnPost>> UnpinPost(Guid id)
{
if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized();
@@ -760,7 +761,7 @@ public class PostController(
}
[HttpPatch("{id:guid}")]
public async Task<ActionResult<Post>> UpdatePost(
public async Task<ActionResult<SnPost>> UpdatePost(
Guid id,
[FromBody] PostRequest request,
[FromQuery(Name = "pub")] string? pubName
@@ -780,14 +781,14 @@ public class PostController(
if (post is null) return NotFound();
var accountId = Guid.Parse(currentUser.Id);
if (!await pub.IsMemberWithRole(post.Publisher.Id, accountId, Publisher.PublisherMemberRole.Editor))
if (!await pub.IsMemberWithRole(post.Publisher.Id, accountId, PublisherMemberRole.Editor))
return StatusCode(403, "You need at least be an editor to edit this publisher's post.");
if (pubName is not null)
{
var publisher = await pub.GetPublisherByName(pubName);
if (publisher is null) return NotFound();
if (!await pub.IsMemberWithRole(publisher.Id, accountId, Publisher.PublisherMemberRole.Editor))
if (!await pub.IsMemberWithRole(publisher.Id, accountId, PublisherMemberRole.Editor))
return StatusCode(403, "You need at least be an editor to transfer this post to this publisher.");
post.PublisherId = publisher.Id;
post.Publisher = publisher;
@@ -879,7 +880,7 @@ public class PostController(
}
[HttpDelete("{id:guid}")]
public async Task<ActionResult<Post>> DeletePost(Guid id)
public async Task<ActionResult<SnPost>> DeletePost(Guid id)
{
if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized();

View File

@@ -3,7 +3,6 @@ using System.Text.RegularExpressions;
using AngleSharp.Common;
using DysonNetwork.Shared;
using DysonNetwork.Shared.Cache;
using DysonNetwork.Shared.Data;
using DysonNetwork.Shared.Proto;
using DysonNetwork.Shared.Registry;
using DysonNetwork.Sphere.WebReader;
@@ -13,6 +12,7 @@ using DysonNetwork.Sphere.Publisher;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Localization;
using NodaTime;
using DysonNetwork.Shared.Models;
namespace DysonNetwork.Sphere.Post;
@@ -32,7 +32,7 @@ public partial class PostService(
{
private const string PostFileUsageIdentifier = "post";
private static List<Post> TruncatePostContent(List<Post> input)
private static List<SnPost> TruncatePostContent(List<SnPost> input)
{
const int maxLength = 256;
const int embedMaxLength = 80;
@@ -62,7 +62,7 @@ public partial class PostService(
return input;
}
public (string title, string content) ChopPostForNotification(Post post)
public (string title, string content) ChopPostForNotification(SnPost post)
{
var content = !string.IsNullOrEmpty(post.Description)
? post.Description?.Length >= 40 ? post.Description[..37] + "..." : post.Description
@@ -75,8 +75,8 @@ public partial class PostService(
return (title, content);
}
public async Task<Post> PostAsync(
Post post,
public async Task<SnPost> PostAsync(
SnPost post,
List<string>? attachments = null,
List<string>? tags = null,
List<string>? categories = null
@@ -101,7 +101,7 @@ public partial class PostService(
queryRequest.Ids.AddRange(attachments);
var queryResponse = await files.GetFileBatchAsync(queryRequest);
post.Attachments = queryResponse.Files.Select(CloudFileReferenceObject.FromProtoValue).ToList();
post.Attachments = queryResponse.Files.Select(SnCloudFileReferenceObject.FromProtoValue).ToList();
// Re-order the list to match the id list places
post.Attachments = attachments
.Select(id => post.Attachments.First(a => a.Id == id))
@@ -116,7 +116,7 @@ public partial class PostService(
var existingSlugs = existingTags.Select(t => t.Slug).ToHashSet();
var missingSlugs = tags.Where(slug => !existingSlugs.Contains(slug)).ToList();
var newTags = missingSlugs.Select(slug => new PostTag { Slug = slug }).ToList();
var newTags = missingSlugs.Select(slug => new SnPostTag { Slug = slug }).ToList();
if (newTags.Count > 0)
{
await db.PostTags.AddRangeAsync(newTags);
@@ -208,8 +208,8 @@ public partial class PostService(
return post;
}
public async Task<Post> UpdatePostAsync(
Post post,
public async Task<SnPost> UpdatePostAsync(
SnPost post,
List<string>? attachments = null,
List<string>? tags = null,
List<string>? categories = null,
@@ -248,7 +248,7 @@ public partial class PostService(
queryRequest.Ids.AddRange(attachments);
var queryResponse = await files.GetFileBatchAsync(queryRequest);
post.Attachments = queryResponse.Files.Select(CloudFileReferenceObject.FromProtoValue).ToList();
post.Attachments = queryResponse.Files.Select(SnCloudFileReferenceObject.FromProtoValue).ToList();
}
if (tags is not null)
@@ -259,7 +259,7 @@ public partial class PostService(
var existingSlugs = existingTags.Select(t => t.Slug).ToHashSet();
var missingSlugs = tags.Where(slug => !existingSlugs.Contains(slug)).ToList();
var newTags = missingSlugs.Select(slug => new PostTag { Slug = slug }).ToList();
var newTags = missingSlugs.Select(slug => new SnPostTag { Slug = slug }).ToList();
if (newTags.Count > 0)
{
await db.PostTags.AddRangeAsync(newTags);
@@ -288,7 +288,7 @@ public partial class PostService(
[GeneratedRegex(@"https?://(?!.*\.\w{1,6}(?:[#?]|$))[^\s]+", RegexOptions.IgnoreCase)]
private static partial Regex GetLinkRegex();
public async Task<Post> PreviewPostLinkAsync(Post item)
public async Task<SnPost> PreviewPostLinkAsync(SnPost item)
{
if (item.Type != PostType.Moment || string.IsNullOrEmpty(item.Content)) return item;
@@ -348,7 +348,7 @@ public partial class PostService(
/// This method is designed to be called from a background task
/// </summary>
/// <param name="post">The post to process link previews for</param>
private async Task ProcessPostLinkPreviewAsync(Post post)
private async Task ProcessPostLinkPreviewAsync(SnPost post)
{
try
{
@@ -387,7 +387,7 @@ public partial class PostService(
}
}
public async Task DeletePostAsync(Post post)
public async Task DeletePostAsync(SnPost post)
{
// Delete all file references for this post
await fileRefs.DeleteResourceReferencesAsync(
@@ -420,7 +420,7 @@ public partial class PostService(
}
}
public async Task<Post> PinPostAsync(Post post, Account currentUser, PostPinMode pinMode)
public async Task<SnPost> PinPostAsync(SnPost post, Account currentUser, PostPinMode pinMode)
{
var accountId = Guid.Parse(currentUser.Id);
if (post.RepliedPostId != null)
@@ -430,14 +430,14 @@ public partial class PostService(
if (post.RepliedPost == null) throw new ArgumentNullException(nameof(post.RepliedPost));
if (!await ps.IsMemberWithRole(post.RepliedPost.PublisherId, accountId,
Publisher.PublisherMemberRole.Editor))
Shared.Models.PublisherMemberRole.Editor))
throw new InvalidOperationException("Only editors of original post can pin replies.");
post.PinMode = pinMode;
}
else
{
if (!await ps.IsMemberWithRole(post.PublisherId, accountId, Publisher.PublisherMemberRole.Editor))
if (!await ps.IsMemberWithRole(post.PublisherId, accountId, Shared.Models.PublisherMemberRole.Editor))
throw new InvalidOperationException("Only editors can pin replies.");
post.PinMode = pinMode;
@@ -449,7 +449,7 @@ public partial class PostService(
return post;
}
public async Task<Post> UnpinPostAsync(Post post, Account currentUser)
public async Task<SnPost> UnpinPostAsync(SnPost post, Account currentUser)
{
var accountId = Guid.Parse(currentUser.Id);
if (post.RepliedPostId != null)
@@ -457,12 +457,12 @@ public partial class PostService(
if (post.RepliedPost == null) throw new ArgumentNullException(nameof(post.RepliedPost));
if (!await ps.IsMemberWithRole(post.RepliedPost.PublisherId, accountId,
Publisher.PublisherMemberRole.Editor))
Shared.Models.PublisherMemberRole.Editor))
throw new InvalidOperationException("Only editors of original post can unpin replies.");
}
else
{
if (!await ps.IsMemberWithRole(post.PublisherId, accountId, Publisher.PublisherMemberRole.Editor))
if (!await ps.IsMemberWithRole(post.PublisherId, accountId, Shared.Models.PublisherMemberRole.Editor))
throw new InvalidOperationException("Only editors can unpin posts.");
}
@@ -484,14 +484,14 @@ public partial class PostService(
/// <param name="isSelfReact">Indicate this reaction is by the original post himself</param>
/// <param name="sender">The account that creates this reaction</param>
public async Task<bool> ModifyPostVotes(
Post post,
PostReaction reaction,
SnPost post,
SnPostReaction reaction,
Account sender,
bool isRemoving,
bool isSelfReact
)
{
var isExistingReaction = await db.Set<PostReaction>()
var isExistingReaction = await db.Set<SnPostReaction>()
.AnyAsync(r => r.PostId == post.Id && r.AccountId == reaction.AccountId);
if (isRemoving)
@@ -576,7 +576,7 @@ public partial class PostService(
public async Task<Dictionary<string, int>> GetPostReactionMap(Guid postId)
{
return await db.Set<PostReaction>()
return await db.Set<SnPostReaction>()
.Where(r => r.PostId == postId)
.GroupBy(r => r.Symbol)
.ToDictionaryAsync(
@@ -587,7 +587,7 @@ public partial class PostService(
public async Task<Dictionary<Guid, Dictionary<string, int>>> GetPostReactionMapBatch(List<Guid> postIds)
{
return await db.Set<PostReaction>()
return await db.Set<SnPostReaction>()
.Where(r => postIds.Contains(r.PostId))
.GroupBy(r => r.PostId)
.ToDictionaryAsync(
@@ -603,7 +603,7 @@ public partial class PostService(
public async Task<Dictionary<Guid, Dictionary<string, bool>>> GetPostReactionMadeMapBatch(List<Guid> postIds,
Guid accountId)
{
var reactions = await db.Set<PostReaction>()
var reactions = await db.Set<SnPostReaction>()
.Where(r => postIds.Contains(r.PostId) && r.AccountId == accountId)
.Select(r => new { r.PostId, r.Symbol })
.ToListAsync();
@@ -653,10 +653,10 @@ public partial class PostService(
});
}
public async Task<List<Post>> LoadPublishers(List<Post> posts)
public async Task<List<SnPost>> LoadPublishers(List<SnPost> posts)
{
var publisherIds = posts
.SelectMany<Post, Guid?>(e =>
.SelectMany<SnPost, Guid?>(e =>
[
e.PublisherId,
e.RepliedPost?.PublisherId,
@@ -688,7 +688,7 @@ public partial class PostService(
return posts;
}
public async Task<List<Post>> LoadInteractive(List<Post> posts, Account? currentUser = null)
public async Task<List<SnPost>> LoadInteractive(List<SnPost> posts, Account? currentUser = null)
{
if (posts.Count == 0) return posts;
@@ -738,7 +738,7 @@ public partial class PostService(
);
}
private async Task LoadPostEmbed(Post post, Account? currentUser)
private async Task LoadPostEmbed(SnPost post, Account? currentUser)
{
if (!post.Meta!.TryGetValue("embeds", out var value))
return;
@@ -778,8 +778,8 @@ public partial class PostService(
}
}
public async Task<List<Post>> LoadPostInfo(
List<Post> posts,
public async Task<List<SnPost>> LoadPostInfo(
List<SnPost> posts,
Account? currentUser = null,
bool truncate = false
)
@@ -801,7 +801,7 @@ public partial class PostService(
return posts;
}
public async Task<Post> LoadPostInfo(Post post, Account? currentUser = null, bool truncate = false)
public async Task<SnPost> LoadPostInfo(SnPost post, Account? currentUser = null, bool truncate = false)
{
// Convert single post to list, process it, then return the single post
var posts = await LoadPostInfo([post], currentUser, truncate);
@@ -810,7 +810,7 @@ public partial class PostService(
private const string FeaturedPostCacheKey = "posts:featured";
public async Task<List<Post>> ListFeaturedPostsAsync(Account? currentUser = null)
public async Task<List<SnPost>> ListFeaturedPostsAsync(Account? currentUser = null)
{
// Check cache first for featured post IDs
var featuredIds = await cache.GetAsync<List<Guid>>(FeaturedPostCacheKey);
@@ -877,7 +877,7 @@ public partial class PostService(
var records = reactSocialPoints
.Where(p => !existingFeaturedPostIds.Contains(p.Key))
.Select(e => new PostFeaturedRecord
.Select(e => new SnPostFeaturedRecord
{
PostId = e.Key,
SocialCredits = e.Value
@@ -904,7 +904,7 @@ public partial class PostService(
return posts;
}
public async Task<PostAward> AwardPost(
public async Task<SnPostAward> AwardPost(
Guid postId,
Guid accountId,
decimal amount,
@@ -915,7 +915,7 @@ public partial class PostService(
var post = await db.Posts.Where(p => p.Id == postId).FirstOrDefaultAsync();
if (post is null) throw new InvalidOperationException("Post not found");
var award = new PostAward
var award = new SnPostAward
{
Amount = amount,
Attitude = attitude,
@@ -983,11 +983,11 @@ public partial class PostService(
public static class PostQueryExtensions
{
public static IQueryable<Post> FilterWithVisibility(
this IQueryable<Post> source,
public static IQueryable<SnPost> FilterWithVisibility(
this IQueryable<SnPost> source,
Account? currentUser,
List<Guid> userFriends,
List<Publisher.Publisher> publishers,
List<Shared.Models.SnPublisher> publishers,
bool isListing = false
)
{

View File

@@ -1,169 +0,0 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text.Json.Serialization;
using DysonNetwork.Shared.Data;
using DysonNetwork.Sphere.Post;
using Microsoft.EntityFrameworkCore;
using NodaTime;
using NodaTime.Serialization.Protobuf;
using VerificationMark = DysonNetwork.Shared.Data.VerificationMark;
using Account = DysonNetwork.Shared.Data.AccountReference;
namespace DysonNetwork.Sphere.Publisher;
public enum PublisherType
{
Individual,
Organizational
}
[Index(nameof(Name), IsUnique = true)]
public class Publisher : ModelBase, IIdentifiedResource
{
public Guid Id { get; set; } = Guid.NewGuid();
public PublisherType Type { get; set; }
[MaxLength(256)] public string Name { get; set; } = string.Empty;
[MaxLength(256)] public string Nick { get; set; } = string.Empty;
[MaxLength(4096)] public string? Bio { get; set; }
// Outdated fields, for backward compability
[MaxLength(32)] public string? PictureId { get; set; }
[MaxLength(32)] public string? BackgroundId { get; set; }
[Column(TypeName = "jsonb")] public CloudFileReferenceObject? Picture { get; set; }
[Column(TypeName = "jsonb")] public CloudFileReferenceObject? Background { get; set; }
[Column(TypeName = "jsonb")] public VerificationMark? Verification { get; set; }
[JsonIgnore] public ICollection<Post.Post> Posts { get; set; } = new List<Post.Post>();
[JsonIgnore] public ICollection<Poll.Poll> Polls { get; set; } = new List<Poll.Poll>();
[JsonIgnore] public ICollection<PostCollection> Collections { get; set; } = new List<PostCollection>();
[JsonIgnore] public ICollection<PublisherMember> Members { get; set; } = new List<PublisherMember>();
[JsonIgnore] public ICollection<PublisherFeature> Features { get; set; } = new List<PublisherFeature>();
[JsonIgnore]
public ICollection<PublisherSubscription> Subscriptions { get; set; } = new List<PublisherSubscription>();
public Guid? AccountId { get; set; }
public Guid? RealmId { get; set; }
[JsonIgnore] public Realm.Realm? Realm { get; set; }
[NotMapped] public Account? Account { get; set; }
public string ResourceIdentifier => $"publisher:{Id}";
public Shared.Proto.Publisher ToProto(AppDatabase db)
{
var p = new Shared.Proto.Publisher()
{
Id = Id.ToString(),
Type = Type == PublisherType.Individual
? Shared.Proto.PublisherType.PubIndividual
: Shared.Proto.PublisherType.PubOrganizational,
Name = Name,
Nick = Nick,
Bio = Bio,
AccountId = AccountId?.ToString() ?? string.Empty,
RealmId = RealmId?.ToString() ?? string.Empty,
CreatedAt = Google.Protobuf.WellKnownTypes.Timestamp.FromDateTimeOffset(CreatedAt.ToDateTimeOffset()),
UpdatedAt = Google.Protobuf.WellKnownTypes.Timestamp.FromDateTimeOffset(UpdatedAt.ToDateTimeOffset())
};
if (Picture is not null)
{
p.Picture = new Shared.Proto.CloudFile
{
Id = Picture.Id,
Name = Picture.Name,
MimeType = Picture.MimeType,
Hash = Picture.Hash,
Size = Picture.Size,
};
}
if (Background is not null)
{
p.Background = new Shared.Proto.CloudFile
{
Id = Background.Id,
Name = Background.Name,
MimeType = Background.MimeType,
Hash = Background.Hash,
Size = Background.Size,
};
}
return p;
}
}
public enum PublisherMemberRole
{
Owner = 100,
Manager = 75,
Editor = 50,
Viewer = 25
}
public class PublisherMember : ModelBase
{
public Guid PublisherId { get; set; }
[JsonIgnore] public Publisher Publisher { get; set; } = null!;
public Guid AccountId { get; set; }
[NotMapped] public Account? Account { get; set; }
public PublisherMemberRole Role { get; set; } = PublisherMemberRole.Viewer;
public Instant? JoinedAt { get; set; }
public Shared.Proto.PublisherMember ToProto()
{
return new Shared.Proto.PublisherMember()
{
PublisherId = PublisherId.ToString(),
AccountId = AccountId.ToString(),
Role = Role switch
{
PublisherMemberRole.Owner => Shared.Proto.PublisherMemberRole.Owner,
PublisherMemberRole.Manager => Shared.Proto.PublisherMemberRole.Manager,
PublisherMemberRole.Editor => Shared.Proto.PublisherMemberRole.Editor,
PublisherMemberRole.Viewer => Shared.Proto.PublisherMemberRole.Viewer,
_ => throw new ArgumentOutOfRangeException(nameof(Role), Role, null)
},
JoinedAt = JoinedAt?.ToTimestamp()
};
}
}
public enum PublisherSubscriptionStatus
{
Active,
Expired,
Cancelled
}
public class PublisherSubscription : ModelBase
{
public Guid Id { get; set; }
public Guid PublisherId { get; set; }
[JsonIgnore] public Publisher Publisher { get; set; } = null!;
public Guid AccountId { get; set; }
public PublisherSubscriptionStatus Status { get; set; } = PublisherSubscriptionStatus.Active;
public int Tier { get; set; } = 0;
}
public class PublisherFeature : ModelBase
{
public Guid Id { get; set; }
[MaxLength(1024)] public string Flag { get; set; } = null!;
public Instant? ExpiredAt { get; set; }
public Guid PublisherId { get; set; }
public Publisher Publisher { get; set; } = null!;
}
public abstract class PublisherFeatureFlag
{
public static List<string> AllFlags => [Develop];
public static string Develop = "develop";
}

View File

@@ -1,8 +1,7 @@
using System.ComponentModel.DataAnnotations;
using DysonNetwork.Shared.Auth;
using DysonNetwork.Shared.Data;
using DysonNetwork.Shared.Models;
using DysonNetwork.Shared.Proto;
using DysonNetwork.Sphere.Realm;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
@@ -23,7 +22,7 @@ public class PublisherController(
: ControllerBase
{
[HttpGet("{name}")]
public async Task<ActionResult<Publisher>> GetPublisher(string name)
public async Task<ActionResult<SnPublisher>> GetPublisher(string name)
{
var publisher = await db.Publishers
.Where(e => e.Name == name)
@@ -34,7 +33,7 @@ public class PublisherController(
var account = await accounts.GetAccountAsync(
new GetAccountRequest { Id = publisher.AccountId.Value.ToString() }
);
publisher.Account = AccountReference.FromProtoValue(account);
publisher.Account = SnAccount.FromProtoValue(account);
return Ok(publisher);
}
@@ -48,7 +47,7 @@ public class PublisherController(
}
[HttpGet("of/{accountId:guid}")]
public async Task<ActionResult<List<Publisher>>> GetAccountManagedPublishers(Guid accountId)
public async Task<ActionResult<List<SnPublisher>>> GetAccountManagedPublishers(Guid accountId)
{
var members = await db.PublisherMembers
.Where(m => m.AccountId == accountId)
@@ -61,7 +60,7 @@ public class PublisherController(
[HttpGet]
[Authorize]
public async Task<ActionResult<List<Publisher>>> ListManagedPublishers()
public async Task<ActionResult<List<SnPublisher>>> ListManagedPublishers()
{
if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized();
var accountId = Guid.Parse(currentUser.Id);
@@ -77,7 +76,7 @@ public class PublisherController(
[HttpGet("invites")]
[Authorize]
public async Task<ActionResult<List<PublisherMember>>> ListInvites()
public async Task<ActionResult<List<SnPublisherMember>>> ListInvites()
{
if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized();
var accountId = Guid.Parse(currentUser.Id);
@@ -99,7 +98,7 @@ public class PublisherController(
[HttpPost("invites/{name}")]
[Authorize]
public async Task<ActionResult<PublisherMember>> InviteMember(string name,
public async Task<ActionResult<SnPublisherMember>> InviteMember(string name,
[FromBody] PublisherMemberRequest request)
{
if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized();
@@ -117,7 +116,7 @@ public class PublisherController(
if (!await ps.IsMemberWithRole(publisher.Id, accountId, request.Role))
return StatusCode(403, "You cannot invite member has higher permission than yours.");
var newMember = new PublisherMember
var newMember = new SnPublisherMember
{
AccountId = Guid.Parse(relatedUser.Id),
PublisherId = publisher.Id,
@@ -145,7 +144,7 @@ public class PublisherController(
[HttpPost("invites/{name}/accept")]
[Authorize]
public async Task<ActionResult<Publisher>> AcceptMemberInvite(string name)
public async Task<ActionResult<SnPublisher>> AcceptMemberInvite(string name)
{
if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized();
var accountId = Guid.Parse(currentUser.Id);
@@ -270,7 +269,7 @@ public class PublisherController(
[HttpPost("individual")]
[Authorize]
[RequiredPermission("global", "publishers.create")]
public async Task<ActionResult<Publisher>> CreatePublisherIndividual([FromBody] PublisherRequest request)
public async Task<ActionResult<SnPublisher>> CreatePublisherIndividual([FromBody] PublisherRequest request)
{
if (string.IsNullOrEmpty(request.Name) || string.IsNullOrEmpty(request.Nick))
return BadRequest("Name and Nick are required.");
@@ -288,7 +287,7 @@ public class PublisherController(
"your name firstly to get your name back."
);
CloudFileReferenceObject? picture = null, background = null;
SnCloudFileReferenceObject? picture = null, background = null;
if (request.PictureId is not null)
{
var queryResult = await files.GetFileAsync(
@@ -296,7 +295,7 @@ public class PublisherController(
);
if (queryResult is null)
throw new InvalidOperationException("Invalid picture id, unable to find the file on cloud.");
picture = CloudFileReferenceObject.FromProtoValue(queryResult);
picture = SnCloudFileReferenceObject.FromProtoValue(queryResult);
}
if (request.BackgroundId is not null)
@@ -306,7 +305,7 @@ public class PublisherController(
);
if (queryResult is null)
throw new InvalidOperationException("Invalid background id, unable to find the file on cloud.");
background = CloudFileReferenceObject.FromProtoValue(queryResult);
background = SnCloudFileReferenceObject.FromProtoValue(queryResult);
}
var publisher = await ps.CreateIndividualPublisher(
@@ -338,7 +337,7 @@ public class PublisherController(
[HttpPost("organization/{realmSlug}")]
[Authorize]
[RequiredPermission("global", "publishers.create")]
public async Task<ActionResult<Publisher>> CreatePublisherOrganization(string realmSlug,
public async Task<ActionResult<SnPublisher>> CreatePublisherOrganization(string realmSlug,
[FromBody] PublisherRequest request)
{
if (string.IsNullOrEmpty(request.Name) || string.IsNullOrEmpty(request.Nick))
@@ -362,7 +361,7 @@ public class PublisherController(
if (duplicateNameCount > 0)
return BadRequest("The name you requested has already been taken");
CloudFileReferenceObject? picture = null, background = null;
SnCloudFileReferenceObject? picture = null, background = null;
if (request.PictureId is not null)
{
var queryResult = await files.GetFileAsync(
@@ -370,7 +369,7 @@ public class PublisherController(
);
if (queryResult is null)
throw new InvalidOperationException("Invalid picture id, unable to find the file on cloud.");
picture = CloudFileReferenceObject.FromProtoValue(queryResult);
picture = SnCloudFileReferenceObject.FromProtoValue(queryResult);
}
if (request.BackgroundId is not null)
@@ -380,7 +379,7 @@ public class PublisherController(
);
if (queryResult is null)
throw new InvalidOperationException("Invalid background id, unable to find the file on cloud.");
background = CloudFileReferenceObject.FromProtoValue(queryResult);
background = SnCloudFileReferenceObject.FromProtoValue(queryResult);
}
var publisher = await ps.CreateOrganizationPublisher(
@@ -414,7 +413,7 @@ public class PublisherController(
[HttpPatch("{name}")]
[Authorize]
public async Task<ActionResult<Publisher>> UpdatePublisher(string name, PublisherRequest request)
public async Task<ActionResult<SnPublisher>> UpdatePublisher(string name, PublisherRequest request)
{
if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized();
var accountId = Guid.Parse(currentUser.Id);
@@ -442,7 +441,7 @@ public class PublisherController(
);
if (queryResult is null)
throw new InvalidOperationException("Invalid picture id, unable to find the file on cloud.");
var picture = CloudFileReferenceObject.FromProtoValue(queryResult);
var picture = SnCloudFileReferenceObject.FromProtoValue(queryResult);
// Remove old references for the publisher picture
if (publisher.Picture is not null)
@@ -470,7 +469,7 @@ public class PublisherController(
);
if (queryResult is null)
throw new InvalidOperationException("Invalid background id, unable to find the file on cloud.");
var background = CloudFileReferenceObject.FromProtoValue(queryResult);
var background = SnCloudFileReferenceObject.FromProtoValue(queryResult);
// Remove old references for the publisher background
if (publisher.Background is not null)
@@ -518,7 +517,7 @@ public class PublisherController(
[HttpDelete("{name}")]
[Authorize]
public async Task<ActionResult<Publisher>> DeletePublisher(string name)
public async Task<ActionResult<SnPublisher>> DeletePublisher(string name)
{
if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized();
var accountId = Guid.Parse(currentUser.Id);
@@ -564,7 +563,7 @@ public class PublisherController(
}
[HttpGet("{name}/members")]
public async Task<ActionResult<List<PublisherMember>>> ListMembers(
public async Task<ActionResult<List<SnPublisherMember>>> ListMembers(
string name,
[FromQuery] int offset = 0,
[FromQuery] int take = 20
@@ -594,7 +593,7 @@ public class PublisherController(
[HttpGet("{name}/members/me")]
[Authorize]
public async Task<ActionResult<PublisherMember>> GetCurrentIdentity(string name)
public async Task<ActionResult<SnPublisherMember>> GetCurrentIdentity(string name)
{
if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized();
var accountId = Guid.Parse(currentUser.Id);

View File

@@ -1,8 +1,7 @@
using DysonNetwork.Shared.Cache;
using DysonNetwork.Shared.Data;
using DysonNetwork.Shared.Models;
using DysonNetwork.Shared.Proto;
using DysonNetwork.Shared.Registry;
using DysonNetwork.Sphere.Post;
using Microsoft.EntityFrameworkCore;
using NodaTime;
@@ -15,7 +14,7 @@ public class PublisherService(
AccountClientHelper accountsHelper
)
{
public async Task<Publisher?> GetPublisherByName(string name)
public async Task<SnPublisher?> GetPublisherByName(string name)
{
return await db.Publishers
.Where(e => e.Name == name)
@@ -24,12 +23,12 @@ public class PublisherService(
private const string UserPublishersCacheKey = "accounts:{0}:publishers";
public async Task<List<Publisher>> GetUserPublishers(Guid userId)
public async Task<List<SnPublisher>> GetUserPublishers(Guid userId)
{
var cacheKey = string.Format(UserPublishersCacheKey, userId);
// Try to get publishers from the cache first
var publishers = await cache.GetAsync<List<Publisher>>(cacheKey);
var publishers = await cache.GetAsync<List<SnPublisher>>(cacheKey);
if (publishers is not null)
return publishers;
@@ -48,16 +47,16 @@ public class PublisherService(
return publishers;
}
public async Task<Dictionary<Guid, List<Publisher>>> GetUserPublishersBatch(List<Guid> userIds)
public async Task<Dictionary<Guid, List<SnPublisher>>> GetUserPublishersBatch(List<Guid> userIds)
{
var result = new Dictionary<Guid, List<Publisher>>();
var result = new Dictionary<Guid, List<SnPublisher>>();
var missingIds = new List<Guid>();
// Try to get publishers from cache for each user
foreach (var userId in userIds)
{
var cacheKey = string.Format(UserPublishersCacheKey, userId);
var publishers = await cache.GetAsync<List<Publisher>>(cacheKey);
var publishers = await cache.GetAsync<List<SnPublisher>>(cacheKey);
if (publishers != null)
result[userId] = publishers;
else
@@ -103,12 +102,12 @@ public class PublisherService(
public const string SubscribedPublishersCacheKey = "accounts:{0}:subscribed-publishers";
public async Task<List<Publisher>> GetSubscribedPublishers(Guid userId)
public async Task<List<SnPublisher>> GetSubscribedPublishers(Guid userId)
{
var cacheKey = string.Format(SubscribedPublishersCacheKey, userId);
// Try to get publishers from the cache first
var publishers = await cache.GetAsync<List<Publisher>>(cacheKey);
var publishers = await cache.GetAsync<List<SnPublisher>>(cacheKey);
if (publishers is not null)
return publishers;
@@ -130,12 +129,12 @@ public class PublisherService(
private const string PublisherMembersCacheKey = "publishers:{0}:members";
public async Task<List<PublisherMember>> GetPublisherMembers(Guid publisherId)
public async Task<List<SnPublisherMember>> GetPublisherMembers(Guid publisherId)
{
var cacheKey = string.Format(PublisherMembersCacheKey, publisherId);
// Try to get members from the cache first
var members = await cache.GetAsync<List<PublisherMember>>(cacheKey);
var members = await cache.GetAsync<List<SnPublisherMember>>(cacheKey);
if (members is not null)
return members;
@@ -150,16 +149,16 @@ public class PublisherService(
return members;
}
public async Task<Publisher> CreateIndividualPublisher(
public async Task<SnPublisher> CreateIndividualPublisher(
Account account,
string? name,
string? nick,
string? bio,
CloudFileReferenceObject? picture,
CloudFileReferenceObject? background
SnCloudFileReferenceObject? picture,
SnCloudFileReferenceObject? background
)
{
var publisher = new Publisher
var publisher = new SnPublisher
{
Type = PublisherType.Individual,
Name = name ?? account.Name,
@@ -167,12 +166,12 @@ public class PublisherService(
Bio = bio ?? account.Profile.Bio,
Picture = picture ?? (account.Profile.Picture is null
? null
: CloudFileReferenceObject.FromProtoValue(account.Profile.Picture)),
: SnCloudFileReferenceObject.FromProtoValue(account.Profile.Picture)),
Background = background ?? (account.Profile.Background is null
? null
: CloudFileReferenceObject.FromProtoValue(account.Profile.Background)),
: SnCloudFileReferenceObject.FromProtoValue(account.Profile.Background)),
AccountId = Guid.Parse(account.Id),
Members = new List<PublisherMember>
Members = new List<SnPublisherMember>
{
new()
{
@@ -213,26 +212,26 @@ public class PublisherService(
return publisher;
}
public async Task<Publisher> CreateOrganizationPublisher(
Realm.Realm realm,
public async Task<SnPublisher> CreateOrganizationPublisher(
Shared.Models.SnRealm realm,
Account account,
string? name,
string? nick,
string? bio,
CloudFileReferenceObject? picture,
CloudFileReferenceObject? background
SnCloudFileReferenceObject? picture,
SnCloudFileReferenceObject? background
)
{
var publisher = new Publisher
var publisher = new SnPublisher
{
Type = PublisherType.Organizational,
Name = name ?? realm.Slug,
Nick = nick ?? realm.Name,
Bio = bio ?? realm.Description,
Picture = picture ?? CloudFileReferenceObject.FromProtoValue(account.Profile.Picture),
Background = background ?? CloudFileReferenceObject.FromProtoValue(account.Profile.Background),
Picture = picture ?? SnCloudFileReferenceObject.FromProtoValue(account.Profile.Picture),
Background = background ?? SnCloudFileReferenceObject.FromProtoValue(account.Profile.Background),
RealmId = realm.Id,
Members = new List<PublisherMember>
Members = new List<SnPublisherMember>
{
new()
{
@@ -379,14 +378,14 @@ public class PublisherService(
return member != null && member.Role >= requiredRole;
}
public async Task<PublisherMember> LoadMemberAccount(PublisherMember member)
public async Task<SnPublisherMember> LoadMemberAccount(SnPublisherMember member)
{
var account = await accountsHelper.GetAccount(member.AccountId);
member.Account = AccountReference.FromProtoValue(account);
member.Account = SnAccount.FromProtoValue(account);
return member;
}
public async Task<List<PublisherMember>> LoadMemberAccounts(ICollection<PublisherMember> members)
public async Task<List<SnPublisherMember>> LoadMemberAccounts(ICollection<SnPublisherMember> members)
{
var accountIds = members.Select(m => m.AccountId).ToList();
var accounts = (await accountsHelper.GetAccountBatch(accountIds)).ToDictionary(a => Guid.Parse(a.Id), a => a);
@@ -394,7 +393,7 @@ public class PublisherService(
return members.Select(m =>
{
if (accounts.TryGetValue(m.AccountId, out var account))
m.Account = AccountReference.FromProtoValue(account);
m.Account = SnAccount.FromProtoValue(account);
return m;
}).ToList();
}

View File

@@ -1,3 +1,4 @@
using DysonNetwork.Shared.Models;
using DysonNetwork.Shared.Proto;
using Grpc.Core;
using Microsoft.EntityFrameworkCore;
@@ -12,7 +13,7 @@ public class PublisherServiceGrpc(PublisherService service, AppDatabase db)
ServerCallContext context
)
{
Publisher? p = null;
SnPublisher? p = null;
switch (request.QueryCase)
{
case GetPublisherRequest.QueryOneofCase.Id:

View File

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

View File

@@ -1,5 +1,6 @@
using DysonNetwork.Shared;
using DysonNetwork.Shared.Cache;
using DysonNetwork.Shared.Models;
using DysonNetwork.Shared.Proto;
using DysonNetwork.Sphere.Localization;
using DysonNetwork.Sphere.Post;
@@ -49,7 +50,7 @@ public class PublisherSubscriptionService(
/// </summary>
/// <param name="post">The new post</param>
/// <returns>The number of subscribers notified</returns>
public async Task<int> NotifySubscriberPost(Post.Post post)
public async Task<int> NotifySubscriberPost(SnPost post)
{
if (post.RepliedPostId is not null)
return 0;
@@ -74,7 +75,7 @@ public class PublisherSubscriptionService(
if (subscribers.Count == 0)
return 0;
List<PostCategorySubscription> categorySubscribers = [];
List<SnPostCategorySubscription> categorySubscribers = [];
if (post.Categories.Count > 0)
{
var categoryIds = post.Categories.Select(x => x.Id).ToList();

View File

@@ -1,56 +0,0 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text.Json.Serialization;
using DysonNetwork.Shared.Data;
using DysonNetwork.Sphere.Chat;
using Microsoft.EntityFrameworkCore;
using NodaTime;
namespace DysonNetwork.Sphere.Realm;
[Index(nameof(Slug), IsUnique = true)]
public class Realm : ModelBase, IIdentifiedResource
{
public Guid Id { get; set; }
[MaxLength(1024)] public string Slug { get; set; } = string.Empty;
[MaxLength(1024)] public string Name { get; set; } = string.Empty;
[MaxLength(4096)] public string Description { get; set; } = string.Empty;
public bool IsCommunity { get; set; }
public bool IsPublic { get; set; }
// Outdated fields, for backward compability
[MaxLength(32)] public string? PictureId { get; set; }
[MaxLength(32)] public string? BackgroundId { get; set; }
[Column(TypeName = "jsonb")] public CloudFileReferenceObject? Picture { get; set; }
[Column(TypeName = "jsonb")] public CloudFileReferenceObject? Background { get; set; }
[Column(TypeName = "jsonb")] public VerificationMark? Verification { get; set; }
[JsonIgnore] public ICollection<RealmMember> Members { get; set; } = new List<RealmMember>();
[JsonIgnore] public ICollection<ChatRoom> ChatRooms { get; set; } = new List<ChatRoom>();
public Guid AccountId { get; set; }
public string ResourceIdentifier => $"realm:{Id}";
}
public abstract class RealmMemberRole
{
public const int Owner = 100;
public const int Moderator = 50;
public const int Normal = 0;
}
public class RealmMember : ModelBase
{
public Guid RealmId { get; set; }
public Realm Realm { get; set; } = null!;
public Guid AccountId { get; set; }
[NotMapped] public AccountReference? Account { get; set; }
[NotMapped] public AccountStatusReference? Status { get; set; }
public int Role { get; set; } = RealmMemberRole.Normal;
public Instant? JoinedAt { get; set; }
public Instant? LeaveAt { get; set; }
}

View File

@@ -1,5 +1,5 @@
using DysonNetwork.Shared.Models;
using DysonNetwork.Shared.Proto;
using DysonNetwork.Sphere.Chat;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
@@ -12,7 +12,7 @@ public class RealmChatController(AppDatabase db, RealmService rs) : ControllerBa
{
[HttpGet("chat")]
[Authorize]
public async Task<ActionResult<List<ChatRoom>>> ListRealmChat(string slug)
public async Task<ActionResult<List<SnChatRoom>>> ListRealmChat(string slug)
{
var currentUser = HttpContext.Items["CurrentUser"] as Account;
var accountId = currentUser is null ? Guid.Empty : Guid.Parse(currentUser.Id);

View File

@@ -1,5 +1,4 @@
using System.ComponentModel.DataAnnotations;
using DysonNetwork.Shared.Data;
using DysonNetwork.Shared.Proto;
using DysonNetwork.Shared.Registry;
using Microsoft.AspNetCore.Authorization;
@@ -7,6 +6,7 @@ using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using NodaTime;
using Google.Protobuf.WellKnownTypes;
using DysonNetwork.Shared.Models;
namespace DysonNetwork.Sphere.Realm;
@@ -53,7 +53,7 @@ public class RealmController(
[HttpGet("invites")]
[Authorize]
public async Task<ActionResult<List<RealmMember>>> ListInvites()
public async Task<ActionResult<List<SnRealmMember>>> ListInvites()
{
if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized();
var accountId = Guid.Parse(currentUser.Id);
@@ -75,7 +75,7 @@ public class RealmController(
[HttpPost("invites/{slug}")]
[Authorize]
public async Task<ActionResult<RealmMember>> InviteMember(string slug,
public async Task<ActionResult<SnRealmMember>> InviteMember(string slug,
[FromBody] RealmMemberRequest request)
{
if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized();
@@ -110,7 +110,7 @@ public class RealmController(
if (hasExistingMember)
return BadRequest("This user has been joined the realm or leave cannot be invited again.");
var member = new RealmMember
var member = new SnRealmMember
{
AccountId = Guid.Parse(relatedUser.Id),
RealmId = realm.Id,
@@ -211,7 +211,7 @@ public class RealmController(
[HttpGet("{slug}/members")]
public async Task<ActionResult<List<RealmMember>>> ListMembers(
public async Task<ActionResult<List<SnRealmMember>>> ListMembers(
string slug,
[FromQuery] int offset = 0,
[FromQuery] int take = 20,
@@ -281,7 +281,7 @@ public class RealmController(
[HttpGet("{slug}/members/me")]
[Authorize]
public async Task<ActionResult<RealmMember>> GetCurrentIdentity(string slug)
public async Task<ActionResult<SnRealmMember>> GetCurrentIdentity(string slug)
{
if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized();
var accountId = Guid.Parse(currentUser.Id);
@@ -362,7 +362,7 @@ public class RealmController(
AccountId = Guid.Parse(currentUser.Id),
IsCommunity = request.IsCommunity ?? false,
IsPublic = request.IsPublic ?? false,
Members = new List<RealmMember>
Members = new List<SnRealmMember>
{
new()
{
@@ -377,14 +377,14 @@ public class RealmController(
{
var pictureResult = await files.GetFileAsync(new GetFileRequest { Id = request.PictureId });
if (pictureResult is null) return BadRequest("Invalid picture id, unable to find the file on cloud.");
realm.Picture = CloudFileReferenceObject.FromProtoValue(pictureResult);
realm.Picture = SnCloudFileReferenceObject.FromProtoValue(pictureResult);
}
if (request.BackgroundId is not null)
{
var backgroundResult = await files.GetFileAsync(new GetFileRequest { Id = request.BackgroundId });
if (backgroundResult is null) return BadRequest("Invalid background id, unable to find the file on cloud.");
realm.Background = CloudFileReferenceObject.FromProtoValue(backgroundResult);
realm.Background = SnCloudFileReferenceObject.FromProtoValue(backgroundResult);
}
db.Realms.Add(realm);
@@ -479,7 +479,7 @@ public class RealmController(
});
}
realm.Picture = CloudFileReferenceObject.FromProtoValue(pictureResult);
realm.Picture = SnCloudFileReferenceObject.FromProtoValue(pictureResult);
// Create a new reference
await fileRefs.CreateReferenceAsync(new CreateReferenceRequest
@@ -504,7 +504,7 @@ public class RealmController(
});
}
realm.Background = CloudFileReferenceObject.FromProtoValue(backgroundResult);
realm.Background = SnCloudFileReferenceObject.FromProtoValue(backgroundResult);
// Create a new reference
await fileRefs.CreateReferenceAsync(new CreateReferenceRequest
@@ -542,7 +542,7 @@ public class RealmController(
[HttpPost("{slug}/members/me")]
[Authorize]
public async Task<ActionResult<RealmMember>> JoinRealm(string slug)
public async Task<ActionResult<SnRealmMember>> JoinRealm(string slug)
{
if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized();
@@ -560,7 +560,7 @@ public class RealmController(
if (existingMember is not null)
return BadRequest("You are already a member of this realm.");
var member = new RealmMember
var member = new SnRealmMember
{
AccountId = Guid.Parse(currentUser.Id),
RealmId = realm.Id,
@@ -629,7 +629,7 @@ public class RealmController(
[HttpPatch("{slug}/members/{memberId:guid}/role")]
[Authorize]
public async Task<ActionResult<RealmMember>> UpdateMemberRole(string slug, Guid memberId, [FromBody] int newRole)
public async Task<ActionResult<SnRealmMember>> UpdateMemberRole(string slug, Guid memberId, [FromBody] int newRole)
{
if (newRole >= RealmMemberRole.Owner) return BadRequest("Unable to set realm member to owner or greater role.");
if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized();

View File

@@ -1,6 +1,7 @@
using DysonNetwork.Shared;
using DysonNetwork.Shared.Cache;
using DysonNetwork.Shared.Data;
using DysonNetwork.Shared.Models;
using DysonNetwork.Shared.Proto;
using DysonNetwork.Shared.Registry;
using DysonNetwork.Sphere.Localization;
@@ -39,7 +40,7 @@ public class RealmService(
return realms;
}
public async Task SendInviteNotify(RealmMember member)
public async Task SendInviteNotify(SnRealmMember member)
{
var account = await accounts.GetAccountAsync(new GetAccountRequest { Id = member.AccountId.ToString() });
CultureService.SetCultureInfo(account);
@@ -71,14 +72,14 @@ public class RealmService(
return member?.Role >= maxRequiredRole;
}
public async Task<RealmMember> LoadMemberAccount(RealmMember member)
public async Task<SnRealmMember> LoadMemberAccount(SnRealmMember member)
{
var account = await accountsHelper.GetAccount(member.AccountId);
member.Account = AccountReference.FromProtoValue(account);
member.Account = SnAccount.FromProtoValue(account);
return member;
}
public async Task<List<RealmMember>> LoadMemberAccounts(ICollection<RealmMember> members)
public async Task<List<SnRealmMember>> LoadMemberAccounts(ICollection<SnRealmMember> members)
{
var accountIds = members.Select(m => m.AccountId).ToList();
var accounts = (await accountsHelper.GetAccountBatch(accountIds)).ToDictionary(a => Guid.Parse(a.Id), a => a);
@@ -86,7 +87,7 @@ public class RealmService(
return members.Select(m =>
{
if (accounts.TryGetValue(m.AccountId, out var account))
m.Account = AccountReference.FromProtoValue(account);
m.Account = SnAccount.FromProtoValue(account);
return m;
}).ToList();
}

View File

@@ -1,5 +1,6 @@
using System.Text.Json;
using System.Text.Json.Serialization;
using DysonNetwork.Shared.Models;
using DysonNetwork.Shared.Proto;
using DysonNetwork.Shared.Stream;
using DysonNetwork.Sphere.Chat;
@@ -9,7 +10,7 @@ using Microsoft.EntityFrameworkCore;
using NATS.Client.Core;
using NATS.Client.JetStream.Models;
using NATS.Net;
using WebSocketPacket = DysonNetwork.Shared.Data.WebSocketPacket;
using WebSocketPacket = DysonNetwork.Shared.Models.WebSocketPacket;
namespace DysonNetwork.Sphere.Startup;

View File

@@ -1,49 +0,0 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text.Json.Serialization;
using DysonNetwork.Shared.Data;
using Microsoft.EntityFrameworkCore;
namespace DysonNetwork.Sphere.Sticker;
[Index(nameof(Slug))] // The slug index shouldn't be unique, the sticker slug can be repeated across packs.
public class Sticker : ModelBase, IIdentifiedResource
{
public Guid Id { get; set; } = Guid.NewGuid();
[MaxLength(128)] public string Slug { get; set; } = null!;
// Outdated fields, for backward compability
[MaxLength(32)] public string? ImageId { get; set; }
[Column(TypeName = "jsonb")] public CloudFileReferenceObject? Image { get; set; } = null!;
public Guid PackId { get; set; }
[JsonIgnore] public StickerPack Pack { get; set; } = null!;
public string ResourceIdentifier => $"sticker:{Id}";
}
[Index(nameof(Prefix), IsUnique = true)]
public class StickerPack : ModelBase
{
public Guid Id { get; set; } = Guid.NewGuid();
[MaxLength(1024)] public string Name { get; set; } = null!;
[MaxLength(4096)] public string Description { get; set; } = string.Empty;
[MaxLength(128)] public string Prefix { get; set; } = null!;
public List<Sticker> Stickers { get; set; } = [];
[JsonIgnore] public List<StickerPackOwnership> Ownerships { get; set; } = [];
public Guid PublisherId { get; set; }
public Publisher.Publisher Publisher { get; set; } = null!;
}
public class StickerPackOwnership : ModelBase
{
public Guid Id { get; set; } = Guid.NewGuid();
public Guid PackId { get; set; }
public StickerPack Pack { get; set; } = null!;
public Guid AccountId { get; set; }
[NotMapped] public AccountReference Account { get; set; } = null!;
}

View File

@@ -1,6 +1,6 @@
using System.ComponentModel.DataAnnotations;
using DysonNetwork.Shared.Auth;
using DysonNetwork.Shared.Data;
using DysonNetwork.Shared.Models;
using DysonNetwork.Shared.Proto;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
@@ -20,7 +20,7 @@ public class StickerController(
private async Task<IActionResult> _CheckStickerPackPermissions(
Guid packId,
Account currentUser,
Publisher.PublisherMemberRole requiredRole
Shared.Models.PublisherMemberRole requiredRole
)
{
var pack = await db.StickerPacks
@@ -46,7 +46,7 @@ public class StickerController(
[FromQuery(Name = "query")] string? query = null
)
{
Publisher.Publisher? publisher = null;
Shared.Models.SnPublisher? publisher = null;
if (pubName is not null)
publisher = await db.Publishers.FirstOrDefaultAsync(p => p.Name == pubName);
@@ -168,7 +168,7 @@ public class StickerController(
.FirstOrDefaultAsync(m => m.AccountId == accountId && m.PublisherId == pack.PublisherId);
if (member is null)
return StatusCode(403, "You are not a member of this publisher");
if (member.Role < Publisher.PublisherMemberRole.Editor)
if (member.Role < Shared.Models.PublisherMemberRole.Editor)
return StatusCode(403, "You need to be at least an editor to update sticker packs");
if (request.Name is not null)
@@ -200,7 +200,7 @@ public class StickerController(
.FirstOrDefaultAsync(m => m.AccountId == accountId && m.PublisherId == pack.PublisherId);
if (member is null)
return StatusCode(403, "You are not a member of this publisher");
if (member.Role < Publisher.PublisherMemberRole.Editor)
if (member.Role < Shared.Models.PublisherMemberRole.Editor)
return StatusCode(403, "You need to be an editor to delete sticker packs");
await st.DeleteStickerPackAsync(pack);
@@ -262,7 +262,7 @@ public class StickerController(
return Unauthorized();
var permissionCheck =
await _CheckStickerPackPermissions(packId, currentUser, Publisher.PublisherMemberRole.Editor);
await _CheckStickerPackPermissions(packId, currentUser, Shared.Models.PublisherMemberRole.Editor);
if (permissionCheck is not OkResult)
return permissionCheck;
@@ -277,14 +277,14 @@ public class StickerController(
if (request.Slug is not null)
sticker.Slug = request.Slug;
CloudFileReferenceObject? image = null;
SnCloudFileReferenceObject? image = null;
if (request.ImageId is not null)
{
var file = await files.GetFileAsync(new GetFileRequest { Id = request.ImageId });
if (file is null)
return BadRequest("Image not found");
sticker.ImageId = request.ImageId;
sticker.Image = CloudFileReferenceObject.FromProtoValue(file);
sticker.Image = SnCloudFileReferenceObject.FromProtoValue(file);
}
sticker = await st.UpdateStickerAsync(sticker, image);
@@ -298,7 +298,7 @@ public class StickerController(
return Unauthorized();
var permissionCheck =
await _CheckStickerPackPermissions(packId, currentUser, Publisher.PublisherMemberRole.Editor);
await _CheckStickerPackPermissions(packId, currentUser, Shared.Models.PublisherMemberRole.Editor);
if (permissionCheck is not OkResult)
return permissionCheck;
@@ -329,7 +329,7 @@ public class StickerController(
return BadRequest("Image is required.");
var permissionCheck =
await _CheckStickerPackPermissions(packId, currentUser, Publisher.PublisherMemberRole.Editor);
await _CheckStickerPackPermissions(packId, currentUser, Shared.Models.PublisherMemberRole.Editor);
if (permissionCheck is not OkResult)
return permissionCheck;
@@ -351,7 +351,7 @@ public class StickerController(
{
Slug = request.Slug,
ImageId = file.Id,
Image = CloudFileReferenceObject.FromProtoValue(file),
Image = SnCloudFileReferenceObject.FromProtoValue(file),
Pack = pack
};

View File

@@ -1,5 +1,5 @@
using DysonNetwork.Shared.Cache;
using DysonNetwork.Shared.Data;
using DysonNetwork.Shared.Models;
using DysonNetwork.Shared.Proto;
using Microsoft.EntityFrameworkCore;
@@ -33,7 +33,7 @@ public class StickerService(
return sticker;
}
public async Task<Sticker> UpdateStickerAsync(Sticker sticker, CloudFileReferenceObject? newImage)
public async Task<Sticker> UpdateStickerAsync(Sticker sticker, SnCloudFileReferenceObject? newImage)
{
if (newImage is not null)
{

View File

@@ -2,6 +2,7 @@ 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;
@@ -41,7 +42,7 @@ public class WebFeed : ModelBase
[Column(TypeName = "jsonb")] public WebFeedConfig Config { get; set; } = new();
public Guid PublisherId { get; set; }
public Publisher.Publisher Publisher { get; set; } = null!;
public Shared.Models.SnPublisher Publisher { get; set; } = null!;
[JsonIgnore] public ICollection<WebArticle> Articles { get; set; } = new List<WebArticle>();
}
@@ -53,5 +54,5 @@ public class WebFeedSubscription : ModelBase
public Guid FeedId { get; set; }
public WebFeed Feed { get; set; } = null!;
public Guid AccountId { get; set; }
[NotMapped] public AccountReference Account { get; set; } = null!;
[NotMapped] public SnAccount Account { get; set; } = null!;
}

View File

@@ -52,7 +52,7 @@ public class WebFeedController(WebFeedService webFeed, Publisher.PublisherServic
if (publisher is null) return NotFound();
var accountId = Guid.Parse(currentUser.Id);
if (!await ps.IsMemberWithRole(publisher.Id, accountId, Publisher.PublisherMemberRole.Editor))
if (!await ps.IsMemberWithRole(publisher.Id, accountId, Shared.Models.PublisherMemberRole.Editor))
return StatusCode(403, "You must be an editor of the publisher to create a web feed");
var feed = await webFeed.CreateWebFeedAsync(publisher, request);
@@ -69,7 +69,7 @@ public class WebFeedController(WebFeedService webFeed, Publisher.PublisherServic
if (publisher is null) return NotFound();
var accountId = Guid.Parse(currentUser.Id);
if (!await ps.IsMemberWithRole(publisher.Id, accountId, Publisher.PublisherMemberRole.Editor))
if (!await ps.IsMemberWithRole(publisher.Id, accountId, Shared.Models.PublisherMemberRole.Editor))
return StatusCode(403, "You must be an editor of the publisher to update a web feed");
var feed = await webFeed.GetFeedAsync(id, publisherId: publisher.Id);
@@ -90,7 +90,7 @@ public class WebFeedController(WebFeedService webFeed, Publisher.PublisherServic
if (publisher is null) return NotFound();
var accountId = Guid.Parse(currentUser.Id);
if (!await ps.IsMemberWithRole(publisher.Id, accountId, Publisher.PublisherMemberRole.Editor))
if (!await ps.IsMemberWithRole(publisher.Id, accountId, Shared.Models.PublisherMemberRole.Editor))
return StatusCode(403, "You must be an editor of the publisher to delete a web feed");
var feed = await webFeed.GetFeedAsync(id, publisherId: publisher.Id);
@@ -113,7 +113,7 @@ public class WebFeedController(WebFeedService webFeed, Publisher.PublisherServic
if (publisher is null) return NotFound();
var accountId = Guid.Parse(currentUser.Id);
if (!await ps.IsMemberWithRole(publisher.Id, accountId, Publisher.PublisherMemberRole.Editor))
if (!await ps.IsMemberWithRole(publisher.Id, accountId, Shared.Models.PublisherMemberRole.Editor))
return StatusCode(403, "You must be an editor of the publisher to scrape a web feed");
var feed = await webFeed.GetFeedAsync(id, publisherId: publisher.Id);

View File

@@ -11,7 +11,7 @@ public class WebFeedService(
WebReaderService webReaderService
)
{
public async Task<WebFeed> CreateWebFeedAsync(Publisher.Publisher publisher,
public async Task<WebFeed> CreateWebFeedAsync(Shared.Models.SnPublisher publisher,
WebFeedController.WebFeedRequest request)
{
var feed = new WebFeed