Compare commits

..
19 Commits
Author SHA1 Message Date
heavyrian2012 88d764fb6d update version and release note 2025-08-02 10:45:59 +08:00
heavyrian2012 08b3886238 解决机器人回调配置带上发送人信息功能无效问题 2025-08-02 10:38:09 +08:00
heavyrian2012 7e73c2880b 支持客户端上传本地角标,当需要推送时会把角标数字带上 2025-07-29 11:51:11 +08:00
heavyrian2012 1359ce5250 解决上传文件可能内存泄漏的问题 2025-07-18 21:17:13 +08:00
heavyrian2012 56eaf938a8 添加注释 2025-07-16 17:50:18 +08:00
heavyrian2012 6ef6ed2906 添加群组成员时支持部分成员失败 2025-07-05 16:47:15 +08:00
heavyrian2012 63f37e8984 更新sdk接口测试的说明 2025-07-04 14:03:06 +08:00
heavyrian2012 337302c551 update readme 2025-06-29 11:32:04 +08:00
heavyrian2012 721f27a58a 搜索用户可以指定搜索用户或者机器人 2025-06-22 14:59:34 +08:00
heavyrian2012 ced74280d8 version and release note 2025-06-19 19:19:21 +08:00
heavyrian2012 18617c67f4 api/version和gettoken都添加节点信息 2025-06-19 19:15:35 +08:00
heavyrian2012 883866ce39 配置文件添加注释 2025-06-17 16:02:40 +08:00
heavyrian2012 2e135d4794 群组成员表添加一条索引 2025-06-14 12:38:16 +08:00
heavyrian2012 1d6faa5796 server api支持修改群组类型 2025-05-29 14:18:29 +08:00
heavyrian2012 731fa00cc9 创建/更新频道接口添加频道菜单属性 2025-05-12 14:27:07 +08:00
heavyrian2012 4da9173c5f 修改撤回时间配置,可以配置为不允许撤回 2025-05-10 08:12:20 +08:00
heavyrian2012 94e430cc83 解决外置消息审核回调没有回调成功的问题 2025-05-05 16:52:19 +08:00
heavyrian2012 7e92d1e0c5 Server API创建频道时,需要同时返回频道ID和频道密钥 2025-04-25 23:10:43 +08:00
heavyrian2012 4fa79bfeac 频道和机器人API添加对端口的检查提示 2025-04-22 12:21:45 +08:00
47 changed files with 698 additions and 188 deletions
+2 -1
View File
@@ -44,7 +44,8 @@
| [organization-platform](https://github.com/wildfirechat/organization-platform) | [organization-platform](https://gitee.com/wfchat/organization-platform) | 野火组织通讯录服务。 |
| [android-chat](https://github.com/wildfirechat/android-chat) | [android-chat](https://gitee.com/wfchat/android-chat) | 野火IM Android SDK源码和App源码。 |
| [ios-chat](https://github.com/wildfirechat/ios-chat) | [ios-chat](https://gitee.com/wfchat/ios-chat) | 野火IM iOS SDK源码和App源码。|
| [pc-chat](https://github.com/wildfirechat/vue-pc-chat) | [pc-chat](https://gitee.com/wfchat/vue-pc-chat) | 基于[Electron](https://electronjs.org/)的PC 端,支持Windows、Mac、Linux(包括国产化linux系统和CPU)。 |
| [pc-chat(electron)](https://github.com/wildfirechat/vue-pc-chat) | [pc-chat(electron)](https://gitee.com/wfchat/vue-pc-chat) | 基于[Electron](https://electronjs.org/)开发的PC 端 | |
| [pc-chat(Qt)](https://github.com/wildfirechat/qt-pc-chat) | [pc-chat(Qt)](https://gitee.com/wfchat/qt-pc-chat) | 基于Qt开发的PC 端 | |
| [web-chat](https://github.com/wildfirechat/vue-chat) | [web-chat](https://gitee.com/wfchat/vue-chat) | 野火IM Web 端, [体验地址](https://web.wildfirechat.cn)。 |
| [wx-chat](https://github.com/wildfirechat/wx-chat) | [wx-chat](https://gitee.com/wfchat/wx-chat) | 小程序平台的Demo(支持微信、百度、阿里、字节、QQ 等小程序平台)。 |
| [uni-chat](https://github.com/wildfirechat/uni-chat) | [uni-chat](https://gitee.com/wfchat/uni-chat) | UniApp平台移动端应用(使用原生插件)。 |
+5 -1
View File
@@ -111,7 +111,7 @@ message.disable_remote_search false
##如果要避免数据库中明文存储消息内容,请打开这个开关和message.disable_remote_search开关
message.encrypt_message_content false
##允许客户端撤回用户自己发送的消息时限,单位是秒。
##允许客户端撤回用户自己发送的消息时限,单位是秒。0是不允许撤回;-1是无限制撤回。
##Server API不受此限制,可以撤回任意时限内的消息
##群组管理员或群主撤回群成员消息不受此限制,可以撤回任意时限内的消息。但管理员或群主撤回自己的消息还是需要准守此时间限制。
##修改此参数需要同步修改客户端UI,客户端UI代码有判断撤回是否显示的逻辑。
@@ -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
+1
View File
@@ -0,0 +1 @@
CREATE INDEX `user_gid_mid_dt_index` ON `t_group_member` (`_gid`, `_mid`, `_dt`);
+1
View File
@@ -0,0 +1 @@
CREATE INDEX `user_gid_mid_dt_index` ON `t_group_member` (`_gid`, `_mid`, `_dt`);
+1 -1
View File
@@ -5,7 +5,7 @@
<relativePath>../</relativePath>
<artifactId>wildfirechat-parent</artifactId>
<groupId>cn.wildfirechat</groupId>
<version>1.3.5</version>
<version>1.3.7</version>
</parent>
<artifactId>moquette-broker</artifactId>
@@ -37,6 +37,7 @@ public class PushMessage {
public boolean republish;
public long messageId;
public long callStartUid;
public int existBadgeNumber;
public PushMessage(String sender, int conversationType, String target, int line, int messageContentType, long serverTime, String senderName, String senderPortrait, String targetName, String targetPortrait, int unReceivedMsg, int mentionedType, boolean isHiddenDetail, String language) {
this.sender = sender;
@@ -81,10 +81,6 @@ public class PushServer {
}
MemorySessionStore.Session session = sessionsStore.getSession(deviceId);
int badge = session.getUnReceivedMsgs();
if (badge <= 0) {
badge = 1;
}
if (StringUtil.isNullOrEmpty(session.getDeviceToken())) {
LOG.warn("Device token is empty for device {}", deviceId);
return;
@@ -94,7 +90,6 @@ public class PushServer {
pushMessage.pushType = session.getPushType();
pushMessage.pushContent = pushContent;
pushMessage.deviceToken = session.getDeviceToken();
pushMessage.unReceivedMsg = badge;
pushMessage.userId = session.getUsername();
if (session.getPlatform() == ProtoConstants.Platform.Platform_iOS ||
session.getPlatform() == ProtoConstants.Platform.Platform_iPad ||
@@ -284,9 +284,10 @@ public class UploadFileAction extends Action {
savedThunkSize += readableBytesSize;
offset += readableBytesSize;
byteBuf.release();
byteBuf = null;
if (savedThunkSize >= remoteFileSize) {
byteBuf.release();
fileUpload.release();
response.setStatus(HttpResponseStatus.OK);
@@ -51,14 +51,7 @@ public class AliasPutAction extends AdminAction {
ByteBuf byteBuf = Unpooled.buffer();
byteBuf.writeBytes(result);
ErrorCode errorCode = ErrorCode.fromCode(byteBuf.readByte());
if (errorCode == ErrorCode.ERROR_CODE_SUCCESS) {
byte[] data = new byte[byteBuf.readableBytes()];
byteBuf.readBytes(data);
String channelId = new String(data);
return new Result(ErrorCode.ERROR_CODE_SUCCESS, new OutputCreateChannel(channelId));
} else {
return new Result(errorCode);
}
return new Result(errorCode);
});
return false;
} else {
@@ -53,8 +53,11 @@ public class CreateChannelAction extends AdminAction {
if (errorCode == ErrorCode.ERROR_CODE_SUCCESS) {
byte[] data = new byte[byteBuf.readableBytes()];
byteBuf.readBytes(data);
String channelId = new String(data);
return new Result(ErrorCode.ERROR_CODE_SUCCESS, new OutputCreateChannel(channelId));
String str = new String(data);
String[] ss = str.split("\\|");
String channelId = ss[0];
String secret = ss[1];
return new Result(ErrorCode.ERROR_CODE_SUCCESS, new OutputCreateChannel(channelId, secret));
} else {
return new Result(errorCode);
}
@@ -20,6 +20,7 @@ import io.netty.handler.codec.http.FullHttpRequest;
import cn.wildfirechat.common.ErrorCode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import win.liyufan.im.GitRepositoryState;
import win.liyufan.im.IMTopic;
import java.util.Base64;
@@ -53,7 +54,7 @@ public class GetIMTokenAction extends AdminAction {
LOG.info("get im token success {},{},{}", userId, input.getClientId(), token.substring(0, Math.min(10, token.length())));
return new Result(errorCode1, new OutputGetIMTokenData(userId, token));
return new Result(errorCode1, new OutputGetIMTokenData(userId, token, GitRepositoryState.globalLabel));
} else {
return new Result(errorCode1);
}
@@ -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";
@@ -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<WFCMessage.AddGroupMemberReques
}
}
ErrorCode errorCode = m_messagesStore.addGroupMembers(fromUser, isAdmin, request.getGroupId(), request.getAddedMemberList(), request.getExtra());
Map<String, Integer> 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<String> 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;
}
}
@@ -16,6 +16,7 @@ import io.netty.buffer.ByteBuf;
import cn.wildfirechat.common.ErrorCode;
import win.liyufan.im.IMTopic;
import static cn.wildfirechat.proto.ProtoConstants.RequestSourceType.Request_From_Admin;
import static win.liyufan.im.IMTopic.PutUserSettingTopic;
import static win.liyufan.im.UserSettingScope.kUserSettingMyChannels;
@@ -42,7 +43,13 @@ public class CreateChannelHandler extends GroupHandler<WFCMessage.ChannelInfo> {
if (errorCode == ErrorCode.ERROR_CODE_SUCCESS) {
WFCMessage.ModifyUserSettingReq modifyUserSettingReq = WFCMessage.ModifyUserSettingReq.newBuilder().setScope(kUserSettingMyChannels).setKey(request.getTargetId()).setValue("1").build();
mServer.onApiMessage(fromUser, null, modifyUserSettingReq.toByteArray(), 0, fromUser, PutUserSettingTopic, requestSourceType);
byte[] data = request.getTargetId().getBytes();
byte[] data;
if (requestSourceType == Request_From_Admin) {
//When server api create channel, need return channelId and secret together.
data = (request.getTargetId() + "|" + request.getSecret()).getBytes();
} else {
data = request.getTargetId().getBytes();
}
ackPayload.ensureWritable(data.length).writeBytes(data);
return ErrorCode.ERROR_CODE_SUCCESS;
} else {
@@ -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<WFCMessage.CreateGroupRequest> {
@Override
@@ -51,14 +54,21 @@ public class CreateGroupHandler extends GroupHandler<WFCMessage.CreateGroupReque
}
}
Map<String, Integer> 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<WFCMessage.CreateGroupReque
WFCMessage.MessageContent content = new GroupNotificationBinaryContent(groupInfo.getTargetId(), fromUser, groupInfo.getName(), "").setExtra(request.getMemberExtra()).getCreateGroupNotifyContent();
sendGroupNotification(fromUser, groupInfo.getTargetId(), request.getToLineList(), content);
}
if(!failedMembers.isEmpty()) {
WFCMessage.MessageContent content = new GroupNotificationBinaryContent(groupInfo.getTargetId(), fromUser, null, "").setMi(failedMembers).getGroupNotifyContent(ProtoConstants.MESSAGE_CONTENT_TYPE_REJECT_JOIN_GROUP);
sendGroupNotification(fromUser, groupInfo.getTargetId(), request.getToLineList(), content);
}
}
byte[] data = groupInfo.getTargetId().getBytes();
ackPayload.ensureWritable(data.length).writeBytes(data);
return ErrorCode.ERROR_CODE_SUCCESS;
if(failedMembers.isEmpty()) {
return ErrorCode.ERROR_CODE_SUCCESS;
} else {
return ErrorCode.ERROR_CODE_PARTLY_SUCCESS;
}
}
}
@@ -255,7 +255,7 @@ public class SendMessageHandler extends IMHandler<WFCMessage.Message> {
} else {
if(mRemoteSensitiveMessageTypes.contains(message.getContent().getType())) {
final WFCMessage.Message finalMsg = message;
publisher.forwardMessageWithCallback(message, mRemoteSensitiveServerUrl, clientID, new HttpUtils.HttpCallback() {
publisher.forwardMessageWithCallback(message, clientID, mRemoteSensitiveServerUrl, new HttpUtils.HttpCallback() {
@Override
public void onSuccess(String content) {
if(StringUtil.isNullOrEmpty(content)) {
@@ -21,7 +21,7 @@ import java.util.List;
public class UserSearchHandler extends IMHandler<WFCMessage.SearchUserRequest> {
@Override
public ErrorCode action(ByteBuf ackPayload, String clientID, String fromUser, ProtoConstants.RequestSourceType requestSourceType, WFCMessage.SearchUserRequest request, Qos1PublishHandler.IMCallback callback) {
List<WFCMessage.User> users = m_messagesStore.searchUser(request.getKeyword(), request.getFuzzy(), request.getPage());
List<WFCMessage.User> users = m_messagesStore.searchUser(request.getKeyword(), request.getFuzzy(), request.getType(), request.getPage());
WFCMessage.SearchUserResult.Builder builder = WFCMessage.SearchUserResult.newBuilder();
builder.addAllEntry(users);
byte[] data = builder.build().toByteArray();
@@ -36,6 +36,8 @@ import java.util.function.Function;
import static cn.wildfirechat.common.IMExceptionEvent.EventType.RDBS_Exception;
import static cn.wildfirechat.proto.ProtoConstants.PersistFlag.Transparent;
import static cn.wildfirechat.proto.ProtoConstants.UserSearchUserType.UserSearchUserType_ONLY_ROBOT;
import static cn.wildfirechat.proto.ProtoConstants.UserSearchUserType.UserSearchUserType_ONLY_USER;
import static io.moquette.BrokerConstants.GROUP_INFO_MARK_DELETION;
import static io.moquette.server.Constants.MAX_MESSAGE_QUEUE;
import static cn.wildfirechat.proto.ProtoConstants.SearchUserType.*;
@@ -169,7 +171,7 @@ public class DatabaseStore {
return null;
}
List<WFCMessage.User> searchUserByNameMobileUserId(String keyword, int searchType) {
List<WFCMessage.User> searchUserByNameMobileUserId(String keyword, int searchType, int userType) {
ArrayList<WFCMessage.User> out = new ArrayList<>();
Connection connection = null;
PreparedStatement statement = null;
@@ -203,7 +205,15 @@ public class DatabaseStore {
sql += " where (`_name` = ? or `_mobile` = ? or `_uid` = ?) ";
}
sql += " and `_type` <> 2 and `_deleted` = 0"; //can search normal user(0) and robot(1) and admin(100), can not search things
if(userType == UserSearchUserType_ONLY_USER) {
sql += " and _type <> 2 "; //can not search device
sql += " and _type <> 1 ";
} else if(userType == UserSearchUserType_ONLY_ROBOT) {
sql += " and _type = 1 ";
} else {
sql += " and _type <> 2 "; //can not search device
}
sql += " and _deleted = 0 ";
if(searchType == SearchUserType_Name || searchType == SearchUserType_Mobile || searchType == SearchUserType_UserId) {
sql += " limit 1";
@@ -408,7 +418,7 @@ public class DatabaseStore {
return out;
}
List<WFCMessage.User> searchUserByDisplayName(String keyword, int page, List<WFCMessage.User> nameOrIdMatched) {
List<WFCMessage.User> searchUserByDisplayName(String keyword, int userType, int page, List<WFCMessage.User> nameOrIdMatched) {
Connection connection = null;
PreparedStatement statement = null;
ResultSet rs = null;
@@ -419,7 +429,18 @@ public class DatabaseStore {
connection = DBUtil.getConnection();
String sql = "select u._uid, u._name, u._display_name, u._portrait, u._mobile, u._gender, u._email, u._address, u._company, u._social, u._extra, u._dt, u._type " +
" from t_user u left join (select _uid, _value from t_user_setting where _scope = 27) s on u._uid = s._uid " +
" where u._display_name like ? ESCAPE '!' and u._type <> 2 and u._deleted = 0 ";
" where u._display_name like ? ESCAPE '!' ";
if(userType == UserSearchUserType_ONLY_USER) {
sql += " and u._type <> 2 ";
sql += " and u._type <> 1 ";
} else if(userType == UserSearchUserType_ONLY_ROBOT) {
sql += " and u._type = 1 ";
} else {
sql += " and u._type <> 2 ";
}
sql += " and u._deleted = 0 ";
if(nameOrIdMatched.size() == 1) {
sql += " and u._uid <> ? and u._name <> ?";
} else if(nameOrIdMatched.size() == 2) {
@@ -523,15 +544,15 @@ public class DatabaseStore {
return out;
}
List<WFCMessage.User> searchUserFromDB(String keyword, int searchType, int page) {
List<WFCMessage.User> nameOrIdMatched = searchUserByNameMobileUserId(keyword, searchType);
List<WFCMessage.User> searchUserFromDB(String keyword, int searchType, int userType, int page) {
List<WFCMessage.User> nameOrIdMatched = searchUserByNameMobileUserId(keyword, searchType, userType);
List<WFCMessage.User> out = new ArrayList<>();
if(page == 0) {
out.addAll(nameOrIdMatched);
}
if(searchType == SearchUserType_General || searchType == SearchUserType_Name_Mobile_DisplayName) {
List<WFCMessage.User> general = searchUserByDisplayName(keyword, page, nameOrIdMatched);
List<WFCMessage.User> general = searchUserByDisplayName(keyword, userType, page, nameOrIdMatched);
general.removeAll(nameOrIdMatched);
out.addAll(general);
}
@@ -56,6 +56,7 @@ import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import static cn.wildfirechat.common.IMExceptionEvent.EventType.EVENT_CALLBACK_Exception;
@@ -167,6 +168,7 @@ public class MemoryMessagesStore implements IMessagesStore {
private Set<String> mAllowStrangerChatSet = new HashSet<>();
private Set<Integer> mAllowStrangerLineSet = new HashSet<>();
private boolean mDisableStrangerAddGroup = false;
private boolean mGroupAllowPartSuccess = false;
private boolean mIDUseUUID = true;
@@ -630,6 +632,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) {}
@@ -838,6 +845,18 @@ public class MemoryMessagesStore implements IMessagesStore {
return pullType;
}
private final Map<String, Integer> unreceivedMsgCount = new ConcurrentHashMap<>();
@Override
public void increaseUnreceivedMsgCount(String user) {
unreceivedMsgCount.compute(user, (s, integer) -> integer == null ? 1 : integer+1);
}
@Override
public int getUnreceivedMsgCount(String user) {
return unreceivedMsgCount.getOrDefault(user, 0);
}
@Override
public Set<String> getAllEnds() {
return databaseStore.getAllEnds(mBroadcastTargetFromUserTable);
@@ -852,7 +871,7 @@ public class MemoryMessagesStore implements IMessagesStore {
MemorySessionStore.Session session = m_Server.getStore().sessionsStore().getSession(exceptClientId);
session.refreshLastActiveTime();
if (pullType != ProtoConstants.PullType.Pull_ChatRoom) {
session.setUnReceivedMsgs(0);
unreceivedMsgCount.put(user, 0);
} else {
session.refreshLastChatroomActiveTime();
}
@@ -1282,7 +1301,7 @@ public class MemoryMessagesStore implements IMessagesStore {
}
@Override
public ErrorCode canAddGroupMembers(String fromUser, List<WFCMessage.GroupMember> memberList) {
public ErrorCode canAddGroupMembers(String fromUser, List<WFCMessage.GroupMember> memberList, Map<String, Integer> failedMembers) {
HazelcastInstance hzInstance = m_Server.getHazelcastInstance();
MultiMap<String, FriendData> friendsMap = hzInstance.getMultiMap(USER_FRIENDS);
IMap<String, WFCMessage.User> mUserMap = hzInstance.getMap(USERS);
@@ -1308,7 +1327,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 +1356,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 +1377,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 +1394,7 @@ public class MemoryMessagesStore implements IMessagesStore {
}
@Override
public WFCMessage.GroupInfo createGroup(String fromUser, WFCMessage.GroupInfo groupInfo, List<WFCMessage.GroupMember> memberList, String memberExtra, boolean isAdmin) {
public WFCMessage.GroupInfo createGroup(String fromUser, WFCMessage.GroupInfo groupInfo, List<WFCMessage.GroupMember> memberList, String memberExtra, boolean isAdmin, Map<String, Integer> failedMembers) {
HazelcastInstance hzInstance = m_Server.getHazelcastInstance();
IMap<String, WFCMessage.GroupInfo> mIMap = hzInstance.getMap(GROUPS_MAP);
@@ -1383,6 +1416,9 @@ public class MemoryMessagesStore implements IMessagesStore {
List<WFCMessage.GroupMember> 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 +1613,7 @@ public class MemoryMessagesStore implements IMessagesStore {
}
@Override
public ErrorCode addGroupMembers(String operator, boolean isAdmin, String groupId, List<WFCMessage.GroupMember> memberList, String extra) {
public ErrorCode addGroupMembers(String operator, boolean isAdmin, String groupId, List<WFCMessage.GroupMember> memberList, String extra, Map<String, Integer> failedMembers) {
HazelcastInstance hzInstance = m_Server.getHazelcastInstance();
IMap<String, WFCMessage.GroupInfo> mIMap = hzInstance.getMap(GROUPS_MAP);
@@ -1650,6 +1686,10 @@ public class MemoryMessagesStore implements IMessagesStore {
List<WFCMessage.GroupMember> 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 +1722,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 +1745,10 @@ public class MemoryMessagesStore implements IMessagesStore {
List<String> memberIds = new ArrayList<>();
for (WFCMessage.GroupMember member : memberList) {
if(failedMembers.containsKey(member.getMemberId())) {
continue;
}
if (member.getType() != GroupMemberType_Removed) {
memberIds.add(member.getMemberId());
}
@@ -1963,6 +2011,14 @@ public class MemoryMessagesStore implements IMessagesStore {
newInfoBuilder.setPrivateChat(Integer.parseInt(value));
else if(modifyType == Modify_Group_Searchable)
newInfoBuilder.setSearchable(Integer.parseInt(value));
else if(modifyType == Modify_Group_Type) {
int newType = Integer.parseInt(value);
if(newType < 0 || newType > ProtoConstants.GroupType.GroupType_Organization) {
LOG.error("modify group type failure, invalid group type {}", newType);
return ErrorCode.INVALID_PARAMETER;
}
newInfoBuilder.setType(newType);
}
else
return ErrorCode.INVALID_PARAMETER;
@@ -2480,7 +2536,7 @@ public class MemoryMessagesStore implements IMessagesStore {
}
boolean isExpired = false;
if (!canRecall && message.getFromUser().equals(operatorId)) {
if (mRecallTimeLimit > 0 && now - message.getServerTimestamp() > mRecallTimeLimit * 1000) {
if (mRecallTimeLimit >= 0 && now - message.getServerTimestamp() > mRecallTimeLimit * 1000) {
isExpired = true;
} else {
canRecall = true;
@@ -3101,7 +3157,7 @@ public class MemoryMessagesStore implements IMessagesStore {
}
@Override
public List<WFCMessage.User> searchUser(String keyword, int searchType, int page) {
public List<WFCMessage.User> searchUser(String keyword, int searchType, int userType, int page) {
if (mDisableSearch) {
return new ArrayList<>();
}
@@ -3122,7 +3178,7 @@ public class MemoryMessagesStore implements IMessagesStore {
return new ArrayList<>();
}
return databaseStore.searchUserFromDB(keyword, searchType, page);
return databaseStore.searchUserFromDB(keyword, searchType, userType, page);
}
@Override
@@ -4484,7 +4540,7 @@ public class MemoryMessagesStore implements IMessagesStore {
} else if(modifyType == Modify_Channel_Menu) {
OutputGetChannelInfo.OutputMenuList outputMenuButtons = GsonUtil.gson.fromJson(value, OutputGetChannelInfo.OutputMenuList.class);
if (!outputMenuButtons.isEmpty()) {
for (OutputGetChannelInfo.OutputMenu outputMenuButton : outputMenuButtons) {
for (PojoChannelMenu outputMenuButton : outputMenuButtons) {
newInfoBuilder.addMenu(outputMenuButton.toPbInfo());
}
}
@@ -4740,6 +4796,11 @@ public class MemoryMessagesStore implements IMessagesStore {
return mGroupVisibleQuitKickoffNotification;
}
@Override
public boolean isGroupAllowPartSuccess() {
return mGroupAllowPartSuccess;
}
@Override
public int getGroupForbiddenClientOperation() {
return mGroupForbiddenClientOperation;
@@ -92,10 +92,6 @@ public class MemorySessionStore implements ISessionsStore {
return unReceivedMsgs;
}
public void setUnReceivedMsgs(int unReceivedMsgs) {
this.unReceivedMsgs = unReceivedMsgs;
}
public int getPushType() {
return pushType;
}
@@ -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<Integer> contentTypes);
long insertUserMessages(String sender, int conversationType, String target, int line, int messageContentType, String userId, long messageId, boolean directing);
ErrorCode canAddGroupMembers(String operator, List<WFCMessage.GroupMember> memberList);
WFCMessage.GroupInfo createGroup(String operator, WFCMessage.GroupInfo groupInfo, List<WFCMessage.GroupMember> memberList, String memberExtra, boolean isAdmin);
ErrorCode addGroupMembers(String operator, boolean isAdmin, String groupId, List<WFCMessage.GroupMember> memberList, String extra);
ErrorCode canAddGroupMembers(String operator, List<WFCMessage.GroupMember> memberList, Map<String, Integer> failedMembers);
WFCMessage.GroupInfo createGroup(String operator, WFCMessage.GroupInfo groupInfo, List<WFCMessage.GroupMember> memberList, String memberExtra, boolean isAdmin, Map<String, Integer> failedMembers);
ErrorCode addGroupMembers(String operator, boolean isAdmin, String groupId, List<WFCMessage.GroupMember> memberList, String extra, Map<String, Integer> failedMembers);
ErrorCode kickoffGroupMembers(String operator, boolean isAdmin, String groupId, List<String> memberList);
ErrorCode quitGroup(String operator, String groupId, boolean admin);
void clearUserGroups(String userId);
@@ -154,7 +154,7 @@ public interface IMessagesStore {
WFCMessage.User getUserInfoByName(String name);
WFCMessage.User getUserInfoByMobile(String mobile);
List<WFCMessage.User> getUserInfosByEmail(String email);
List<WFCMessage.User> searchUser(String keyword, int searchType, int page);
List<WFCMessage.User> searchUser(String keyword, int searchType, int userType, int page);
List<WFCMessage.User> getUserInfoList(int count, int offset);
@@ -235,6 +235,9 @@ public interface IMessagesStore {
WFCMessage.Message getMessage(long messageId);
void increaseUnreceivedMsgCount(String user);
int getUnreceivedMsgCount(String user);
boolean isAllowClientCustomGroupNotification();
boolean isAllowRobotCustomGroupNotification();
int getVisibleQuitKickoffNotification();
@@ -253,7 +256,7 @@ public interface IMessagesStore {
boolean isChannelCallbackWithSenderInfo();
boolean isChannelCallbackWithTargetInfo();
boolean isChannelNewCallbackFeature();
boolean isGroupAllowPartSuccess();
boolean isRobotAutoAcceptFriendRequest();
long getPushExpiredTimes();
@@ -178,19 +178,10 @@ public class MessagesPublisher {
if (message == null) {
message = m_messagesStore.getMessage(messageId);
}
OutputClient outputClient = null;
if(m_messagesStore.isRobotCallbackWithClientInfo() && !StringUtil.isNullOrEmpty(exceptClientId)) {
Session session = m_sessionsStore.getSession(exceptClientId);
if(session != null && session.getUsername().equals(sender)) {
outputClient = new OutputClient(session.getPlatform(), exceptClientId);
}
}
final WFCMessage.Message finalMsg = message;
OutputClient finalOutputClient = outputClient;
OutputMessageData outputMessageData = getOutputMessageWithExtraInfo(message, exceptClientId, m_messagesStore.isRobotCallbackWithClientInfo() , m_messagesStore.isRobotCallbackWithSenderInfo(), m_messagesStore.isRobotCallbackWithTargetInfo());
Server.getServer().getCallbackScheduler().execute(() -> {
try {
HttpUtils.httpJsonPost(robot.getCallback(), GsonUtil.gson.toJson(OutputMessageData.fromProtoMessage(finalMsg, finalOutputClient), OutputMessageData.class), HttpUtils.HttpPostType.POST_TYPE_Robot_Message_Callback);
HttpUtils.httpJsonPost(robot.getCallback(), GsonUtil.gson.toJson(outputMessageData, OutputMessageData.class), HttpUtils.HttpPostType.POST_TYPE_Robot_Message_Callback);
} catch (Exception e) {
e.printStackTrace();
Utility.printExecption(LOG, e, EVENT_CALLBACK_Exception);
@@ -324,7 +315,7 @@ public class MessagesPublisher {
if (!StringUtil.isNullOrEmpty(pushContent) || messageContentType == 400) {
if (!isConvSilent && (persistFlag & 0x02) > 0) {
targetSession.setUnReceivedMsgs(targetSession.getUnReceivedMsgs() + 1);
m_messagesStore.increaseUnreceivedMsgCount(user);
}
}
}
@@ -423,13 +414,25 @@ public class MessagesPublisher {
name = fd.getAlias();
}
}
this.messageSender.sendPush(sender, conversationType, target, line, messageId, targetSession.getClientID(), pushContent, pushData, callStartUid, messageContentType, serverTime, name, senderPortrait, targetName, targetPortrait, targetSession.getUnReceivedMsgs(), curMentionType, isHiddenDetail, targetSession.getLanguage());
this.messageSender.sendPush(sender, conversationType, target, line, messageId, targetSession.getClientID(), pushContent, pushData, callStartUid, messageContentType, serverTime, name, senderPortrait, targetName, targetPortrait, m_messagesStore.getUnreceivedMsgCount(user), curMentionType, isHiddenDetail, targetSession.getLanguage(), getExistBadgeNumber(user));
}
}
}
}
private int getExistBadgeNumber(String user) {
int existBadgeNumber = 0;
WFCMessage.UserSettingEntry userSettingData = m_messagesStore.getUserSetting(user, UserSettingScope.kUserSettingScopeSyncBadge, "");
if(userSettingData != null && !StringUtil.isNullOrEmpty(userSettingData.getValue())) {
try {
existBadgeNumber = Integer.parseInt(userSettingData.getValue());
} catch (NumberFormatException e) {}
}
return existBadgeNumber;
}
public boolean sendOfflineNotify(String clientId) {
boolean targetIsActive = this.connectionDescriptors.isConnected(clientId);
if (targetIsActive) {
@@ -595,7 +598,7 @@ public class MessagesPublisher {
}
if (IMTopic.NotifyFriendRequestTopic.equals(topic)) {
messageSender.sendPush(fromUser, receiver, targetSession.getClientID(), pushContent, PushServer.PushMessageType.PUSH_MESSAGE_TYPE_FRIEND_REQUEST, System.currentTimeMillis(), fromUserName, targetSession.getUnReceivedMsgs() + 1, targetSession.getLanguage());
messageSender.sendPush(fromUser, receiver, targetSession.getClientID(), pushContent, PushServer.PushMessageType.PUSH_MESSAGE_TYPE_FRIEND_REQUEST, System.currentTimeMillis(), fromUserName, m_messagesStore.getUnreceivedMsgCount(receiver) + 1, targetSession.getLanguage(), getExistBadgeNumber(receiver));
}
}
}
@@ -37,17 +37,18 @@ class PersistentQueueMessageSender {
this.connectionDescriptorStore = connectionDescriptorStore;
}
void sendPush(String sender, int conversationType, String target, int line, long messageId, String deviceId, String pushContent, String pushData, long callStartUid, int messageContentType, long serverTime, String senderName, String senderPortrait, String targetName, String targetPortrait, int unReceivedMsg, int mentionType, boolean isHiddenDetail, String language) {
void sendPush(String sender, int conversationType, String target, int line, long messageId, String deviceId, String pushContent, String pushData, long callStartUid, int messageContentType, long serverTime, String senderName, String senderPortrait, String targetName, String targetPortrait, int unReceivedMsg, int mentionType, boolean isHiddenDetail, String language, int existBadgeNumber) {
LOG.info("Send push to {}, message from {}", deviceId, sender);
PushMessage pushMessage = new PushMessage(sender, conversationType, target, line, messageContentType, serverTime, senderName, senderPortrait, targetName, targetPortrait, unReceivedMsg, mentionType, isHiddenDetail, language);
pushMessage.pushContent = pushContent;
pushMessage.pushData = pushData;
pushMessage.messageId = messageId;
pushMessage.callStartUid = callStartUid;
pushMessage.existBadgeNumber = existBadgeNumber;
PushServer.getServer().pushMessage(pushMessage, deviceId, pushContent);
}
void sendPush(String sender, String target, String deviceId, String pushContent, int pushContentType, long serverTime, String senderName, int unReceivedMsg, String language) {
void sendPush(String sender, String target, String deviceId, String pushContent, int pushContentType, long serverTime, String senderName, int unReceivedMsg, String language, int existBadgeNumber) {
LOG.info("Send push to {}, message from {}", deviceId, sender);
PushMessage pushMessage = new PushMessage(sender, target, serverTime, senderName, unReceivedMsg, language, pushContentType);
pushMessage.pushContent = pushContent;
@@ -12,6 +12,7 @@ import io.moquette.server.Server;
import java.io.*;
import java.util.Properties;
import java.util.UUID;
public class GitRepositoryState {
public final String tags;
@@ -28,6 +29,8 @@ public class GitRepositoryState {
public final String commitMessageFull;
public final String commitMessageShort;
public final String commitTime;
public static final String globalLabel = UUID.randomUUID().toString();
public String label;
public final String closestTagName;
public final String closestTagCommitCount;
@@ -63,6 +66,7 @@ public class GitRepositoryState {
this.buildHost = String.valueOf(properties.get("git.build.host"));
this.buildVersion = String.valueOf(properties.get("git.build.version"));
this.runTime = Server.getServer().getRunTime();
this.label = globalLabel;
}
public static GitRepositoryState getGitRepositoryState() throws IOException {
@@ -21,4 +21,5 @@ public interface UserSettingScope {
int kUserSettingGroupRemark = 26;
int kUserSettingPrivacySearchable = 27;
int kUserSettingAddFriendStrategy = 28;
int kUserSettingScopeSyncBadge = 29;
}
+1 -1
View File
@@ -5,7 +5,7 @@
<parent>
<artifactId>wildfirechat-parent</artifactId>
<groupId>cn.wildfirechat</groupId>
<version>1.3.5</version>
<version>1.3.7</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -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"),
@@ -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<String, Integer> mi;
private String extra;
public GroupNotificationBinaryContent() {
@@ -92,6 +95,11 @@ public class GroupNotificationBinaryContent {
this.ms = ms;
}
public GroupNotificationBinaryContent setMi(Map<String, Integer> mi) {
this.mi = mi;
return this;
}
public GroupNotificationBinaryContent setExtra(String extra) {
this.extra = extra;
return this;
@@ -12,6 +12,9 @@ package cn.wildfirechat.pojos;
import cn.wildfirechat.proto.WFCMessage;
import io.netty.util.internal.StringUtil;
import java.util.ArrayList;
import java.util.List;
public class InputCreateChannel {
private String owner;
private String name;
@@ -24,6 +27,7 @@ public class InputCreateChannel {
private int state;
private String extra;
private long updateDt;
public List<PojoChannelMenu> menus;
public WFCMessage.ChannelInfo toProtoChannelInfo() {
WFCMessage.ChannelInfo.Builder builder = WFCMessage.ChannelInfo.newBuilder().setOwner(owner);
@@ -48,6 +52,12 @@ public class InputCreateChannel {
else
builder = builder.setUpdateDt(System.currentTimeMillis());
if (menus != null && !menus.isEmpty()) {
for (PojoChannelMenu menu : menus) {
builder.addMenu(menu.toPbInfo());
}
}
return builder.build();
}
@@ -13,9 +13,11 @@ import cn.wildfirechat.proto.WFCMessage;
public class OutputCreateChannel {
private String targetId;
private String secret;
public OutputCreateChannel(String targetId) {
public OutputCreateChannel(String targetId, String secret) {
this.targetId = targetId;
this.secret = secret;
}
public String getTargetId() {
@@ -25,4 +27,12 @@ public class OutputCreateChannel {
public void setTargetId(String targetId) {
this.targetId = targetId;
}
public String getSecret() {
return secret;
}
public void setSecret(String secret) {
this.secret = secret;
}
}
@@ -16,61 +16,7 @@ import java.util.ArrayList;
import java.util.List;
public class OutputGetChannelInfo {
public static class OutputMenu {
public String menuId;
public String type;
public String name;
public String key;
public String url;
public String mediaId;
public String articleId;
public String appId;
public String appPage;
public String extra;
public List<OutputMenu> subMenus;
public static OutputMenu fromPbInfo(WFCMessage.ChannelMenu channelMenuMenu) {
OutputMenu out = new OutputMenu();
out.menuId = channelMenuMenu.getMenuId();
out.type = channelMenuMenu.getType();
out.name = channelMenuMenu.getName();
out.key = channelMenuMenu.getKey();
out.url = channelMenuMenu.getUrl();
out.mediaId = channelMenuMenu.getMediaId();
out.articleId = channelMenuMenu.getArticleId();
out.appId = channelMenuMenu.getAppId();
out.appPage = channelMenuMenu.getAppPage();
out.extra = channelMenuMenu.getExtra();
if (channelMenuMenu.getSubMenuCount() > 0) {
out.subMenus = new ArrayList<>();
for (WFCMessage.ChannelMenu menuMenu : channelMenuMenu.getSubMenuList()) {
out.subMenus.add(fromPbInfo(menuMenu));
}
}
return out;
}
public WFCMessage.ChannelMenu.Builder toPbInfo() {
WFCMessage.ChannelMenu.Builder builder = WFCMessage.ChannelMenu.newBuilder();
builder.setType(type);
builder.setName(name);
if (!StringUtil.isNullOrEmpty(menuId)) builder.setMenuId(menuId);
if (!StringUtil.isNullOrEmpty(key)) builder.setKey(key);
if (!StringUtil.isNullOrEmpty(url)) builder.setUrl(url);
if (!StringUtil.isNullOrEmpty(mediaId)) builder.setMediaId(mediaId);
if (!StringUtil.isNullOrEmpty(articleId)) builder.setArticleId(articleId);
if (!StringUtil.isNullOrEmpty(appId)) builder.setAppId(appId);
if (!StringUtil.isNullOrEmpty(appPage)) builder.setAppPage(appPage);
if (!StringUtil.isNullOrEmpty(extra)) builder.setExtra(extra);
if (subMenus != null && !subMenus.isEmpty()) {
subMenus.forEach(menuMenu -> builder.addSubMenu(menuMenu.toPbInfo()));
}
return builder;
}
}
public static class OutputMenuList extends ArrayList<OutputMenu> {
public static class OutputMenuList extends ArrayList<PojoChannelMenu> {
}
private String channelId;
@@ -85,7 +31,7 @@ public class OutputGetChannelInfo {
private String callback;
private int automatic;
private String secret;
public List<OutputMenu> menus;
public List<PojoChannelMenu> menus;
public String getChannelId() {
return channelId;
@@ -200,7 +146,7 @@ public class OutputGetChannelInfo {
if (channelInfo.getMenuCount() > 0) {
out.menus = new ArrayList<>();
for (WFCMessage.ChannelMenu channelMenuMenu : channelInfo.getMenuList()) {
out.menus.add(OutputMenu.fromPbInfo(channelMenuMenu));
out.menus.add(PojoChannelMenu.fromPbInfo(channelMenuMenu));
}
}
return out;
@@ -3,13 +3,15 @@ package cn.wildfirechat.pojos;
public class OutputGetIMTokenData {
private String userId;
private String token;
private String serverLabel;
public OutputGetIMTokenData() {
}
public OutputGetIMTokenData(String userId, String imToken) {
public OutputGetIMTokenData(String userId, String imToken, String label) {
this.userId = userId;
this.token = imToken;
this.serverLabel = label;
}
public String getUserId() {
@@ -27,4 +29,12 @@ public class OutputGetIMTokenData {
public void setToken(String token) {
this.token = token;
}
public String getServerLabel() {
return serverLabel;
}
public void setServerLabel(String serverLabel) {
this.serverLabel = serverLabel;
}
}
@@ -0,0 +1,60 @@
package cn.wildfirechat.pojos;
import cn.wildfirechat.proto.WFCMessage;
import io.netty.util.internal.StringUtil;
import java.util.ArrayList;
import java.util.List;
public class PojoChannelMenu {
public String menuId;
public String type;
public String name;
public String key;
public String url;
public String mediaId;
public String articleId;
public String appId;
public String appPage;
public String extra;
public List<PojoChannelMenu> subMenus;
public static PojoChannelMenu fromPbInfo(WFCMessage.ChannelMenu channelMenuMenu) {
PojoChannelMenu out = new PojoChannelMenu();
out.menuId = channelMenuMenu.getMenuId();
out.type = channelMenuMenu.getType();
out.name = channelMenuMenu.getName();
out.key = channelMenuMenu.getKey();
out.url = channelMenuMenu.getUrl();
out.mediaId = channelMenuMenu.getMediaId();
out.articleId = channelMenuMenu.getArticleId();
out.appId = channelMenuMenu.getAppId();
out.appPage = channelMenuMenu.getAppPage();
out.extra = channelMenuMenu.getExtra();
if (channelMenuMenu.getSubMenuCount() > 0) {
out.subMenus = new ArrayList<>();
for (WFCMessage.ChannelMenu menuMenu : channelMenuMenu.getSubMenuList()) {
out.subMenus.add(fromPbInfo(menuMenu));
}
}
return out;
}
public WFCMessage.ChannelMenu.Builder toPbInfo() {
WFCMessage.ChannelMenu.Builder builder = WFCMessage.ChannelMenu.newBuilder();
builder.setType(type);
builder.setName(name);
if (!StringUtil.isNullOrEmpty(menuId)) builder.setMenuId(menuId);
if (!StringUtil.isNullOrEmpty(key)) builder.setKey(key);
if (!StringUtil.isNullOrEmpty(url)) builder.setUrl(url);
if (!StringUtil.isNullOrEmpty(mediaId)) builder.setMediaId(mediaId);
if (!StringUtil.isNullOrEmpty(articleId)) builder.setArticleId(articleId);
if (!StringUtil.isNullOrEmpty(appId)) builder.setAppId(appId);
if (!StringUtil.isNullOrEmpty(appPage)) builder.setAppPage(appPage);
if (!StringUtil.isNullOrEmpty(extra)) builder.setExtra(extra);
if (subMenus != null && !subMenus.isEmpty()) {
subMenus.forEach(menuMenu -> builder.addSubMenu(menuMenu.toPbInfo()));
}
return builder;
}
}
@@ -3,6 +3,7 @@ package cn.wildfirechat.pojos.mesh;
public class PojoSearchUserReq {
public String keyword;
public int searchType;
public int userType;
public int page;
public String domainId;
@@ -22,6 +23,14 @@ public class PojoSearchUserReq {
this.searchType = searchType;
}
public int getUserType() {
return userType;
}
public void setUserType(int userType) {
this.userType = userType;
}
public int getPage() {
return page;
}
@@ -172,6 +172,7 @@ public class ProtoConstants {
int Modify_Group_Max_Member_Count = 8;
//仅专业版的server api支持
int Modify_Group_Super_Group = 9;
int Modify_Group_Type = 10;
}
//ModifyGroupInfoRequest -> type
@@ -237,6 +238,12 @@ public class ProtoConstants {
int SearchUserType_Name_Mobile_DisplayName = 100;
}
public interface UserSearchUserType {
int UserSearchUserType_ALL = 0;
int UserSearchUserType_ONLY_USER = 1;
int UserSearchUserType_ONLY_ROBOT = 2;
}
public interface DisableSearchMask {
int DisableSearchDisplayNameMask = 1;
int DisableSearchNameMask = 2;
@@ -389,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;
}
@@ -54041,6 +54041,31 @@ public final class WFCMessage {
* <code>optional int32 page = 3;</code>
*/
int getPage();
// optional string domain_id = 4;
/**
* <code>optional string domain_id = 4;</code>
*/
boolean hasDomainId();
/**
* <code>optional string domain_id = 4;</code>
*/
java.lang.String getDomainId();
/**
* <code>optional string domain_id = 4;</code>
*/
com.google.protobuf.ByteString
getDomainIdBytes();
// optional int32 type = 5;
/**
* <code>optional int32 type = 5;</code>
*/
boolean hasType();
/**
* <code>optional int32 type = 5;</code>
*/
int getType();
}
/**
* Protobuf type {@code SearchUserRequest}
@@ -54108,6 +54133,16 @@ public final class WFCMessage {
page_ = input.readInt32();
break;
}
case 34: {
bitField0_ |= 0x00000008;
domainId_ = input.readBytes();
break;
}
case 40: {
bitField0_ |= 0x00000010;
type_ = input.readInt32();
break;
}
}
}
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
@@ -54223,10 +54258,71 @@ public final class WFCMessage {
return page_;
}
// optional string domain_id = 4;
public static final int DOMAIN_ID_FIELD_NUMBER = 4;
private java.lang.Object domainId_;
/**
* <code>optional string domain_id = 4;</code>
*/
public boolean hasDomainId() {
return ((bitField0_ & 0x00000008) == 0x00000008);
}
/**
* <code>optional string domain_id = 4;</code>
*/
public java.lang.String getDomainId() {
java.lang.Object ref = domainId_;
if (ref instanceof java.lang.String) {
return (java.lang.String) ref;
} else {
com.google.protobuf.ByteString bs =
(com.google.protobuf.ByteString) ref;
java.lang.String s = bs.toStringUtf8();
if (bs.isValidUtf8()) {
domainId_ = s;
}
return s;
}
}
/**
* <code>optional string domain_id = 4;</code>
*/
public com.google.protobuf.ByteString
getDomainIdBytes() {
java.lang.Object ref = domainId_;
if (ref instanceof java.lang.String) {
com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
domainId_ = b;
return b;
} else {
return (com.google.protobuf.ByteString) ref;
}
}
// optional int32 type = 5;
public static final int TYPE_FIELD_NUMBER = 5;
private int type_;
/**
* <code>optional int32 type = 5;</code>
*/
public boolean hasType() {
return ((bitField0_ & 0x00000010) == 0x00000010);
}
/**
* <code>optional int32 type = 5;</code>
*/
public int getType() {
return type_;
}
private void initFields() {
keyword_ = "";
fuzzy_ = 0;
page_ = 0;
domainId_ = "";
type_ = 0;
}
private byte memoizedIsInitialized = -1;
public final boolean isInitialized() {
@@ -54253,6 +54349,12 @@ public final class WFCMessage {
if (((bitField0_ & 0x00000004) == 0x00000004)) {
output.writeInt32(3, page_);
}
if (((bitField0_ & 0x00000008) == 0x00000008)) {
output.writeBytes(4, getDomainIdBytes());
}
if (((bitField0_ & 0x00000010) == 0x00000010)) {
output.writeInt32(5, type_);
}
getUnknownFields().writeTo(output);
}
@@ -54274,6 +54376,14 @@ public final class WFCMessage {
size += com.google.protobuf.CodedOutputStream
.computeInt32Size(3, page_);
}
if (((bitField0_ & 0x00000008) == 0x00000008)) {
size += com.google.protobuf.CodedOutputStream
.computeBytesSize(4, getDomainIdBytes());
}
if (((bitField0_ & 0x00000010) == 0x00000010)) {
size += com.google.protobuf.CodedOutputStream
.computeInt32Size(5, type_);
}
size += getUnknownFields().getSerializedSize();
memoizedSerializedSize = size;
return size;
@@ -54396,6 +54506,10 @@ public final class WFCMessage {
bitField0_ = (bitField0_ & ~0x00000002);
page_ = 0;
bitField0_ = (bitField0_ & ~0x00000004);
domainId_ = "";
bitField0_ = (bitField0_ & ~0x00000008);
type_ = 0;
bitField0_ = (bitField0_ & ~0x00000010);
return this;
}
@@ -54436,6 +54550,14 @@ public final class WFCMessage {
to_bitField0_ |= 0x00000004;
}
result.page_ = page_;
if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
to_bitField0_ |= 0x00000008;
}
result.domainId_ = domainId_;
if (((from_bitField0_ & 0x00000010) == 0x00000010)) {
to_bitField0_ |= 0x00000010;
}
result.type_ = type_;
result.bitField0_ = to_bitField0_;
onBuilt();
return result;
@@ -54463,6 +54585,14 @@ public final class WFCMessage {
if (other.hasPage()) {
setPage(other.getPage());
}
if (other.hasDomainId()) {
bitField0_ |= 0x00000008;
domainId_ = other.domainId_;
onChanged();
}
if (other.hasType()) {
setType(other.getType());
}
this.mergeUnknownFields(other.getUnknownFields());
return this;
}
@@ -54634,6 +54764,113 @@ public final class WFCMessage {
return this;
}
// optional string domain_id = 4;
private java.lang.Object domainId_ = "";
/**
* <code>optional string domain_id = 4;</code>
*/
public boolean hasDomainId() {
return ((bitField0_ & 0x00000008) == 0x00000008);
}
/**
* <code>optional string domain_id = 4;</code>
*/
public java.lang.String getDomainId() {
java.lang.Object ref = domainId_;
if (!(ref instanceof java.lang.String)) {
java.lang.String s = ((com.google.protobuf.ByteString) ref)
.toStringUtf8();
domainId_ = s;
return s;
} else {
return (java.lang.String) ref;
}
}
/**
* <code>optional string domain_id = 4;</code>
*/
public com.google.protobuf.ByteString
getDomainIdBytes() {
java.lang.Object ref = domainId_;
if (ref instanceof String) {
com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
domainId_ = b;
return b;
} else {
return (com.google.protobuf.ByteString) ref;
}
}
/**
* <code>optional string domain_id = 4;</code>
*/
public Builder setDomainId(
java.lang.String value) {
if (value == null) {
throw new NullPointerException();
}
bitField0_ |= 0x00000008;
domainId_ = value;
onChanged();
return this;
}
/**
* <code>optional string domain_id = 4;</code>
*/
public Builder clearDomainId() {
bitField0_ = (bitField0_ & ~0x00000008);
domainId_ = getDefaultInstance().getDomainId();
onChanged();
return this;
}
/**
* <code>optional string domain_id = 4;</code>
*/
public Builder setDomainIdBytes(
com.google.protobuf.ByteString value) {
if (value == null) {
throw new NullPointerException();
}
bitField0_ |= 0x00000008;
domainId_ = value;
onChanged();
return this;
}
// optional int32 type = 5;
private int type_ ;
/**
* <code>optional int32 type = 5;</code>
*/
public boolean hasType() {
return ((bitField0_ & 0x00000010) == 0x00000010);
}
/**
* <code>optional int32 type = 5;</code>
*/
public int getType() {
return type_;
}
/**
* <code>optional int32 type = 5;</code>
*/
public Builder setType(int value) {
bitField0_ |= 0x00000010;
type_ = value;
onChanged();
return this;
}
/**
* <code>optional int32 type = 5;</code>
*/
public Builder clearType() {
bitField0_ = (bitField0_ & ~0x00000010);
type_ = 0;
onChanged();
return this;
}
// @@protoc_insertion_point(builder_scope:SearchUserRequest)
}
@@ -67604,44 +67841,45 @@ public final class WFCMessage {
"ead\030\004 \001(\003\022\021\n\tnode_addr\030\005 \001(\t\022\021\n\tnode_por" +
"t\030\006 \001(\005\022\023\n\013server_time\030\007 \001(\003\"P\n\rIMHttpWr",
"apper\022\r\n\005token\030\001 \002(\t\022\021\n\tclient_id\030\002 \002(\t\022" +
"\017\n\007request\030\003 \002(\t\022\014\n\004data\030\004 \001(\014\"A\n\021Search" +
"\017\n\007request\030\003 \002(\t\022\014\n\004data\030\004 \001(\014\"b\n\021Search" +
"UserRequest\022\017\n\007keyword\030\001 \002(\t\022\r\n\005fuzzy\030\002 " +
"\001(\005\022\014\n\004page\030\003 \001(\005\"(\n\020SearchUserResult\022\024\n" +
"\005entry\030\001 \003(\0132\005.User\"@\n\026GetChatroomInfoRe" +
"quest\022\023\n\013chatroom_id\030\001 \002(\t\022\021\n\tupdate_dt\030" +
"\002 \001(\003\"\227\001\n\014ChatroomInfo\022\r\n\005title\030\001 \002(\t\022\014\n" +
"\004desc\030\002 \001(\t\022\020\n\010portrait\030\003 \001(\t\022\024\n\014member_" +
"count\030\004 \001(\005\022\021\n\tcreate_dt\030\005 \001(\003\022\021\n\tupdate" +
"_dt\030\006 \001(\003\022\r\n\005extra\030\007 \001(\t\022\r\n\005state\030\010 \001(\005\"",
"F\n\034GetChatroomMemberInfoRequest\022\023\n\013chatr" +
"oom_id\030\001 \002(\t\022\021\n\tmax_count\030\002 \001(\005\";\n\022Chatr" +
"oomMemberInfo\022\024\n\014member_count\030\001 \001(\005\022\017\n\007m" +
"embers\030\002 \003(\t\"\026\n\010INT64Buf\022\n\n\002id\030\001 \002(\003\"4\n\023" +
"NotifyRecallMessage\022\n\n\002id\030\001 \002(\003\022\021\n\tfrom_" +
"user\030\002 \002(\t\"/\n\020BlackUserRequest\022\013\n\003uid\030\001 " +
"\002(\t\022\016\n\006status\030\002 \002(\005\"\323\001\n\014RouteRequest\022\013\n\003" +
"app\030\001 \001(\t\022\020\n\010platform\030\002 \001(\005\022\021\n\tpush_type" +
"\030\003 \001(\005\022\023\n\013device_name\030\004 \001(\t\022\026\n\016device_ve" +
"rsion\030\005 \001(\t\022\022\n\nphone_name\030\006 \001(\t\022\020\n\010langu",
"age\030\007 \001(\t\022\024\n\014carrier_name\030\010 \001(\t\022\023\n\013app_v" +
"ersion\030\t \001(\t\022\023\n\013sdk_version\030\n \001(\t\"D\n\rRou" +
"teResponse\022\014\n\004host\030\001 \002(\t\022\021\n\tlong_port\030\002 " +
"\002(\005\022\022\n\nshort_port\030\003 \002(\005\"G\n\017GetTokenReque" +
"st\022\017\n\007user_id\030\001 \002(\t\022\021\n\tclient_id\030\002 \002(\t\022\020" +
"\n\010platform\030\003 \001(\005\"r\n\022LoadRemoteMessages\022#" +
"\n\014conversation\030\001 \002(\0132\r.Conversation\022\022\n\nb" +
"efore_uid\030\002 \002(\003\022\r\n\005count\030\003 \002(\005\022\024\n\014conten" +
"t_type\030\004 \003(\005\"a\n\020MultiCastMessage\022\021\n\tfrom" +
"_user\030\001 \002(\t\022 \n\007content\030\002 \002(\0132\017.MessageCo",
"ntent\022\n\n\002to\030\003 \003(\t\022\014\n\004line\030\004 \002(\005\"E\n\035Recal" +
"lMultiCastMessageRequest\022\022\n\nmessage_id\030\001" +
" \002(\003\022\020\n\010receiver\030\002 \003(\t\"@\n\017AuthCodeReques" +
"t\022\021\n\ttarget_id\030\001 \002(\t\022\014\n\004type\030\002 \002(\005\022\014\n\004ho" +
"st\030\003 \002(\t\"o\n\030ApplicationConfigRequest\022\r\n\005" +
"appId\030\001 \002(\t\022\017\n\007appType\030\002 \002(\005\022\021\n\ttimestam" +
"p\030\003 \002(\003\022\r\n\005nonce\030\004 \002(\t\022\021\n\tsignature\030\005 \002(" +
"\tB/\n\025cn.wildfirechat.protoB\nWFCMessageZ\n" +
"./go;proto"
"\001(\005\022\014\n\004page\030\003 \001(\005\022\021\n\tdomain_id\030\004 \001(\t\022\014\n\004" +
"type\030\005 \001(\005\"(\n\020SearchUserResult\022\024\n\005entry\030" +
"\001 \003(\0132\005.User\"@\n\026GetChatroomInfoRequest\022\023" +
"\n\013chatroom_id\030\001 \002(\t\022\021\n\tupdate_dt\030\002 \001(\003\"\227" +
"\001\n\014ChatroomInfo\022\r\n\005title\030\001 \002(\t\022\014\n\004desc\030\002" +
" \001(\t\022\020\n\010portrait\030\003 \001(\t\022\024\n\014member_count\030\004" +
" \001(\005\022\021\n\tcreate_dt\030\005 \001(\003\022\021\n\tupdate_dt\030\006 \001",
"(\003\022\r\n\005extra\030\007 \001(\t\022\r\n\005state\030\010 \001(\005\"F\n\034GetC" +
"hatroomMemberInfoRequest\022\023\n\013chatroom_id\030" +
"\001 \002(\t\022\021\n\tmax_count\030\002 \001(\005\";\n\022ChatroomMemb" +
"erInfo\022\024\n\014member_count\030\001 \001(\005\022\017\n\007members\030" +
"\002 \003(\t\"\026\n\010INT64Buf\022\n\n\002id\030\001 \002(\003\"4\n\023NotifyR" +
"ecallMessage\022\n\n\002id\030\001 \002(\003\022\021\n\tfrom_user\030\002 " +
"\002(\t\"/\n\020BlackUserRequest\022\013\n\003uid\030\001 \002(\t\022\016\n\006" +
"status\030\002 \002(\005\"\323\001\n\014RouteRequest\022\013\n\003app\030\001 \001" +
"(\t\022\020\n\010platform\030\002 \001(\005\022\021\n\tpush_type\030\003 \001(\005\022" +
"\023\n\013device_name\030\004 \001(\t\022\026\n\016device_version\030\005",
" \001(\t\022\022\n\nphone_name\030\006 \001(\t\022\020\n\010language\030\007 \001" +
"(\t\022\024\n\014carrier_name\030\010 \001(\t\022\023\n\013app_version\030" +
"\t \001(\t\022\023\n\013sdk_version\030\n \001(\t\"D\n\rRouteRespo" +
"nse\022\014\n\004host\030\001 \002(\t\022\021\n\tlong_port\030\002 \002(\005\022\022\n\n" +
"short_port\030\003 \002(\005\"G\n\017GetTokenRequest\022\017\n\007u" +
"ser_id\030\001 \002(\t\022\021\n\tclient_id\030\002 \002(\t\022\020\n\010platf" +
"orm\030\003 \001(\005\"r\n\022LoadRemoteMessages\022#\n\014conve" +
"rsation\030\001 \002(\0132\r.Conversation\022\022\n\nbefore_u" +
"id\030\002 \002(\003\022\r\n\005count\030\003 \002(\005\022\024\n\014content_type\030" +
"\004 \003(\005\"a\n\020MultiCastMessage\022\021\n\tfrom_user\030\001",
" \002(\t\022 \n\007content\030\002 \002(\0132\017.MessageContent\022\n" +
"\n\002to\030\003 \003(\t\022\014\n\004line\030\004 \002(\005\"E\n\035RecallMultiC" +
"astMessageRequest\022\022\n\nmessage_id\030\001 \002(\003\022\020\n" +
"\010receiver\030\002 \003(\t\"@\n\017AuthCodeRequest\022\021\n\tta" +
"rget_id\030\001 \002(\t\022\014\n\004type\030\002 \002(\005\022\014\n\004host\030\003 \002(" +
"\t\"o\n\030ApplicationConfigRequest\022\r\n\005appId\030\001" +
" \002(\t\022\017\n\007appType\030\002 \002(\005\022\021\n\ttimestamp\030\003 \002(\003" +
"\022\r\n\005nonce\030\004 \002(\t\022\021\n\tsignature\030\005 \002(\tB/\n\025cn" +
".wildfirechat.protoB\nWFCMessageZ\n./go;pr" +
"oto"
};
com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
@@ -68007,7 +68245,7 @@ public final class WFCMessage {
internal_static_SearchUserRequest_fieldAccessorTable = new
com.google.protobuf.GeneratedMessage.FieldAccessorTable(
internal_static_SearchUserRequest_descriptor,
new java.lang.String[] { "Keyword", "Fuzzy", "Page", });
new java.lang.String[] { "Keyword", "Fuzzy", "Page", "DomainId", "Type", });
internal_static_SearchUserResult_descriptor =
getDescriptor().getMessageTypes().get(60);
internal_static_SearchUserResult_fieldAccessorTable = new
+1 -1
View File
@@ -6,7 +6,7 @@
<!--<relativePath>../pom.xml</relativePath>-->
<artifactId>wildfirechat-parent</artifactId>
<groupId>cn.wildfirechat</groupId>
<version>1.3.5</version>
<version>1.3.7</version>
</parent>
<artifactId>distribution</artifactId>
+1 -1
View File
@@ -1,5 +1,5 @@
部署IM服务后,可以使用Server SDK通过API来检查服务的部署情况,可以执行:
```shell
java -jar checker.jar http://127.0.0.1:18080 123456 http://127.0.0.1 true false
java -jar checker.jar http://127.0.0.1:18080 123456 http://127.0.0.1 false false
```
来检查。检查之后会产生垃圾数据,请在检查之后停掉IM服务后,再删除掉IM服务数据库。此检查仅检查API,检查通过并不代表部署肯定成功,还需要客户端来验证。
@@ -33,6 +33,8 @@ local_port 80
## MySQL需要把事物隔离级别改成"Read committed",使用命令来修改"set global transaction_isolation='read-committed';",其他数据库默认已经是这个级别不用修改
## 如果使用MySQL,请在c3p0.xml文件中配置JDBC信息。
## 如果是MySQL5.7,需要开启长索引的支持,在数据库中执行命令:"set global innodb_large_prefix=on;"。其他版本默认支持,不用修改。
## 如果使用MySQL 8.0.30以上版本,有个特性是创建表时如果没有主键将会自动创建一个主键"my_key_id",如果此功能打开,在执行mysql脚本V19__add_id_for_sensitive_word.sql时将会报错,提示不能2个主键。
## 解决办法就是运行出错后删除掉系统自动创建的主键"my_key_id",然后继续执行。
embed.db 1
## 是否自动清理历史消息记录,当为true时,IM服务会定时扫描t_messages_x和t_user_messages_x表,清除掉3年前的历史消息。
@@ -106,7 +108,7 @@ message.disable_remote_search false
##如果要避免数据库中明文存储消息内容,请打开这个开关和message.disable_remote_search开关
message.encrypt_message_content false
##允许客户端撤回用户自己发送的消息时限,单位是秒。
##允许客户端撤回用户自己发送的消息时限,单位是秒。0是不允许撤回;-1是无限制撤回。
##Server API不受此限制,可以撤回任意时限内的消息
##群组管理员或群主撤回群成员消息不受此限制,可以撤回任意时限内的消息。但管理员或群主撤回自己的消息还是需要准守此时间限制。
##修改此参数需要同步修改客户端UI,客户端UI代码有判断撤回是否显示的逻辑。
@@ -244,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
+1 -1
View File
@@ -12,7 +12,7 @@
<artifactId>wildfirechat-parent</artifactId>
<packaging>pom</packaging>
<version>1.3.5</version>
<version>1.3.7</version>
<name>Wildfire Chat</name>
<description>Wildfire Chat Server</description>
<inceptionYear>2019</inceptionYear>
+16 -1
View File
@@ -8,9 +8,24 @@
7. *** 从0.68 版本起添加了pc在线是否默认手机接收推送的开关,默认为开,与以前版本作用相反,请注意兼容(可以关掉与之前保持一致或者升级客户端) ***
8. *** 从0.78 版本起把MySQL数据库中关键字都改为大小写敏感,另外生成id的方法也做了改变,只生成小写的id,避免出现id重复的问题,建议所有客户都升级 ***
9. *** 从0.79 版本起把log4j升级到log4j2,因为log4j已经不再维护而且还有已知的漏洞,建议所有客户都升级,升级时注意更新log4j2的配置文件 ***
10. *** 5. 0.97版本更改了启动脚本```wildfirechat.sh```,如果是升级服务,请注意更新启动脚本。***
10. *** 0.97版本更改了启动脚本```wildfirechat.sh```,如果是升级服务,请注意更新启动脚本。***
# 更新记录
--------------
Release note 1.3.7:
1. 搜索用户可以指定搜索机器人、普通用户或者所有。
2. 添加群组成员时,允许部分失败。
3. 解决内置存储上传文件时可能内存泄漏。
4. 支持客户端上传本地角标,用于推送得到较为精确的角标数字。
5. 解决机器人回调配置携带发送者用户信息无效的问题。
--------------
Release note 1.3.6:
1. Server API创建频道时,返回频道ID和频道密钥。
2. 解决外置审核替换内容没有成功的问题。
3. 修改撤回消息限制,可以运行不限制撤回。
4. 创建/更新频道接口可以传菜单参数。
5. Server API支持修改群组类型。
--------------
Release note 1.3.5:
+1 -1
View File
@@ -3,7 +3,7 @@
<parent>
<artifactId>wildfirechat-parent</artifactId>
<groupId>cn.wildfirechat</groupId>
<version>1.3.5</version>
<version>1.3.7</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -51,7 +51,7 @@ public class ChannelServiceApi {
return channelHttpUtils.httpJsonPost(path, null, OutputGetChannelInfo.class);
}
public IMResult<Void> modifyChannelMenu(List<OutputGetChannelInfo.OutputMenu> menus) throws Exception {
public IMResult<Void> modifyChannelMenu(List<PojoChannelMenu> menus) throws Exception {
String menuStr = new Gson().toJson(menus);
return modifyChannelInfo(ProtoConstants.ModifyChannelInfoType.Modify_Channel_Menu, menuStr);
}
@@ -1004,6 +1004,12 @@ public class Main {
}
static void testReadMessageContentFromDB() throws Exception {
//需要注意几点:
// 1 WFCMessage类不能混淆,如果混淆 WFCMessage.MessageContent.parseFrom(data) 就会失败。
// 2 MessageContentFactory方法会自动查找所有的消息类,包括文本/图片/语音等。也有可能在某些环境下找不到这些类。可以检查MessageContentFactory
// 类的源码,修改registerAllMessageContent方法,确保能找到所有的内容类。也可以显式调用注册的方法把所有已知消息都注册一遍,比如:
// MessageContentFactory.registerCustomMessageContent(TextMessageContent.class); //这里示例只写了文本的,其他所有已知消息都需要注册一遍。
//从数据库t_messages_x表中读取到消息内容字段_data的二进制数据为
byte[] data = {8,1,18,5,72,101,108,108,111,64,3};
//1. 先把二进制数据转化为协议栈消息内容。
@@ -1974,8 +1980,8 @@ public class Main {
System.exit(-1);
}
List<OutputGetChannelInfo.OutputMenu> menus = new ArrayList<>();
OutputGetChannelInfo.OutputMenu menu1 = new OutputGetChannelInfo.OutputMenu();
List<PojoChannelMenu> menus = new ArrayList<>();
PojoChannelMenu menu1 = new PojoChannelMenu();
menu1.menuId = UUID.randomUUID().toString();
menu1.type = "view";
menu1.name = "一级菜单1";
@@ -1983,7 +1989,7 @@ public class Main {
menu1.url = "http://www.baidu.com";
menus.add(menu1);
OutputGetChannelInfo.OutputMenu menu2 = new OutputGetChannelInfo.OutputMenu();
PojoChannelMenu menu2 = new PojoChannelMenu();
menu2.menuId = UUID.randomUUID().toString();
menu2.type = "view";
menu2.name = "一级菜单2";
@@ -1992,7 +1998,7 @@ public class Main {
menu2.subMenus = new ArrayList<>();
menus.add(menu2);
OutputGetChannelInfo.OutputMenu menu21 = new OutputGetChannelInfo.OutputMenu();
PojoChannelMenu menu21 = new PojoChannelMenu();
menu21.menuId = UUID.randomUUID().toString();
menu21.type = "click";
menu21.name = "二级菜单21";
@@ -39,12 +39,13 @@ public class MeshAdmin {
return AdminHttpUtils.httpJsonPost(path, getUserInfo, OutputUserInfoList.class);
}
public static IMResult<PojoSearchUserRes> searchUser(String keyword, int searchType, int page) throws Exception {
public static IMResult<PojoSearchUserRes> searchUser(String keyword, int searchType, int userType, int page) throws Exception {
String path = APIPath.Search_User;
PojoSearchUserReq req = new PojoSearchUserReq();
req.keyword = keyword;
req.searchType = searchType;
req.page = page;
req.userType = userType;
return AdminHttpUtils.httpJsonPost(path, req, PojoSearchUserRes.class);
}
@@ -22,6 +22,8 @@ import org.slf4j.LoggerFactory;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.lang.reflect.Type;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.concurrent.TimeUnit;
@@ -35,10 +37,29 @@ public class ChannelHttpUtils extends JsonUtils {
private String channelSecret;
private final CloseableHttpClient httpClient;
private final int port;
private void checkPort() {
if (port != 80 && port != 443) {
if (port == 18080) {
LOG.warn("您传入的频道API地址中的端口是18080,18080端口默认为管理API端口,频道API端口应该为IM服务的HTTP端口,默认为80,请确认是否使用错误!");
} else {
LOG.warn("您传入的频道API地址中的端口不是80/443,频道API的端口和客户端使用端口一样,都应该为IM服务的HTTP端口,默认为80,请确实是否正确?如果您定制化了IM服务端口或者使用其他端口反向代理IM服务的HTTP端口请忽略此提示。");
}
}
}
public ChannelHttpUtils(String imurl, String channelId, String secret) {
this.imurl = imurl.trim();
this.channelId = channelId.trim();
this.channelSecret = secret.trim();
try {
URL url = new URL(this.imurl);
this.port = url.getPort();
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
checkPort();
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
cm.setValidateAfterInactivity(1000);
int connectTimeout = 5000; // 连接超时时间
@@ -118,6 +139,7 @@ public class ChannelHttpUtils extends JsonUtils {
return fromJsonObject(content, clazz);
}
} catch (Exception e) {
checkPort();
e.printStackTrace();
throw e;
}finally{
@@ -3,18 +3,15 @@ package cn.wildfirechat.sdk.utilities;
import cn.wildfirechat.sdk.model.IMResult;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import ikidou.reflect.TypeBuilder;
import io.netty.util.internal.StringUtil;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.slf4j.Logger;
@@ -22,7 +19,8 @@ import org.slf4j.LoggerFactory;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.lang.reflect.Type;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.concurrent.TimeUnit;
@@ -36,10 +34,29 @@ public class RobotHttpUtils extends JsonUtils {
private final String robotSecret;
private final CloseableHttpClient httpClient;
private final int port;
private void checkPort() {
if (port != 80 && port != 443) {
if (port == 18080) {
LOG.warn("您传入的机器人API地址中的端口是18080,18080端口默认为管理API端口,机器人API端口应该为IM服务的HTTP端口,默认为80,请确认是否使用错误!");
} else {
LOG.warn("您传入的机器人API地址中的端口不是80/443,机器人API的端口和客户端使用端口一样,都应该为IM服务的HTTP端口,默认为80,请确实是否正确?如果您定制化了IM服务端口或者使用其他端口反向代理IM服务的HTTP端口请忽略此提示。");
}
}
}
public RobotHttpUtils(String url, String robotId, String robotSecret) {
this.url = url.trim();
this.robotId = robotId.trim();
this.robotSecret = robotSecret.trim();
try {
URL u = new URL(this.url);
this.port = u.getPort();
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
checkPort();
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
cm.setValidateAfterInactivity(1000);
int connectTimeout = 5000; // 连接超时时间
@@ -61,7 +78,6 @@ public class RobotHttpUtils extends JsonUtils {
.build();
}
public <T> IMResult<T> httpJsonPost(String path, Object object, Class<T> clazz) throws Exception{
if (isNullOrEmpty(url) || isNullOrEmpty(path)) {
LOG.error("Not init IM SDK correctly. Do you forget init it?");
@@ -121,6 +137,7 @@ public class RobotHttpUtils extends JsonUtils {
return fromJsonObject(content, clazz);
}
} catch (Exception e) {
checkPort();
e.printStackTrace();
throw e;
}finally{