using AutoMapper; using AutoMapper.QueryableExtensions; using IM_API.Domain.Events; using IM_API.Dtos.Group; using IM_API.Exceptions; using IM_API.Interface.Services; using IM_API.Models; using IM_API.Tools; using MassTransit; using Microsoft.EntityFrameworkCore; using System; namespace IM_API.Services { public class GroupService : IGroupService { private readonly ImContext _context; private readonly IMapper _mapper; private readonly ILogger _logger; private readonly IPublishEndpoint _endPoint; private readonly IUserService _userService; public GroupService(ImContext context, IMapper mapper, ILogger logger, IPublishEndpoint publishEndpoint, IUserService userService) { _context = context; _mapper = mapper; _logger = logger; _endPoint = publishEndpoint; _userService = userService; } private async Task> validFriendshipAsync (int userId, List ids) { DateTime dateTime = DateTime.UtcNow; //验证被邀请用户是否为好友 return await _context.Friends .Where(f => f.UserId == userId && ids.Contains(f.FriendId)) .Select(f => f.FriendId) .ToListAsync(); } public async Task CreateGroupAsync(int userId, GroupCreateDto groupCreateDto) { List userIds = groupCreateDto.UserIDs ?? []; using var transaction = await _context.Database.BeginTransactionAsync(); try { //先创建群 DateTime dateTime = DateTime.Now; Group group = _mapper.Map(groupCreateDto); group.GroupMaster = userId; _context.Groups.Add(group); await _context.SaveChangesAsync(); if (userIds.Count > 0) { //邀请好友 await InviteUsersAsync(userId, group.Id ,userIds); } await transaction.CommitAsync(); await _endPoint.Publish(new GroupJoinEvent { EventId = Guid.NewGuid(), AggregateId = userId.ToString(), GroupId = group.Id, OccurredAt = dateTime, OperatorId = userId, UserId = userId, IsCreated = true }); return _mapper.Map(group); } catch { await transaction.RollbackAsync(); throw; } } public Task DeleteGroupAsync(int userId, int groupId) { throw new NotImplementedException(); } public async Task InviteUsersAsync(int userId, int groupId, List userIds) { var group = await _context.Groups.FirstOrDefaultAsync( x => x.Id == groupId) ?? throw new BaseException(CodeDefine.GROUP_NOT_FOUND); //过滤非好友 var groupInviteIds = await validFriendshipAsync(userId, userIds); var inviteList = groupInviteIds.Select(id => new GroupInvite { Created = DateTime.UtcNow, GroupId = group.Id, InviteUser = userId, InvitedUser = id, StateEnum = GroupInviteState.Pending }).ToList(); _context.GroupInvites.AddRange(inviteList); await _context.SaveChangesAsync(); await _endPoint.Publish(new GroupInviteEvent { GroupId = groupId, AggregateId = userId.ToString(), OccurredAt = DateTime.UtcNow, EventId = Guid.NewGuid(), Ids = userIds, OperatorId = userId, UserId = userId }); } public async Task MakeGroupMemberAsync(int userId, int groupId ,GroupMemberRole? role) { var isExist = await _context.GroupMembers.AnyAsync(x => x.GroupId == groupId && x.UserId == userId); if (isExist) return; var groupMember = new GroupMember { UserId = userId, Created = DateTime.UtcNow, RoleEnum = role ?? GroupMemberRole.Normal, GroupId = groupId }; _context.GroupMembers.Add(groupMember); await _context.SaveChangesAsync(); } public Task JoinGroupAsync(int userId, int groupId) { throw new NotImplementedException(); } public async Task> GetGroupListAsync(int userId, int page, int limit, bool desc) { var query = _context.GroupMembers .Where(x => x.UserId == userId) .Select(s => s.Group); if (desc) { query = query.OrderByDescending(x => x.Id); } var list = await query .Skip((page - 1) * limit) .Take(limit) .ProjectTo(_mapper.ConfigurationProvider) .ToListAsync(); return list; } public async Task UpdateGroupConversationAsync(GroupUpdateConversationDto dto) { var group = await _context.Groups.FirstOrDefaultAsync(x => x.Id == dto.GroupId); if (group is null) return; group.LastMessage = dto.LastMessage; group.MaxSequenceId = dto.MaxSequenceId; group.LastSenderName = dto.LastSenderName; group.LastUpdateTime = dto.LastUpdateTime; _context.Groups.Update(group); await _context.SaveChangesAsync(); } public async Task HandleGroupInviteAsync(int userid, HandleGroupInviteDto dto) { var user = _userService.GetUserInfoAsync(userid); var inviteInfo = await _context.GroupInvites.FirstOrDefaultAsync(x => x.Id == dto.InviteId) ?? throw new BaseException(CodeDefine.INVALID_ACTION); if (inviteInfo.InvitedUser != userid) throw new BaseException(CodeDefine.AUTH_FAILED); inviteInfo.StateEnum = dto.Action; _context.GroupInvites.Update(inviteInfo); await _context.SaveChangesAsync(); await _endPoint.Publish(new GroupInviteActionUpdateEvent { Action = dto.Action, AggregateId = userid.ToString(), OccurredAt = DateTime.UtcNow, EventId = Guid.NewGuid(), GroupId = inviteInfo.GroupId, InviteId = inviteInfo.Id, InviteUserId = inviteInfo.InviteUser.Value, OperatorId = userid, UserId = userid }); } public async Task HandleGroupRequestAsync(int userid, HandleGroupRequestDto dto) { var user = _userService.GetUserInfoAsync(userid); //判断请求存在 var requestInfo = await _context.GroupRequests.FirstOrDefaultAsync(x => x.Id == dto.RequestId) ?? throw new BaseException(CodeDefine.INVALID_ACTION); //判断成员存在 var memberInfo = await _context.GroupMembers.FirstOrDefaultAsync(x => x.UserId == userid) ?? throw new BaseException(CodeDefine.NO_GROUP_PERMISSION); //判断成员权限 if (memberInfo.RoleEnum != GroupMemberRole.Master && memberInfo.RoleEnum != GroupMemberRole.Administrator) throw new BaseException(CodeDefine.NO_GROUP_PERMISSION); requestInfo.StateEnum = dto.Action; _context.GroupRequests.Update(requestInfo); await _context.SaveChangesAsync(); await _endPoint.Publish(new GroupRequestUpdateEvent { Action = requestInfo.StateEnum, AdminUserId = userid, AggregateId = userid.ToString(), OccurredAt = DateTime.UtcNow, EventId = Guid.NewGuid(), GroupId = requestInfo.GroupId, OperatorId = userid, UserId = requestInfo.UserId, RequestId = requestInfo.Id }); } public async Task MakeGroupRequestAsync(int userId, int? adminUserId, int groupId) { var requestInfo = await _context.GroupRequests .FirstOrDefaultAsync(x => x.UserId == userId && x.GroupId == groupId); if (requestInfo != null) return; var member = await _context.GroupMembers.FirstOrDefaultAsync( x => x.UserId == adminUserId && x.GroupId == groupId); var request = new GroupRequest { Created = DateTime.UtcNow, Description = string.Empty, GroupId = groupId, UserId = userId, StateEnum = GroupRequestState.Pending }; if(member != null && ( member.RoleEnum == GroupMemberRole.Administrator || member.RoleEnum == GroupMemberRole.Master)) { request.StateEnum = GroupRequestState.Passed; } _context.GroupRequests.Add(request); await _context.SaveChangesAsync(); await _endPoint.Publish(new GroupRequestEvent { OccurredAt = DateTime.UtcNow, Description = request.Description, GroupId = request.GroupId, Action = request.StateEnum, UserId = userId, AggregateId = userId.ToString(), EventId = Guid.NewGuid(), OperatorId = userId }); return; } } }