From 6ef6ed29064e9a2020f9c3e10f661d9b90676234 Mon Sep 17 00:00:00 2001 From: heavyrian2012 Date: Sat, 5 Jul 2025 16:47:15 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E7=BE=A4=E7=BB=84=E6=88=90?= =?UTF-8?q?=E5=91=98=E6=97=B6=E6=94=AF=E6=8C=81=E9=83=A8=E5=88=86=E6=88=90?= =?UTF-8?q?=E5=91=98=E5=A4=B1=E8=B4=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- broker/config/wildfirechat.conf | 4 ++ .../java/io/moquette/BrokerConstants.java | 1 + .../io/moquette/imhandler/AddGroupMember.java | 26 ++++++++- .../imhandler/CreateGroupHandler.java | 26 +++++++-- .../persistence/MemoryMessagesStore.java | 54 ++++++++++++++++--- .../java/io/moquette/spi/IMessagesStore.java | 8 +-- .../cn/wildfirechat/common/ErrorCode.java | 2 + .../pojos/GroupNotificationBinaryContent.java | 8 +++ .../cn/wildfirechat/proto/ProtoConstants.java | 2 + .../src/main/resources/wildfirechat.conf | 4 ++ 10 files changed, 119 insertions(+), 16 deletions(-) diff --git a/broker/config/wildfirechat.conf b/broker/config/wildfirechat.conf index 0f90426d..dcb879f3 100755 --- a/broker/config/wildfirechat.conf +++ b/broker/config/wildfirechat.conf @@ -248,6 +248,10 @@ group.visible_quit_or_kickoff_notification 0 ## 是否禁止陌生人拉人入群,默认为false group.disable_stranger_invite false +## 创建群组或者加人时。可能会有成员加入失败(黑名单,或者不允许陌生人拉入群)。当出现有成员失败时,如果此开关为关,操作会失败。 +## 如果此开关打开,操作会返回成功,另外在群里发送一条通知消息 XXX 拒绝加入群组。默认为开。 +group.add_member_allow_part_success true + ## 群组信息是否标记删除 group.enable_mark_deletion true diff --git a/broker/src/main/java/io/moquette/BrokerConstants.java b/broker/src/main/java/io/moquette/BrokerConstants.java index 10069337..d25cec55 100755 --- a/broker/src/main/java/io/moquette/BrokerConstants.java +++ b/broker/src/main/java/io/moquette/BrokerConstants.java @@ -205,6 +205,7 @@ public final class BrokerConstants { public static final String GROUP_Forbidden_Client_Operation = "group.forbidden_client_operation"; public static final String GROUP_Disable_Stranger_Invite = "group.disable_stranger_invite"; + public static final String GROUP_ADD_MEMBER_ALLOW_PART_SUCCESS = "group.add_member_allow_part_success"; public static final String GROUP_INFO_MARK_DELETION = "group.enable_mark_deletion"; diff --git a/broker/src/main/java/io/moquette/imhandler/AddGroupMember.java b/broker/src/main/java/io/moquette/imhandler/AddGroupMember.java index 51c80884..32ee6ecd 100644 --- a/broker/src/main/java/io/moquette/imhandler/AddGroupMember.java +++ b/broker/src/main/java/io/moquette/imhandler/AddGroupMember.java @@ -16,6 +16,10 @@ import io.netty.buffer.ByteBuf; import cn.wildfirechat.common.ErrorCode; import win.liyufan.im.IMTopic; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + import static cn.wildfirechat.common.ErrorCode.ERROR_CODE_SUCCESS; @Handler(value = IMTopic.AddGroupMemberTopic) @@ -38,16 +42,34 @@ public class AddGroupMember extends GroupHandler failedMembers = new HashMap<>(); + if(requestSourceType == ProtoConstants.RequestSourceType.Request_From_User) { + ErrorCode errorCode = m_messagesStore.canAddGroupMembers(fromUser, request.getAddedMemberList(), failedMembers); + if (errorCode != ErrorCode.ERROR_CODE_SUCCESS) { + return errorCode; + } + } + + ErrorCode errorCode = m_messagesStore.addGroupMembers(fromUser, isAdmin, request.getGroupId(), request.getAddedMemberList(), request.getExtra(), failedMembers); if (errorCode == ERROR_CODE_SUCCESS) { if (request.hasNotifyContent() && request.getNotifyContent().getType() > 0) { sendGroupNotification(fromUser, request.getGroupId(), request.getToLineList(), request.getNotifyContent()); } else { - WFCMessage.MessageContent content = new GroupNotificationBinaryContent(request.getGroupId(), fromUser, null, getMemberIdList(request.getAddedMemberList())).setExtra(request.getExtra()).getAddGroupNotifyContent(); + List added = getMemberIdList(request.getAddedMemberList()); + added.removeAll(failedMembers.keySet()); + WFCMessage.MessageContent content = new GroupNotificationBinaryContent(request.getGroupId(), fromUser, null, added).setExtra(request.getExtra()).getAddGroupNotifyContent(); sendGroupNotification(fromUser, request.getGroupId(), request.getToLineList(), content); } } + if (errorCode == ERROR_CODE_SUCCESS && !failedMembers.isEmpty()) { + WFCMessage.MessageContent content = new GroupNotificationBinaryContent(request.getGroupId(), fromUser, null, "").setMi(failedMembers).getGroupNotifyContent(ProtoConstants.MESSAGE_CONTENT_TYPE_REJECT_JOIN_GROUP); + sendGroupNotification(fromUser, request.getGroupId(), request.getToLineList(), content); + } + + if(errorCode == ERROR_CODE_SUCCESS && !failedMembers.isEmpty()) { + return ErrorCode.ERROR_CODE_PARTLY_SUCCESS; + } return errorCode; } } diff --git a/broker/src/main/java/io/moquette/imhandler/CreateGroupHandler.java b/broker/src/main/java/io/moquette/imhandler/CreateGroupHandler.java index 5d98e639..010399ca 100644 --- a/broker/src/main/java/io/moquette/imhandler/CreateGroupHandler.java +++ b/broker/src/main/java/io/moquette/imhandler/CreateGroupHandler.java @@ -17,6 +17,9 @@ import io.netty.buffer.ByteBuf; import cn.wildfirechat.common.ErrorCode; import win.liyufan.im.IMTopic; +import java.util.HashMap; +import java.util.Map; + @Handler(value = IMTopic.CreateGroupTopic) public class CreateGroupHandler extends GroupHandler { @Override @@ -51,14 +54,21 @@ public class CreateGroupHandler extends GroupHandler failedMembers = new HashMap<>(); if(requestSourceType == ProtoConstants.RequestSourceType.Request_From_User) { - ErrorCode errorCode = m_messagesStore.canAddGroupMembers(fromUser, request.getGroup().getMembersList()); + ErrorCode errorCode = m_messagesStore.canAddGroupMembers(fromUser, request.getGroup().getMembersList(), failedMembers); if (errorCode != ErrorCode.ERROR_CODE_SUCCESS) { return errorCode; } } - WFCMessage.GroupInfo groupInfo = m_messagesStore.createGroup(fromUser, request.getGroup().getGroupInfo(), request.getGroup().getMembersList(), request.getMemberExtra(), isAdmin); + if (request.getGroup().getGroupInfo().getTargetId().length() > 64 + || request.getGroup().getGroupInfo().getName().length() > 64 + || request.getGroup().getGroupInfo().getPortrait().length() > 1024) { + return ErrorCode.INVALID_PARAMETER; + } + + WFCMessage.GroupInfo groupInfo = m_messagesStore.createGroup(fromUser, request.getGroup().getGroupInfo(), request.getGroup().getMembersList(), request.getMemberExtra(), isAdmin, failedMembers); if (groupInfo != null && groupInfo.getDeleted() == 0) { if(request.hasNotifyContent() && request.getNotifyContent().getType() > 0) { sendGroupNotification(fromUser, groupInfo.getTargetId(), request.getToLineList(), request.getNotifyContent()); @@ -66,9 +76,19 @@ public class CreateGroupHandler extends GroupHandler mAllowStrangerChatSet = new HashSet<>(); private Set mAllowStrangerLineSet = new HashSet<>(); private boolean mDisableStrangerAddGroup = false; + private boolean mGroupAllowPartSuccess = false; private boolean mIDUseUUID = true; @@ -630,6 +631,11 @@ public class MemoryMessagesStore implements IMessagesStore { } + try { + mGroupAllowPartSuccess = "true".equals(server.getConfig().getProperty(BrokerConstants.GROUP_ADD_MEMBER_ALLOW_PART_SUCCESS, "false")); + } catch (Exception e) { + } + try { mRobotCallbackWithClientInfo = Boolean.parseBoolean(server.getConfig().getProperty(BrokerConstants.ROBOT_Callback_With_Client_Info, "false")); } catch (Exception e) {} @@ -1282,7 +1288,7 @@ public class MemoryMessagesStore implements IMessagesStore { } @Override - public ErrorCode canAddGroupMembers(String fromUser, List memberList) { + public ErrorCode canAddGroupMembers(String fromUser, List memberList, Map failedMembers) { HazelcastInstance hzInstance = m_Server.getHazelcastInstance(); MultiMap friendsMap = hzInstance.getMultiMap(USER_FRIENDS); IMap mUserMap = hzInstance.getMap(USERS); @@ -1308,7 +1314,12 @@ public class MemoryMessagesStore implements IMessagesStore { for (FriendData friendData : friendDatas) { if (friendData.getFriendUid().equals(fromUser)) { if (friendData.getBlacked() == 1) { - return ErrorCode.ERROR_CODE_IN_BLACK_LIST; + LOG.error("Add group member failure, because inviter {} is blocked by invitee {}", fromUser, targetUser); + if(isGroupAllowPartSuccess()) { + failedMembers.put(targetUser, 1); //black + } else { + return ErrorCode.ERROR_CODE_IN_BLACK_LIST; + } } else { if (friendData.getState() == 0) { allow = true; @@ -1332,7 +1343,11 @@ public class MemoryMessagesStore implements IMessagesStore { continue; } - return ErrorCode.ERROR_CODE_NOT_RIGHT; + if(isGroupAllowPartSuccess()) { + failedMembers.put(targetUser, 2);//stranger + } else { + return ErrorCode.ERROR_CODE_NOT_RIGHT; + } } } else { for (WFCMessage.GroupMember groupMember : memberList) { @@ -1349,7 +1364,12 @@ public class MemoryMessagesStore implements IMessagesStore { for (FriendData friendData : friendDatas) { if (friendData.getFriendUid().equals(fromUser)) { if (friendData.getBlacked() == 1) { - return ErrorCode.ERROR_CODE_IN_BLACK_LIST; + LOG.error("Add group member failure, because inviter {} is blocked by invitee {}", fromUser, targetUser); + if(isGroupAllowPartSuccess()) { + failedMembers.put(targetUser, 1); //black + } else { + return ErrorCode.ERROR_CODE_IN_BLACK_LIST; + } } else { break; } @@ -1361,7 +1381,7 @@ public class MemoryMessagesStore implements IMessagesStore { } @Override - public WFCMessage.GroupInfo createGroup(String fromUser, WFCMessage.GroupInfo groupInfo, List memberList, String memberExtra, boolean isAdmin) { + public WFCMessage.GroupInfo createGroup(String fromUser, WFCMessage.GroupInfo groupInfo, List memberList, String memberExtra, boolean isAdmin, Map failedMembers) { HazelcastInstance hzInstance = m_Server.getHazelcastInstance(); IMap mIMap = hzInstance.getMap(GROUPS_MAP); @@ -1383,6 +1403,9 @@ public class MemoryMessagesStore implements IMessagesStore { List updatedMemberList = new ArrayList<>(); boolean hasOwnerMember = false; for (WFCMessage.GroupMember member : memberList) { + if(failedMembers.containsKey(member.getMemberId())) { + continue; + } WFCMessage.GroupMember.Builder builder = member.toBuilder(); builder.setUpdateDt(dt).setCreateDt(dt); if (member.getMemberId().equals(owner)) { @@ -1577,7 +1600,7 @@ public class MemoryMessagesStore implements IMessagesStore { } @Override - public ErrorCode addGroupMembers(String operator, boolean isAdmin, String groupId, List memberList, String extra) { + public ErrorCode addGroupMembers(String operator, boolean isAdmin, String groupId, List memberList, String extra, Map failedMembers) { HazelcastInstance hzInstance = m_Server.getHazelcastInstance(); IMap mIMap = hzInstance.getMap(GROUPS_MAP); @@ -1650,6 +1673,10 @@ public class MemoryMessagesStore implements IMessagesStore { List tmp = new ArrayList<>(); int newMemberCount = 0; for (WFCMessage.GroupMember member : memberList) { + if(failedMembers.containsKey(member.getMemberId())) { + continue; + } + if (existMemberIds.contains(member.getMemberId()) && member.getType() != GroupMemberType_Removed) { if(!isAdmin) continue; @@ -1682,7 +1709,11 @@ public class MemoryMessagesStore implements IMessagesStore { if (memberList.size() == 0) { if (!isAdmin) { - return ErrorCode.ERROR_CODE_ALREADY_IN_GROUP; + if(failedMembers.isEmpty()) { + return ErrorCode.ERROR_CODE_ALREADY_IN_GROUP; + } else { + return ErrorCode.ERROR_CODE_SUCCESS; + } } else { return ErrorCode.ERROR_CODE_SUCCESS; } @@ -1701,6 +1732,10 @@ public class MemoryMessagesStore implements IMessagesStore { List memberIds = new ArrayList<>(); for (WFCMessage.GroupMember member : memberList) { + if(failedMembers.containsKey(member.getMemberId())) { + continue; + } + if (member.getType() != GroupMemberType_Removed) { memberIds.add(member.getMemberId()); } @@ -4748,6 +4783,11 @@ public class MemoryMessagesStore implements IMessagesStore { return mGroupVisibleQuitKickoffNotification; } + @Override + public boolean isGroupAllowPartSuccess() { + return mGroupAllowPartSuccess; + } + @Override public int getGroupForbiddenClientOperation() { return mGroupForbiddenClientOperation; diff --git a/broker/src/main/java/io/moquette/spi/IMessagesStore.java b/broker/src/main/java/io/moquette/spi/IMessagesStore.java index 4a451404..a4537d02 100755 --- a/broker/src/main/java/io/moquette/spi/IMessagesStore.java +++ b/broker/src/main/java/io/moquette/spi/IMessagesStore.java @@ -102,9 +102,9 @@ public interface IMessagesStore { WFCMessage.PullMessageResult fetchMessage(String user, String exceptClientId, long fromMessageId, int pullType); WFCMessage.PullMessageResult loadRemoteMessages(String user, WFCMessage.Conversation conversation, long beforeUid, int count, Collection contentTypes); long insertUserMessages(String sender, int conversationType, String target, int line, int messageContentType, String userId, long messageId, boolean directing); - ErrorCode canAddGroupMembers(String operator, List memberList); - WFCMessage.GroupInfo createGroup(String operator, WFCMessage.GroupInfo groupInfo, List memberList, String memberExtra, boolean isAdmin); - ErrorCode addGroupMembers(String operator, boolean isAdmin, String groupId, List memberList, String extra); + ErrorCode canAddGroupMembers(String operator, List memberList, Map failedMembers); + WFCMessage.GroupInfo createGroup(String operator, WFCMessage.GroupInfo groupInfo, List memberList, String memberExtra, boolean isAdmin, Map failedMembers); + ErrorCode addGroupMembers(String operator, boolean isAdmin, String groupId, List memberList, String extra, Map failedMembers); ErrorCode kickoffGroupMembers(String operator, boolean isAdmin, String groupId, List memberList); ErrorCode quitGroup(String operator, String groupId, boolean admin); void clearUserGroups(String userId); @@ -253,7 +253,7 @@ public interface IMessagesStore { boolean isChannelCallbackWithSenderInfo(); boolean isChannelCallbackWithTargetInfo(); boolean isChannelNewCallbackFeature(); - + boolean isGroupAllowPartSuccess(); boolean isRobotAutoAcceptFriendRequest(); long getPushExpiredTimes(); diff --git a/common/src/main/java/cn/wildfirechat/common/ErrorCode.java b/common/src/main/java/cn/wildfirechat/common/ErrorCode.java index cc72f1da..1a65c298 100755 --- a/common/src/main/java/cn/wildfirechat/common/ErrorCode.java +++ b/common/src/main/java/cn/wildfirechat/common/ErrorCode.java @@ -65,6 +65,8 @@ public enum ErrorCode { ERROR_CODE_CONFERENCE_ERROR(90, "Conference server response error"), ERROR_CODE_FUNCTION_DISABLED(220, "function disabled"), + ERROR_CODE_SERVER_BUSY(221, "Server busy"), + ERROR_CODE_PARTLY_SUCCESS(222, "Partly success"), ERROR_CODE_OTHER_CLIENT_ALREADY_IN_CHATROOM(225, "other client already in chatroom"), diff --git a/common/src/main/java/cn/wildfirechat/pojos/GroupNotificationBinaryContent.java b/common/src/main/java/cn/wildfirechat/pojos/GroupNotificationBinaryContent.java index 7d9d1f9b..f280c326 100644 --- a/common/src/main/java/cn/wildfirechat/pojos/GroupNotificationBinaryContent.java +++ b/common/src/main/java/cn/wildfirechat/pojos/GroupNotificationBinaryContent.java @@ -16,6 +16,7 @@ import com.google.protobuf.ByteString; import io.netty.util.internal.StringUtil; import java.util.List; +import java.util.Map; public class GroupNotificationBinaryContent { //groupId @@ -33,6 +34,8 @@ public class GroupNotificationBinaryContent { //value2(member or something) private String m; + private Map mi; + private String extra; public GroupNotificationBinaryContent() { @@ -92,6 +95,11 @@ public class GroupNotificationBinaryContent { this.ms = ms; } + public GroupNotificationBinaryContent setMi(Map mi) { + this.mi = mi; + return this; + } + public GroupNotificationBinaryContent setExtra(String extra) { this.extra = extra; return this; diff --git a/common/src/main/java/cn/wildfirechat/proto/ProtoConstants.java b/common/src/main/java/cn/wildfirechat/proto/ProtoConstants.java index c98bce9f..840ec552 100644 --- a/common/src/main/java/cn/wildfirechat/proto/ProtoConstants.java +++ b/common/src/main/java/cn/wildfirechat/proto/ProtoConstants.java @@ -396,5 +396,7 @@ public class ProtoConstants { public static final int MESSAGE_CONTENT_TYPE_MODIFY_GROUP_EXTRA = 122; public static final int MESSAGE_CONTENT_TYPE_MODIFY_GROUP_MEMBER_EXTRA = 123; + public static final int MESSAGE_CONTENT_TYPE_MODIFY_GROUP_SETTINGS = 124; + public static final int MESSAGE_CONTENT_TYPE_REJECT_JOIN_GROUP = 125; } diff --git a/distribution/src/main/resources/wildfirechat.conf b/distribution/src/main/resources/wildfirechat.conf index 4910b8c8..5c81f95d 100755 --- a/distribution/src/main/resources/wildfirechat.conf +++ b/distribution/src/main/resources/wildfirechat.conf @@ -246,6 +246,10 @@ group.visible_quit_or_kickoff_notification 0 ## 是否禁止陌生人拉人入群,默认为false group.disable_stranger_invite false +## 创建群组或者加人时。可能会有成员加入失败(黑名单,或者不允许陌生人拉入群)。当出现有成员失败时,如果此开关为关,操作会失败。 +## 如果此开关打开,操作会返回成功,另外在群里发送一条通知消息 XXX 拒绝加入群组。默认为开。 +group.add_member_allow_part_success true + ## 群组信息是否标记删除 group.enable_mark_deletion true