♻️ Move most of models to the Shared package
This commit is contained in:
		| @@ -1,5 +1,6 @@ | ||||
| using System.ComponentModel.DataAnnotations; | ||||
| using System.Text.RegularExpressions; | ||||
| using DysonNetwork.Shared.Models; | ||||
| using DysonNetwork.Sphere.Permission; | ||||
| using DysonNetwork.Sphere.Storage; | ||||
| using Microsoft.AspNetCore.Authorization; | ||||
| @@ -32,7 +33,7 @@ public partial class ChatController(AppDatabase db, ChatService cs, ChatRoomServ | ||||
|     [Authorize] | ||||
|     public async Task<ActionResult<Dictionary<Guid, ChatSummaryResponse>>> GetChatSummary() | ||||
|     { | ||||
|         if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized(); | ||||
|         if (HttpContext.Items["CurrentUser"] is not Shared.Models.Account currentUser) return Unauthorized(); | ||||
|  | ||||
|         var unreadMessages = await cs.CountUnreadMessageForUser(currentUser.Id); | ||||
|         var lastMessages = await cs.ListLastMessageForUser(currentUser.Id); | ||||
| @@ -65,7 +66,7 @@ public partial class ChatController(AppDatabase db, ChatService cs, ChatRoomServ | ||||
|     public async Task<ActionResult<List<Message>>> ListMessages(Guid roomId, [FromQuery] int offset, | ||||
|         [FromQuery] int take = 20) | ||||
|     { | ||||
|         var currentUser = HttpContext.Items["CurrentUser"] as Account.Account; | ||||
|         var currentUser = HttpContext.Items["CurrentUser"] as Shared.Models.Account; | ||||
|  | ||||
|         var room = await db.ChatRooms.FirstOrDefaultAsync(r => r.Id == roomId); | ||||
|         if (room is null) return NotFound(); | ||||
| @@ -102,7 +103,7 @@ public partial class ChatController(AppDatabase db, ChatService cs, ChatRoomServ | ||||
|     [HttpGet("{roomId:guid}/messages/{messageId:guid}")] | ||||
|     public async Task<ActionResult<Message>> GetMessage(Guid roomId, Guid messageId) | ||||
|     { | ||||
|         var currentUser = HttpContext.Items["CurrentUser"] as Account.Account; | ||||
|         var currentUser = HttpContext.Items["CurrentUser"] as Shared.Models.Account; | ||||
|  | ||||
|         var room = await db.ChatRooms.FirstOrDefaultAsync(r => r.Id == roomId); | ||||
|         if (room is null) return NotFound(); | ||||
| @@ -139,7 +140,7 @@ public partial class ChatController(AppDatabase db, ChatService cs, ChatRoomServ | ||||
|     [RequiredPermission("global", "chat.messages.create")] | ||||
|     public async Task<ActionResult> SendMessage([FromBody] SendMessageRequest request, Guid roomId) | ||||
|     { | ||||
|         if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized(); | ||||
|         if (HttpContext.Items["CurrentUser"] is not Shared.Models.Account currentUser) return Unauthorized(); | ||||
|  | ||||
|         request.Content = TextSanitizer.Sanitize(request.Content); | ||||
|         if (string.IsNullOrWhiteSpace(request.Content) && | ||||
| @@ -216,7 +217,7 @@ public partial class ChatController(AppDatabase db, ChatService cs, ChatRoomServ | ||||
|     [Authorize] | ||||
|     public async Task<ActionResult> UpdateMessage([FromBody] SendMessageRequest request, Guid roomId, Guid messageId) | ||||
|     { | ||||
|         if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized(); | ||||
|         if (HttpContext.Items["CurrentUser"] is not Shared.Models.Account currentUser) return Unauthorized(); | ||||
|  | ||||
|         request.Content = TextSanitizer.Sanitize(request.Content); | ||||
|  | ||||
| @@ -269,7 +270,7 @@ public partial class ChatController(AppDatabase db, ChatService cs, ChatRoomServ | ||||
|     [Authorize] | ||||
|     public async Task<ActionResult> DeleteMessage(Guid roomId, Guid messageId) | ||||
|     { | ||||
|         if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized(); | ||||
|         if (HttpContext.Items["CurrentUser"] is not Shared.Models.Account currentUser) return Unauthorized(); | ||||
|  | ||||
|         var message = await db.ChatMessages | ||||
|             .Include(m => m.Sender) | ||||
| @@ -295,7 +296,7 @@ public partial class ChatController(AppDatabase db, ChatService cs, ChatRoomServ | ||||
|     [HttpPost("{roomId:guid}/sync")] | ||||
|     public async Task<ActionResult<SyncResponse>> GetSyncData([FromBody] SyncRequest request, Guid roomId) | ||||
|     { | ||||
|         if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) | ||||
|         if (HttpContext.Items["CurrentUser"] is not Shared.Models.Account currentUser) | ||||
|             return Unauthorized(); | ||||
|  | ||||
|         var isMember = await db.ChatMembers | ||||
|   | ||||
| @@ -1,144 +0,0 @@ | ||||
| using System.ComponentModel.DataAnnotations; | ||||
| using System.ComponentModel.DataAnnotations.Schema; | ||||
| using System.Text.Json.Serialization; | ||||
| using DysonNetwork.Sphere.Storage; | ||||
| 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; } | ||||
|     public Account.Account 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? 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; } | ||||
|     public Account.Account 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 | ||||
|         }; | ||||
|     } | ||||
| } | ||||
| @@ -1,6 +1,7 @@ | ||||
| using Microsoft.AspNetCore.Mvc; | ||||
| using Microsoft.EntityFrameworkCore; | ||||
| using System.ComponentModel.DataAnnotations; | ||||
| using DysonNetwork.Shared.Models; | ||||
| using DysonNetwork.Sphere.Account; | ||||
| using DysonNetwork.Sphere.Localization; | ||||
| using DysonNetwork.Sphere.Permission; | ||||
| @@ -36,7 +37,7 @@ public class ChatRoomController( | ||||
|         if (chatRoom is null) return NotFound(); | ||||
|         if (chatRoom.Type != ChatRoomType.DirectMessage) return Ok(chatRoom); | ||||
|  | ||||
|         if (HttpContext.Items["CurrentUser"] is Account.Account currentUser) | ||||
|         if (HttpContext.Items["CurrentUser"] is Shared.Models.Account currentUser) | ||||
|             chatRoom = await crs.LoadDirectMessageMembers(chatRoom, currentUser.Id); | ||||
|  | ||||
|         return Ok(chatRoom); | ||||
| @@ -46,7 +47,7 @@ public class ChatRoomController( | ||||
|     [Authorize] | ||||
|     public async Task<ActionResult<List<ChatRoom>>> ListJoinedChatRooms() | ||||
|     { | ||||
|         if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) | ||||
|         if (HttpContext.Items["CurrentUser"] is not Shared.Models.Account currentUser) | ||||
|             return Unauthorized(); | ||||
|         var userId = currentUser.Id; | ||||
|  | ||||
| @@ -72,7 +73,7 @@ public class ChatRoomController( | ||||
|     [Authorize] | ||||
|     public async Task<ActionResult<ChatRoom>> CreateDirectMessage([FromBody] DirectMessageRequest request) | ||||
|     { | ||||
|         if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) | ||||
|         if (HttpContext.Items["CurrentUser"] is not Shared.Models.Account currentUser) | ||||
|             return Unauthorized(); | ||||
|  | ||||
|         var relatedUser = await db.Accounts.FindAsync(request.RelatedUserId); | ||||
| @@ -134,7 +135,7 @@ public class ChatRoomController( | ||||
|     [Authorize] | ||||
|     public async Task<ActionResult<ChatRoom>> GetDirectChatRoom(Guid userId) | ||||
|     { | ||||
|         if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) | ||||
|         if (HttpContext.Items["CurrentUser"] is not Shared.Models.Account currentUser) | ||||
|             return Unauthorized(); | ||||
|  | ||||
|         var room = await db.ChatRooms | ||||
| @@ -164,7 +165,7 @@ public class ChatRoomController( | ||||
|     [RequiredPermission("global", "chat.create")] | ||||
|     public async Task<ActionResult<ChatRoom>> CreateChatRoom(ChatRoomRequest request) | ||||
|     { | ||||
|         if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized(); | ||||
|         if (HttpContext.Items["CurrentUser"] is not Shared.Models.Account currentUser) return Unauthorized(); | ||||
|         if (request.Name is null) return BadRequest("You cannot create a chat room without a name."); | ||||
|  | ||||
|         var chatRoom = new ChatRoom | ||||
| @@ -236,7 +237,7 @@ public class ChatRoomController( | ||||
|     [HttpPatch("{id:guid}")] | ||||
|     public async Task<ActionResult<ChatRoom>> UpdateChatRoom(Guid id, [FromBody] ChatRoomRequest request) | ||||
|     { | ||||
|         if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized(); | ||||
|         if (HttpContext.Items["CurrentUser"] is not Shared.Models.Account currentUser) return Unauthorized(); | ||||
|  | ||||
|         var chatRoom = await db.ChatRooms | ||||
|             .Where(e => e.Id == id) | ||||
| @@ -321,7 +322,7 @@ public class ChatRoomController( | ||||
|     [HttpDelete("{id:guid}")] | ||||
|     public async Task<ActionResult> DeleteChatRoom(Guid id) | ||||
|     { | ||||
|         if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized(); | ||||
|         if (HttpContext.Items["CurrentUser"] is not Shared.Models.Account currentUser) return Unauthorized(); | ||||
|  | ||||
|         var chatRoom = await db.ChatRooms | ||||
|             .Where(e => e.Id == id) | ||||
| @@ -356,7 +357,7 @@ public class ChatRoomController( | ||||
|     [Authorize] | ||||
|     public async Task<ActionResult<ChatMember>> GetRoomIdentity(Guid roomId) | ||||
|     { | ||||
|         if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) | ||||
|         if (HttpContext.Items["CurrentUser"] is not Shared.Models.Account currentUser) | ||||
|             return Unauthorized(); | ||||
|  | ||||
|         var member = await db.ChatMembers | ||||
| @@ -375,7 +376,7 @@ public class ChatRoomController( | ||||
|     public async Task<ActionResult<List<ChatMember>>> ListMembers(Guid roomId, [FromQuery] int take = 20, | ||||
|         [FromQuery] int skip = 0, [FromQuery] bool withStatus = false, [FromQuery] string? status = null) | ||||
|     { | ||||
|         var currentUser = HttpContext.Items["CurrentUser"] as Account.Account; | ||||
|         var currentUser = HttpContext.Items["CurrentUser"] as Shared.Models.Account; | ||||
|  | ||||
|         var room = await db.ChatRooms | ||||
|             .FirstOrDefaultAsync(r => r.Id == roomId); | ||||
| @@ -448,7 +449,7 @@ public class ChatRoomController( | ||||
|     public async Task<ActionResult<ChatMember>> InviteMember(Guid roomId, | ||||
|         [FromBody] ChatMemberRequest request) | ||||
|     { | ||||
|         if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized(); | ||||
|         if (HttpContext.Items["CurrentUser"] is not Shared.Models.Account currentUser) return Unauthorized(); | ||||
|         var userId = currentUser.Id; | ||||
|  | ||||
|         var relatedUser = await db.Accounts.FindAsync(request.RelatedUserId); | ||||
| @@ -519,7 +520,7 @@ public class ChatRoomController( | ||||
|     [Authorize] | ||||
|     public async Task<ActionResult<List<ChatMember>>> ListChatInvites() | ||||
|     { | ||||
|         if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized(); | ||||
|         if (HttpContext.Items["CurrentUser"] is not Shared.Models.Account currentUser) return Unauthorized(); | ||||
|         var userId = currentUser.Id; | ||||
|  | ||||
|         var members = await db.ChatMembers | ||||
| @@ -544,7 +545,7 @@ public class ChatRoomController( | ||||
|     [Authorize] | ||||
|     public async Task<ActionResult<ChatRoom>> AcceptChatInvite(Guid roomId) | ||||
|     { | ||||
|         if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized(); | ||||
|         if (HttpContext.Items["CurrentUser"] is not Shared.Models.Account currentUser) return Unauthorized(); | ||||
|         var userId = currentUser.Id; | ||||
|  | ||||
|         var member = await db.ChatMembers | ||||
| @@ -571,7 +572,7 @@ public class ChatRoomController( | ||||
|     [Authorize] | ||||
|     public async Task<ActionResult> DeclineChatInvite(Guid roomId) | ||||
|     { | ||||
|         if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized(); | ||||
|         if (HttpContext.Items["CurrentUser"] is not Shared.Models.Account currentUser) return Unauthorized(); | ||||
|         var userId = currentUser.Id; | ||||
|  | ||||
|         var member = await db.ChatMembers | ||||
| @@ -600,7 +601,7 @@ public class ChatRoomController( | ||||
|         [FromBody] ChatMemberNotifyRequest request | ||||
|     ) | ||||
|     { | ||||
|         if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized(); | ||||
|         if (HttpContext.Items["CurrentUser"] is not Shared.Models.Account currentUser) return Unauthorized(); | ||||
|  | ||||
|         var chatRoom = await db.ChatRooms | ||||
|             .Where(r => r.Id == roomId) | ||||
| @@ -629,7 +630,7 @@ public class ChatRoomController( | ||||
|     public async Task<ActionResult<ChatMember>> 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.Account currentUser) return Unauthorized(); | ||||
|         if (HttpContext.Items["CurrentUser"] is not Shared.Models.Account currentUser) return Unauthorized(); | ||||
|  | ||||
|         var chatRoom = await db.ChatRooms | ||||
|             .Where(r => r.Id == roomId) | ||||
| @@ -688,7 +689,7 @@ public class ChatRoomController( | ||||
|     [Authorize] | ||||
|     public async Task<ActionResult> RemoveChatMember(Guid roomId, Guid memberId) | ||||
|     { | ||||
|         if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized(); | ||||
|         if (HttpContext.Items["CurrentUser"] is not Shared.Models.Account currentUser) return Unauthorized(); | ||||
|  | ||||
|         var chatRoom = await db.ChatRooms | ||||
|             .Where(r => r.Id == roomId) | ||||
| @@ -736,7 +737,7 @@ public class ChatRoomController( | ||||
|     [Authorize] | ||||
|     public async Task<ActionResult<ChatRoom>> JoinChatRoom(Guid roomId) | ||||
|     { | ||||
|         if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized(); | ||||
|         if (HttpContext.Items["CurrentUser"] is not Shared.Models.Account currentUser) return Unauthorized(); | ||||
|  | ||||
|         var chatRoom = await db.ChatRooms | ||||
|             .Where(r => r.Id == roomId) | ||||
| @@ -774,7 +775,7 @@ public class ChatRoomController( | ||||
|     [Authorize] | ||||
|     public async Task<ActionResult> LeaveChat(Guid roomId) | ||||
|     { | ||||
|         if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized(); | ||||
|         if (HttpContext.Items["CurrentUser"] is not Shared.Models.Account currentUser) return Unauthorized(); | ||||
|  | ||||
|         var member = await db.ChatMembers | ||||
|             .Where(m => m.AccountId == currentUser.Id) | ||||
| @@ -807,7 +808,7 @@ public class ChatRoomController( | ||||
|         return NoContent(); | ||||
|     } | ||||
|  | ||||
|     private async Task _SendInviteNotify(ChatMember member, Account.Account sender) | ||||
|     private async Task _SendInviteNotify(ChatMember member, Shared.Models.Account sender) | ||||
|     { | ||||
|         string title = localizer["ChatInviteTitle"]; | ||||
|  | ||||
|   | ||||
| @@ -1,3 +1,4 @@ | ||||
| using DysonNetwork.Shared.Models; | ||||
| using DysonNetwork.Sphere.Storage; | ||||
| using Microsoft.EntityFrameworkCore; | ||||
| using NodaTime; | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| using System.Text.RegularExpressions; | ||||
| using DysonNetwork.Shared.Models; | ||||
| using DysonNetwork.Sphere.Account; | ||||
| using DysonNetwork.Sphere.Chat.Realtime; | ||||
| using DysonNetwork.Sphere.Connection; | ||||
| @@ -241,7 +242,7 @@ public partial class ChatService( | ||||
|             Priority = 10, | ||||
|         }; | ||||
|  | ||||
|         List<Account.Account> accountsToNotify = []; | ||||
|         List<Shared.Models.Account> accountsToNotify = []; | ||||
|         foreach (var member in members) | ||||
|         { | ||||
|             scopedWs.SendPacketToAccount(member.AccountId, new WebSocketPacket | ||||
|   | ||||
| @@ -1,67 +0,0 @@ | ||||
| using System.ComponentModel.DataAnnotations; | ||||
| using System.ComponentModel.DataAnnotations.Schema; | ||||
| using System.Text.Json.Serialization; | ||||
| using DysonNetwork.Sphere.Storage; | ||||
| using Microsoft.EntityFrameworkCore; | ||||
| 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; } = [];  | ||||
|  | ||||
|     // Outdated fields, keep for backward compability | ||||
|     public ICollection<CloudFile> OutdatedAttachments { get; set; } = new List<CloudFile>(); | ||||
|     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}"; | ||||
| } | ||||
|  | ||||
| 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; } | ||||
| } | ||||
|  | ||||
| /// <summary> | ||||
| /// The data model for updating the last read at field for chat member, | ||||
| /// after the refactor of the unread system, this no longer stored in the database. | ||||
| /// Not only used for the data transmission object | ||||
| /// </summary> | ||||
| [NotMapped] | ||||
| public class MessageReadReceipt | ||||
| { | ||||
|     public Guid SenderId { get; set; } | ||||
| } | ||||
| @@ -36,7 +36,7 @@ public interface IRealtimeService | ||||
|     /// <param name="sessionId">The session identifier</param> | ||||
|     /// <param name="isAdmin">The user is the admin of session</param> | ||||
|     /// <returns>User-specific token for the session</returns> | ||||
|     string GetUserToken(Account.Account account, string sessionId, bool isAdmin = false); | ||||
|     string GetUserToken(Shared.Models.Account account, string sessionId, bool isAdmin = false); | ||||
|      | ||||
|     /// <summary> | ||||
|     /// Processes incoming webhook requests from the realtime service provider | ||||
|   | ||||
| @@ -4,6 +4,7 @@ using Livekit.Server.Sdk.Dotnet; | ||||
| using Microsoft.EntityFrameworkCore; | ||||
| using NodaTime; | ||||
| using System.Text.Json; | ||||
| using DysonNetwork.Shared.Models; | ||||
|  | ||||
| namespace DysonNetwork.Sphere.Chat.Realtime; | ||||
|  | ||||
| @@ -111,7 +112,7 @@ public class LivekitRealtimeService : IRealtimeService | ||||
|     } | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public string GetUserToken(Account.Account account, string sessionId, bool isAdmin = false) | ||||
|     public string GetUserToken(Shared.Models.Account account, string sessionId, bool isAdmin = false) | ||||
|     { | ||||
|         var token = _accessToken.WithIdentity(account.Name) | ||||
|             .WithName(account.Nick) | ||||
|   | ||||
| @@ -1,50 +0,0 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.ComponentModel.DataAnnotations.Schema; | ||||
| using System.Text.Json; | ||||
| using System.Text.Json.Serialization; | ||||
| 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; | ||||
|     } | ||||
| } | ||||
| @@ -1,3 +1,4 @@ | ||||
| using DysonNetwork.Shared.Models; | ||||
| using DysonNetwork.Sphere.Chat.Realtime; | ||||
| using Livekit.Server.Sdk.Dotnet; | ||||
| using Microsoft.AspNetCore.Authorization; | ||||
| @@ -46,7 +47,7 @@ public class RealtimeCallController( | ||||
|     [Authorize] | ||||
|     public async Task<ActionResult<RealtimeCall>> GetOngoingCall(Guid roomId) | ||||
|     { | ||||
|         if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized(); | ||||
|         if (HttpContext.Items["CurrentUser"] is not Shared.Models.Account currentUser) return Unauthorized(); | ||||
|  | ||||
|         var member = await db.ChatMembers | ||||
|             .Where(m => m.AccountId == currentUser.Id && m.ChatRoomId == roomId) | ||||
| @@ -71,7 +72,7 @@ public class RealtimeCallController( | ||||
|     [Authorize] | ||||
|     public async Task<ActionResult<JoinCallResponse>> JoinCall(Guid roomId) | ||||
|     { | ||||
|         if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized(); | ||||
|         if (HttpContext.Items["CurrentUser"] is not Shared.Models.Account currentUser) return Unauthorized(); | ||||
|  | ||||
|         // Check if the user is a member of the chat room | ||||
|         var member = await db.ChatMembers | ||||
| @@ -144,7 +145,7 @@ public class RealtimeCallController( | ||||
|     [Authorize] | ||||
|     public async Task<ActionResult<RealtimeCall>> StartCall(Guid roomId) | ||||
|     { | ||||
|         if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized(); | ||||
|         if (HttpContext.Items["CurrentUser"] is not Shared.Models.Account currentUser) return Unauthorized(); | ||||
|  | ||||
|         var member = await db.ChatMembers | ||||
|             .Where(m => m.AccountId == currentUser.Id && m.ChatRoomId == roomId) | ||||
| @@ -163,7 +164,7 @@ public class RealtimeCallController( | ||||
|     [Authorize] | ||||
|     public async Task<ActionResult<RealtimeCall>> EndCall(Guid roomId) | ||||
|     { | ||||
|         if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized(); | ||||
|         if (HttpContext.Items["CurrentUser"] is not Shared.Models.Account currentUser) return Unauthorized(); | ||||
|  | ||||
|         var member = await db.ChatMembers | ||||
|             .Where(m => m.AccountId == currentUser.Id && m.ChatRoomId == roomId) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user