Direct messages

This commit is contained in:
LittleSheep 2025-05-04 15:09:44 +08:00
parent d0a92bc8b3
commit 573f984e2c
3 changed files with 96 additions and 11 deletions

View File

@ -43,7 +43,7 @@ public partial class ChatController(AppDatabase db, ChatService cs) : Controller
var member = await db.ChatMembers
.Where(m => m.AccountId == currentUser.Id && m.ChatRoomId == roomId)
.FirstOrDefaultAsync();
if (member == null || member.Role < ChatMemberRole.Normal)
if (member == null || member.Role < ChatMemberRole.Member)
return StatusCode(403, "You are not a member of this chat room.");
}
@ -81,7 +81,7 @@ public partial class ChatController(AppDatabase db, ChatService cs) : Controller
var member = await db.ChatMembers
.Where(m => m.AccountId == currentUser.Id && m.ChatRoomId == roomId)
.FirstOrDefaultAsync();
if (member == null || member.Role < ChatMemberRole.Normal)
if (member == null || member.Role < ChatMemberRole.Member)
return StatusCode(403, "You are not a member of this chat room.");
}
@ -118,7 +118,7 @@ public partial class ChatController(AppDatabase db, ChatService cs) : Controller
.Include(m => m.Account)
.Include(m => m.Account.Profile)
.FirstOrDefaultAsync();
if (member == null || member.Role < ChatMemberRole.Normal) return StatusCode(403, "You need to be a normal member to send messages here.");
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
{

View File

@ -34,7 +34,7 @@ public enum ChatMemberRole
{
Owner = 100,
Moderator = 50,
Normal = 0
Member = 0
}
public enum ChatMemberNotify
@ -54,7 +54,7 @@ public class ChatMember : ModelBase
[MaxLength(1024)] public string? Nick { get; set; }
public ChatMemberRole Role { get; set; } = ChatMemberRole.Normal;
public ChatMemberRole Role { get; set; } = ChatMemberRole.Member;
public ChatMemberNotify Notify { get; set; } = ChatMemberNotify.All;
public Instant? JoinedAt { get; set; }
public bool IsBot { get; set; } = false;

View File

@ -26,19 +26,102 @@ public class ChatRoomController(AppDatabase db, FileService fs, ChatRoomService
[HttpGet]
public async Task<ActionResult<List<ChatRoom>>> ListJoinedChatRooms()
{
if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized();
if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser)
return Unauthorized();
var userId = currentUser.Id;
var members = await db.ChatMembers
var chatRooms = await db.ChatMembers
.Where(m => m.AccountId == userId)
.Where(m => m.JoinedAt != null)
.Include(e => e.ChatRoom)
.Include(m => m.ChatRoom)
.Select(m => m.ChatRoom)
.ToListAsync();
return members.ToList();
var directRoomsId = chatRooms
.Where(r => r.Type == ChatRoomType.DirectMessage)
.Select(r => r.Id)
.ToList();
var directMembers = directRoomsId.Count != 0
? await db.ChatMembers
.Where(m => directRoomsId.Contains(m.ChatRoomId))
.Where(m => m.AccountId != userId)
.Include(m => m.Account)
.Include(m => m.Account.Profile)
.ToDictionaryAsync(m => m.ChatRoomId, m => m)
: new Dictionary<long, ChatMember>();
// Map the results
var result = chatRooms.Select(r =>
{
if (r.Type == ChatRoomType.DirectMessage && directMembers.TryGetValue(r.Id, out var otherMember))
r.Members = new List<ChatMember> { otherMember };
return r;
}).ToList();
return Ok(result);
}
public class DmCreationRequest
{
[Required] public long RelatedUserId { get; set; }
}
[HttpPost("direct")]
[Authorize]
public async Task<ActionResult<ChatRoom>> CreateDirectMessage([FromBody] DmCreationRequest request)
{
if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser)
return Unauthorized();
var relatedUser = await db.Accounts.FindAsync(request.RelatedUserId);
if (relatedUser is null)
return BadRequest("Related user was not found");
// Check if DM already exists between these users
var existingDm = await db.ChatRooms
.Include(c => c.Members)
.Where(c => c.Type == ChatRoomType.DirectMessage && c.Members.Count == 2)
.Where(c => c.Members.Any(m => m.AccountId == currentUser.Id))
.Where(c => c.Members.Any(m => m.AccountId == request.RelatedUserId))
.FirstOrDefaultAsync();
if (existingDm != null)
return Ok(existingDm); // Return existing DM if found
// Create new DM chat room
var dmRoom = new ChatRoom
{
Name = $"DM between #{currentUser.Id} and #{request.RelatedUserId}",
Type = ChatRoomType.DirectMessage,
IsPublic = false,
Members = new List<ChatMember>
{
new()
{
AccountId = currentUser.Id,
Role = ChatMemberRole.Owner,
JoinedAt = NodaTime.Instant.FromDateTimeUtc(DateTime.UtcNow)
},
new()
{
AccountId = request.RelatedUserId,
Role = ChatMemberRole.Member,
JoinedAt = null, // Pending status
}
}
};
db.ChatRooms.Add(dmRoom);
await db.SaveChangesAsync();
var invitedMember = dmRoom.Members.First(m => m.AccountId == request.RelatedUserId);
await crs.SendInviteNotify(invitedMember);
return Ok(dmRoom);
}
public class ChatRoomRequest
{
[Required] [MaxLength(1024)] public string? Name { get; set; }
@ -60,6 +143,7 @@ public class ChatRoomController(AppDatabase db, FileService fs, ChatRoomService
{
Name = request.Name,
Description = request.Description ?? string.Empty,
Type = ChatRoomType.Group,
Members = new List<ChatMember>
{
new()
@ -106,6 +190,7 @@ public class ChatRoomController(AppDatabase db, FileService fs, ChatRoomService
return Ok(chatRoom);
}
[HttpPatch("{id:long}")]
public async Task<ActionResult<ChatRoom>> UpdateChatRoom(long id, [FromBody] ChatRoomRequest request)
{
@ -395,7 +480,7 @@ public class ChatRoomController(AppDatabase db, FileService fs, ChatRoomService
[HttpPatch("{roomId:long}/members/{memberId:long}/role")]
[Authorize]
public async Task<ActionResult<ChatMember>> UpdateChatMemberRole(long roomId, long memberId,
public async Task<ActionResult<ChatMember>> UpdateChatMemberRole(long roomId, long memberId,
[FromBody] ChatMemberRequest request)
{
if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized();
@ -515,7 +600,7 @@ public class ChatRoomController(AppDatabase db, FileService fs, ChatRoomService
.Where(m => m.Role == ChatMemberRole.Owner)
.Where(m => m.AccountId != currentUser.Id)
.AnyAsync();
if (!otherOwners)
return BadRequest("The last owner cannot leave the chat. Transfer ownership first or delete the chat.");
}