🗃️ Add nonce column to chat messages and fix column typo
This migration adds a new "nonce" column to the "chat_messages" table to ensure message uniqueness or integrity. Additionally, it corrects a typo in the "members_mentioned" column name to improve consistency and clarity.
This commit is contained in:
@ -1,6 +1,7 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Text.RegularExpressions;
|
||||
using DysonNetwork.Sphere.Storage;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
@ -19,17 +20,75 @@ public partial class ChatController(AppDatabase db, ChatService cs) : Controller
|
||||
public class SendMessageRequest
|
||||
{
|
||||
[MaxLength(4096)] public string? Content { get; set; }
|
||||
public List<CloudFile>? Attachments { get; set; }
|
||||
[MaxLength(36)] public string? Nonce { get; set; }
|
||||
public List<string>? AttachmentsId { get; set; }
|
||||
public Dictionary<string, object>? Meta { get; set; }
|
||||
}
|
||||
|
||||
[HttpGet("{roomId:long}/members/me")]
|
||||
[Authorize]
|
||||
public async Task<ActionResult<ChatMember>> GetCurrentIdentity(long roomId)
|
||||
{
|
||||
if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser)
|
||||
return Unauthorized();
|
||||
|
||||
var member = await db.ChatMembers
|
||||
.Where(m => m.AccountId == currentUser.Id && m.ChatRoomId == roomId)
|
||||
.Include(m => m.Account)
|
||||
.FirstOrDefaultAsync();
|
||||
|
||||
if (member == null)
|
||||
return NotFound();
|
||||
|
||||
return Ok(member);
|
||||
}
|
||||
|
||||
[HttpGet("{roomId:long}/messages")]
|
||||
public async Task<ActionResult<List<Message>>> ListMessages(long roomId, [FromQuery] int offset, [FromQuery] int take = 20)
|
||||
{
|
||||
var currentUser = HttpContext.Items["CurrentUser"] as Account.Account;
|
||||
|
||||
var room = await db.ChatRooms.FirstOrDefaultAsync(r => r.Id == roomId);
|
||||
if (room is null) return NotFound();
|
||||
|
||||
if (!room.IsPublic)
|
||||
{
|
||||
if (currentUser is null) return Unauthorized();
|
||||
|
||||
var member = await db.ChatMembers
|
||||
.Where(m => m.AccountId == currentUser.Id && m.ChatRoomId == roomId)
|
||||
.FirstOrDefaultAsync();
|
||||
if (member == null || member.Role < ChatMemberRole.Normal)
|
||||
return StatusCode(403, "You are not a member of this chat room.");
|
||||
}
|
||||
|
||||
var totalCount = await db.ChatMessages
|
||||
.Where(m => m.ChatRoomId == roomId)
|
||||
.CountAsync();
|
||||
var messages = await db.ChatMessages
|
||||
.Where(m => m.ChatRoomId == roomId)
|
||||
.OrderByDescending(m => m.CreatedAt)
|
||||
.Include(m => m.Sender)
|
||||
.Include(m => m.Sender.Account)
|
||||
.Include(m => m.Attachments)
|
||||
.Skip(offset)
|
||||
.Take(take)
|
||||
.ToListAsync();
|
||||
|
||||
Response.Headers["X-Total"] = totalCount.ToString();
|
||||
|
||||
return Ok(messages);
|
||||
}
|
||||
|
||||
[GeneratedRegex(@"@([A-Za-z0-9_-]+)")]
|
||||
private static partial Regex MentionRegex();
|
||||
|
||||
[HttpPost("{roomId:long}/messages")]
|
||||
[Authorize]
|
||||
public async Task<ActionResult> SendMessage([FromBody] SendMessageRequest request, long roomId)
|
||||
{
|
||||
if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized();
|
||||
if (string.IsNullOrWhiteSpace(request.Content) && (request.Attachments == null || request.Attachments.Count == 0))
|
||||
if (string.IsNullOrWhiteSpace(request.Content) && (request.AttachmentsId == null || request.AttachmentsId.Count == 0))
|
||||
return BadRequest("You cannot send an empty message.");
|
||||
|
||||
var member = await db.ChatMembers
|
||||
@ -38,16 +97,27 @@ public partial class ChatController(AppDatabase db, ChatService cs) : Controller
|
||||
.Include(m => m.ChatRoom.Realm)
|
||||
.FirstOrDefaultAsync();
|
||||
if (member == null || member.Role < ChatMemberRole.Normal) return StatusCode(403, "You need to be a normal member to send messages here.");
|
||||
currentUser.Profile = null;
|
||||
member.Account = currentUser;
|
||||
|
||||
var message = new Message
|
||||
{
|
||||
SenderId = member.Id,
|
||||
ChatRoomId = roomId,
|
||||
Nonce = request.Nonce ?? Guid.NewGuid().ToString(),
|
||||
Meta = request.Meta ?? new Dictionary<string, object>(),
|
||||
};
|
||||
if (request.Content is not null)
|
||||
message.Content = request.Content;
|
||||
if (request.Attachments is not null)
|
||||
message.Attachments = request.Attachments;
|
||||
if (request.AttachmentsId is not null)
|
||||
{
|
||||
var attachments = await db.Files
|
||||
.Where(f => request.AttachmentsId.Contains(f.Id))
|
||||
.ToListAsync();
|
||||
message.Attachments = attachments
|
||||
.OrderBy(f => request.AttachmentsId.IndexOf(f.Id))
|
||||
.ToList();
|
||||
}
|
||||
|
||||
if (request.Content is not null)
|
||||
{
|
||||
@ -55,17 +125,16 @@ public partial class ChatController(AppDatabase db, ChatService cs) : Controller
|
||||
.Matches(request.Content)
|
||||
.Select(m => m.Groups[1].Value)
|
||||
.ToList();
|
||||
if (mentioned is not null && mentioned.Count > 0)
|
||||
if (mentioned.Count > 0)
|
||||
{
|
||||
var mentionedMembers = await db.ChatMembers
|
||||
.Where(m => mentioned.Contains(m.Account.Name))
|
||||
.Select(m => m.Id)
|
||||
.ToListAsync();
|
||||
message.MembersMetioned = mentionedMembers;
|
||||
message.MembersMentioned = mentionedMembers;
|
||||
}
|
||||
}
|
||||
|
||||
member.Account = currentUser;
|
||||
var result = await cs.SendMessageAsync(message, member, member.ChatRoom);
|
||||
|
||||
return Ok(result);
|
||||
@ -78,9 +147,9 @@ public partial class ChatController(AppDatabase db, ChatService cs) : Controller
|
||||
}
|
||||
|
||||
[HttpGet("{roomId:long}/sync")]
|
||||
public async Task<ActionResult<SyncResponse>> GetSyncData([FromQuery] SyncRequest request, long roomId)
|
||||
public async Task<ActionResult<SyncResponse>> GetSyncData([FromBody] SyncRequest request, long roomId)
|
||||
{
|
||||
if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser)
|
||||
if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser)
|
||||
return Unauthorized();
|
||||
|
||||
var isMember = await db.ChatMembers
|
||||
|
Reference in New Issue
Block a user