183 lines
7.6 KiB
C#
183 lines
7.6 KiB
C#
using AutoMapper;
|
|
using IM_API.Dtos.Conversation;
|
|
using IM_API.Exceptions;
|
|
using IM_API.Interface.Services;
|
|
using IM_API.Models;
|
|
using IM_API.Tools;
|
|
using IM_API.VOs.Conversation;
|
|
using Microsoft.EntityFrameworkCore;
|
|
|
|
namespace IM_API.Services
|
|
{
|
|
public class ConversationService : IConversationService
|
|
{
|
|
private readonly ImContext _context;
|
|
private readonly IMapper _mapper;
|
|
public ConversationService(ImContext context, IMapper mapper)
|
|
{
|
|
_context = context;
|
|
_mapper = mapper;
|
|
}
|
|
#region 删除用户会话
|
|
public async Task<bool> ClearConversationsAsync(int userId)
|
|
{
|
|
await _context.Conversations.Where(x => x.UserId == userId).ExecuteDeleteAsync();
|
|
return true;
|
|
}
|
|
|
|
|
|
#endregion
|
|
#region 获取用户会话列表
|
|
public async Task<List<ConversationVo>> GetConversationsAsync(int userId)
|
|
{
|
|
// 1. 获取私聊会话
|
|
var privateList = await (from c in _context.Conversations
|
|
join f in _context.Friends on new { c.UserId, c.TargetId }
|
|
equals new { UserId = f.UserId, TargetId = f.FriendId }
|
|
join u in _context.Users on c.TargetId equals u.Id
|
|
where c.UserId == userId && c.ChatType == ChatType.PRIVATE
|
|
select new { c, u.Avatar, f.RemarkName })
|
|
.ToListAsync();
|
|
|
|
// 2. 获取群聊会话
|
|
var groupList = await (from c in _context.Conversations
|
|
join g in _context.Groups on c.TargetId equals g.Id
|
|
where c.UserId == userId && c.ChatType == ChatType.GROUP
|
|
select new { c, g.Avatar, g.Name,g.MaxSequenceId,g.LastMessage })
|
|
.ToListAsync();
|
|
|
|
var privateDtos = privateList.Select(x =>
|
|
{
|
|
var dto = _mapper.Map<ConversationVo>(x.c);
|
|
dto.TargetAvatar = x.Avatar;
|
|
dto.TargetName = x.RemarkName;
|
|
return dto;
|
|
});
|
|
|
|
var groupDtos = groupList.Select(x =>
|
|
{
|
|
var dto = _mapper.Map<ConversationVo>(x.c);
|
|
dto.TargetAvatar = x.Avatar;
|
|
dto.TargetName = x.Name;
|
|
dto.UnreadCount = (int)(x.MaxSequenceId - x.c.LastReadSequenceId ?? 0);
|
|
dto.LastSequenceId = x.MaxSequenceId;
|
|
dto.LastMessage = x.LastMessage;
|
|
return dto;
|
|
});
|
|
|
|
// 4. 合并并排序
|
|
return privateDtos.Concat(groupDtos)
|
|
.OrderByDescending(x => x.DateTime)
|
|
.ToList();
|
|
}
|
|
#endregion
|
|
#region 删除单个会话
|
|
public async Task<bool> DeleteConversationAsync(int conversationId)
|
|
{
|
|
var conversation = await _context.Conversations.FirstOrDefaultAsync(x => x.Id == conversationId);
|
|
if (conversation == null) throw new BaseException(CodeDefine.CONVERSATION_NOT_FOUND);
|
|
_context.Conversations.Remove(conversation);
|
|
await _context.SaveChangesAsync();
|
|
return true;
|
|
}
|
|
|
|
|
|
#endregion
|
|
#region 获取用户所有统一聊天凭证
|
|
public async Task<List<string>> GetUserAllStreamKeyAsync(int userId)
|
|
{
|
|
return await _context.Conversations.Where(x => x.UserId == userId)
|
|
.Select(x => x.StreamKey)
|
|
.Distinct()
|
|
.ToListAsync();
|
|
}
|
|
#endregion
|
|
|
|
#region 获取单个会话信息
|
|
public async Task<ConversationVo> GetConversationByIdAsync(int userId, int conversationId)
|
|
{
|
|
var conversation = await _context.Conversations
|
|
.FirstOrDefaultAsync(
|
|
x => x.UserId == userId && x.Id == conversationId
|
|
);
|
|
if (conversation is null) throw new BaseException(CodeDefine.CONVERSATION_NOT_FOUND);
|
|
var dto = _mapper.Map<ConversationVo>(conversation);
|
|
if(conversation.ChatType == ChatType.PRIVATE)
|
|
{
|
|
var friendInfo = await _context.Friends.Include(n => n.FriendNavigation).FirstOrDefaultAsync(
|
|
x => x.UserId == conversation.UserId && x.FriendId == conversation.TargetId
|
|
);
|
|
if (friendInfo is null) throw new BaseException(CodeDefine.FRIEND_RELATION_NOT_FOUND);
|
|
_mapper.Map(friendInfo,dto);
|
|
}
|
|
if(conversation.ChatType == ChatType.GROUP)
|
|
{
|
|
var groupInfo = await _context.Groups.FirstOrDefaultAsync(
|
|
x => x.Id == conversation.TargetId
|
|
);
|
|
if (groupInfo is null) throw new BaseException(CodeDefine.GROUP_NOT_FOUND);
|
|
_mapper.Map(groupInfo, dto);
|
|
}
|
|
return dto;
|
|
}
|
|
#endregion
|
|
|
|
public async Task<bool> ClearUnreadCountAsync(int userId, int conversationId)
|
|
{
|
|
var conversation = await _context.Conversations.FirstOrDefaultAsync(x => x.UserId == userId && x.Id == conversationId);
|
|
if (conversation is null) throw new BaseException(CodeDefine.CONVERSATION_NOT_FOUND);
|
|
var message = await _context.Messages
|
|
.Where(x => x.StreamKey == conversation.StreamKey)
|
|
.OrderByDescending(x => x.SequenceId)
|
|
.FirstOrDefaultAsync();
|
|
if(message != null)
|
|
{
|
|
conversation.UnreadCount = 0;
|
|
conversation.LastMessage = message.Content;
|
|
conversation.LastReadSequenceId = message.SequenceId;
|
|
conversation.LastMessageTime = message.Created;
|
|
_context.Conversations.Update(conversation);
|
|
await _context.SaveChangesAsync();
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
public async Task MakeConversationAsync(int userAId, int userBId, ChatType chatType)
|
|
{
|
|
var userAcExist = await _context.Conversations.AnyAsync(x => x.UserId == userAId && x.TargetId == userBId);
|
|
if (userAcExist) return;
|
|
var streamKey = chatType == ChatType.PRIVATE ?
|
|
StreamKeyBuilder.Private(userAId, userBId) : StreamKeyBuilder.Group(userBId);
|
|
var conversation = new Conversation()
|
|
{
|
|
ChatType = chatType,
|
|
LastMessage = "",
|
|
LastMessageTime = DateTime.Now,
|
|
LastReadSequenceId = null,
|
|
StreamKey = streamKey,
|
|
TargetId = userBId,
|
|
UnreadCount = 0,
|
|
UserId = userAId
|
|
|
|
};
|
|
_context.Conversations.Add(conversation);
|
|
await _context.SaveChangesAsync();
|
|
}
|
|
public async Task UpdateConversationAfterSentAsync(UpdateConversationDto dto)
|
|
{
|
|
var cList = await _context.Conversations.Where(x => x.StreamKey == dto.StreamKey).ToListAsync();
|
|
foreach(var c in cList)
|
|
{
|
|
bool isSender = dto.SenderId == c.UserId;
|
|
c.LastMessage = dto.LastMessage;
|
|
c.LastMessageTime = dto.DateTime;
|
|
c.LastReadSequenceId = isSender ? dto.LastSequenceId : c.LastReadSequenceId;
|
|
c.UnreadCount = isSender ? 0 : c.UnreadCount + 1;
|
|
}
|
|
_context.Conversations.UpdateRange(cList);
|
|
await _context.SaveChangesAsync();
|
|
}
|
|
}
|
|
} |