diff --git a/im-center-api/src/main/java/cn/axzo/im/center/api/feign/GroupApi.java b/im-center-api/src/main/java/cn/axzo/im/center/api/feign/GroupApi.java index 10a5d17..3e67e8b 100644 --- a/im-center-api/src/main/java/cn/axzo/im/center/api/feign/GroupApi.java +++ b/im-center-api/src/main/java/cn/axzo/im/center/api/feign/GroupApi.java @@ -4,8 +4,11 @@ import cn.axzo.framework.domain.web.result.ApiResult; import cn.axzo.im.center.api.vo.req.GroupAddMembersRequest; import cn.axzo.im.center.api.vo.req.GroupCreateRequest; import cn.axzo.im.center.api.vo.req.GroupDismissRequest; +import cn.axzo.im.center.api.vo.req.GroupGetMembersRequest; +import cn.axzo.im.center.api.vo.req.GroupRemoveMembersRequest; import cn.axzo.im.center.api.vo.resp.GroupAddMembersResponse; import cn.axzo.im.center.api.vo.resp.GroupCreateResponse; +import cn.axzo.im.center.api.vo.resp.GroupGetMembersResponse; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.PostMapping; @@ -19,13 +22,34 @@ public interface GroupApi { String INTRODUCE_MESSAGE = "邀请您加入群聊"; + /** + * 创建群 + */ @PostMapping("/api/im/group/createGroup") ApiResult createGroup(@RequestBody @Validated GroupCreateRequest request); + /** + * 解散群 + */ @PostMapping("/api/im/group/dismissGroup") ApiResult dismissGroup(@RequestBody @Validated GroupDismissRequest request); + /** + * 添加群成员 + */ @PostMapping("/api/im/group/addMembers") ApiResult addMembers(@RequestBody @Validated GroupAddMembersRequest request); + /** + * 移除群成员 + */ + @PostMapping("/api/im/group/removeMembers") + ApiResult removeMembers(@RequestBody @Validated GroupRemoveMembersRequest request); + + /** + * 获取群成员列表 + */ + @PostMapping("/api/im/group/getMembers") + ApiResult getMembers(@RequestBody @Validated GroupGetMembersRequest request); + } \ No newline at end of file diff --git a/im-center-api/src/main/java/cn/axzo/im/center/api/vo/PersonAccountAttribute.java b/im-center-api/src/main/java/cn/axzo/im/center/api/vo/PersonAccountAttribute.java index 93a89f9..b84ed90 100644 --- a/im-center-api/src/main/java/cn/axzo/im/center/api/vo/PersonAccountAttribute.java +++ b/im-center-api/src/main/java/cn/axzo/im/center/api/vo/PersonAccountAttribute.java @@ -76,12 +76,14 @@ public class PersonAccountAttribute { public boolean equals(Object o) { if (!(o instanceof PersonAccountAttribute)) return false; PersonAccountAttribute that = (PersonAccountAttribute) o; - return Objects.equals(personId, that.personId) && Objects.equals(ouId, that.ouId) && appType == that.appType; + return Objects.equals(personId, that.personId) + && Objects.equals(ouIdOrDefault(), that.ouIdOrDefault()) + && appType == that.appType; } @Override public int hashCode() { - return Objects.hash(personId, ouId, appType); + return Objects.hash(personId, ouIdOrDefault(), appType); } @Override diff --git a/im-center-api/src/main/java/cn/axzo/im/center/api/vo/group/GroupInfo.java b/im-center-api/src/main/java/cn/axzo/im/center/api/vo/group/GroupInfo.java new file mode 100644 index 0000000..1e99f96 --- /dev/null +++ b/im-center-api/src/main/java/cn/axzo/im/center/api/vo/group/GroupInfo.java @@ -0,0 +1,64 @@ +package cn.axzo.im.center.api.vo.group; + +import cn.axzo.im.center.common.enums.GroupType; +import cn.axzo.im.center.common.enums.YesOrNo; +import lombok.Getter; +import lombok.Setter; + +import java.util.Date; + +/** + * @author yanglin + */ +@Setter +@Getter +public class GroupInfo { + /** + * 群id + */ + private Long tid; + /** + * 群名称 + */ + private String name; + /** + * 群业务id + */ + private String bizCode; + /** + * 群类型. VISA: 变洽签, WORKSPACE: 项目群, WORKSPACE_OU: 项目单位群, WORKSPACE_TEAM: 项目班组群 + */ + private GroupType type; + /** + * 群头像 + */ + private String avatar; + /** + * 群成员数量 + */ + private Long memberCount; + /** + * 群成员上限 + */ + private Long memberLimit; + /** + * 群主账号 + */ + private String ownerAccount; + /** + * 群主personId + */ + private Long ownerPersonId; + /** + * 群创建人ouId + */ + private Long createPersonId; + /** + * 是否解散 + */ + private YesOrNo isDismissed; + /** + * 创建时间 + */ + private Date createAt; +} \ No newline at end of file diff --git a/im-center-api/src/main/java/cn/axzo/im/center/api/vo/group/GroupMemberInfo.java b/im-center-api/src/main/java/cn/axzo/im/center/api/vo/group/GroupMemberInfo.java new file mode 100644 index 0000000..ba669d5 --- /dev/null +++ b/im-center-api/src/main/java/cn/axzo/im/center/api/vo/group/GroupMemberInfo.java @@ -0,0 +1,25 @@ +package cn.axzo.im.center.api.vo.group; + +import cn.axzo.im.center.common.enums.AppTypeEnum; +import lombok.Getter; +import lombok.Setter; + +/** + * @author yanglin + */ +@Setter +@Getter +public class GroupMemberInfo { + /** + * 群成员personId + */ + private Long personId; + /** + * 群成员ouId + */ + private Long personOuId; + /** + * 群成员端类型 + */ + private AppTypeEnum appType; +} \ No newline at end of file diff --git a/im-center-api/src/main/java/cn/axzo/im/center/api/vo/mq/GroupMembersChangeMessage.java b/im-center-api/src/main/java/cn/axzo/im/center/api/vo/mq/GroupMembersChangeMessage.java index 0a98b5f..ba5b4ec 100644 --- a/im-center-api/src/main/java/cn/axzo/im/center/api/vo/mq/GroupMembersChangeMessage.java +++ b/im-center-api/src/main/java/cn/axzo/im/center/api/vo/mq/GroupMembersChangeMessage.java @@ -1,13 +1,10 @@ package cn.axzo.im.center.api.vo.mq; -import cn.axzo.im.center.common.enums.AppTypeEnum; -import cn.axzo.im.center.common.enums.GroupType; -import cn.axzo.im.center.common.enums.YesOrNo; +import cn.axzo.im.center.api.vo.group.GroupInfo; +import cn.axzo.im.center.api.vo.group.GroupMemberInfo; import lombok.Getter; import lombok.Setter; -import java.util.Date; - /** * @author yanglin */ @@ -17,41 +14,11 @@ public class GroupMembersChangeMessage extends MqMessage { /** * 群信息 */ - private GroupInfo groupInfo; + private GroupInfo group; /** - * 账号信息 + * 群成员信息 */ - private AccountInfo account; + private GroupMemberInfo member; - @Setter @Getter - public static class GroupInfo { - private Long id; - private Long tid; - private String name; - private String bizCode; - private GroupType type; - private String avatar; - private Long memberCount; - private Long memberLimit; - private String ownerAccount; - private Long ownerPersonId; - private Long createPersonId; - private YesOrNo isDismissed; - private Date createAt; - private Date updateAt; - } - - @Setter @Getter - public static class AccountInfo { - private Long id; - private Long tid; - private String imAccount; - private Long personId; - private Long personOuId; - private AppTypeEnum appType; - private YesOrNo isRobot; - private Date createAt; - private Date updateAt; - } } \ No newline at end of file diff --git a/im-center-api/src/main/java/cn/axzo/im/center/api/vo/req/GroupAddMembersRequest.java b/im-center-api/src/main/java/cn/axzo/im/center/api/vo/req/GroupAddMembersRequest.java index 41a7f2c..6f4a330 100644 --- a/im-center-api/src/main/java/cn/axzo/im/center/api/vo/req/GroupAddMembersRequest.java +++ b/im-center-api/src/main/java/cn/axzo/im/center/api/vo/req/GroupAddMembersRequest.java @@ -1,12 +1,10 @@ package cn.axzo.im.center.api.vo.req; -import cn.axzo.im.center.api.feign.GroupApi; import cn.axzo.im.center.api.vo.PersonAccountAttribute; import com.alibaba.fastjson.JSON; import lombok.Getter; import lombok.Setter; -import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; import java.util.HashSet; @@ -22,12 +20,6 @@ public class GroupAddMembersRequest { @NotNull(message = "群ID不能为空") private Long tid; - /** - * 邀请发送的文字,最大长度 150 位字符 - */ - @NotBlank(message = "邀请发送的文字不能为空") - private String introduceMessage = GroupApi.INTRODUCE_MESSAGE; - /** * 群成员, 不包含群主. members数量不能超过199 */ diff --git a/im-center-api/src/main/java/cn/axzo/im/center/api/vo/req/GroupCreateRequest.java b/im-center-api/src/main/java/cn/axzo/im/center/api/vo/req/GroupCreateRequest.java index 3ee64ad..8afff1b 100644 --- a/im-center-api/src/main/java/cn/axzo/im/center/api/vo/req/GroupCreateRequest.java +++ b/im-center-api/src/main/java/cn/axzo/im/center/api/vo/req/GroupCreateRequest.java @@ -1,6 +1,5 @@ package cn.axzo.im.center.api.vo.req; -import cn.axzo.im.center.api.feign.GroupApi; import cn.axzo.im.center.api.vo.PersonAccountAttribute; import cn.axzo.im.center.common.enums.GroupType; import com.alibaba.fastjson.JSON; @@ -55,12 +54,6 @@ public class GroupCreateRequest { */ private Long memberLimit; - /** - * 邀请发送的文字,最大长度 150 位字符 - */ - @NotBlank(message = "邀请发送的文字不能为空") - private String introduceMessage = GroupApi.INTRODUCE_MESSAGE; - /** * 群头像,最大长度 1024 位字符 */ diff --git a/im-center-api/src/main/java/cn/axzo/im/center/api/vo/req/GroupGetMembersRequest.java b/im-center-api/src/main/java/cn/axzo/im/center/api/vo/req/GroupGetMembersRequest.java new file mode 100644 index 0000000..ed84b2f --- /dev/null +++ b/im-center-api/src/main/java/cn/axzo/im/center/api/vo/req/GroupGetMembersRequest.java @@ -0,0 +1,18 @@ +package cn.axzo.im.center.api.vo.req; + +import lombok.Getter; +import lombok.Setter; + +import javax.validation.constraints.NotNull; + +/** + * @author yanglin + */ +@Setter +@Getter +public class GroupGetMembersRequest { + + @NotNull(message = "群ID不能为空") + private Long tid; + +} diff --git a/im-center-api/src/main/java/cn/axzo/im/center/api/vo/req/GroupRemoveMembersRequest.java b/im-center-api/src/main/java/cn/axzo/im/center/api/vo/req/GroupRemoveMembersRequest.java new file mode 100644 index 0000000..62dc102 --- /dev/null +++ b/im-center-api/src/main/java/cn/axzo/im/center/api/vo/req/GroupRemoveMembersRequest.java @@ -0,0 +1,27 @@ +package cn.axzo.im.center.api.vo.req; + +import cn.axzo.im.center.api.vo.PersonAccountAttribute; +import lombok.Getter; +import lombok.Setter; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.util.Set; + +/** + * @author yanglin + */ +@Setter +@Getter +public class GroupRemoveMembersRequest { + + @NotNull(message = "群ID不能为空") + private Long tid; + + /** + * 一次性最多传200个 + */ + @NotEmpty(message = "群成员不能为空") + private Set members; + +} \ No newline at end of file diff --git a/im-center-api/src/main/java/cn/axzo/im/center/api/vo/req/SendTemplateMessageParam.java b/im-center-api/src/main/java/cn/axzo/im/center/api/vo/req/SendTemplateMessageParam.java index 7cb48c0..29dca84 100644 --- a/im-center-api/src/main/java/cn/axzo/im/center/api/vo/req/SendTemplateMessageParam.java +++ b/im-center-api/src/main/java/cn/axzo/im/center/api/vo/req/SendTemplateMessageParam.java @@ -93,7 +93,7 @@ public class SendTemplateMessageParam { public Long determineSenderOuId() { if (sender != null) - return sender.getOuId(); + return sender.ouIdOrDefault(); return 0L; } diff --git a/im-center-api/src/main/java/cn/axzo/im/center/api/vo/resp/GroupGetMembersResponse.java b/im-center-api/src/main/java/cn/axzo/im/center/api/vo/resp/GroupGetMembersResponse.java new file mode 100644 index 0000000..07c18fe --- /dev/null +++ b/im-center-api/src/main/java/cn/axzo/im/center/api/vo/resp/GroupGetMembersResponse.java @@ -0,0 +1,19 @@ +package cn.axzo.im.center.api.vo.resp; + +import cn.axzo.im.center.api.vo.group.GroupMemberInfo; +import lombok.Getter; +import lombok.Setter; + +import java.util.List; + +/** + * @author yanglin + */ +@Setter +@Getter +public class GroupGetMembersResponse { + /** + * 群成员信息列表 + */ + private List member; +} \ No newline at end of file diff --git a/im-center-server/src/main/java/cn/axzo/im/channel/netease/client/NimClient.java b/im-center-server/src/main/java/cn/axzo/im/channel/netease/client/NimClient.java index 6bc6a17..1b4c514 100644 --- a/im-center-server/src/main/java/cn/axzo/im/channel/netease/client/NimClient.java +++ b/im-center-server/src/main/java/cn/axzo/im/channel/netease/client/NimClient.java @@ -12,6 +12,8 @@ import cn.axzo.im.channel.netease.dto.NimGroupDismissRequest; import cn.axzo.im.channel.netease.dto.NimGroupDismissResponse; import cn.axzo.im.channel.netease.dto.NimGroupGetInfoRequest; import cn.axzo.im.channel.netease.dto.NimGroupGetInfoResponse; +import cn.axzo.im.channel.netease.dto.NimGroupRemoveMembersRequest; +import cn.axzo.im.channel.netease.dto.NimGroupRemoveMembersResponse; import cn.axzo.im.channel.netease.dto.NimQueryEventRequest; import cn.axzo.im.channel.netease.dto.NimQueryEventResponse; import cn.axzo.im.channel.netease.dto.NimQueryMessageRequest; @@ -76,6 +78,9 @@ public interface NimClient { @PostMapping(value = "/team/add.action") NimGroupAddMembersResponse addMembers(NimGroupAddMembersRequest request); + @PostMapping(value = "/team/kick.action") + NimGroupRemoveMembersResponse removeMembers(NimGroupRemoveMembersRequest request); + @Data class NimCodeResponse { private Integer code; diff --git a/im-center-server/src/main/java/cn/axzo/im/channel/netease/dto/GroupMemberRequest.java b/im-center-server/src/main/java/cn/axzo/im/channel/netease/dto/GroupMemberRequest.java new file mode 100644 index 0000000..90a9230 --- /dev/null +++ b/im-center-server/src/main/java/cn/axzo/im/channel/netease/dto/GroupMemberRequest.java @@ -0,0 +1,27 @@ +package cn.axzo.im.channel.netease.dto; + +import com.alibaba.fastjson.JSON; +import lombok.Getter; +import lombok.Setter; +import org.apache.commons.lang3.StringUtils; + +import java.util.Collection; + +/** + * @author yanglin + */ +@Setter +@Getter +public class GroupMemberRequest { + + private String members; + + public void addMembers(Collection members) { + if (StringUtils.isBlank(this.members)) + this.members = "[]"; + this.members = JSON.parseArray(this.members) + .fluentAddAll(members) + .toJSONString(); + } + +} diff --git a/im-center-server/src/main/java/cn/axzo/im/channel/netease/dto/NimGroupAddMembersRequest.java b/im-center-server/src/main/java/cn/axzo/im/channel/netease/dto/NimGroupAddMembersRequest.java index 6924b90..33a8539 100644 --- a/im-center-server/src/main/java/cn/axzo/im/channel/netease/dto/NimGroupAddMembersRequest.java +++ b/im-center-server/src/main/java/cn/axzo/im/channel/netease/dto/NimGroupAddMembersRequest.java @@ -2,31 +2,21 @@ package cn.axzo.im.channel.netease.dto; import cn.axzo.im.channel.netease.client.FormRequest; import com.alibaba.fastjson.JSON; -import lombok.Data; -import org.apache.commons.lang3.StringUtils; - -import java.util.Collection; +import lombok.Getter; +import lombok.Setter; /** * @author yanglin */ -@Data +@Setter +@Getter @FormRequest -public class NimGroupAddMembersRequest { +public class NimGroupAddMembersRequest extends GroupMemberRequest { private Long tid; private String owner; - private String members; private String msg; - public void addMembers(Collection members) { - if (StringUtils.isBlank(this.members)) - this.members = "[]"; - this.members = JSON.parseArray(this.members) - .fluentAddAll(members) - .toJSONString(); - } - @Override public String toString() { return JSON.toJSONString(this); diff --git a/im-center-server/src/main/java/cn/axzo/im/channel/netease/dto/NimGroupCreateRequest.java b/im-center-server/src/main/java/cn/axzo/im/channel/netease/dto/NimGroupCreateRequest.java index 0097886..87eeb46 100644 --- a/im-center-server/src/main/java/cn/axzo/im/channel/netease/dto/NimGroupCreateRequest.java +++ b/im-center-server/src/main/java/cn/axzo/im/channel/netease/dto/NimGroupCreateRequest.java @@ -3,17 +3,16 @@ package cn.axzo.im.channel.netease.dto; import cn.axzo.im.channel.netease.client.FormRequest; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.annotation.JSONField; -import lombok.Data; +import lombok.Getter; +import lombok.Setter; import org.apache.commons.lang3.StringUtils; -import java.util.Collection; - /** * @author yanglin */ -@Data +@Setter @Getter @FormRequest -public class NimGroupCreateRequest { +public class NimGroupCreateRequest extends GroupMemberRequest { /** * 群名称,最大长度 64 位字符 @@ -26,12 +25,6 @@ public class NimGroupCreateRequest { */ private String owner; - /** - * 邀请的群成员列表,\["aaa","bbb"\](JSONArray 对应的 accid,如果解析出错会报 414) - * members 与 owner 总和上限为 200。members 中无需再加 owner 自己的账号 - */ - private String members; - /** * 群描述,最大长度 512 位字符 */ @@ -93,14 +86,6 @@ public class NimGroupCreateRequest { */ private String attach; - public void addMembers(Collection members) { - if (StringUtils.isBlank(this.members)) - this.members = "[]"; - this.members = JSON.parseArray(this.members) - .fluentAddAll(members) - .toJSONString(); - } - public void addAttachment(String key, Object value) { if (StringUtils.isBlank(this.attach)) this.attach = "{}"; diff --git a/im-center-server/src/main/java/cn/axzo/im/channel/netease/dto/NimGroupRemoveMembersRequest.java b/im-center-server/src/main/java/cn/axzo/im/channel/netease/dto/NimGroupRemoveMembersRequest.java new file mode 100644 index 0000000..1c3828f --- /dev/null +++ b/im-center-server/src/main/java/cn/axzo/im/channel/netease/dto/NimGroupRemoveMembersRequest.java @@ -0,0 +1,22 @@ +package cn.axzo.im.channel.netease.dto; + +import cn.axzo.im.channel.netease.client.FormRequest; +import com.alibaba.fastjson.JSON; +import lombok.Getter; +import lombok.Setter; + +/** + * @author yanglin + */ +@Setter +@Getter +@FormRequest +public class NimGroupRemoveMembersRequest extends GroupMemberRequest { + private Long tid; + private String owner; + + @Override + public String toString() { + return JSON.toJSONString(this); + } +} \ No newline at end of file diff --git a/im-center-server/src/main/java/cn/axzo/im/channel/netease/dto/NimGroupRemoveMembersResponse.java b/im-center-server/src/main/java/cn/axzo/im/channel/netease/dto/NimGroupRemoveMembersResponse.java new file mode 100644 index 0000000..2f02fac --- /dev/null +++ b/im-center-server/src/main/java/cn/axzo/im/channel/netease/dto/NimGroupRemoveMembersResponse.java @@ -0,0 +1,21 @@ +package cn.axzo.im.channel.netease.dto; + +import cn.axzo.im.channel.netease.client.NimClient; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import lombok.Getter; +import lombok.Setter; + +/** + * @author yanglin + */ +@Setter +@Getter +public class NimGroupRemoveMembersResponse extends NimClient.NimCodeResponse { + private JSONObject faccid; + + @Override + public String toString() { + return JSON.toJSONString(this); + } +} diff --git a/im-center-server/src/main/java/cn/axzo/im/controller/PrivateController.java b/im-center-server/src/main/java/cn/axzo/im/controller/PrivateController.java index dab47ef..e0b7d74 100644 --- a/im-center-server/src/main/java/cn/axzo/im/controller/PrivateController.java +++ b/im-center-server/src/main/java/cn/axzo/im/controller/PrivateController.java @@ -1,12 +1,16 @@ package cn.axzo.im.controller; +import cn.axzo.im.center.api.vo.req.GroupAddMembersRequest; +import cn.axzo.im.center.api.vo.req.GroupCreateRequest; +import cn.axzo.im.center.api.vo.req.GroupDismissRequest; +import cn.axzo.im.center.api.vo.req.GroupRemoveMembersRequest; import cn.axzo.im.center.api.vo.req.SendMessageParam; import cn.axzo.im.channel.netease.client.NimClient; -import cn.axzo.im.channel.netease.dto.NimGroupDismissRequest; import cn.axzo.im.channel.netease.dto.NimGroupGetInfoRequest; import cn.axzo.im.channel.netease.dto.NimQueryEventRequest; import cn.axzo.im.channel.netease.dto.NimQueryMessageRequest; import cn.axzo.im.channel.netease.dto.NimRevokeMessageRequest; +import cn.axzo.im.group.GroupManager; import cn.axzo.im.job.CreateMessageHistoryJob; import cn.axzo.im.job.ExpungeImTaskJob; import cn.axzo.im.job.RevokeAllMessagesJob; @@ -34,6 +38,7 @@ public class PrivateController { private final CreateMessageHistoryJob createMessageHistoryJob; private final MessageController messageController; private final ExpungeImTaskJob expungeImTaskJob; + private final GroupManager groupManager; @PostMapping("/private/revoke") public Object revoke(@Valid @RequestBody NimRevokeMessageRequest request) { @@ -76,9 +81,27 @@ public class PrivateController { return CommonResponse.success(count); } + @PostMapping("/private/group/createGroup") + public Object createGroup(@Valid @RequestBody GroupCreateRequest request) { + return CommonResponse.success(groupManager.createGroup(request)); + } + @PostMapping("/private/group/dismissGroup") - public Object dismissGroup(@Valid @RequestBody NimGroupDismissRequest request) { - return CommonResponse.success(nimClient.dismissGroup(request)); + public Object dismissGroup(@Valid @RequestBody GroupDismissRequest request) { + groupManager.dismissGroup(request); + return CommonResponse.success(); + } + + @PostMapping("/private/group/addMembers") + public Object addMembers(@Valid @RequestBody GroupAddMembersRequest request) { + groupManager.addMembers(request); + return CommonResponse.success(); + } + + @PostMapping("/private/group/removeMembers") + public Object removeMembers(@Valid @RequestBody GroupRemoveMembersRequest request) { + groupManager.removeMembers(request); + return CommonResponse.success(); } @PostMapping("/private/group/getGroupInfo") diff --git a/im-center-server/src/main/java/cn/axzo/im/dao/mapper/GroupAccountMapper.java b/im-center-server/src/main/java/cn/axzo/im/dao/mapper/GroupMapperMapper.java similarity index 51% rename from im-center-server/src/main/java/cn/axzo/im/dao/mapper/GroupAccountMapper.java rename to im-center-server/src/main/java/cn/axzo/im/dao/mapper/GroupMapperMapper.java index ab253f1..61477c6 100644 --- a/im-center-server/src/main/java/cn/axzo/im/dao/mapper/GroupAccountMapper.java +++ b/im-center-server/src/main/java/cn/axzo/im/dao/mapper/GroupMapperMapper.java @@ -1,10 +1,10 @@ package cn.axzo.im.dao.mapper; -import cn.axzo.im.entity.GroupAccount; +import cn.axzo.im.entity.GroupMember; import com.baomidou.mybatisplus.core.mapper.BaseMapper; /** * @author yanglin */ -public interface GroupAccountMapper extends BaseMapper { +public interface GroupMapperMapper extends BaseMapper { } diff --git a/im-center-server/src/main/java/cn/axzo/im/dao/repository/GroupAccountDao.java b/im-center-server/src/main/java/cn/axzo/im/dao/repository/GroupAccountDao.java deleted file mode 100644 index b15ab1d..0000000 --- a/im-center-server/src/main/java/cn/axzo/im/dao/repository/GroupAccountDao.java +++ /dev/null @@ -1,28 +0,0 @@ -package cn.axzo.im.dao.repository; - -import cn.axzo.im.dao.mapper.GroupAccountMapper; -import cn.axzo.im.entity.GroupAccount; -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import org.springframework.stereotype.Repository; - -import java.util.List; - -/** - * @author yanglin - */ -@Repository("groupAccountDao") -public class GroupAccountDao extends ServiceImpl { - - public List getByTid(Long tid) { - return lambdaQuery() - .eq(GroupAccount::getTid, tid) - .list(); - } - - public void deleteAccounts(Long tid) { - lambdaUpdate() - .eq(GroupAccount::getTid, tid) - .remove(); - } - -} \ No newline at end of file diff --git a/im-center-server/src/main/java/cn/axzo/im/dao/repository/GroupMemberDao.java b/im-center-server/src/main/java/cn/axzo/im/dao/repository/GroupMemberDao.java new file mode 100644 index 0000000..4042ceb --- /dev/null +++ b/im-center-server/src/main/java/cn/axzo/im/dao/repository/GroupMemberDao.java @@ -0,0 +1,64 @@ +package cn.axzo.im.dao.repository; + +import cn.axzo.im.center.api.vo.PersonAccountAttribute; +import cn.axzo.im.dao.mapper.GroupMapperMapper; +import cn.axzo.im.entity.GroupMember; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.stereotype.Repository; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Set; + +import static java.util.stream.Collectors.toSet; + +/** + * @author yanglin + */ +@Repository("groupMemberDao") +public class GroupMemberDao extends ServiceImpl { + + public void deleteAccounts(Long tid) { + lambdaUpdate() + .eq(GroupMember::getTid, tid) + .remove(); + } + + public Set getGroupPersons(Long tid) { + return getByTid(tid).stream() + .map(account -> { + PersonAccountAttribute person = new PersonAccountAttribute(); + person.setPersonId(account.getPersonId() + ""); + person.setOuId(account.getPersonOuId()); + person.setAppType(account.getAppType()); + return person; + }) + .collect(toSet()); + } + + public List getByTid(Long tid) { + return lambdaQuery() + .eq(GroupMember::getTid, tid) + .list(); + } + + public List getByPersons( + Long tid, Collection persons) { + if (CollectionUtils.isEmpty(persons)) + return Collections.emptyList(); + return lambdaQuery() + .eq(GroupMember::getTid, tid) + .nested(wrapper -> { + for (PersonAccountAttribute person : persons) { + wrapper.or() + .eq(GroupMember::getPersonId, Long.parseLong(person.getPersonId())) + .eq(GroupMember::getPersonOuId, person.ouIdOrDefault()) + .eq(GroupMember::getAppType, person.getAppType()); + } + }) + .list(); + } + +} \ No newline at end of file diff --git a/im-center-server/src/main/java/cn/axzo/im/entity/GroupAccount.java b/im-center-server/src/main/java/cn/axzo/im/entity/GroupMember.java similarity index 86% rename from im-center-server/src/main/java/cn/axzo/im/entity/GroupAccount.java rename to im-center-server/src/main/java/cn/axzo/im/entity/GroupMember.java index c21eae7..98e2387 100644 --- a/im-center-server/src/main/java/cn/axzo/im/entity/GroupAccount.java +++ b/im-center-server/src/main/java/cn/axzo/im/entity/GroupMember.java @@ -13,8 +13,8 @@ import java.util.Date; */ @Setter @Getter -@TableName(value = "im_group_account", autoResultMap = true) -public class GroupAccount { +@TableName(value = "im_group_member", autoResultMap = true) +public class GroupMember { private Long id; private Long tid; private String imAccount; diff --git a/im-center-server/src/main/java/cn/axzo/im/group/GroupBroadcaster.java b/im-center-server/src/main/java/cn/axzo/im/group/GroupBroadcaster.java index b147ea3..665da59 100644 --- a/im-center-server/src/main/java/cn/axzo/im/group/GroupBroadcaster.java +++ b/im-center-server/src/main/java/cn/axzo/im/group/GroupBroadcaster.java @@ -3,12 +3,13 @@ package cn.axzo.im.group; import cn.axzo.basics.common.BeanMapper; import cn.axzo.framework.rocketmq.Event; import cn.axzo.im.center.api.vo.mq.GroupMembersChangeMessage; +import cn.axzo.im.center.api.vo.req.GroupInfo; +import cn.axzo.im.center.api.vo.mq.GroupMembersChangeMessage.MemberInfo; import cn.axzo.im.config.MqProducer; import cn.axzo.im.dao.repository.GroupDao; import cn.axzo.im.entity.Group; -import cn.axzo.im.entity.GroupAccount; +import cn.axzo.im.entity.GroupMember; import cn.axzo.im.event.inner.EventTypeEnum; -import cn.axzo.im.group.domain.GroupMembersDiff; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -24,27 +25,26 @@ class GroupBroadcaster { private final MqProducer mqProducer; private final GroupDao groupDao; - void fireMembersAdded(Group group, GroupMembersDiff diff) { - diff.diff(); - fireMembersChanged(group, diff.getAdded(), EventTypeEnum.GROUP_ADD_MEMBERS); + void fireMembersAdded(Group group, Collection accounts) { + fireMembersChanged(group, accounts, EventTypeEnum.GROUP_ADD_MEMBERS); } - void fireMembersRemoved(Group group, GroupMembersDiff diff) { - diff.diff(); - fireMembersChanged(group, diff.getRemoved(), EventTypeEnum.GROUP_REMOVE_MEMBERS); + void fireMembersRemoved(Group group, Collection accounts) { + fireMembersChanged(group, accounts, EventTypeEnum.GROUP_REMOVE_MEMBERS); } - private void fireMembersChanged(Group group, Collection accounts, EventTypeEnum eventType) { + private void fireMembersChanged(Group group, Collection accounts, EventTypeEnum eventType) { if (accounts.isEmpty()) return; Group effectiveGroup = groupDao.getById(group.getId()); - for (GroupAccount account : accounts) { + for (GroupMember account : accounts) { GroupMembersChangeMessage message = new GroupMembersChangeMessage(); - message.setGroupInfo(BeanMapper.copyBean(effectiveGroup, GroupMembersChangeMessage.GroupInfo.class)); - message.setAccount(BeanMapper.copyBean(account, GroupMembersChangeMessage.AccountInfo.class)); + message.setGroup(BeanMapper.copyBean(effectiveGroup, GroupInfo.class)); + message.setMember(BeanMapper.copyBean(account, MemberInfo.class)); Event event = Event.builder() - .targetId(account.getImAccount()) + .targetId(String.format("%d:%d", group.getTid(), account.getPersonId())) .targetType(eventType.getModel()) .eventCode(eventType.getEventCode()) + .shardingKey(group.getId() + "") .data(message) .build(); mqProducer.send(event); diff --git a/im-center-server/src/main/java/cn/axzo/im/group/GroupController.java b/im-center-server/src/main/java/cn/axzo/im/group/GroupController.java index 888c082..f03f9bb 100644 --- a/im-center-server/src/main/java/cn/axzo/im/group/GroupController.java +++ b/im-center-server/src/main/java/cn/axzo/im/group/GroupController.java @@ -1,16 +1,25 @@ package cn.axzo.im.group; +import cn.axzo.basics.common.BeanMapper; import cn.axzo.framework.domain.web.result.ApiResult; import cn.axzo.im.center.api.feign.GroupApi; +import cn.axzo.im.center.api.vo.group.GroupMemberInfo; import cn.axzo.im.center.api.vo.req.GroupAddMembersRequest; import cn.axzo.im.center.api.vo.req.GroupCreateRequest; import cn.axzo.im.center.api.vo.req.GroupDismissRequest; +import cn.axzo.im.center.api.vo.req.GroupGetMembersRequest; +import cn.axzo.im.center.api.vo.req.GroupRemoveMembersRequest; import cn.axzo.im.center.api.vo.resp.GroupAddMembersResponse; import cn.axzo.im.center.api.vo.resp.GroupCreateResponse; +import cn.axzo.im.center.api.vo.resp.GroupGetMembersResponse; +import cn.axzo.im.dao.repository.GroupMemberDao; +import cn.axzo.im.entity.GroupMember; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.RestController; +import java.util.List; + /** * @author yanglin */ @@ -20,6 +29,7 @@ import org.springframework.web.bind.annotation.RestController; public class GroupController implements GroupApi { private final GroupManager groupManager; + private final GroupMemberDao groupMemberDao; @Override public ApiResult createGroup(GroupCreateRequest request) { @@ -37,4 +47,18 @@ public class GroupController implements GroupApi { return ApiResult.ok(groupManager.addMembers(request)); } + @Override + public ApiResult addMembers(GroupRemoveMembersRequest request) { + groupManager.removeMembers(request); + return ApiResult.ok(); + } + + @Override + public ApiResult getMembers(GroupGetMembersRequest request) { + List members = groupMemberDao.getByTid(request.getTid()); + GroupGetMembersResponse response = new GroupGetMembersResponse(); + response.setMember(BeanMapper.copyList(members, GroupMemberInfo.class)); + return ApiResult.ok(response); + } + } \ No newline at end of file diff --git a/im-center-server/src/main/java/cn/axzo/im/group/GroupLogger.java b/im-center-server/src/main/java/cn/axzo/im/group/GroupLogger.java new file mode 100644 index 0000000..bc0a9d1 --- /dev/null +++ b/im-center-server/src/main/java/cn/axzo/im/group/GroupLogger.java @@ -0,0 +1,8 @@ +package cn.axzo.im.group; + +/** + * @author yanglin + */ +public interface GroupLogger { + void log(String message, Object... args); +} \ No newline at end of file diff --git a/im-center-server/src/main/java/cn/axzo/im/group/GroupManager.java b/im-center-server/src/main/java/cn/axzo/im/group/GroupManager.java index 5d04b2b..66dc9dd 100644 --- a/im-center-server/src/main/java/cn/axzo/im/group/GroupManager.java +++ b/im-center-server/src/main/java/cn/axzo/im/group/GroupManager.java @@ -5,6 +5,7 @@ import cn.axzo.im.center.api.vo.PersonAccountAttribute; import cn.axzo.im.center.api.vo.req.GroupAddMembersRequest; import cn.axzo.im.center.api.vo.req.GroupCreateRequest; import cn.axzo.im.center.api.vo.req.GroupDismissRequest; +import cn.axzo.im.center.api.vo.req.GroupRemoveMembersRequest; import cn.axzo.im.center.api.vo.resp.GroupAddMembersResponse; import cn.axzo.im.center.api.vo.resp.GroupCreateResponse; import cn.axzo.im.channel.netease.client.NimClient; @@ -17,15 +18,15 @@ import cn.axzo.im.channel.netease.dto.NimGroupDismissResponse; import cn.axzo.im.channel.netease.dto.NimGroupGetInfoRequest; import cn.axzo.im.channel.netease.dto.NimGroupGetInfoResponse; import cn.axzo.im.channel.netease.dto.NimGroupInfo; -import cn.axzo.im.dao.repository.GroupAccountDao; +import cn.axzo.im.channel.netease.dto.NimGroupRemoveMembersRequest; +import cn.axzo.im.channel.netease.dto.NimGroupRemoveMembersResponse; import cn.axzo.im.dao.repository.GroupDao; +import cn.axzo.im.dao.repository.GroupMemberDao; import cn.axzo.im.entity.Group; -import cn.axzo.im.entity.GroupAccount; -import cn.axzo.im.group.domain.GroupMembersDiff; +import cn.axzo.im.entity.GroupMember; import cn.axzo.im.service.AccountService; -import cn.axzo.im.service.domain.PersonImAccounts; +import cn.axzo.im.service.domain.ImAccounts; import cn.axzo.im.utils.BizAssertions; -import cn.hutool.core.map.MapUtil; import com.alibaba.fastjson.JSON; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -39,45 +40,49 @@ import java.util.List; import java.util.Optional; import java.util.Set; +import static java.util.stream.Collectors.toList; + /** * @author yanglin */ @Slf4j @Component @RequiredArgsConstructor -class GroupManager { +public class GroupManager { private final NimClient nimClient; private final GroupDao groupDao; - private final GroupAccountDao groupAccountDao; + private final GroupMemberDao groupMemberDao; private final GroupSupport groupSupport; private final AccountService accountService; private final GroupBroadcaster groupBroadcaster; @Transactional public GroupCreateResponse createGroup(GroupCreateRequest request) { - PersonImAccounts accounts = accountService.findPersonAccounts(request.getOwnerAndMembers()); - Group group = groupSupport.buildNewGroup(request, accounts); + BizAssertions.assertTrue(request.getOwnerAndMembers().size() > 1, "群成员数量(含群主)不能少于2"); + ImAccounts imAccounts = accountService.getAccountsByPersons(request.getOwnerAndMembers()); + Group group = groupSupport.buildNewGroup(request, imAccounts); + BizAssertions.assertFalse(group.isMemberLimitReached( + request.getOwnerAndMembers().size()), "无法创建群, 群成员数量超过上限" + group.getMemberLimit()); try { groupDao.save(group); } catch (DuplicateKeyException e) { log.warn("重复创建群, request={}", request, e); throw new ServiceException(403, String.format("群已经存在: %s", request.getName())); } - NimGroupCreateRequest nimRequest = groupSupport.buildNimCreateGroupRequest(request, group, accounts); + NimGroupCreateRequest nimRequest = groupSupport + .buildNimCreateGroupRequest(request, imAccounts); NimGroupCreateResponse nimResponse = nimClient.createGroup(nimRequest); log.info("创建群, request={}, response={}", nimRequest, nimResponse); BizAssertions.assertTrue(nimResponse.isSuccess(), "创建群失败: {}", nimResponse.getDesc()); groupDao.updateTid(group.getId(), nimResponse.getTid()); - GroupMembersDiff memberDiff = createMembersDiff(nimResponse.getTid()); - syncGroupAccounts(group); - groupBroadcaster.fireMembersAdded(group, memberDiff); + group = groupDao.getById(group.getId()); + syncGroupMembers(group); + groupBroadcaster.fireMembersAdded(group, groupMemberDao.getByTid(nimResponse.getTid())); GroupCreateResponse response = new GroupCreateResponse(); response.setTid(nimResponse.getTid()); - Set notFound = accounts.getAccountNotFoundPersons(request.getMembers()); - if (!notFound.isEmpty()) - groupSupport.log("创建群[TID:{}], IM账号不存在列表: {}", group.getTid(), JSON.toJSONString(notFound)); - response.setAccountsNotFound(notFound); + response.setAccountsNotFound(imAccounts.getAccountNotFoundPersons( + groupSupport, "创建群", group, request.getMembers())); return response; } @@ -98,37 +103,61 @@ class GroupManager { public GroupAddMembersResponse addMembers(GroupAddMembersRequest request) { Group group = findGroupForUpdateOrThrow(request.getTid()); BizAssertions.assertFalse(group.isDismissed(), "群已经解散: {}", group.getTid()); - NimGroupInfo groupInfo = fetchGroupInfo(group).orElse(null); - BizAssertions.assertNotNull(groupInfo, "[NIM] 群不存在: {}", group.getTid()); - PersonImAccounts accounts = accountService.findPersonAccounts(request.getMembers()); + // sync members 1 + syncGroupMembers(group); + // prepare add members + Set preMembers = groupMemberDao.getGroupPersons(group.getTid()); + List toAddMembers = request.getMembers().stream() + .filter(member -> !preMembers.contains(member)) + .collect(toList()); + if (group.isMemberLimitReached(preMembers.size() + toAddMembers.size())) + throw new ServiceException("群聊人数上限" + group.getMemberLimit() +"人, 请删除部分已选人员"); + ImAccounts imAccounts = accountService.getAccountsByPersons(toAddMembers); + if (imAccounts.isAccountEmpty()) { + groupSupport.log("添加群成员[TID:{}], 有效群成员IM账号列表为空. 请求成员信息: {}", + group.getTid(), JSON.toJSONString(request.getMembers())); + return new GroupAddMembersResponse(); + } NimGroupAddMembersRequest nimRequest = groupSupport - .buildAddMembersRequest(request, group, groupInfo.getOwner().getAccid(), accounts); - GroupMembersDiff memberDiff = createMembersDiff(group.getTid()); + .buildAddMembersRequest(group, group.getOwnerAccount(), imAccounts); + // add members NimGroupAddMembersResponse nimResponse = nimClient.addMembers(nimRequest); log.info("添加群成员, request={}, response={}", nimRequest, nimResponse); BizAssertions.assertTrue(nimResponse.isSuccess(), "添加群成员失败: {}", nimResponse.getDesc()); - if (MapUtil.isNotEmpty(nimResponse.getFaccid())) - groupSupport.log("添加群成员[TID:{}], 错误信息: {}", - group.getTid(), JSON.toJSONString(nimResponse.getFaccid())); - syncGroupAccounts(group); - groupBroadcaster.fireMembersAdded(group, memberDiff); + // sync members 2 + syncGroupMembers(group); + groupBroadcaster.fireMembersAdded(group, groupMemberDao + .getByPersons(group.getTid(), toAddMembers)); GroupAddMembersResponse response = new GroupAddMembersResponse(); - Set notFound = accounts.getAccountNotFoundPersons(request.getMembers()); - if (!notFound.isEmpty()) - groupSupport.log("创建群[TID:{}], IM账号不存在列表: {}", group.getTid(), JSON.toJSONString(notFound)); - response.setAccountsNotFound(notFound); + response.setAccountsNotFound(imAccounts.getAccountNotFoundPersons( + groupSupport, "添加群成员", group, request.getMembers())); return response; } - private void syncGroupAccounts(Group group) { - NimGroupInfo groupInfo = fetchGroupInfo(group).orElse(null); - if (groupInfo == null) return; - groupAccountDao.deleteAccounts(group.getTid()); - List accounts = groupSupport - .parseGroupAccounts(group, groupInfo.getOwnerAndMembers()); - if (CollectionUtils.isNotEmpty(accounts)) - groupAccountDao.saveBatch(accounts); - groupDao.updateMembersCount(group.getTid(), accounts.size()); + @Transactional + public void removeMembers(GroupRemoveMembersRequest request) { + Group group = findGroupForUpdateOrThrow(request.getTid()); + BizAssertions.assertFalse(group.isDismissed(), "群已经解散: {}", group.getTid()); + ImAccounts imAccounts = accountService.getAccountsByPersons(request.getMembers()); + if (imAccounts.isAccountEmpty()) { + groupSupport.log("添加群成员[TID:{}], 有效群成员IM账号列表为空. 请求成员信息: {}", + group.getTid(), JSON.toJSONString(request.getMembers())); + return; + } + syncGroupMembers(group); + List toRemoveMembers = groupMemberDao.getByPersons( + group.getTid(), request.getMembers()); + if (CollectionUtils.isEmpty(toRemoveMembers)) + return; + NimGroupRemoveMembersRequest nimRequest = groupSupport + .buildRemoveMembersRequest(group, group.getOwnerAccount(), imAccounts); + NimGroupRemoveMembersResponse nimResponse = nimClient.removeMembers(nimRequest); + log.info("移除群成员, request={}, response={}", nimRequest, nimResponse); + if (nimResponse.isSuccess()) { + syncGroupMembers(group); + // 不比较直接发消息 + groupBroadcaster.fireMembersAdded(group, toRemoveMembers); + } } @NotNull @@ -138,6 +167,17 @@ class GroupManager { return group; } + private void syncGroupMembers(Group group) { + NimGroupInfo groupInfo = fetchGroupInfo(group).orElse(null); + if (groupInfo == null) return; + groupMemberDao.deleteAccounts(group.getTid()); + List accounts = groupSupport + .parseGroupMembers(group, groupInfo.getOwnerAndMembers()); + if (CollectionUtils.isNotEmpty(accounts)) + groupMemberDao.saveBatch(accounts); + groupDao.updateMembersCount(group.getTid(), accounts.size()); + } + private Optional fetchGroupInfo(Group group) { NimGroupGetInfoRequest nimRequest = new NimGroupGetInfoRequest(); nimRequest.setTid(group.getTid()); @@ -152,7 +192,4 @@ class GroupManager { return Optional.of(nimResponse.getTinfo()); } - private GroupMembersDiff createMembersDiff(Long tid) { - return new GroupMembersDiff(() -> groupAccountDao.getByTid(tid)); - } } \ No newline at end of file diff --git a/im-center-server/src/main/java/cn/axzo/im/group/GroupSupport.java b/im-center-server/src/main/java/cn/axzo/im/group/GroupSupport.java index 87b3864..3dbb7a1 100644 --- a/im-center-server/src/main/java/cn/axzo/im/group/GroupSupport.java +++ b/im-center-server/src/main/java/cn/axzo/im/group/GroupSupport.java @@ -1,17 +1,18 @@ package cn.axzo.im.group; +import cn.axzo.im.center.api.feign.GroupApi; import cn.axzo.im.center.api.vo.PersonAccountAttribute; -import cn.axzo.im.center.api.vo.req.GroupAddMembersRequest; import cn.axzo.im.center.api.vo.req.GroupCreateRequest; import cn.axzo.im.center.common.enums.YesOrNo; import cn.axzo.im.channel.netease.dto.NimGroupAddMembersRequest; import cn.axzo.im.channel.netease.dto.NimGroupCreateRequest; import cn.axzo.im.channel.netease.dto.NimGroupDismissRequest; import cn.axzo.im.channel.netease.dto.NimGroupMemberInfo; +import cn.axzo.im.channel.netease.dto.NimGroupRemoveMembersRequest; import cn.axzo.im.entity.Group; -import cn.axzo.im.entity.GroupAccount; +import cn.axzo.im.entity.GroupMember; import cn.axzo.im.service.ChatGroupService; -import cn.axzo.im.service.domain.PersonImAccounts; +import cn.axzo.im.service.domain.ImAccounts; import cn.axzo.im.utils.BizAssertions; import cn.axzo.im.utils.ImAccountParser; import lombok.RequiredArgsConstructor; @@ -29,11 +30,11 @@ import java.util.Set; @Slf4j @Component @RequiredArgsConstructor -class GroupSupport { +public class GroupSupport implements GroupLogger { private final ChatGroupService chatGroupService; - Group buildNewGroup(GroupCreateRequest request, PersonImAccounts accounts) { + Group buildNewGroup(GroupCreateRequest request, ImAccounts accounts) { String owner = accounts.findAccount(request.getOwner()).orElse(null); BizAssertions.assertNotNull(owner, "群主没有IM账号, 无法创建群. {}", request.getOwner()); Group group = new Group(); @@ -52,18 +53,16 @@ class GroupSupport { } NimGroupCreateRequest buildNimCreateGroupRequest( - GroupCreateRequest request, Group group, PersonImAccounts accounts) { - BizAssertions.assertFalse(group.isMemberLimitReached( - accounts.getAccountSize()), "无法创建群, 群成员数量超过上限"); - String owner = accounts.findAccount(request.getOwner()).orElse(null); + GroupCreateRequest request, ImAccounts imAccounts) { + String owner = imAccounts.findAccount(request.getOwner()).orElse(null); BizAssertions.assertNotNull(owner, "群主没有IM账号, 无法创建群. {}", request.getOwner()); - BizAssertions.assertTrue(accounts.getAccountSize() > 1, "无法创建群. 存在的群成员IM账号数量需要大于等于2"); + BizAssertions.assertTrue(imAccounts.getAccountSize() > 1, "无法创建群. 存在的群成员IM账号数量需要大于等于2"); NimGroupCreateRequest nimRequest = new NimGroupCreateRequest(); nimRequest.setName(request.getName()); nimRequest.setOwner(owner); - nimRequest.addMembers(accounts.filterAccounts(account -> !account.equals(owner))); - nimRequest.setIntroduceMessage(request.getIntroduceMessage()); + nimRequest.addMembers(imAccounts.filterAccounts(account -> !account.equals(owner))); + nimRequest.setIntroduceMessage(GroupApi.INTRODUCE_MESSAGE); nimRequest.setIcon(request.getAvatar()); nimRequest.addAttachment(Group.ATTACHMENT_GROUP_TYPE, request.getGroupType()); return nimRequest; @@ -77,16 +76,27 @@ class GroupSupport { } NimGroupAddMembersRequest buildAddMembersRequest( - GroupAddMembersRequest request, Group group, String owner, PersonImAccounts accounts) { + Group group, String owner, ImAccounts accounts) { + BizAssertions.assertNotEmpty(accounts.getAccounts(), "有效群成员IM账号列表为空"); NimGroupAddMembersRequest nimRequest = new NimGroupAddMembersRequest(); nimRequest.setTid(group.getTid()); nimRequest.setOwner(owner); - nimRequest.setMsg(request.getIntroduceMessage()); + nimRequest.setMsg(GroupApi.INTRODUCE_MESSAGE); nimRequest.addMembers(accounts.getAccounts()); return nimRequest; } - void log(String message, Object... args) { + NimGroupRemoveMembersRequest buildRemoveMembersRequest( + Group group, String owner, ImAccounts accounts) { + BizAssertions.assertNotEmpty(accounts.getAccounts(), "有效群成员IM账号列表为空"); + NimGroupRemoveMembersRequest nimRequest = new NimGroupRemoveMembersRequest(); + nimRequest.setTid(group.getTid()); + nimRequest.setOwner(owner); + nimRequest.addMembers(accounts.getAccounts()); + return nimRequest; + } + + public void log(String message, Object... args) { try { chatGroupService.sendDingRobot(MessageFormatter.arrayFormat(message, args).getMessage()); } catch (Exception e) { @@ -94,11 +104,11 @@ class GroupSupport { } } - List parseGroupAccounts(Group group, Set members) { - ArrayList accounts = new ArrayList<>(); + List parseGroupMembers(Group group, Set members) { + ArrayList accounts = new ArrayList<>(); for (NimGroupMemberInfo member : members) { PersonAccountAttribute person = ImAccountParser.parsePerson(member.getAccid()).orElse(null); - GroupAccount account = new GroupAccount(); + GroupMember account = new GroupMember(); accounts.add(account); account.setTid(group.getTid()); account.setImAccount(member.getAccid()); @@ -116,4 +126,5 @@ class GroupSupport { } return accounts; } + } \ No newline at end of file diff --git a/im-center-server/src/main/java/cn/axzo/im/group/domain/GroupMembersDiff.java b/im-center-server/src/main/java/cn/axzo/im/group/domain/GroupMembersDiff.java deleted file mode 100644 index 7480069..0000000 --- a/im-center-server/src/main/java/cn/axzo/im/group/domain/GroupMembersDiff.java +++ /dev/null @@ -1,57 +0,0 @@ -package cn.axzo.im.group.domain; - -import cn.axzo.im.entity.GroupAccount; - -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.function.Supplier; -import java.util.stream.Collectors; - -/** - * @author yanglin - */ -@SuppressWarnings("DuplicatedCode") -public class GroupMembersDiff { - - private final Supplier> accountsProvider; - private final Map before; - private Map after; - - public GroupMembersDiff(Supplier> accountsProvider) { - this.accountsProvider = accountsProvider; - this.before = reload(); - } - - public void diff() { - if (after == null) - after = reload(); - } - - public Collection getAdded() { - HashMap accounts = new HashMap<>(); - for (GroupAccount account : after.values()) { - String imAccount = account.getImAccount(); - if (!before.containsKey(imAccount) && !accounts.containsKey(imAccount)) - accounts.put(imAccount, account); - } - return accounts.values(); - } - - public Collection getRemoved() { - HashMap accounts = new HashMap<>(); - for (GroupAccount account : before.values()) { - String imAccount = account.getImAccount(); - if (!after.containsKey(imAccount) && !accounts.containsKey(imAccount)) - accounts.put(imAccount, account); - } - return accounts.values(); - } - - private Map reload() { - return accountsProvider.get().stream() - .collect(Collectors.toMap(GroupAccount::getImAccount, account -> account)); - } - -} \ No newline at end of file diff --git a/im-center-server/src/main/java/cn/axzo/im/service/AccountService.java b/im-center-server/src/main/java/cn/axzo/im/service/AccountService.java index 734da4b..63e6a89 100644 --- a/im-center-server/src/main/java/cn/axzo/im/service/AccountService.java +++ b/im-center-server/src/main/java/cn/axzo/im/service/AccountService.java @@ -32,7 +32,7 @@ import cn.axzo.im.entity.AccountRegister; import cn.axzo.im.entity.RobotInfo; import cn.axzo.im.entity.bo.AccountQueryParam; import cn.axzo.im.gateway.ProfilesApiGateway; -import cn.axzo.im.service.domain.PersonImAccounts; +import cn.axzo.im.service.domain.ImAccounts; import cn.axzo.im.utils.MiscUtils; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; @@ -580,9 +580,9 @@ public class AccountService { AccountTypeEnum.CUSTOM, AppTypeEnum.SYSTEM, appKey); } - public PersonImAccounts findPersonAccounts(Collection persons) { + public ImAccounts getAccountsByPersons(Collection persons) { if (CollectionUtils.isEmpty(persons)) - return new PersonImAccounts(Collections.emptyList()); + return new ImAccounts(Collections.emptyList()); List accounts = accountRegisterDao.lambdaQuery() .nested(wrapper -> { for (PersonAccountAttribute person : persons) { @@ -593,7 +593,7 @@ public class AccountService { } }) .list(); - return new PersonImAccounts(accounts); + return new ImAccounts(accounts); } } \ No newline at end of file diff --git a/im-center-server/src/main/java/cn/axzo/im/service/domain/PersonImAccounts.java b/im-center-server/src/main/java/cn/axzo/im/service/domain/ImAccounts.java similarity index 73% rename from im-center-server/src/main/java/cn/axzo/im/service/domain/PersonImAccounts.java rename to im-center-server/src/main/java/cn/axzo/im/service/domain/ImAccounts.java index 1be4cf8..4100883 100644 --- a/im-center-server/src/main/java/cn/axzo/im/service/domain/PersonImAccounts.java +++ b/im-center-server/src/main/java/cn/axzo/im/service/domain/ImAccounts.java @@ -1,7 +1,10 @@ package cn.axzo.im.service.domain; +import cn.axzo.framework.jackson.utility.JSON; import cn.axzo.im.center.api.vo.PersonAccountAttribute; import cn.axzo.im.entity.AccountRegister; +import cn.axzo.im.entity.Group; +import cn.axzo.im.group.GroupLogger; import lombok.RequiredArgsConstructor; import lombok.Setter; import org.apache.commons.collections.CollectionUtils; @@ -20,17 +23,25 @@ import static java.util.stream.Collectors.toSet; */ @Setter @RequiredArgsConstructor -public class PersonImAccounts { +public class ImAccounts { private final List imAccounts; - public Set - getAccountNotFoundPersons(Set persons) { + public boolean isAccountEmpty() { + return imAccounts.isEmpty(); + } + + public Set getAccountNotFoundPersons( + GroupLogger logger, String operation, + Group group, Set persons) { if (CollectionUtils.isEmpty(persons)) return Collections.emptySet(); - return persons.stream() + Set notFound = persons.stream() .filter(person -> !findAccount(person).isPresent()) .collect(toSet()); + if (!notFound.isEmpty()) + logger.log("{}[TID:{}], IM账号不存在列表: {}", operation, group.getTid(), JSON.toJSONString(notFound)); + return notFound; } public Set filterAccounts(Predicate filter) { diff --git a/im-center-server/src/main/java/cn/axzo/im/utils/ImAccountParser.java b/im-center-server/src/main/java/cn/axzo/im/utils/ImAccountParser.java index 04afb3e..4251ed3 100644 --- a/im-center-server/src/main/java/cn/axzo/im/utils/ImAccountParser.java +++ b/im-center-server/src/main/java/cn/axzo/im/utils/ImAccountParser.java @@ -24,7 +24,7 @@ public class ImAccountParser { PersonAccountAttribute person = new PersonAccountAttribute(); person.setPersonId(personId); - person.setOuId(ouId != null ? Long.parseLong(ouId.substring(1)) : null); + person.setOuId(ouId != null ? Long.parseLong(ouId) : null); person.setAppType(appType); return Optional.of(person); } diff --git a/im-center-server/src/test/java/cn/axzo/im/group/GroupManagerTest.java b/im-center-server/src/test/java/cn/axzo/im/group/GroupManagerTest.java index 122fbef..fee3326 100644 --- a/im-center-server/src/test/java/cn/axzo/im/group/GroupManagerTest.java +++ b/im-center-server/src/test/java/cn/axzo/im/group/GroupManagerTest.java @@ -24,10 +24,11 @@ class GroupManagerTest { @Test void createGroup() { + int idx = 6; GroupCreateRequest request = new GroupCreateRequest(); request.setGroupType(GroupType.VISA); - request.setBizCode("yl-group-2"); - request.setName("杨林测试群2"); + request.setBizCode("yl-group-" + idx); + request.setName("杨林测试群" + idx); request.setOwner(PersonAccountAttribute.cmp(9000399522L, 10616L)); request.addMember(PersonAccountAttribute.cm(9000399522L)); request.setAvatar("https://axzo-app.oss-cn-chengdu.aliyuncs.com/dev/common/92c412eb7e62542998cc10059fa7619e6.jpg"); @@ -38,14 +39,14 @@ class GroupManagerTest { @Test void dismissGroup() { GroupDismissRequest request = new GroupDismissRequest(); - request.setTid(32504762462L); + request.setTid(32543625538L); groupManager.dismissGroup(request); } @Test void addMembers() { GroupAddMembersRequest request = new GroupAddMembersRequest(); - request.setTid(32505385179L); + request.setTid(32544969049L); request.addMember(PersonAccountAttribute.cmp(13335L, 8507L)); request.addMember(PersonAccountAttribute.cmp(13335000000L, 8507L)); GroupAddMembersResponse response = groupManager.addMembers(request);