Compare commits

..
52 Commits
Author SHA1 Message Date
heavyrain.lee 5d9196939f 修正聊天室错误 2020-01-11 11:06:17 +08:00
heavyrain.lee 2e4cf566c7 add exception log 2020-01-10 12:34:31 +08:00
heavyrain.lee a856b96b59 update 2020-01-10 11:37:07 +08:00
heavyrain.lee 9eb5fdd805 更新用户信息时,先写入数据库再存入缓存中,防止异步操作写入数据库失败造成数据不一致 2020-01-10 10:25:34 +08:00
heavyrain.lee bace7ec70c 加强对群组权限的检查 2020-01-08 23:20:20 +08:00
heavyrain.lee 0bcf2fea7b update version to 0.37 2020-01-08 14:56:36 +08:00
heavyrain.lee 60730c57cb update sdk test case 2020-01-08 14:49:21 +08:00
heavyrain.lee 3b61f8f6dd 添加频道获取自己信息的接口 2020-01-08 11:40:59 +08:00
heavyrain.lee e6ca9f5c78 更新channel接口,订阅/取消订阅只能逐个操作 2020-01-06 12:02:54 +08:00
heavyrain.lee 95beca8e05 fix build error 2020-01-05 23:47:57 +08:00
heavyrain.lee 7c4fe831b3 优化聊天室逻辑,添加聊天室空闲退出时间和发消息重新加入配置 2020-01-05 12:36:36 +08:00
heavyrain.lee e4da3780f5 添加频道sdk 2020-01-04 17:04:43 +08:00
heavyrain.lee 998f01a584 默认关掉设备在线状态回调 2020-01-04 14:51:46 +08:00
heavyrain.lee d71644c209 添加设置/获取备注api,添加用户在线状态回调功能 2020-01-04 14:47:27 +08:00
imhao183 70c390dea9 添加设置/获取备注api,添加用户在线状态回调功能 2020-01-04 14:45:49 +08:00
imhao183 41d326d40f 禁止私聊添加对机器人/管理员/物联网设备的例外 2020-01-04 14:35:34 +08:00
x86 1dbf431e4d 处理好友请求间隔 2020-01-02 10:15:25 +08:00
imhao183 0c0d712869 update 2019-12-30 16:00:14 +08:00
imhao183 73015c7a17 更新黑名单逻辑 2019-12-30 15:20:59 +08:00
imhao183 9baa1f9b23 修正编译错误,优化部分逻辑 2019-12-30 08:54:46 +08:00
imhao183 190da8934f 修改配置,增加如下功能
1,添加黑名单处理策略,发送失败或者忽略掉对方。
2,添加好友再次请求的时间间隔配置和好友请求被拒绝后再次请求的时间间隔配置
2019-12-30 08:48:17 +08:00
heavyrain.lee 9d1031594e 清除重复devicetoken时对包名进行判断,如果不同包名的client不清除重复推送token 2019-12-28 18:18:40 +08:00
imhao183 1d987c1569 remove useless files 2019-12-27 09:43:02 +08:00
imhao183 ac225b1541 添加退出群组api接口 2019-12-27 09:41:44 +08:00
imhao183 11375133ba 禁止发送消息给被封禁用户 2019-12-26 21:18:34 +08:00
imhao183 91b209d0fa 添加是否允许陌生人聊天的配置 2019-12-26 19:35:15 +08:00
imhao183 216860c573 update 2019-12-24 12:32:24 +08:00
imhao183 c7579877a1 修正sdk好友和频道接口错误 2019-12-24 11:43:47 +08:00
imhao183 6c5354d17b 优化session处理 2019-12-18 11:37:39 +08:00
imhao183 c98bd1fb9b update version to 0.36 2019-12-18 10:54:08 +08:00
imhao183 fe525e9483 优化用户session逻辑 2019-12-18 09:02:59 +08:00
imhao183 6acea9b140 创建群时同步操作 2019-12-17 14:39:49 +08:00
imhao183 4beb573052 add ignore 2019-12-17 14:36:49 +08:00
imhao183 220e010193 update version to 0.35 2019-12-13 13:02:27 +08:00
imhao183 865888824c Revert "Fix race condition during SensitiveFilter update"
This reverts commit ab7b20871a.
2019-12-13 12:58:07 +08:00
imhao183 583df110fd Revert "Fix potential GZIPOutputStream resource leak on exception"
This reverts commit 6c7d2ab3ad.
2019-12-13 12:57:59 +08:00
imhao183 f204bd693e Revert "fix build error"
This reverts commit 5cd2e7affe.
2019-12-13 12:57:46 +08:00
x86 b6be1ca045 fix pull message issue 2019-12-10 23:34:15 +08:00
imhao183 beb403a9f7 添加搜索类型 2019-12-06 10:36:26 +08:00
imhao183 00f1187200 添加群主进群时,修改群主的的状态问题 2019-12-05 15:42:20 +08:00
heavyrain.lee 7ee490cc1b update version to 0.34 2019-12-03 13:54:17 +08:00
imhao183 3dc0ae7a47 update 2019-12-03 08:24:15 +08:00
imhao183 994a8b5c4a 添加服务器为客户缓存消息数量的配置 2019-12-03 08:10:38 +08:00
imhao183 5cd2e7affe fix build error 2019-12-02 15:21:04 +08:00
heavyrain.lee f29ffe4cd2 Merge pull request #124 from k81/wildfirechat
Fix race condition during SensitiveFilter update and potential resource leak of GZIPOutputStream on exception
2019-12-02 14:43:55 +08:00
gitlab-runner 6c7d2ab3ad Fix potential GZIPOutputStream resource leak on exception 2019-11-30 23:05:28 +08:00
gitlab-runner ab7b20871a Fix race condition during SensitiveFilter update 2019-11-30 17:27:56 +08:00
imhao183 6883418e22 解决okhttp内存泄漏问题 2019-11-30 14:25:41 +08:00
fengyun 32f7266a5f add deleted property 2019-11-30 13:11:25 +08:00
fengyun 35db76e9cd set use deleted 2019-11-30 13:11:18 +08:00
heavyrain.lee 4f6aa87b9f update proto 2019-11-30 13:10:53 +08:00
fengyun f5816e20dd add get user group list and destroy user function 2019-11-30 11:46:52 +08:00
78 changed files with 2430 additions and 337 deletions
+3
View File
@@ -56,3 +56,6 @@ broker/media
common/target
server/target
sdk/target
moments/target
monitor
wildfire_jmeter
+27
View File
@@ -58,6 +58,28 @@ message.roaming 0
##是否开启拉取远程历史消息
message.remote_history_message 0
##服务器为每个用户缓存的消息数量。这个值改得太大,拉取消息时间变长,另外会占用大量内存。
message.max_queue 1024
##是否禁止陌生人聊天
message.disable_stranger_chat false
##黑名单处理策略,0 发送失败,返回被拉黑的错误码;1 发送成功但消息被服务器直接丢弃;
message.blacklist.strategy 0
##好友请求重复发送的间隔,单位是毫秒,默认是7天,0为不限制
friend.repeat_request_duration 604800000
##好友请求被拒绝后再次发送的间隔,单位是毫秒,默认是30天,0为不限制
friend.reject_request_duration 2592000000
## 聊天室观众空闲退出时间,单位为毫秒,默认为15分钟,0为永远不退出
chatroom.participant_idle_time 900000
## 用户向聊天室发送消息,自动加入聊天室
chatroom.rejoin_when_active true
#*********************************************************************
# hazelcase configuration
#*********************************************************************
@@ -113,6 +135,11 @@ push.android.server.address http://localhost:8085/android/push
##苹果推送服务器地址
push.ios.server.address http://localhost:8085/ios/push
#*********************************************************************
# User online status event callback
#*********************************************************************
##用户在线状态事件回调地址
#user.online_status_callback http://localhost:8888/user/online_event
#*********************************************************************
# MongoDB configuration
+1
View File
@@ -0,0 +1 @@
alter table `t_user` add column `_deleted` tinyint DEFAULT 0;
+1
View File
@@ -0,0 +1 @@
alter table `t_user` add column `_deleted` tinyint DEFAULT 0;
+1 -1
View File
@@ -5,7 +5,7 @@
<relativePath>../</relativePath>
<artifactId>wildfirechat-parent</artifactId>
<groupId>cn.wildfirechat</groupId>
<version>0.33</version>
<version>0.37</version>
</parent>
<artifactId>moquette-broker</artifactId>
@@ -21,6 +21,7 @@ import io.netty.handler.codec.http.HttpResponseEncoder;
import io.netty.handler.stream.ChunkedWriteHandler;
import com.xiaoleilu.loServer.action.ClassUtil;
import org.slf4j.LoggerFactory;
import win.liyufan.im.Utility;
import java.io.IOException;
@@ -141,6 +142,7 @@ public class LoServer {
}
} catch (IOException e) {
e.printStackTrace();
Utility.printExecption(Logger, e);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
@@ -57,7 +57,7 @@ public class RouteAction extends Action {
try {
bytes = Base64.getDecoder().decode(str);
} catch (IllegalArgumentException e) {
sendResponse(response, ErrorCode.ERROR_CODE_SECRECT_KEY_MISMATCH, null, base64Response);
sendResponse(response, ErrorCode.ERROR_CODE_INVALID_DATA, null, base64Response);
return true;
}
@@ -65,7 +65,7 @@ public class RouteAction extends Action {
byte[] cbytes = Base64.getDecoder().decode(cid);
cbytes = AES.AESDecrypt(cbytes, "", true);
if (cbytes == null) {
sendResponse(response, ErrorCode.ERROR_CODE_SECRECT_KEY_MISMATCH, null, base64Response);
sendResponse(response, ErrorCode.ERROR_CODE_INVALID_DATA, null, base64Response);
return true;
}
cid = new String(cbytes);
@@ -74,7 +74,7 @@ public class RouteAction extends Action {
byte[] ubytes = Base64.getDecoder().decode(uid);
ubytes = AES.AESDecrypt(ubytes, "", true);
if (ubytes == null) {
sendResponse(response, ErrorCode.ERROR_CODE_SECRECT_KEY_MISMATCH, null, base64Response);
sendResponse(response, ErrorCode.ERROR_CODE_INVALID_DATA, null, base64Response);
return true;
}
uid = new String(ubytes);
@@ -28,7 +28,7 @@ public class UnknownErrorAction extends Action{
@Override
public boolean action(Request request, Response response) {
response.setStatus(HttpResponseStatus.NOT_FOUND);
response.setStatus(HttpResponseStatus.INTERNAL_SERVER_ERROR);
return true;
}
}
@@ -9,6 +9,7 @@
package com.xiaoleilu.loServer.action.admin;
import com.google.gson.Gson;
import com.xiaoleilu.loServer.LoServer;
import com.xiaoleilu.loServer.RestResult;
import com.xiaoleilu.loServer.action.Action;
import com.xiaoleilu.loServer.handler.Request;
@@ -17,9 +18,12 @@ import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.util.internal.StringUtil;
import org.apache.commons.codec.digest.DigestUtils;
import cn.wildfirechat.common.ErrorCode;
import org.slf4j.LoggerFactory;
import win.liyufan.im.RateLimiter;
import win.liyufan.im.Utility;
abstract public class AdminAction extends Action {
private static final org.slf4j.Logger LOG = LoggerFactory.getLogger(AdminAction.class);
private static String SECRET_KEY = "123456";
private static boolean NO_CHECK_TIME = false;
private final RateLimiter mLimitCounter = new RateLimiter(10, 500);
@@ -50,8 +54,9 @@ abstract public class AdminAction extends Action {
Long ts;
try {
ts = Long.parseLong(timestamp);
} catch (NumberFormatException e) {
} catch (Exception e) {
e.printStackTrace();
Utility.printExecption(LOG, e);
return ErrorCode.INVALID_PARAMETER;
}
@@ -0,0 +1,58 @@
/*
* This file is part of the Wildfire Chat package.
* (c) Heavyrain2012 <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
package com.xiaoleilu.loServer.action.admin;
import cn.wildfirechat.common.APIPath;
import cn.wildfirechat.pojos.InputGetAlias;
import cn.wildfirechat.pojos.InputGetFriendList;
import cn.wildfirechat.pojos.OutputGetAlias;
import cn.wildfirechat.pojos.OutputStringList;
import com.google.gson.Gson;
import com.xiaoleilu.loServer.RestResult;
import com.xiaoleilu.loServer.annotation.HttpMethod;
import com.xiaoleilu.loServer.annotation.Route;
import com.xiaoleilu.loServer.handler.Request;
import com.xiaoleilu.loServer.handler.Response;
import com.xiaoleilu.loServer.model.FriendData;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.HttpResponseStatus;
import java.util.ArrayList;
import java.util.List;
@Route(APIPath.Friend_Get_Alias)
@HttpMethod("POST")
public class AliasGetAction extends AdminAction {
@Override
public boolean isTransactionAction() {
return true;
}
@Override
public boolean action(Request request, Response response) {
if (request.getNettyRequest() instanceof FullHttpRequest) {
InputGetAlias input = getRequestBody(request.getNettyRequest(), InputGetAlias.class);
List<FriendData> dataList = messagesStore.getFriendList(input.getOperator(), null, 0);
List<String> list = new ArrayList<>();
OutputGetAlias out = new OutputGetAlias(input.getOperator(), input.getTargetId());
for (FriendData data : dataList) {
if (data.getFriendUid().equals(input.getTargetId())) {
out.setAlias(data.getAlias());
break;
}
}
response.setStatus(HttpResponseStatus.OK);
RestResult result = RestResult.ok(out);
response.setContent(new Gson().toJson(result));
}
return true;
}
}
@@ -0,0 +1,49 @@
/*
* This file is part of the Wildfire Chat package.
* (c) Heavyrain2012 <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
package com.xiaoleilu.loServer.action.admin;
import cn.wildfirechat.common.APIPath;
import cn.wildfirechat.common.ErrorCode;
import cn.wildfirechat.pojos.InputGetFriendList;
import cn.wildfirechat.pojos.InputUpdateAlias;
import cn.wildfirechat.pojos.OutputStringList;
import com.google.gson.Gson;
import com.xiaoleilu.loServer.RestResult;
import com.xiaoleilu.loServer.annotation.HttpMethod;
import com.xiaoleilu.loServer.annotation.Route;
import com.xiaoleilu.loServer.handler.Request;
import com.xiaoleilu.loServer.handler.Response;
import com.xiaoleilu.loServer.model.FriendData;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.HttpResponseStatus;
import java.util.ArrayList;
import java.util.List;
@Route(APIPath.Friend_Set_Alias)
@HttpMethod("POST")
public class AliasPutAction extends AdminAction {
@Override
public boolean isTransactionAction() {
return true;
}
@Override
public boolean action(Request request, Response response) {
if (request.getNettyRequest() instanceof FullHttpRequest) {
InputUpdateAlias input = getRequestBody(request.getNettyRequest(), InputUpdateAlias.class);
ErrorCode errorCode = messagesStore.setFriendAliasRequest(input.getOperator(), input.getTargetId(), input.getAlias(), new long[1]);
response.setStatus(HttpResponseStatus.OK);
RestResult result = RestResult.resultOf(errorCode);
response.setContent(new Gson().toJson(result));
}
return true;
}
}
@@ -44,7 +44,8 @@ public class CreateChannelAction extends AdminAction {
if (request.getNettyRequest() instanceof FullHttpRequest) {
InputCreateChannel inputCreateChannel = getRequestBody(request.getNettyRequest(), InputCreateChannel.class);
if (inputCreateChannel != null
&& !StringUtil.isNullOrEmpty(inputCreateChannel.getName())) {
&& !StringUtil.isNullOrEmpty(inputCreateChannel.getName())
&& !StringUtil.isNullOrEmpty(inputCreateChannel.getOwner())) {
if(StringUtil.isNullOrEmpty(inputCreateChannel.getTargetId())) {
@@ -58,7 +59,10 @@ public class CreateChannelAction extends AdminAction {
byteBuf.writeBytes(result);
ErrorCode errorCode = ErrorCode.fromCode(byteBuf.readByte());
if (errorCode == ErrorCode.ERROR_CODE_SUCCESS) {
sendResponse(response, null, new OutputCreateChannel(inputCreateChannel.getTargetId()));
byte[] data = new byte[byteBuf.readableBytes()];
byteBuf.readBytes(data);
String secret = new String(data);
sendResponse(response, null, new OutputCreateChannel(inputCreateChannel.getTargetId(), secret));
} else {
sendResponse(response, errorCode, null);
}
@@ -22,11 +22,15 @@ import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.util.internal.StringUtil;
import cn.wildfirechat.common.ErrorCode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import win.liyufan.im.UUIDGenerator;
import win.liyufan.im.Utility;
@Route(APIPath.Create_Robot)
@HttpMethod("POST")
public class CreateRobotAction extends AdminAction {
private static final Logger LOG = LoggerFactory.getLogger(CreateRobotAction.class);
@Override
public boolean isTransactionAction() {
@@ -55,7 +59,16 @@ public class CreateRobotAction extends AdminAction {
WFCMessage.User newUser = inputCreateRobot.toUser();
messagesStore.addUserInfo(newUser, inputCreateRobot.getPassword());
try {
messagesStore.addUserInfo(newUser, inputCreateRobot.getPassword());
} catch (Exception e) {
e.printStackTrace();
Utility.printExecption(LOG, e);
response.setStatus(HttpResponseStatus.OK);
RestResult result = RestResult.resultOf(ErrorCode.ERROR_CODE_SERVER_ERROR, e.getMessage());
response.setContent(new Gson().toJson(result));
return true;
}
if (StringUtil.isNullOrEmpty(inputCreateRobot.getOwner())) {
inputCreateRobot.setOwner(inputCreateRobot.getUserId());
@@ -22,11 +22,16 @@ import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.util.internal.StringUtil;
import cn.wildfirechat.common.ErrorCode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import win.liyufan.im.DBUtil;
import win.liyufan.im.UUIDGenerator;
import win.liyufan.im.Utility;
@Route(APIPath.Create_User)
@HttpMethod("POST")
public class CreateUserAction extends AdminAction {
private static final Logger LOG = LoggerFactory.getLogger(CreateUserAction.class);
@Override
public boolean isTransactionAction() {
@@ -75,7 +80,17 @@ public class CreateUserAction extends AdminAction {
newUserBuilder.setUpdateDt(System.currentTimeMillis());
messagesStore.addUserInfo(newUserBuilder.build(), inputCreateUser.getPassword());
try {
messagesStore.addUserInfo(newUserBuilder.build(), inputCreateUser.getPassword());
} catch (Exception e) {
e.printStackTrace();
Utility.printExecption(LOG, e);
response.setStatus(HttpResponseStatus.OK);
RestResult result = RestResult.resultOf(ErrorCode.ERROR_CODE_SERVER_ERROR, e.getMessage());
response.setContent(new Gson().toJson(result));
return true;
}
response.setStatus(HttpResponseStatus.OK);
RestResult result = RestResult.ok(new OutputCreateUser(inputCreateUser.getUserId(), inputCreateUser.getName()));
@@ -0,0 +1,97 @@
/*
* This file is part of the Wildfire Chat package.
* (c) Heavyrain2012 <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
package com.xiaoleilu.loServer.action.admin;
import cn.wildfirechat.common.APIPath;
import cn.wildfirechat.common.ErrorCode;
import cn.wildfirechat.pojos.InputDestroyUser;
import cn.wildfirechat.pojos.InputOutputUserInfo;
import cn.wildfirechat.pojos.OutputCreateUser;
import cn.wildfirechat.pojos.OutputGetIMTokenData;
import cn.wildfirechat.proto.WFCMessage;
import com.google.gson.Gson;
import com.xiaoleilu.loServer.RestResult;
import com.xiaoleilu.loServer.annotation.HttpMethod;
import com.xiaoleilu.loServer.annotation.Route;
import com.xiaoleilu.loServer.handler.Request;
import com.xiaoleilu.loServer.handler.Response;
import io.moquette.persistence.RPCCenter;
import io.moquette.persistence.TargetEntry;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.util.internal.StringUtil;
import win.liyufan.im.IMTopic;
import win.liyufan.im.UUIDGenerator;
import java.util.Base64;
import java.util.concurrent.Executor;
@Route(APIPath.Destroy_User)
@HttpMethod("POST")
public class DestroyUserAction extends AdminAction {
@Override
public boolean isTransactionAction() {
return true;
}
@Override
public boolean action(Request request, Response response) {
if (request.getNettyRequest() instanceof FullHttpRequest) {
InputDestroyUser inputDestroyUser = getRequestBody(request.getNettyRequest(), InputDestroyUser.class);
if (inputDestroyUser != null
&& !StringUtil.isNullOrEmpty(inputDestroyUser.getUserId())) {
WFCMessage.IDBuf idBuf = WFCMessage.IDBuf.newBuilder().setId(inputDestroyUser.getUserId()).build();
RPCCenter.getInstance().sendRequest(inputDestroyUser.getUserId(), null, IMTopic.DestroyUserTopic, idBuf.toByteArray(), inputDestroyUser.getUserId(), TargetEntry.Type.TARGET_TYPE_USER, new RPCCenter.Callback() {
@Override
public void onSuccess(byte[] result) {
ErrorCode errorCode1 = ErrorCode.fromCode(result[0]);
if (errorCode1 == ErrorCode.ERROR_CODE_SUCCESS) {
//ba errorcode qudiao
byte[] data = new byte[result.length -1];
for (int i = 0; i < data.length; i++) {
data[i] = result[i+1];
}
String token = Base64.getEncoder().encodeToString(data);
sendResponse(response, null, null);
} else {
sendResponse(response, errorCode1, null);
}
}
@Override
public void onError(ErrorCode errorCode) {
sendResponse(response, errorCode, null);
}
@Override
public void onTimeout() {
sendResponse(response, ErrorCode.ERROR_CODE_TIMEOUT, null);
}
@Override
public Executor getResponseExecutor() {
return command -> {
ctx.executor().execute(command);
};
}
}, true);
return false;
} else {
response.setStatus(HttpResponseStatus.OK);
RestResult result = RestResult.resultOf(ErrorCode.INVALID_PARAMETER);
response.setContent(new Gson().toJson(result));
}
}
return true;
}
}
@@ -9,6 +9,7 @@
package com.xiaoleilu.loServer.action.admin;
import cn.wildfirechat.common.APIPath;
import cn.wildfirechat.pojos.OutputStringList;
import com.google.gson.Gson;
import com.xiaoleilu.loServer.RestResult;
import com.xiaoleilu.loServer.annotation.HttpMethod;
@@ -44,7 +45,7 @@ public class FriendRelationGetAction extends AdminAction {
}
}
response.setStatus(HttpResponseStatus.OK);
RestResult result = RestResult.ok(list);
RestResult result = RestResult.ok(new OutputStringList(list));
response.setContent(new Gson().toJson(result));
}
return true;
@@ -0,0 +1,63 @@
/*
* This file is part of the Wildfire Chat package.
* (c) Heavyrain2012 <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
package com.xiaoleilu.loServer.action.admin;
import cn.wildfirechat.common.APIPath;
import cn.wildfirechat.common.ErrorCode;
import cn.wildfirechat.pojos.InputGetGroup;
import cn.wildfirechat.pojos.InputUserId;
import cn.wildfirechat.pojos.OutputGroupIds;
import cn.wildfirechat.pojos.PojoGroupInfo;
import cn.wildfirechat.proto.WFCMessage;
import com.google.gson.Gson;
import com.xiaoleilu.loServer.RestResult;
import com.xiaoleilu.loServer.annotation.HttpMethod;
import com.xiaoleilu.loServer.annotation.Route;
import com.xiaoleilu.loServer.handler.Request;
import com.xiaoleilu.loServer.handler.Response;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.util.internal.StringUtil;
import java.util.ArrayList;
import java.util.Set;
@Route(APIPath.Get_User_Groups)
@HttpMethod("POST")
public class GetUserGroupsAction extends AdminAction {
@Override
public boolean isTransactionAction() {
return true;
}
@Override
public boolean action(Request request, Response response) {
if (request.getNettyRequest() instanceof FullHttpRequest) {
InputUserId inputUserId = getRequestBody(request.getNettyRequest(), InputUserId.class);
if (inputUserId != null
&& (!StringUtil.isNullOrEmpty(inputUserId.getUserId()))) {
Set<String> groupIds = messagesStore.getUserGroupIds(inputUserId.getUserId());
response.setStatus(HttpResponseStatus.OK);
OutputGroupIds outputGroupIds = new OutputGroupIds();
outputGroupIds.setGroupIds(new ArrayList<>(groupIds));
RestResult result = RestResult.ok(outputGroupIds);
response.setContent(new Gson().toJson(result));
} else {
response.setStatus(HttpResponseStatus.OK);
RestResult result = RestResult.resultOf(ErrorCode.INVALID_PARAMETER);
response.setContent(new Gson().toJson(result));
}
}
return true;
}
}
@@ -0,0 +1,85 @@
/*
* This file is part of the Wildfire Chat package.
* (c) Heavyrain2012 <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
package com.xiaoleilu.loServer.action.admin;
import cn.wildfirechat.common.APIPath;
import cn.wildfirechat.common.ErrorCode;
import cn.wildfirechat.pojos.InputKickoffGroupMember;
import cn.wildfirechat.pojos.InputQuitGroup;
import com.google.gson.Gson;
import com.xiaoleilu.loServer.RestResult;
import com.xiaoleilu.loServer.annotation.HttpMethod;
import com.xiaoleilu.loServer.annotation.Route;
import com.xiaoleilu.loServer.handler.Request;
import com.xiaoleilu.loServer.handler.Response;
import io.moquette.persistence.RPCCenter;
import io.moquette.persistence.TargetEntry;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.HttpResponseStatus;
import win.liyufan.im.IMTopic;
import java.util.concurrent.Executor;
@Route(APIPath.Group_Member_Quit)
@HttpMethod("POST")
public class QuitGroupMemberAction extends AdminAction {
@Override
public boolean isTransactionAction() {
return true;
}
@Override
public boolean action(Request request, Response response) {
if (request.getNettyRequest() instanceof FullHttpRequest) {
InputQuitGroup inputQuitGroup = getRequestBody(request.getNettyRequest(), InputQuitGroup.class);
if (inputQuitGroup.isValide()) {
RPCCenter.getInstance().sendRequest(inputQuitGroup.getOperator(), null, IMTopic.QuitGroupTopic, inputQuitGroup.toProtoGroupRequest().toByteArray(), inputQuitGroup.getOperator(), TargetEntry.Type.TARGET_TYPE_USER, new RPCCenter.Callback() {
@Override
public void onSuccess(byte[] result) {
ByteBuf byteBuf = Unpooled.buffer();
byteBuf.writeBytes(result);
ErrorCode errorCode = ErrorCode.fromCode(byteBuf.readByte());
if (errorCode == ErrorCode.ERROR_CODE_SUCCESS) {
sendResponse(response, null, null);
} else {
sendResponse(response, errorCode, null);
}
}
@Override
public void onError(ErrorCode errorCode) {
sendResponse(response, errorCode, null);
}
@Override
public void onTimeout() {
sendResponse(response, ErrorCode.ERROR_CODE_TIMEOUT, null);
}
@Override
public Executor getResponseExecutor() {
return command -> {
ctx.executor().execute(command);
};
}
}, true);
return false;
} else {
response.setStatus(HttpResponseStatus.OK);
RestResult result = RestResult.resultOf(ErrorCode.INVALID_PARAMETER);
response.setContent(new Gson().toJson(result));
}
}
return true;
}
}
@@ -12,6 +12,7 @@ import cn.wildfirechat.proto.WFCMessage;
import com.google.gson.Gson;
import com.xiaoleilu.loServer.RestResult;
import com.xiaoleilu.loServer.action.Action;
import com.xiaoleilu.loServer.action.admin.AdminAction;
import com.xiaoleilu.loServer.handler.Request;
import com.xiaoleilu.loServer.handler.Response;
import io.moquette.spi.impl.Utils;
@@ -21,9 +22,12 @@ import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.util.internal.StringUtil;
import org.apache.commons.codec.digest.DigestUtils;
import cn.wildfirechat.common.ErrorCode;
import org.slf4j.LoggerFactory;
import win.liyufan.im.RateLimiter;
import win.liyufan.im.Utility;
abstract public class ChannelAction extends Action {
private static final org.slf4j.Logger LOG = LoggerFactory.getLogger(ChannelAction.class);
private final RateLimiter mLimitCounter = new RateLimiter(10, 200);
protected WFCMessage.ChannelInfo channelInfo;
@@ -45,8 +49,9 @@ abstract public class ChannelAction extends Action {
Long ts;
try {
ts = Long.parseLong(timestamp);
} catch (NumberFormatException e) {
} catch (Exception e) {
e.printStackTrace();
Utility.printExecption(LOG, e);
return ErrorCode.INVALID_PARAMETER;
}
@@ -14,6 +14,7 @@ import com.xiaoleilu.loServer.RestResult;
import com.xiaoleilu.loServer.action.Action;
import com.xiaoleilu.loServer.handler.Request;
import com.xiaoleilu.loServer.handler.Response;
import io.moquette.imhandler.IMHandler;
import io.moquette.spi.impl.Utils;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.HttpRequest;
@@ -21,11 +22,15 @@ import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.util.internal.StringUtil;
import org.apache.commons.codec.digest.DigestUtils;
import cn.wildfirechat.common.ErrorCode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import win.liyufan.im.RateLimiter;
import win.liyufan.im.Utility;
import java.io.UnsupportedEncodingException;
abstract public class RobotAction extends Action {
protected static final Logger LOG = LoggerFactory.getLogger(RobotAction.class);
private final RateLimiter mLimitCounter = new RateLimiter(10, 1000);
protected WFCMessage.Robot robot;
@@ -47,8 +52,9 @@ abstract public class RobotAction extends Action {
Long ts;
try {
ts = Long.parseLong(timestamp);
} catch (NumberFormatException e) {
} catch (Exception e) {
e.printStackTrace();
Utility.printExecption(LOG, e);
return ErrorCode.INVALID_PARAMETER;
}
@@ -89,6 +95,7 @@ abstract public class RobotAction extends Action {
return t;
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
Utility.printExecption(LOG, e);
}
}
return null;
@@ -21,6 +21,7 @@ import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.HttpResponseStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import win.liyufan.im.Utility;
/**
* Action处理单元
@@ -51,6 +52,8 @@ abstract public class ActionHandler extends SimpleChannelInboundHandler<FullHttp
this.doAction(ctx, request, response);
}
} catch (Exception e) {
e.printStackTrace();
Utility.printExecption(Logger, e);
Action errorAction = ServerSetting.getErrorAction(ServerSetting.MAPPING_ERROR);
request.putParam(UnknownErrorAction.ERROR_PARAM_NAME, e);
response.setContent(e.toString());
@@ -20,6 +20,7 @@ import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.util.internal.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -37,7 +38,7 @@ public class IMActionHandler extends ActionHandler {
@Override
boolean isValidePath(String path) {
if (!path.startsWith("/admin")) {
if (!StringUtil.isNullOrEmpty(path) && !path.startsWith("/admin")) {
return true;
}
return false;
@@ -88,6 +88,8 @@ public final class BrokerConstants {
public static final String PUSH_ANDROID_SERVER_ADDRESS = "push.android.server.address";
public static final String PUSH_IOS_SERVER_ADDRESS = "push.ios.server.address";
public static final String USER_ONLINE_STATUS_CALLBACK = "user.online_status_callback";
public static final String HZ_Cluster_Node_External_IP = "node_external_ip";
public static final String HZ_Cluster_Node_External_Long_Port = "node_external_long_port";
public static final String HZ_Cluster_Node_External_Short_Port = "node_external_short_port";
@@ -115,6 +117,17 @@ public final class BrokerConstants {
public static final String MESSAGE_ROAMING = "message.roaming";
public static final String MESSAGE_Remote_History_Message = "message.remote_history_message";
public static final String MESSAGE_Max_Queue = "message.max_queue";
public static final String MESSAGE_Disable_Stranger_Chat = "message.disable_stranger_chat";
public static final String MESSAGE_Blacklist_Strategy = "message.blacklist.strategy";
public static final String FRIEND_Repeat_Request_Duration = "friend.repeat_request_duration";
public static final String FRIEND_Reject_Request_Duration = "friend.reject_request_duration";
public static final String CHATROOM_Participant_Idle_Time = "chatroom.participant_idle_time";
public static final String CHATROOM_Rejoin_When_Active = "chatroom.rejoin_when_active";
private BrokerConstants() {
}
@@ -41,7 +41,7 @@ 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.internalRpcMsg(fromUser, null, modifyUserSettingReq.toByteArray(), 0, fromUser, PutUserSettingTopic, false);
byte[] data = request.getTargetId().getBytes();
byte[] data = request.getSecret().getBytes();
ackPayload.ensureWritable(data.length).writeBytes(data);
return ErrorCode.ERROR_CODE_SUCCESS;
} else {
@@ -0,0 +1,38 @@
/*
* This file is part of the Wildfire Chat package.
* (c) Heavyrain2012 <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
package io.moquette.imhandler;
import cn.wildfirechat.common.ErrorCode;
import cn.wildfirechat.proto.WFCMessage;
import io.moquette.persistence.MemorySessionStore;
import io.moquette.spi.impl.Qos1PublishHandler;
import io.moquette.spi.impl.security.TokenAuthenticator;
import io.netty.buffer.ByteBuf;
import win.liyufan.im.IMTopic;
@Handler(IMTopic.DestroyUserTopic)
public class DestroyUserHandler extends IMHandler<WFCMessage.IDBuf> {
@Override
public ErrorCode action(ByteBuf ackPayload, String clientID, String fromUser, boolean isAdmin, WFCMessage.IDBuf request, Qos1PublishHandler.IMCallback callback) {
if (isAdmin) {
mServer.getImBusinessScheduler().execute(()-> {
m_sessionsStore.clearUserSession(fromUser);
m_messagesStore.clearUserMessages(fromUser);
m_messagesStore.clearUserSettings(fromUser);
m_messagesStore.clearUserFriend(fromUser);
m_messagesStore.clearUserGroups(fromUser);
m_messagesStore.clearUserChannels(fromUser);
m_messagesStore.destoryUser(fromUser);
});
return ErrorCode.ERROR_CODE_SUCCESS;
} else {
return ErrorCode.ERROR_CODE_NOT_RIGHT;
}
}
}
@@ -20,7 +20,7 @@ import win.liyufan.im.IMTopic;
public class GetTokenHandler extends IMHandler<WFCMessage.GetTokenRequest> {
@Override
public ErrorCode action(ByteBuf ackPayload, String clientID, String fromUser, boolean isAdmin, WFCMessage.GetTokenRequest request, Qos1PublishHandler.IMCallback callback) {
MemorySessionStore.Session session = m_sessionsStore.createUserSession(fromUser, clientID, request.getPlatform());
MemorySessionStore.Session session = m_sessionsStore.updateOrCreateUserSession(fromUser, clientID, request.getPlatform());
TokenAuthenticator authenticator = new TokenAuthenticator();
String strToken = authenticator.generateToken(fromUser);
String result = strToken + "|" + session.getSecret() + "|" + session.getDbSecret();
@@ -32,7 +32,7 @@ abstract public class GroupHandler<T> extends IMHandler<T> {
builder.setFromUser(fromUser);
long messageId = MessageShardingUtil.generateId();
builder.setMessageId(messageId);
saveAndPublish(fromUser, null, builder.build());
saveAndPublish(fromUser, null, builder.build(), false);
}
}
@@ -32,7 +32,7 @@ public class HandleFriendRequestHandler extends IMHandler<WFCMessage.HandleFrien
long timestamp = System.currentTimeMillis();
builder.setMessageId(messageId);
builder.setServerTimestamp(timestamp);
saveAndPublish(request.getTargetUid(), null, builder.build());
saveAndPublish(request.getTargetUid(), null, builder.build(), false);
WFCMessage.MessageContent.Builder contentBuilder = WFCMessage.MessageContent.newBuilder().setType(90).setContent("以上是打招呼信息");
builder = WFCMessage.Message.newBuilder();
@@ -44,7 +44,7 @@ public class HandleFriendRequestHandler extends IMHandler<WFCMessage.HandleFrien
messageId = MessageShardingUtil.generateId();
builder.setMessageId(messageId);
saveAndPublish(request.getTargetUid(), null, builder.build());
saveAndPublish(request.getTargetUid(), null, builder.build(), false);
contentBuilder.setContent("你们已经成为好友了,现在可以开始聊天了");
builder.setContent(contentBuilder);
@@ -52,7 +52,7 @@ public class HandleFriendRequestHandler extends IMHandler<WFCMessage.HandleFrien
builder.setMessageId(messageId);
timestamp = System.currentTimeMillis();
builder.setServerTimestamp(timestamp);
saveAndPublish(request.getTargetUid(), null, builder.build());
saveAndPublish(request.getTargetUid(), null, builder.build(), false);
publisher.publishNotification(IMTopic.NotifyFriendTopic, request.getTargetUid(), heads[0]);
publisher.publishNotification(IMTopic.NotifyFriendTopic, fromUser, heads[1]);
@@ -83,11 +83,10 @@ abstract public class IMHandler<T> {
}
}
for (Method method : getClass().getDeclaredMethods()
) {
if (method.getName() == actionName && method.getParameterCount() == 6) {
if (method.getName() == actionName && method.getParameterCount() == 6 && !method.getParameterTypes()[4].equals(Object.class)) {
dataCls = method.getParameterTypes()[4];
break;
}
@@ -239,17 +238,17 @@ abstract public class IMHandler<T> {
Set<String> notifyReceivers = new LinkedHashSet<>();
WFCMessage.Message.Builder messageBuilder = message.toBuilder();
int pullType = m_messagesStore.getNotifyReceivers(username, messageBuilder, notifyReceivers);
int pullType = m_messagesStore.getNotifyReceivers(username, messageBuilder, notifyReceivers, false);
mServer.getImBusinessScheduler().execute(() -> this.publisher.publish2Receivers(messageBuilder.build(), notifyReceivers, clientID, pullType));
return notifyReceivers.size();
}
protected long saveAndPublish(String username, String clientID, WFCMessage.Message message) {
protected long saveAndPublish(String username, String clientID, WFCMessage.Message message, boolean ignoreMsg) {
Set<String> notifyReceivers = new LinkedHashSet<>();
message = m_messagesStore.storeMessage(username, clientID, message);
WFCMessage.Message.Builder messageBuilder = message.toBuilder();
int pullType = m_messagesStore.getNotifyReceivers(username, messageBuilder, notifyReceivers);
int pullType = m_messagesStore.getNotifyReceivers(username, messageBuilder, notifyReceivers, ignoreMsg);
mServer.getImBusinessScheduler().execute(() -> this.publisher.publish2Receivers(messageBuilder.build(), notifyReceivers, clientID, pullType));
return notifyReceivers.size();
}
@@ -8,6 +8,7 @@
package io.moquette.imhandler;
import cn.wildfirechat.proto.ProtoConstants;
import cn.wildfirechat.proto.WFCMessage;
import io.moquette.spi.impl.Qos1PublishHandler;
import io.netty.buffer.ByteBuf;
@@ -24,6 +25,13 @@ public class LoadRemoteMessagesHandler extends IMHandler<WFCMessage.LoadRemoteMe
if (beforeUid == 0) {
beforeUid = Long.MAX_VALUE;
}
if (request.getConversation().getType() == ProtoConstants.ConversationType.ConversationType_Group) {
if (!m_messagesStore.isMemberInGroup(fromUser, request.getConversation().getTarget())) {
return ErrorCode.ERROR_CODE_NOT_IN_GROUP;
}
}
WFCMessage.PullMessageResult result = m_messagesStore.loadRemoteMessages(fromUser, request.getConversation(), beforeUid, request.getCount());
byte[] data = result.toByteArray();
LOG.info("User {} load message with count({}), payload size({})", fromUser, result.getMessageCount(), data.length);
@@ -13,11 +13,18 @@ import io.moquette.spi.impl.Qos1PublishHandler;
import io.netty.buffer.ByteBuf;
import cn.wildfirechat.common.ErrorCode;
import win.liyufan.im.IMTopic;
import win.liyufan.im.Utility;
@Handler(IMTopic.ModifyMyInfoTopic)
public class ModifyMyInfoHandler extends IMHandler<WFCMessage.ModifyMyInfoRequest> {
@Override
public ErrorCode action(ByteBuf ackPayload, String clientID, String fromUser, boolean isAdmin, WFCMessage.ModifyMyInfoRequest request, Qos1PublishHandler.IMCallback callback) {
try {
return m_messagesStore.modifyUserInfo(fromUser, request);
} catch (Exception e) {
e.printStackTrace();
Utility.printExecption(LOG, e);
return ErrorCode.ERROR_CODE_SERVER_ERROR;
}
}
}
@@ -37,7 +37,7 @@ public class RecallMessageHandler extends IMHandler<WFCMessage.INT64Buf> {
//等待客户端实现根据撤回消息更新内容,之后可以删掉这段代码
m_messagesStore.getNotifyReceivers(fromUser, message.toBuilder(), notifyReceivers);
m_messagesStore.getNotifyReceivers(fromUser, message.toBuilder(), notifyReceivers, false);
this.publisher.publishRecall2Receivers(int64Buf.getId(), fromUser, notifyReceivers, clientID);
return errorCode;
@@ -17,6 +17,7 @@ import io.netty.buffer.ByteBuf;
import cn.wildfirechat.common.ErrorCode;
import win.liyufan.im.IMTopic;
import win.liyufan.im.MessageShardingUtil;
import win.liyufan.im.Utility;
import java.util.Set;
@@ -26,6 +27,7 @@ import static cn.wildfirechat.proto.ProtoConstants.ContentType.Text;
public class SendMessageHandler extends IMHandler<WFCMessage.Message> {
private int mSensitiveType = 0; //命中敏感词时,0 失败,1 吞掉, 2 敏感词替换成*。
private String mForwardUrl = null;
private int mBlacklistStrategy = 0; //黑名单中时,0失败,1吞掉。
public SendMessageHandler() {
super();
@@ -38,6 +40,14 @@ public class SendMessageHandler extends IMHandler<WFCMessage.Message> {
mSensitiveType = Integer.parseInt(mServer.getConfig().getProperty(BrokerConstants.SENSITIVE_Filter_Type));
} catch (Exception e) {
e.printStackTrace();
Utility.printExecption(LOG, e);
}
try {
mBlacklistStrategy = Integer.parseInt(mServer.getConfig().getProperty(BrokerConstants.MESSAGE_Blacklist_Strategy));
} catch (Exception e) {
e.printStackTrace();
Utility.printExecption(LOG, e);
}
}
@@ -45,23 +55,33 @@ public class SendMessageHandler extends IMHandler<WFCMessage.Message> {
public ErrorCode action(ByteBuf ackPayload, String clientID, String fromUser, boolean isAdmin, WFCMessage.Message message, Qos1PublishHandler.IMCallback callback) {
ErrorCode errorCode = ErrorCode.ERROR_CODE_SUCCESS;
if (message != null) {
boolean ignoreMsg = false;
if (!isAdmin) { //admin do not check the right
// 不能在端上直接发送撤回和群通知
if (message.getContent().getType() == 80 || (message.getContent().getType() >= 100 && message.getContent().getType() < 200)) {
return ErrorCode.INVALID_PARAMETER;
}
int userStatus = m_messagesStore.getUserStatus(fromUser);
if (userStatus == 1 || userStatus == 2) {
if (userStatus == ProtoConstants.UserStatus.Muted || userStatus == ProtoConstants.UserStatus.Forbidden) {
return ErrorCode.ERROR_CODE_FORBIDDEN_SEND_MSG;
}
if (message.getConversation().getType() == ProtoConstants.ConversationType.ConversationType_Private) {
if (m_messagesStore.isBlacked(message.getConversation().getTarget(), fromUser)) {
return ErrorCode.ERROR_CODE_IN_BLACK_LIST;
errorCode = m_messagesStore.isAllowUserMessage(message.getConversation().getTarget(), fromUser);
if (errorCode != ErrorCode.ERROR_CODE_SUCCESS) {
if (errorCode == ErrorCode.ERROR_CODE_IN_BLACK_LIST && mBlacklistStrategy != ProtoConstants.BlacklistStrategy.Message_Reject) {
ignoreMsg = true;
} else {
return errorCode;
}
}
userStatus = m_messagesStore.getUserStatus(message.getConversation().getTarget());
if (userStatus == ProtoConstants.UserStatus.Forbidden) {
return ErrorCode.ERROR_CODE_USER_FORBIDDEN;
}
}
if (message.getConversation().getType() == ProtoConstants.ConversationType.ConversationType_Group ) {
errorCode = m_messagesStore.canSendMessageInGroup(fromUser, message.getConversation().getTarget());
if (errorCode != ErrorCode.ERROR_CODE_SUCCESS) {
@@ -86,7 +106,7 @@ public class SendMessageHandler extends IMHandler<WFCMessage.Message> {
publisher.forwardMessage(message, mForwardUrl);
}
boolean ignoreMsg = false;
if (!isAdmin && message.getContent().getType() == Text) {
Set<String> matched = m_messagesStore.handleSensitiveWord(message.getContent().getSearchableContent());
if (matched != null && !matched.isEmpty()) {
@@ -109,9 +129,7 @@ public class SendMessageHandler extends IMHandler<WFCMessage.Message> {
}
if (errorCode == ErrorCode.ERROR_CODE_SUCCESS) {
if (!ignoreMsg) {
saveAndPublish(fromUser, clientID, message);
}
saveAndPublish(fromUser, clientID, message, ignoreMsg);
ackPayload = ackPayload.capacity(20);
ackPayload.writeLong(messageId);
ackPayload.writeLong(timestamp);
@@ -31,7 +31,7 @@ public class UploadDeviceTokenHandler extends IMHandler<WFCMessage.UploadDeviceT
session.setDeviceToken(request.getDeviceToken());
session.setPushType(request.getPushType());
m_sessionsStore.updateSessionToken(session, false);
m_sessionsStore.cleanDuplatedToken(session.getClientID(), session.getPushType(), session.getDeviceToken(), false);
m_sessionsStore.cleanDuplatedToken(session.getClientID(), session.getPushType(), session.getDeviceToken(), false, session.getAppName());
}
return ErrorCode.ERROR_CODE_SUCCESS;
@@ -20,7 +20,7 @@ import java.util.List;
public class UserSearchHandler extends IMHandler<WFCMessage.SearchUserRequest> {
@Override
public ErrorCode action(ByteBuf ackPayload, String clientID, String fromUser, boolean isAdmin, WFCMessage.SearchUserRequest request, Qos1PublishHandler.IMCallback callback) {
List<WFCMessage.User> users = m_messagesStore.searchUser(request.getKeyword(), request.getFuzzy() > 0, request.getPage());
List<WFCMessage.User> users = m_messagesStore.searchUser(request.getKeyword(), request.getFuzzy(), request.getPage());
WFCMessage.SearchUserResult.Builder builder = WFCMessage.SearchUserResult.newBuilder();
builder.addAllEntry(users);
byte[] data = builder.build().toByteArray();
@@ -35,6 +35,7 @@ import java.util.function.Function;
import static cn.wildfirechat.proto.ProtoConstants.PersistFlag.Transparent;
import static io.moquette.persistence.MemoryMessagesStore.USER_STATUS;
import static io.moquette.server.Constants.MAX_MESSAGE_QUEUE;
import static cn.wildfirechat.proto.ProtoConstants.SearchUserType.*;
public class DatabaseStore {
private static final Logger LOG = LoggerFactory.getLogger(DatabaseStore.class);
@@ -148,8 +149,12 @@ public class DatabaseStore {
}
return null;
}
List<WFCMessage.User> searchUserFromDB(String keyword, boolean buzzy, int page) {
//searchType
// 0 模糊匹配displayName, 精确匹配账户名和电话号码
// 1 精确匹配账户名和电话号码
// 2 精确匹配账户名
// 3 精确匹配电话号码
List<WFCMessage.User> searchUserFromDB(String keyword, int searchType, int page) {
Connection connection = null;
PreparedStatement statement = null;
ResultSet rs = null;
@@ -169,18 +174,29 @@ public class DatabaseStore {
", `_social`" +
", `_extra`" +
", `_dt` from t_user";
if (buzzy) {
sql += " where (`_display_name` like ? or `_name` = ? or `_mobile` = ?) ";
} else {
sql += " where (`_name` = ? or `_mobile` = ?) ";
switch (searchType) {
case SearchUserType_Name_Mobile:
sql += " where (`_name` = ? or `_mobile` = ?) ";
break;
case SearchUserType_Name:
sql += " where `_name` = ? ";
break;
case SearchUserType_Mobile:
sql += " where `_mobile` = ? ";
break;
case SearchUserType_General:
default:
sql += " where (`_display_name` like ? or `_name` = ? or `_mobile` = ?) ";
break;
}
sql += " and _type <> 2"; //can search normal user(0) and robot(1), can not search things
if (buzzy) {
sql += " limit 20";
} else {
sql += " and _type <> 2"; //can search normal user(0) and robot(1) and admin(100), can not search things
if (searchType == SearchUserType_Name_Mobile || searchType == SearchUserType_Name || searchType == SearchUserType_Mobile) {
sql += " limit 1";
} else {
sql += " limit 20";
}
if (page > 0) {
@@ -190,12 +206,24 @@ public class DatabaseStore {
statement = connection.prepareStatement(sql);
int index = 1;
if (buzzy) {
statement.setString(index++, "%" + keyword + "%");
switch (searchType) {
case SearchUserType_Name_Mobile:
statement.setString(index++, keyword);
statement.setString(index++, keyword);
break;
case SearchUserType_Name:
case SearchUserType_Mobile:
statement.setString(index++, keyword);
break;
case SearchUserType_General:
default:
statement.setString(index++, "%" + keyword + "%");
statement.setString(index++, keyword);
statement.setString(index++, keyword);
break;
}
statement.setString(index++, keyword);
statement.setString(index++, keyword);
rs = statement.executeQuery();
while (rs.next()) {
@@ -788,6 +816,40 @@ public class DatabaseStore {
});
}
void clearUserMessage(final String userId) {
mScheduler.execute(()->{
String tableName = getUserMessageTable(userId);
Connection connection = null;
PreparedStatement statement = null;
try {
connection = DBUtil.getConnection();
String sql = "delete from " + tableName + " where _uid = ?";
statement = connection.prepareStatement(sql);
statement.setString(1, userId);
int count = statement.executeUpdate();
LOG.info("Update rows {}", count);
try {
if (statement!=null) {
statement.close();
}
statement = null;
} catch (SQLException e) {
e.printStackTrace();
Utility.printExecption(LOG, e);
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Utility.printExecption(LOG, e);
} finally {
DBUtil.closeDB(connection, statement);
}
});
}
void removeFavGroup(final String groupId, final List<String> memberIds) {
Connection connection = null;
PreparedStatement statement = null;
@@ -863,6 +925,31 @@ public class DatabaseStore {
});
}
void clearUserSetting(final String userId) {
mScheduler.execute(()->{
Connection connection = null;
PreparedStatement statement = null;
try {
connection = DBUtil.getConnection();
String sql = "delete from t_user_setting where `_uid` = ?";
statement = connection.prepareStatement(sql);
int index = 1;
statement.setString(index++, userId);
int count = statement.executeUpdate();
LOG.info("Update rows {}", count);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Utility.printExecption(LOG, e);
} finally {
DBUtil.closeDB(connection, statement);
}
});
}
List<WFCMessage.UserSettingEntry> getPersistUserSetting(final String userId) {
Connection connection = null;
PreparedStatement statement = null;
@@ -952,78 +1039,76 @@ public class DatabaseStore {
}
void persistGroupInfo(final WFCMessage.GroupInfo groupInfo) {
mScheduler.execute(()->{
Connection connection = null;
PreparedStatement statement = null;
try {
connection = DBUtil.getConnection();
String sql = "insert into t_group (`_gid`" +
", `_name`" +
", `_portrait`" +
", `_owner`" +
", `_type`" +
", `_extra`" +
", `_dt`" +
", `_member_count`" +
", `_mute`" +
", `_join_type`" +
", `_private_chat`" +
", `_searchable`" +
", `_member_dt`) values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" +
" ON DUPLICATE KEY UPDATE " +
"`_name` = ?," +
"`_portrait` = ?," +
"`_owner` = ?," +
"`_type` = ?," +
"`_extra` = ?," +
"`_dt` = ?," +
"`_member_count` = ?," +
"`_mute` = ?" +
", `_join_type` = ?" +
", `_private_chat` = ?" +
", `_searchable` = ?, " +
"`_member_dt` = ?";
Connection connection = null;
PreparedStatement statement = null;
try {
connection = DBUtil.getConnection();
String sql = "insert into t_group (`_gid`" +
", `_name`" +
", `_portrait`" +
", `_owner`" +
", `_type`" +
", `_extra`" +
", `_dt`" +
", `_member_count`" +
", `_mute`" +
", `_join_type`" +
", `_private_chat`" +
", `_searchable`" +
", `_member_dt`) values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" +
" ON DUPLICATE KEY UPDATE " +
"`_name` = ?," +
"`_portrait` = ?," +
"`_owner` = ?," +
"`_type` = ?," +
"`_extra` = ?," +
"`_dt` = ?," +
"`_member_count` = ?," +
"`_mute` = ?" +
", `_join_type` = ?" +
", `_private_chat` = ?" +
", `_searchable` = ?, " +
"`_member_dt` = ?";
statement = connection.prepareStatement(sql);
statement = connection.prepareStatement(sql);
int index = 1;
statement.setString(index++, groupInfo.getTargetId());
statement.setString(index++, groupInfo.getName());
statement.setString(index++, groupInfo.getPortrait());
statement.setString(index++, groupInfo.getOwner());
statement.setInt(index++, groupInfo.getType());
statement.setString(index++, groupInfo.getExtra());
statement.setLong(index++, groupInfo.getUpdateDt() == 0 ? System.currentTimeMillis() : groupInfo.getUpdateDt());
statement.setInt(index++, groupInfo.getMemberCount());
statement.setInt(index++, groupInfo.getMute());
statement.setInt(index++, groupInfo.getJoinType());
statement.setInt(index++, groupInfo.getPrivateChat());
statement.setInt(index++, groupInfo.getSearchable());
statement.setLong(index++, groupInfo.getMemberUpdateDt() == 0 ? System.currentTimeMillis() : groupInfo.getUpdateDt());
int index = 1;
statement.setString(index++, groupInfo.getTargetId());
statement.setString(index++, groupInfo.getName());
statement.setString(index++, groupInfo.getPortrait());
statement.setString(index++, groupInfo.getOwner());
statement.setInt(index++, groupInfo.getType());
statement.setString(index++, groupInfo.getExtra());
statement.setLong(index++, groupInfo.getUpdateDt() == 0 ? System.currentTimeMillis() : groupInfo.getUpdateDt());
statement.setInt(index++, groupInfo.getMemberCount());
statement.setInt(index++, groupInfo.getMute());
statement.setInt(index++, groupInfo.getJoinType());
statement.setInt(index++, groupInfo.getPrivateChat());
statement.setInt(index++, groupInfo.getSearchable());
statement.setLong(index++, groupInfo.getMemberUpdateDt() == 0 ? System.currentTimeMillis() : groupInfo.getUpdateDt());
statement.setString(index++, groupInfo.getName());
statement.setString(index++, groupInfo.getPortrait());
statement.setString(index++, groupInfo.getOwner());
statement.setInt(index++, groupInfo.getType());
statement.setString(index++, groupInfo.getExtra());
statement.setLong(index++, groupInfo.getUpdateDt() == 0 ? System.currentTimeMillis() : groupInfo.getUpdateDt());
statement.setInt(index++, groupInfo.getMemberCount());
statement.setInt(index++, groupInfo.getMute());
statement.setInt(index++, groupInfo.getJoinType());
statement.setInt(index++, groupInfo.getPrivateChat());
statement.setInt(index++, groupInfo.getSearchable());
statement.setLong(index++, groupInfo.getMemberUpdateDt() == 0 ? System.currentTimeMillis() : groupInfo.getUpdateDt());
int count = statement.executeUpdate();
LOG.info("Update rows {}", count);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Utility.printExecption(LOG, e);
} finally {
DBUtil.closeDB(connection, statement);
}
});
statement.setString(index++, groupInfo.getName());
statement.setString(index++, groupInfo.getPortrait());
statement.setString(index++, groupInfo.getOwner());
statement.setInt(index++, groupInfo.getType());
statement.setString(index++, groupInfo.getExtra());
statement.setLong(index++, groupInfo.getUpdateDt() == 0 ? System.currentTimeMillis() : groupInfo.getUpdateDt());
statement.setInt(index++, groupInfo.getMemberCount());
statement.setInt(index++, groupInfo.getMute());
statement.setInt(index++, groupInfo.getJoinType());
statement.setInt(index++, groupInfo.getPrivateChat());
statement.setInt(index++, groupInfo.getSearchable());
statement.setLong(index++, groupInfo.getMemberUpdateDt() == 0 ? System.currentTimeMillis() : groupInfo.getUpdateDt());
int count = statement.executeUpdate();
LOG.info("Update rows {}", count);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Utility.printExecption(LOG, e);
} finally {
DBUtil.closeDB(connection, statement);
}
}
List<MemorySessionStore.Session> getUserActivedSessions(String uid) {
@@ -1070,6 +1155,27 @@ public class DatabaseStore {
return result;
}
void clearUserSessions(String uid) {
Connection connection = null;
PreparedStatement statement = null;
try {
connection = DBUtil.getConnection();
String sql = "delete from t_user_session where `_uid`=?";
statement = connection.prepareStatement(sql);
int index = 1;
statement.setString(index++, uid);
int count = statement.executeUpdate();
LOG.info("Update rows {}", count);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Utility.printExecption(LOG, e);
} finally {
DBUtil.closeDB(connection, statement);
}
}
MemorySessionStore.Session getSession(String uid, String clientId, ClientSession clientSession) {
String sql = "select `_package_name`,`_token`,`_voip_token`,`_secret`,`_db_secret`,`_platform`,`_push_type`,`_device_name`,`_device_version`,`_phone_name`,`_language`,`_carrier_name`, `_dt`, `_deleted` from t_user_session where `_uid` = ? and `_cid` = ? limit 1";
Connection connection = null;
@@ -1422,40 +1528,67 @@ public class DatabaseStore {
return null;
}
void updateGroupMemberCountDt(final String groupId, final int count, final long dt) {
mScheduler.execute(()->{
Connection connection = null;
PreparedStatement statement = null;
try {
connection = DBUtil.getConnection();
Set<String> getUserGroupIds(String userId) {
Connection connection = null;
PreparedStatement statement = null;
ResultSet rs = null;
try {
connection = DBUtil.getConnection();
String sql = "select `_gid` from t_group_member where `_mid` = ? and `_type` <> ?";
statement = connection.prepareStatement(sql);
String sql ;
statement.setString(1, userId);
statement.setInt(2, ProtoConstants.GroupMemberType.GroupMemberType_Removed);
if (count >= 0) {
sql = "update t_group set `_member_count` = ?, `_member_dt` = ? , `_dt` = ? where `_gid` = ?";
} else {
sql = "update t_group set `_member_dt` = ?, `_dt` = ? where `_gid` = ?";
}
statement = connection.prepareStatement(sql);
int index = 1;
if (count >=0) {
statement.setInt(index++, count);
}
statement.setLong(index++, dt);
statement.setLong(index++, dt);
statement.setString(index++, groupId);
int c = statement.executeUpdate();
LOG.info("Update rows {}", c);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Utility.printExecption(LOG, e);
} finally {
DBUtil.closeDB(connection, statement);
rs = statement.executeQuery();
Set<String> out = new HashSet<>();
while (rs.next()) {
String uid = rs.getString(1);
out.add(uid);
}
});
return out;
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Utility.printExecption(LOG, e);
} finally {
DBUtil.closeDB(connection, statement, rs);
}
return null;
}
void updateGroupMemberCountDt(final String groupId, final int count, final long dt) {
Connection connection = null;
PreparedStatement statement = null;
try {
connection = DBUtil.getConnection();
String sql ;
if (count >= 0) {
sql = "update t_group set `_member_count` = ?, `_member_dt` = ? , `_dt` = ? where `_gid` = ?";
} else {
sql = "update t_group set `_member_dt` = ?, `_dt` = ? where `_gid` = ?";
}
statement = connection.prepareStatement(sql);
int index = 1;
if (count >=0) {
statement.setInt(index++, count);
}
statement.setLong(index++, dt);
statement.setLong(index++, dt);
statement.setString(index++, groupId);
int c = statement.executeUpdate();
LOG.info("Update rows {}", c);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Utility.printExecption(LOG, e);
} finally {
DBUtil.closeDB(connection, statement);
}
}
void persistGroupMember(final String groupId, final List<WFCMessage.GroupMember> memberList) {
@@ -1995,7 +2128,7 @@ public class DatabaseStore {
});
}
void updateUser(final WFCMessage.User user) {
void updateUser(final WFCMessage.User user) throws Exception {
LOG.info("Database update user info {} {}", user.getUid(), user.getUpdateDt());
Connection connection = null;
PreparedStatement statement = null;
@@ -2026,6 +2159,7 @@ public class DatabaseStore {
", `_social`=?" +
", `_extra`=?" +
", `_type`=?" +
", `_deleted`=?" +
", `_dt`=?";
statement = connection.prepareStatement(sql);
@@ -2059,6 +2193,7 @@ public class DatabaseStore {
statement.setString(index++, user.getExtra());
statement.setInt(index++, user.getType());
statement.setInt(index++, user.getDeleted());
statement.setLong(index++, user.getUpdateDt() == 0 ? System.currentTimeMillis() : user.getUpdateDt());
int count = statement.executeUpdate();
@@ -2067,6 +2202,7 @@ public class DatabaseStore {
// TODO Auto-generated catch block
e.printStackTrace();
Utility.printExecption(LOG, e);
throw new Exception(e.getMessage());
} finally {
DBUtil.closeDB(connection, statement);
}
@@ -2185,6 +2321,7 @@ public class DatabaseStore {
", `_social`" +
", `_extra`" +
", `_type`" +
", `_deleted`" +
", `_dt` from t_user where `_uid` = ?";
statement = connection.prepareStatement(sql);
@@ -2239,6 +2376,9 @@ public class DatabaseStore {
int type = rs.getInt(index++);
builder.setType(type);
int deleted = rs.getInt(index++);
builder.setDeleted(deleted);
long longValue = rs.getLong(index++);
builder.setUpdateDt(longValue);
@@ -2364,6 +2504,52 @@ public class DatabaseStore {
return null;
}
void removeUserFriend(String userId) {
Connection connection = null;
PreparedStatement statement = null;
try {
connection = DBUtil.getConnection();
String sql = "update t_friend set `_alias` = '', `_state` = 1, `_blacked` = 0, `_dt` = ? where `_uid` = ? or `_friend_uid` = ?";
statement = connection.prepareStatement(sql);
int index = 1;
statement.setLong(index++, System.currentTimeMillis());
statement.setString(index++, userId);
statement.setString(index++, userId);
int count = statement.executeUpdate();
LOG.info("Update rows {}", count);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Utility.printExecption(LOG, e);
} finally {
DBUtil.closeDB(connection, statement);
}
}
void removeUserFriendRequest(String userId) {
Connection connection = null;
PreparedStatement statement = null;
try {
connection = DBUtil.getConnection();
String sql = "delete from t_friend_request where _uid = ? or _friend_uid = ?";
statement = connection.prepareStatement(sql);
int index = 1;
statement.setString(index++, userId);
statement.setString(index++, userId);
int count = statement.executeUpdate();
LOG.info("Update rows {}", count);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Utility.printExecption(LOG, e);
} finally {
DBUtil.closeDB(connection, statement);
}
}
List<WFCMessage.FriendRequest> getPersistFriendRequests(String userId) {
Connection connection = null;
PreparedStatement statement = null;
@@ -22,9 +22,12 @@ import cn.wildfirechat.proto.WFCMessage;
import com.google.protobuf.ByteString;
import com.hazelcast.core.*;
import com.hazelcast.util.StringUtil;
import com.xiaoleilu.hutool.system.UserInfo;
import com.xiaoleilu.loServer.model.FriendData;
import cn.wildfirechat.pojos.InputOutputUserBlockStatus;
import cn.wildfirechat.common.ErrorCode;
import io.moquette.BrokerConstants;
import io.moquette.server.Constants;
import io.moquette.server.Server;
import io.moquette.spi.IMatchingCondition;
import io.moquette.spi.IMessagesStore;
@@ -117,11 +120,54 @@ public class MemoryMessagesStore implements IMessagesStore {
private ConcurrentHashMap<String, Boolean> userPushHiddenDetail = new ConcurrentHashMap<>();
private ConcurrentHashMap<String, Boolean> userConvSlientMap = new ConcurrentHashMap<>();
private long mFriendRequestDuration = 7 * 24 * 60 * 60 * 1000;
private long mFriendRejectDuration = 30 * 24 * 60 * 60 * 1000;
private boolean mDisableStrangerChat = false;
private long mChatroomParticipantIdleTime = 900000;
private boolean mChatroomRejoinWhenActive = true;
MemoryMessagesStore(Server server, DatabaseStore databaseStore) {
m_Server = server;
this.databaseStore = databaseStore;
IS_MESSAGE_ROAMING = "1".equals(m_Server.getConfig().getProperty(MESSAGE_ROAMING));
IS_MESSAGE_REMOTE_HISTORY_MESSAGE = "1".equals(m_Server.getConfig().getProperty(MESSAGE_Remote_History_Message));
Constants.MAX_MESSAGE_QUEUE = Integer.parseInt(m_Server.getConfig().getProperty(MESSAGE_Max_Queue));
try {
mDisableStrangerChat = Boolean.parseBoolean(m_Server.getConfig().getProperty(BrokerConstants.MESSAGE_Disable_Stranger_Chat));
} catch (Exception e) {
e.printStackTrace();
Utility.printExecption(LOG, e);
}
try {
mFriendRequestDuration = Long.parseLong(m_Server.getConfig().getProperty(FRIEND_Repeat_Request_Duration));
} catch (Exception e) {
e.printStackTrace();
Utility.printExecption(LOG, e);
}
try {
mFriendRejectDuration = Long.parseLong(m_Server.getConfig().getProperty(FRIEND_Reject_Request_Duration));
} catch (Exception e) {
e.printStackTrace();
Utility.printExecption(LOG, e);
}
try {
mChatroomRejoinWhenActive = Boolean.parseBoolean(m_Server.getConfig().getProperty(BrokerConstants.CHATROOM_Rejoin_When_Active));
} catch (Exception e) {
e.printStackTrace();
Utility.printExecption(LOG, e);
}
try {
mChatroomParticipantIdleTime = Long.parseLong(m_Server.getConfig().getProperty(CHATROOM_Participant_Idle_Time, "900000"));
} catch (Exception e) {
e.printStackTrace();
Utility.printExecption(LOG, e);
}
}
@Override
@@ -177,12 +223,24 @@ public class MemoryMessagesStore implements IMessagesStore {
@Override
public int getNotifyReceivers(String fromUser, WFCMessage.Message.Builder messageBuilder, Set<String> notifyReceivers) {
public int getNotifyReceivers(String fromUser, WFCMessage.Message.Builder messageBuilder, Set<String> notifyReceivers, boolean ignoreMsg) {
WFCMessage.Message message = messageBuilder.build();
HazelcastInstance hzInstance = m_Server.getHazelcastInstance();
int type = message.getConversation().getType();
int pullType = ProtoConstants.PullType.Pull_Normal;
if (ignoreMsg) {
if (type == ProtoConstants.ConversationType.ConversationType_ChatRoom) {
pullType = ProtoConstants.PullType.Pull_ChatRoom;
}
if (message.getContent().getPersistFlag() != Transparent) {
notifyReceivers.add(fromUser);
}
return pullType;
}
int pullType = 0;
if (type == ProtoConstants.ConversationType.ConversationType_Private) {
notifyReceivers.add(fromUser);
notifyReceivers.add(message.getConversation().getTarget());
@@ -348,8 +406,17 @@ public class MemoryMessagesStore implements IMessagesStore {
continue;
}
if (bundle.getMessage().getContent().getExpireDuration() > 0) {
if (System.currentTimeMillis() < bundle.getMessage().getServerTimestamp() + bundle.getMessage().getContent().getExpireDuration()) {
continue;
}
}
size += bundle.getMessage().getSerializedSize();
if (size >= 512 * 1024) { //3M
if(builder.getMessageCount() == 0){
builder.addMessage(bundle.getMessage());
}
break;
}
builder.addMessage(bundle.getMessage());
@@ -528,13 +595,29 @@ public class MemoryMessagesStore implements IMessagesStore {
@Override
public boolean checkUserClientInChatroom(String user, String clientId, String chatroomId) {
MemorySessionStore.Session session = m_Server.getStore().sessionsStore().getSession(clientId);
if (session == null || System.currentTimeMillis() - session.getLastChatroomActiveTime() > 5 * 60 * 1000) {
handleQuitChatroom(user, clientId, chatroomId);
return false;
}
String existChatroomId = (String)m_Server.getHazelcastInstance().getMap(USER_CHATROOM).get(user);
if (StringUtil.isNullOrEmpty(existChatroomId) && (chatroomId == null || !existChatroomId.equals(chatroomId))) {
if (chatroomId == null) {
if (existChatroomId == null) {
return false;
} else {
chatroomId = existChatroomId;
}
}
if (StringUtil.isNullOrEmpty(existChatroomId) || !existChatroomId.equals(chatroomId)) {
if (mChatroomRejoinWhenActive) {
if (!StringUtil.isNullOrEmpty(existChatroomId)) {
handleQuitChatroom(user, clientId, existChatroomId);
}
handleJoinChatroom(user, clientId, chatroomId);
} else {
return false;
}
}
if (!mChatroomRejoinWhenActive && !checkChatroomParticipantIdelTime(session)) {
handleQuitChatroom(user, clientId, chatroomId);
return false;
}
@@ -684,7 +767,11 @@ public class MemoryMessagesStore implements IMessagesStore {
List<WFCMessage.GroupMember> tmp = new ArrayList<>();
ArrayList<String> newInviteUsers = new ArrayList<>();
for (WFCMessage.GroupMember member : memberList) {
member = member.toBuilder().setType(ProtoConstants.GroupMemberType.GroupMemberType_Normal).setUpdateDt(updateDt).setAlias("").build();
if (member.getMemberId().equals(groupInfo.getOwner())) {
member = member.toBuilder().setType(GroupMemberType_Owner).setUpdateDt(updateDt).setAlias("").build();
} else {
member = member.toBuilder().setType(GroupMemberType_Normal).setUpdateDt(updateDt).setAlias("").build();
}
tmp.add(member);
newInviteUsers.add(member.getMemberId());
}
@@ -772,7 +859,31 @@ public class MemoryMessagesStore implements IMessagesStore {
}
if (groupInfo.getType() != ProtoConstants.GroupType.GroupType_Free && groupInfo.getOwner() != null && groupInfo.getOwner().equals(operator)) {
return ErrorCode.ERROR_CODE_NOT_RIGHT;
MultiMap<String, WFCMessage.GroupMember> groupMembers = hzInstance.getMultiMap(GROUP_MEMBERS);
Collection<WFCMessage.GroupMember> members = groupMembers.get(groupId);
if (members == null || members.size() == 0) {
members = loadGroupMemberFromDB(hzInstance, groupId);
}
WFCMessage.GroupMember newOwner = null;
for (WFCMessage.GroupMember member :members) {
if (!member.getMemberId().equals(operator) && member.getType() != GroupMemberType_Removed) {
newOwner = member;
break;
}
}
if (newOwner == null) {
return dismissGroup(operator, groupId, false);
}
transferGroup(operator, groupId, newOwner.getMemberId(), false);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
removeGroupMember(groupId, Arrays.asList(operator));
@@ -781,6 +892,18 @@ public class MemoryMessagesStore implements IMessagesStore {
return ErrorCode.ERROR_CODE_SUCCESS;
}
@Override
public void clearUserGroups(String userId) {
Set<String> groupIds = databaseStore.getUserGroupIds(userId);
int[] removedCount = new int[1];
for (String groupId : groupIds) {
removedCount[0] = 0;
ErrorCode errorCode = quitGroup(userId, groupId);
LOG.info("clear user {} group {} result {}", userId, groupId, errorCode);
}
}
private void removeGroupUserSettings(String groupId, List<String> users) {
HazelcastInstance hzInstance = m_Server.getHazelcastInstance();
MultiMap<String, WFCMessage.UserSettingEntry> userSettingMap = hzInstance.getMultiMap(USER_SETTING);
@@ -971,6 +1094,11 @@ public class MemoryMessagesStore implements IMessagesStore {
return groupInfo;
}
@Override
public Set<String> getUserGroupIds(String userId) {
return databaseStore.getUserGroupIds(userId);
}
@Override
public ErrorCode getGroupMembers(String groupId, long maxDt, List<WFCMessage.GroupMember> members) {
HazelcastInstance hzInstance = m_Server.getHazelcastInstance();
@@ -1144,8 +1272,9 @@ public class MemoryMessagesStore implements IMessagesStore {
if (members == null || members.size() == 0) {
members = loadGroupMemberFromDB(hzInstance, groupId);
}
for (WFCMessage.GroupMember member : members
) {
boolean isInGroup = false;
for (WFCMessage.GroupMember member : members) {
if (member.getMemberId().equals(memberId)) {
if (member.getType() == GroupMemberType_Silent) {
return ErrorCode.ERROR_CODE_NOT_RIGHT;
@@ -1158,11 +1287,16 @@ public class MemoryMessagesStore implements IMessagesStore {
if (member.getMemberId().equals(memberId) && member.getType() == GroupMemberType_Removed) {
return ErrorCode.ERROR_CODE_NOT_IN_GROUP;
}
isInGroup = true;
break;
}
}
if (!isInGroup) {
return ErrorCode.ERROR_CODE_NOT_IN_GROUP;
}
return ErrorCode.ERROR_CODE_SUCCESS;
}
@@ -1230,6 +1364,18 @@ public class MemoryMessagesStore implements IMessagesStore {
}
}
@Override
public void clearUserMessages(String userId) {
mWriteLock.lock();
try {
userMessages.remove(userId);
} finally {
mWriteLock.unlock();
}
databaseStore.clearUserMessage(userId);
}
@Override
public WFCMessage.Robot getRobot(String robotId) {
HazelcastInstance hzInstance = m_Server.getHazelcastInstance();
@@ -1284,7 +1430,7 @@ public class MemoryMessagesStore implements IMessagesStore {
}
@Override
public ErrorCode modifyUserInfo(String userId, WFCMessage.ModifyMyInfoRequest request) {
public ErrorCode modifyUserInfo(String userId, WFCMessage.ModifyMyInfoRequest request) throws Exception {
HazelcastInstance hzInstance = m_Server.getHazelcastInstance();
IMap<String, WFCMessage.User> mUserMap = hzInstance.getMap(USERS);
@@ -1347,8 +1493,8 @@ public class MemoryMessagesStore implements IMessagesStore {
if (modified) {
builder.setUpdateDt(System.currentTimeMillis());
user = builder.build();
databaseStore.updateUser(user);
mUserMap.set(userId, user);
// databaseStore.updateUser(user);
return ErrorCode.ERROR_CODE_SUCCESS;
} else {
return ErrorCode.ERROR_CODE_NOT_MODIFIED;
@@ -1393,13 +1539,32 @@ public class MemoryMessagesStore implements IMessagesStore {
}
@Override
public void addUserInfo(WFCMessage.User user, String password) {
public void addUserInfo(WFCMessage.User user, String password) throws Exception {
HazelcastInstance hzInstance = m_Server.getHazelcastInstance();
IMap<String, WFCMessage.User> mUserMap = hzInstance.getMap(USERS);
databaseStore.updateUser(user);
mUserMap.put(user.getUid(), user);
databaseStore.updateUserPassword(user.getUid(), password);
}
@Override
public void destoryUser(String userId) {
HazelcastInstance hzInstance = m_Server.getHazelcastInstance();
IMap<String, WFCMessage.User> mUserMap = hzInstance.getMap(USERS);
WFCMessage.User us = mUserMap.get(userId);
if (us != null) {
us = WFCMessage.User.newBuilder().setUid(userId).setUpdateDt(System.currentTimeMillis()).setDisplayName("").setName(userId).setDeleted(1).build();
try {
databaseStore.updateUser(us);
} catch (Exception e) {
e.printStackTrace();
Utility.printExecption(LOG, e);
}
mUserMap.put(userId, us);
}
}
@Override
public WFCMessage.User getUserInfo(String userId) {
if (StringUtil.isNullOrEmpty(userId)) {
@@ -1424,8 +1589,8 @@ public class MemoryMessagesStore implements IMessagesStore {
return getUserInfo(userId);
}
@Override
public List<WFCMessage.User> searchUser(String keyword, boolean buzzy, int page) {
return databaseStore.searchUserFromDB(keyword, buzzy, page);
public List<WFCMessage.User> searchUser(String keyword, int searchType, int page) {
return databaseStore.searchUserFromDB(keyword, searchType, page);
}
@Override
@@ -1550,27 +1715,49 @@ public class MemoryMessagesStore implements IMessagesStore {
}
@Override
public boolean isBlacked(String fromUser, String userId) {
public ErrorCode isAllowUserMessage(String targetUser, String fromUser) {
HazelcastInstance hzInstance = m_Server.getHazelcastInstance();
MultiMap<String, FriendData> friendsMap = hzInstance.getMultiMap(USER_FRIENDS);
Collection<FriendData> friendDatas = friendsMap.get(fromUser);
Collection<FriendData> friendDatas = friendsMap.get(targetUser);
if (friendDatas == null || friendDatas.size() == 0) {
friendDatas = loadFriend(friendsMap, fromUser);
friendDatas = loadFriend(friendsMap, targetUser);
}
for (FriendData friendData : friendDatas) {
if (friendData.getFriendUid().equals(userId)) {
if (friendData.getFriendUid().equals(fromUser)) {
if (friendData.getBlacked() == 1) {
return true;
return ErrorCode.ERROR_CODE_IN_BLACK_LIST;
} else {
return false;
if (friendData.getState() == 0) {
return ErrorCode.ERROR_CODE_SUCCESS;
} else {
break;
}
}
}
}
return false;
if (mDisableStrangerChat) {
//在禁止私聊时,允许机器人,物联网设备及管理员进行私聊。
IMap<String, WFCMessage.User> mUserMap = hzInstance.getMap(USERS);
WFCMessage.User target = mUserMap.get(targetUser);
if (target != null && target.getType() != ProtoConstants.UserType.UserType_Normal) {
return ErrorCode.ERROR_CODE_SUCCESS;
}
target = mUserMap.get(fromUser);
if (target != null && target.getType() != ProtoConstants.UserType.UserType_Normal) {
return ErrorCode.ERROR_CODE_SUCCESS;
}
//admin的usertype为3,所以不需要hardcode为admin添加例外
// if (targetUser.equals("admin") || fromUser.equals("admin")) {
// return ErrorCode.ERROR_CODE_SUCCESS;
// }
return ErrorCode.ERROR_CODE_NOT_RIGHT;
}
return ErrorCode.ERROR_CODE_SUCCESS;
}
@Override
@@ -1689,6 +1876,31 @@ public class MemoryMessagesStore implements IMessagesStore {
return out;
}
@Override
public void clearUserFriend(String userId) {
HazelcastInstance hzInstance = m_Server.getHazelcastInstance();
MultiMap<String, FriendData> friendsMap = hzInstance.getMultiMap(USER_FRIENDS);
Collection<FriendData> friendDatas = friendsMap.get(userId);
if (friendDatas == null || friendDatas.size() == 0) {
friendDatas = loadFriend(friendsMap, userId);
}
databaseStore.removeUserFriend(userId);
databaseStore.removeUserFriendRequest(userId);
MultiMap<String, WFCMessage.FriendRequest> requestMap = hzInstance.getMultiMap(USER_FRIENDS_REQUEST);
requestMap.remove(userId);
if (friendDatas != null) {
for (FriendData fd : friendDatas) {
friendsMap.remove(fd.getFriendUid());
}
friendsMap.remove(userId);
}
}
@Override
public List<WFCMessage.FriendRequest> getFriendRequestList(String userId, long version) {
List<WFCMessage.FriendRequest> out = new ArrayList<>();
@@ -1728,9 +1940,9 @@ public class MemoryMessagesStore implements IMessagesStore {
}
if (existRequest != null && existRequest.getStatus() != ProtoConstants.FriendRequestStatus.RequestStatus_Accepted) {
if (System.currentTimeMillis() - existRequest.getUpdateDt() > 7 * 24 * 60 * 60 * 1000) {
if (mFriendRequestDuration > 0 && System.currentTimeMillis() - existRequest.getUpdateDt() > mFriendRequestDuration) {
if (existRequest.getStatus() == ProtoConstants.FriendRequestStatus.RequestStatus_Rejected
&& System.currentTimeMillis() - existRequest.getUpdateDt() < 30 * 24 * 60 * 60 * 1000) {
&& System.currentTimeMillis() - existRequest.getUpdateDt() < mFriendRejectDuration) {
return ErrorCode.ERROR_CODE_FRIEND_REQUEST_BLOCKED;
}
} else {
@@ -1862,7 +2074,7 @@ public class MemoryMessagesStore implements IMessagesStore {
}
if (existRequest != null) {
if (System.currentTimeMillis() - existRequest.getUpdateDt() > 7 * 24 * 60 * 60 * 1000) {
if (mFriendRequestDuration > 0 && System.currentTimeMillis() - existRequest.getUpdateDt() > mFriendRequestDuration) {
return ErrorCode.ERROR_CODE_FRIEND_REQUEST_OVERTIME;
} else {
existRequest = existRequest.toBuilder().setStatus(ProtoConstants.FriendRequestStatus.RequestStatus_Accepted).setUpdateDt(System.currentTimeMillis()).build();
@@ -1899,7 +2111,7 @@ public class MemoryMessagesStore implements IMessagesStore {
} else {
state = 0;
}
HazelcastInstance hzInstance = m_Server.getHazelcastInstance();
MultiMap<String, FriendData> friendsMap = hzInstance.getMultiMap(USER_FRIENDS);
@@ -1995,6 +2207,18 @@ public class MemoryMessagesStore implements IMessagesStore {
return ErrorCode.ERROR_CODE_SUCCESS;
}
@Override
public boolean checkChatroomParticipantIdelTime(MemorySessionStore.Session session) {
if (session == null) {
return false;
}
if(mChatroomParticipantIdleTime > 0 && System.currentTimeMillis() - session.getLastChatroomActiveTime() > mChatroomParticipantIdleTime) {
return false;
}
return true;
}
@Override
public ErrorCode deleteFriend(String userId, String friendUid, long[] head) {
HazelcastInstance hzInstance = m_Server.getHazelcastInstance();
@@ -2086,6 +2310,7 @@ public class MemoryMessagesStore implements IMessagesStore {
}
} catch (Exception e) {
e.printStackTrace();
Utility.printExecption(LOG, e);
}
}
@@ -2189,6 +2414,14 @@ public class MemoryMessagesStore implements IMessagesStore {
return updateDt;
}
@Override
public void clearUserSettings(String userId) {
databaseStore.clearUserSetting(userId);
HazelcastInstance hzInstance = m_Server.getHazelcastInstance();
MultiMap<String, WFCMessage.UserSettingEntry> userSettingMap = hzInstance.getMultiMap(USER_SETTING);
userSettingMap.remove(userId);
}
@Override
public boolean getUserGlobalSlient(String userId) {
Boolean slient = userGlobalSlientMap.get(userId);
@@ -2246,6 +2479,12 @@ public class MemoryMessagesStore implements IMessagesStore {
return ErrorCode.ERROR_CODE_SUCCESS;
}
@Override
public void clearUserChannels(String userId) {
}
@Override
public ErrorCode modifyChannelInfo(String operator, String channelId, int modifyType, String value) {
HazelcastInstance hzInstance = m_Server.getHazelcastInstance();
@@ -2280,8 +2519,9 @@ public class MemoryMessagesStore implements IMessagesStore {
else if(modifyType == Modify_Channel_OnlyCallback) {
try {
newInfoBuilder.setAutomatic(Integer.parseInt(value));
} catch (NumberFormatException e) {
} catch (Exception e) {
e.printStackTrace();
Utility.printExecption(LOG, e);
}
}
@@ -2531,7 +2771,7 @@ public class MemoryMessagesStore implements IMessagesStore {
}
return UUIDGenerator.getUUID();
}
@Override
public void storeRetained(Topic topic, StoredMessage storedMessage) {
LOG.debug("Store retained message for topic={}, CId={}", topic, storedMessage.getClientID());
@@ -24,12 +24,12 @@ import io.moquette.BrokerConstants;
import io.moquette.server.Constants;
import io.moquette.server.Server;
import io.moquette.spi.ClientSession;
import io.moquette.spi.IMessagesStore.StoredMessage;
import io.moquette.spi.ISessionsStore;
import io.moquette.spi.IMessagesStore.StoredMessage;
import io.netty.handler.codec.mqtt.MqttVersion;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import win.liyufan.im.Utility;
import java.util.*;
import java.util.concurrent.*;
@@ -273,6 +273,7 @@ public class MemorySessionStore implements ISessionsStore {
supportMultiEndpoint = Boolean.parseBoolean(server.getConfig().getProperty(BrokerConstants.SERVER_MULTI_ENDPOINT));
} catch (Exception e) {
e.printStackTrace();
Utility.printExecption(LOG, e);
}
}
@@ -286,7 +287,7 @@ public class MemorySessionStore implements ISessionsStore {
}
@Override
public void cleanDuplatedToken(String cid, int pushType, String token, boolean isVoip) {
public void cleanDuplatedToken(String cid, int pushType, String token, boolean isVoip, String packageName) {
if (StringUtil.isNullOrEmpty(token) || isVoip) {
return;
}
@@ -294,7 +295,7 @@ public class MemorySessionStore implements ISessionsStore {
Iterator<Map.Entry<String, Session>> it = sessions.entrySet().iterator();
while (it.hasNext()) {
Session session = it.next().getValue();
if (!session.getClientID().equals(cid) && (session.pushType == pushType && token.equals(session.deviceToken))) {
if (!session.getClientID().equals(cid) && (session.pushType == pushType && token.equals(session.deviceToken)) && (!StringUtil.isNullOrEmpty(packageName) && packageName.equals(session.getAppName()))) {
session.deviceToken = null;
}
}
@@ -315,15 +316,38 @@ public class MemorySessionStore implements ISessionsStore {
}
@Override
public Session createUserSession(String username, String clientID, int platform) {
public void clearUserSession(String username) {
LOG.info("Fooooooooo <{}>", username);
databaseStore.clearUserSessions(username);
ConcurrentSkipListSet<String> sessionSet = getUserSessionSet(username);
for (String clientID : sessionSet) {
Session s = sessions.remove(clientID);
mServer.getProcessor().kickoffSession(s);
}
userSessions.remove(username);
}
@Override
public Session updateOrCreateUserSession(String username, String clientID, int platform) {
LOG.debug("createUserSession for client <{}>, user <{}>", clientID, username);
Session session = sessions.get(clientID);
if (session != null && !session.username.equals(username)) {
if (userSessions.get(username) != null) {
userSessions.get(username).remove(clientID);
}
}
ClientSession clientSession = new ClientSession(clientID, this);
Session session = databaseStore.getSession(username, clientID, clientSession);
session = databaseStore.getSession(username, clientID, clientSession);
if (session == null) {
session = databaseStore.createSession(username, clientID, clientSession, platform);
}
sessions.put(clientID, session);
if (session.getDeleted() > 0) {
session.setDeleted(0);
@@ -344,6 +368,10 @@ public class MemorySessionStore implements ISessionsStore {
String c = it.next();
if (!clientID.equals(c)) {
Session s = sessions.get(c);
if (s == null) {
it.remove();
continue;
}
boolean remove = false;
if (platform == ProtoConstants.Platform.Platform_Android || platform == ProtoConstants.Platform.Platform_iOS) {
@@ -19,7 +19,7 @@ import java.util.Map;
public class UserLoader implements MapStore<String, WFCMessage.User> {
@Override
public void store(String s, WFCMessage.User user) {
getDatabaseStore().updateUser(user);
// getDatabaseStore().updateUser(user);
}
@Override
@@ -24,8 +24,10 @@ public final class Constants {
public static final String ATTR_CLIENTID = "ClientID";
public static final String CLEAN_SESSION = "cleanSession";
public static final String KEEP_ALIVE = "keepAlive";
public static final int MAX_MESSAGE_QUEUE = 1024; // number of messages
public static final int MAX_CHATROOM_MESSAGE_QUEUE = 256; // number of chatroom messages
public static int MAX_MESSAGE_QUEUE = 1024; // number of messages
public static int MAX_CHATROOM_MESSAGE_QUEUE = 256; // number of chatroom messages
private Constants() {
}
@@ -103,7 +103,7 @@ public class NettyMQTTHandler extends ChannelInboundHandlerAdapter {
String clientID = NettyUtils.clientID(ctx.channel());
if (clientID != null && !clientID.isEmpty()) {
LOG.info("Notifying connection lost event. MqttClientId = {}.", clientID);
m_processor.processConnectionLost(clientID, ctx.channel());
m_processor.processConnectionLost(clientID, ctx.channel(), false);
}
ctx.close();
}
@@ -21,6 +21,7 @@ import cn.wildfirechat.proto.WFCMessage;
import com.xiaoleilu.loServer.model.FriendData;
import cn.wildfirechat.pojos.InputOutputUserBlockStatus;
import io.moquette.persistence.DatabaseStore;
import io.moquette.persistence.MemorySessionStore;
import io.moquette.persistence.UserClientEntry;
import io.moquette.spi.impl.subscriptions.Topic;
import io.netty.buffer.ByteBuf;
@@ -98,7 +99,7 @@ public interface IMessagesStore {
DatabaseStore getDatabaseStore();
WFCMessage.Message storeMessage(String fromUser, String fromClientId, WFCMessage.Message message);
void storeSensitiveMessage(WFCMessage.Message message);
int getNotifyReceivers(String fromUser, WFCMessage.Message.Builder message, Set<String> notifyReceivers);
int getNotifyReceivers(String fromUser, WFCMessage.Message.Builder message, Set<String> notifyReceivers, boolean ignoreMsg);
Set<String> getAllEnds();
WFCMessage.PullMessageResult fetchMessage(String user, String exceptClientId, long fromMessageId, int pullType);
WFCMessage.PullMessageResult loadRemoteMessages(String user, WFCMessage.Conversation conversation, long beforeUid, int count);
@@ -107,11 +108,13 @@ public interface IMessagesStore {
ErrorCode addGroupMembers(String operator, boolean isAdmin, String groupId, List<WFCMessage.GroupMember> memberList);
ErrorCode kickoffGroupMembers(String operator, boolean isAdmin, String groupId, List<String> memberList);
ErrorCode quitGroup(String operator, String groupId);
void clearUserGroups(String userId);
ErrorCode dismissGroup(String operator, String groupId, boolean isAdmin);
ErrorCode modifyGroupInfo(String operator, String groupId, int modifyType, String value, boolean isAdmin);
ErrorCode modifyGroupAlias(String operator, String groupId, String alias);
List<WFCMessage.GroupInfo> getGroupInfos(List<WFCMessage.UserRequest> requests);
WFCMessage.GroupInfo getGroupInfo(String groupId);
Set<String> getUserGroupIds(String userId);
ErrorCode getGroupMembers(String groupId, long maxDt, List<WFCMessage.GroupMember> members);
WFCMessage.GroupMember getGroupMember(String groupId, String memberId);
ErrorCode transferGroup(String operator, String groupId, String newOwner, boolean isAdmin);
@@ -121,20 +124,23 @@ public interface IMessagesStore {
ErrorCode recallMessage(long messageUid, String operatorId, boolean isAdmin);
void clearUserMessages(String userId);
WFCMessage.Robot getRobot(String robotId);
void addRobot(WFCMessage.Robot robot);
ErrorCode getUserInfo(List<WFCMessage.UserRequest> requestList, WFCMessage.PullUserResult.Builder builder);
ErrorCode modifyUserInfo(String userId, WFCMessage.ModifyMyInfoRequest request);
ErrorCode modifyUserInfo(String userId, WFCMessage.ModifyMyInfoRequest request) throws Exception;
ErrorCode modifyUserStatus(String userId, int status);
int getUserStatus(String userId);
List<InputOutputUserBlockStatus> getUserStatusList();
void addUserInfo(WFCMessage.User user, String password);
void addUserInfo(WFCMessage.User user, String password) throws Exception;
void destoryUser(String userId);
WFCMessage.User getUserInfo(String userId);
WFCMessage.User getUserInfoByName(String name);
WFCMessage.User getUserInfoByMobile(String mobile);
List<WFCMessage.User> searchUser(String keyword, boolean buzzy, int page);
List<WFCMessage.User> searchUser(String keyword, int searchType, int page);
boolean updateSystemSetting(int id, String value, String desc);
SystemSettingPojo getSystemSetting(int id);
@@ -154,6 +160,7 @@ public interface IMessagesStore {
ErrorCode login(String name, String password, List<String> userIdRet);
List<FriendData> getFriendList(String userId, String clientId, long version);
void clearUserFriend(String userId);
List<WFCMessage.FriendRequest> getFriendRequestList(String userId, long version);
ErrorCode saveAddFriendRequest(String userId, WFCMessage.AddFriendRequest request, long[] head);
@@ -161,22 +168,26 @@ public interface IMessagesStore {
ErrorCode deleteFriend(String userId, String friendUid, long[] head);
ErrorCode blackUserRequest(String fromUser, String targetUserId, int status, long[] head);
ErrorCode SyncFriendRequestUnread(String userId, long unreadDt, long[] head);
boolean isBlacked(String fromUser, String userId);
ErrorCode isAllowUserMessage(String fromUser, String userId);
ErrorCode setFriendAliasRequest(String fromUser, String targetUserId, String alias, long[] head);
ErrorCode handleJoinChatroom(String userId, String clientId, String chatroomId);
ErrorCode handleQuitChatroom(String userId, String clientId, String chatroomId);
boolean checkChatroomParticipantIdelTime(MemorySessionStore.Session session);
ErrorCode getUserSettings(String userId, long version, WFCMessage.GetUserSettingResult.Builder builder);
WFCMessage.UserSettingEntry getUserSetting(String userId, int scope, String key);
List<WFCMessage.UserSettingEntry> getUserSetting(String userId, int scope);
long updateUserSettings(String userId, WFCMessage.ModifyUserSettingReq request);
void clearUserSettings(String userId);
boolean getUserGlobalSlient(String userId);
boolean getUserPushHiddenDetail(String userId);
boolean getUserConversationSlient(String userId, WFCMessage.Conversation conversation);
ErrorCode createChannel(String operator, WFCMessage.ChannelInfo channelInfo);
void clearUserChannels(String userId);
ErrorCode modifyChannelInfo(String operator, String channelId, int modifyType, String value);
ErrorCode transferChannel(String operator, String channelId, String newOwner);
ErrorCode distoryChannel(String operator, String channelId);
@@ -38,7 +38,7 @@ public interface ISessionsStore {
*/
boolean contains(String clientID);
Session createUserSession(String username, String clientID, int platform);
Session updateOrCreateUserSession(String username, String clientID, int platform);
ErrorCode loadActiveSession(String username, String clientID);
@@ -46,9 +46,11 @@ public interface ISessionsStore {
Session getSession(String clientID);
void cleanDuplatedToken(String cid, int pushType, String token, boolean isVoip);
void cleanDuplatedToken(String cid, int pushType, String token, boolean isVoip, String packageName);
void updateSessionToken(Session session, boolean voip);
void clearUserSession(String username);
/**
* @param clientID
* the client owning the session.
@@ -87,6 +87,7 @@ public class MessagesPublisher {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
Utility.printExecption(LOG, e);
}
chatroomScheduler.shutdown();
}
@@ -216,7 +217,7 @@ public class MessagesPublisher {
targetSession.refreshLastChatroomActiveTime();
}
if(System.currentTimeMillis() - targetSession.getLastChatroomActiveTime() > 5*60*1000) {
if (!m_messagesStore.checkChatroomParticipantIdelTime(targetSession)) {
m_messagesStore.handleQuitChatroom(user, targetSession.getClientID(), target);
continue;
}
@@ -17,7 +17,14 @@
package io.moquette.spi.impl;
import cn.wildfirechat.common.ErrorCode;
import cn.wildfirechat.pojos.SendMessageData;
import cn.wildfirechat.pojos.UserOnlineStatus;
import cn.wildfirechat.proto.ProtoConstants;
import cn.wildfirechat.proto.WFCMessage;
import com.google.gson.Gson;
import com.hazelcast.core.Member;
import com.hazelcast.util.StringUtil;
import io.moquette.BrokerConstants;
import io.moquette.persistence.RPCCenter;
import io.moquette.interception.InterceptHandler;
import io.moquette.interception.messages.InterceptAcknowledgedMessage;
@@ -39,9 +46,12 @@ import io.netty.handler.codec.mqtt.*;
import io.netty.handler.timeout.IdleStateHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import win.liyufan.im.HttpUtils;
import win.liyufan.im.Utility;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import static io.moquette.spi.impl.InternalRepublisher.createPublishForQos;
import static io.moquette.spi.impl.Utils.readBytesAndRewind;
@@ -58,7 +68,7 @@ import static io.moquette.server.ConnectionDescriptor.ConnectionState.*;
*/
public class ProtocolProcessor {
private static ExecutorService executorCallback = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
public void kickoffSession(final MemorySessionStore.Session session) {
mServer.getImBusinessScheduler().execute(()->{
@@ -153,8 +163,15 @@ public class ProtocolProcessor {
this.connectionDescriptors, this.messagesPublisher, sessionsStore, server.getImBusinessScheduler(), server);
mServer = server;
String onlineStatusCallback = server.getConfig().getProperty(BrokerConstants.USER_ONLINE_STATUS_CALLBACK);
if (!com.hazelcast.util.StringUtil.isNullOrEmpty(onlineStatusCallback)) {
mUserOnlineStatusCallback = onlineStatusCallback;
}
}
private String mUserOnlineStatusCallback;
public void processConnect(Channel channel, MqttConnectMessage msg) {
MqttConnectPayload payload = msg.payload();
String clientId = payload.clientIdentifier();
@@ -232,11 +249,20 @@ public class ProtocolProcessor {
MemorySessionStore.Session session = m_sessionsStore.getSession(clientId);
if(session != null) {
session.refreshLastActiveTime();
forwardOnlineStatusEvent(payload.userName(), clientId, session.getPlatform(), UserOnlineStatus.ONLINE);
} else {
forwardOnlineStatusEvent(payload.userName(), clientId, ProtoConstants.Platform.Platform_UNSET, UserOnlineStatus.ONLINE);
}
LOG.info("The CONNECT message has been processed. CId={}, username={}", clientId, payload.userName());
}
public void forwardOnlineStatusEvent(String userId, String clientId, int platform, int status) {
if (!StringUtil.isNullOrEmpty(mUserOnlineStatusCallback)) {
executorCallback.execute(() -> HttpUtils.httpJsonPost(mUserOnlineStatusCallback, new Gson().toJson(new UserOnlineStatus(userId, clientId, platform, status))));
}
}
private MqttConnAckMessage connAck(MqttConnectReturnCode returnCode) {
return connAck(returnCode, false);
}
@@ -265,7 +291,7 @@ public class ProtocolProcessor {
// handle user authentication
if (msg.variableHeader().hasUserName()) {
int status = m_messagesStore.getUserStatus(msg.payload().userName());
if (status == 2) {
if (status == ProtoConstants.UserStatus.Forbidden) {
failedBlocked(channel);
return false;
}
@@ -283,6 +309,7 @@ public class ProtocolProcessor {
}
if (session.getDeleted() != 0) {
LOG.error("user {} session {} is deleted. login failure", msg.payload().userName(), clientId);
return false;
}
@@ -493,7 +520,7 @@ public class ProtocolProcessor {
}
if (!clearSession) {
processConnectionLost(clientID, channel);
processConnectionLost(clientID, channel, clearSession);
return;
}
@@ -534,9 +561,16 @@ public class ProtocolProcessor {
LOG.info("The DISCONNECT message has been processed. CId={}", clientID);
String username = NettyUtils.userName(channel);
MemorySessionStore.Session session = m_sessionsStore.getSession(clientID);
if(session != null) {
forwardOnlineStatusEvent(username, clientID, session.getPlatform(), UserOnlineStatus.LOGOUT);
}
channel.closeFuture();
//disconnect the session
m_sessionsStore.sessionForClient(clientID).disconnect(clearSession);
}
@@ -567,17 +601,21 @@ public class ProtocolProcessor {
return true;
}
public void processConnectionLost(String clientID, Channel channel) {
public void processConnectionLost(String clientID, Channel channel, boolean clearSession) {
LOG.info("Processing connection lost event. CId={}", clientID);
String username = NettyUtils.userName(channel);
MemorySessionStore.Session session = m_sessionsStore.getSession(clientID);
if(session != null) {
session.refreshLastActiveTime();
forwardOnlineStatusEvent(username, clientID, session.getPlatform(), clearSession ? UserOnlineStatus.LOGOUT : UserOnlineStatus.OFFLINE);
}
ConnectionDescriptor oldConnDescr = new ConnectionDescriptor(clientID, channel);
if(connectionDescriptors.removeConnection(oldConnDescr)) {
MemorySessionStore.Session session = m_sessionsStore.getSession(clientID);
if(session != null) {
session.refreshLastActiveTime();
}
String username = NettyUtils.userName(channel);
m_interceptor.notifyClientConnectionLost(clientID, username);
}
}
/**
@@ -187,6 +187,7 @@ public class Qos1PublishHandler extends QosPublishHandler {
gzip.close();
} catch (Exception e) {
e.printStackTrace();
Utility.printExecption(LOG, e);
}
data = out.toByteArray();
code = (byte)ErrorCode.ERROR_CODE_SUCCESS_GZIPED.code;
@@ -53,6 +53,13 @@ public class HttpUtils {
@Override
public void onResponse(Call call, Response response) throws IOException {
LOG.info("POST to {} success with response: {}", url, response.body());
try {
if (response.body() != null) {
response.body().close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
@@ -71,6 +71,7 @@ public interface IMTopic {
String ChannelPullTopic = "CHP";
String GetTokenTopic = "GETTOKEN";
String DestroyUserTopic = "DESTROYUSER";
String LoadRemoteMessagesTopic = "LRM";
}
+1 -1
View File
@@ -5,7 +5,7 @@
<parent>
<artifactId>wildfirechat-parent</artifactId>
<groupId>cn.wildfirechat</groupId>
<version>0.33</version>
<version>0.37</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -0,0 +1,22 @@
/*
* This file is part of the Wildfire Chat package.
* (c) Heavyrain2012 <heavyrain.lee@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
package cn.wildfirechat.pojos;
public class InputDestroyUser {
private String userId;
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
}
@@ -11,6 +11,7 @@ public interface APIPath {
String Sensitive_Query = "/admin/sensitive/query";
String Create_User = "/admin/user/create";
String Destroy_User = "/admin/user/destroy";
String Create_Robot = "/admin/robot/create";
String User_Get_Token = "/admin/user/get_token";
String User_Update_Block_Status = "/admin/user/update_block_status";
@@ -22,6 +23,8 @@ public interface APIPath {
String Friend_Update_Status = "/admin/friend/status";
String Friend_Get_List = "/admin/friend/list";
String Friend_Get_Alias = "/admin/friend/get_alias";
String Friend_Set_Alias = "/admin/friend/set_alias";
String Msg_Send = "/admin/message/send";
String Msg_Recall = "/admin/message/recall";
@@ -36,15 +39,21 @@ public interface APIPath {
String Group_Member_List = "/admin/group/member/list";
String Group_Member_Add = "/admin/group/member/add";
String Group_Member_Kickoff = "/admin/group/member/del";
String Group_Member_Quit = "/admin/group/member/quit";
String Group_Set_Manager = "/admin/group/manager/set";
String Get_User_Groups = "/admin/group/of_user";
String Create_Channel = "/admin/channel/create";
String Get_System_Setting = "/admin/system/get_setting";
String Put_System_Setting = "/admin/system/put_setting";
String Channel_User_Info = "/channel/user_info";
String Channel_Update_Profile = "/channel/update_profile";
String Channel_Get_Profile = "/channel/get_profile";
String Channel_Message_Send = "/channel/message/send";
String Channel_Subscribe = "/channel/subscribe";
String Channel_Subscriber_List = "/channel/subscriber_list";
String Robot_User_Info = "/robot/user_info";
String Robot_Message_Send = "/robot/message/send";
@@ -0,0 +1,36 @@
/*
* This file is part of the Wildfire Chat package.
* (c) Heavyrain2012 <heavyrain.lee@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
package cn.wildfirechat.pojos;
import cn.wildfirechat.proto.ProtoConstants;
import cn.wildfirechat.proto.WFCMessage;
import java.util.ArrayList;
import java.util.List;
public class InputChannelSubscribe {
private String target;
private int subscribe; //1,订阅;0,取消订阅
public String getTarget() {
return target;
}
public void setTarget(String target) {
this.target = target;
}
public int getSubscribe() {
return subscribe;
}
public void setSubscribe(int subscribe) {
this.subscribe = subscribe;
}
}
@@ -0,0 +1,31 @@
/*
* This file is part of the Wildfire Chat package.
* (c) Heavyrain2012 <heavyrain.lee@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
package cn.wildfirechat.pojos;
public class InputGetAlias {
private String operator;
private String targetId;
public String getTargetId() {
return targetId;
}
public void setTargetId(String targetId) {
this.targetId = targetId;
}
public String getOperator() {
return operator;
}
public void setOperator(String operator) {
this.operator = operator;
}
}
@@ -0,0 +1,36 @@
/*
* This file is part of the Wildfire Chat package.
* (c) Heavyrain2012 <heavyrain.lee@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
package cn.wildfirechat.pojos;
import cn.wildfirechat.proto.WFCMessage;
import io.netty.util.internal.StringUtil;
import java.util.Arrays;
public class InputModifyChannelInfo {
private int type;
private String value;
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
@@ -0,0 +1,48 @@
/*
* This file is part of the Wildfire Chat package.
* (c) Heavyrain2012 <heavyrain.lee@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
package cn.wildfirechat.pojos;
import cn.wildfirechat.proto.WFCMessage;
import java.util.List;
public class InputQuitGroup extends InputGroupBase {
private String group_id;
public String getGroup_id() {
return group_id;
}
public void setGroup_id(String group_id) {
this.group_id = group_id;
}
public boolean isValide() {
return true;
}
public WFCMessage.QuitGroupRequest toProtoGroupRequest() {
WFCMessage.QuitGroupRequest.Builder removedGroupBuilder = WFCMessage.QuitGroupRequest.newBuilder();
removedGroupBuilder.setGroupId(group_id);
if (to_lines != null) {
for (Integer line : to_lines
) {
removedGroupBuilder.addToLine(line);
}
}
if (notify_message != null) {
removedGroupBuilder.setNotifyContent(notify_message.toProtoMessageContent());
}
return removedGroupBuilder.build();
}
}
@@ -0,0 +1,40 @@
/*
* This file is part of the Wildfire Chat package.
* (c) Heavyrain2012 <heavyrain.lee@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
package cn.wildfirechat.pojos;
public class InputUpdateAlias {
private String operator;
private String targetId;
private String alias;
public String getTargetId() {
return targetId;
}
public void setTargetId(String targetId) {
this.targetId = targetId;
}
public String getOperator() {
return operator;
}
public void setOperator(String operator) {
this.operator = operator;
}
public String getAlias() {
return alias;
}
public void setAlias(String alias) {
this.alias = alias;
}
}
@@ -0,0 +1,21 @@
/*
* This file is part of the Wildfire Chat package.
* (c) Heavyrain2012 <heavyrain.lee@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
package cn.wildfirechat.pojos;
public class InputUserId {
private String userId;
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
}
@@ -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;
}
}
@@ -0,0 +1,48 @@
/*
* This file is part of the Wildfire Chat package.
* (c) Heavyrain2012 <heavyrain.lee@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
package cn.wildfirechat.pojos;
public class OutputGetAlias {
private String operator;
private String targetId;
private String alias;
public OutputGetAlias() {
}
public OutputGetAlias(String operator, String targetId) {
this.operator = operator;
this.targetId = targetId;
}
public String getTargetId() {
return targetId;
}
public void setTargetId(String targetId) {
this.targetId = targetId;
}
public String getOperator() {
return operator;
}
public void setOperator(String operator) {
this.operator = operator;
}
public String getAlias() {
return alias;
}
public void setAlias(String alias) {
this.alias = alias;
}
}
@@ -0,0 +1,121 @@
/*
* This file is part of the Wildfire Chat package.
* (c) Heavyrain2012 <heavyrain.lee@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
package cn.wildfirechat.pojos;
import cn.wildfirechat.proto.WFCMessage;
public class OutputGetChannelInfo {
private String channelId;
private String name;
private String desc;
private String portrait;
private String extra;
private String owner;
private int status;
private long updateDt;
private String callback;
private int automatic;
public String getChannelId() {
return channelId;
}
public void setChannelId(String channelId) {
this.channelId = channelId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public String getPortrait() {
return portrait;
}
public void setPortrait(String portrait) {
this.portrait = portrait;
}
public String getExtra() {
return extra;
}
public void setExtra(String extra) {
this.extra = extra;
}
public String getOwner() {
return owner;
}
public void setOwner(String owner) {
this.owner = owner;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public long getUpdateDt() {
return updateDt;
}
public void setUpdateDt(long updateDt) {
this.updateDt = updateDt;
}
public String getCallback() {
return callback;
}
public void setCallback(String callback) {
this.callback = callback;
}
public int getAutomatic() {
return automatic;
}
public void setAutomatic(int automatic) {
this.automatic = automatic;
}
public static OutputGetChannelInfo fromPbInfo(WFCMessage.ChannelInfo channelInfo) {
OutputGetChannelInfo out = new OutputGetChannelInfo();
out.automatic = channelInfo.getAutomatic();
out.callback = channelInfo.getCallback();
out.channelId = channelInfo.getTargetId();
out.desc = channelInfo.getDesc();
out.extra = channelInfo.getExtra();
out.name = channelInfo.getName();
out.owner = channelInfo.getOwner();
out.portrait = channelInfo.getPortrait();
out.status = channelInfo.getStatus();
out.updateDt = channelInfo.getUpdateDt();
return out;
}
}
@@ -0,0 +1,23 @@
/*
* This file is part of the Wildfire Chat package.
* (c) Heavyrain2012 <heavyrain.lee@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
package cn.wildfirechat.pojos;
import java.util.List;
public class OutputGroupIds {
private List<String> groupIds;
public List<String> getGroupIds() {
return groupIds;
}
public void setGroupIds(List<String> groupIds) {
this.groupIds = groupIds;
}
}
@@ -0,0 +1,22 @@
package cn.wildfirechat.pojos;
import java.util.List;
public class OutputStringList {
private List<String> list;
public OutputStringList() {
}
public OutputStringList(List<String> list) {
this.list = list;
}
public List<String> getList() {
return list;
}
public void setList(List<String> list) {
this.list = list;
}
}
@@ -0,0 +1,66 @@
/*
* This file is part of the Wildfire Chat package.
* (c) Heavyrain2012 <heavyrain.lee@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
package cn.wildfirechat.pojos;
import cn.wildfirechat.proto.ProtoConstants;
import cn.wildfirechat.proto.WFCMessage;
import io.netty.util.internal.StringUtil;
import java.util.ArrayList;
import java.util.List;
public class SendChannelMessageData {
private List<String> targets;
private int line;
private MessagePayload payload;
public List<String> getTargets() {
return targets;
}
public void setTargets(List<String> targets) {
this.targets = targets;
}
public int getLine() {
return line;
}
public void setLine(int line) {
this.line = line;
}
public MessagePayload getPayload() {
return payload;
}
public void setPayload(MessagePayload payload) {
this.payload = payload;
}
public static boolean isValide(SendChannelMessageData sendMessageData) {
if(sendMessageData == null ||
sendMessageData.getPayload() == null) {
return false;
}
return true;
}
public WFCMessage.Message toProtoMessage(String channelId, String channelOwner) {
if (targets == null) {
targets = new ArrayList<>();
}
return WFCMessage.Message.newBuilder().setFromUser(channelOwner)
.setConversation(WFCMessage.Conversation.newBuilder().setType(ProtoConstants.ConversationType.ConversationType_Channel).setTarget(channelId).setLine(line))
.addAllTo(targets)
.setContent(payload.toProtoMessageContent())
.build();
}
}
@@ -0,0 +1,21 @@
package cn.wildfirechat.pojos;
public class UserOnlineStatus {
public static final int ONLINE = 0;
public static final int OFFLINE = 1;
public static final int LOGOUT = -1;
public String userId;
public String clientId;
public int platform;
public int status;
public long timestamp;
public UserOnlineStatus(String userId, String clientId, int platform, int status) {
this.userId = userId;
this.clientId = clientId;
this.platform = platform;
this.status = status;
this.timestamp = System.currentTimeMillis();
}
}
@@ -125,6 +125,8 @@ public class ProtoConstants {
int UserType_Normal = 0;
int UserType_Robot = 1;
int UserType_Device = 2;
int UserType_Admin = 3;
int UserType_Super_Admin = 100;
}
@@ -132,6 +134,23 @@ public class ProtoConstants {
int Group_Max_Member_Count = 1;
}
public interface SearchUserType {
int SearchUserType_General = 0;
int SearchUserType_Name_Mobile = 1;
int SearchUserType_Name = 2;
int SearchUserType_Mobile = 3;
}
public interface UserStatus {
int Normal = 0;
int Muted = 1;
int Forbidden = 2;
}
public interface BlacklistStrategy {
int Message_Reject = 0;
int Message_Ignore = 1;
}
@@ -22192,6 +22192,16 @@ public final class WFCMessage {
* </pre>
*/
int getType();
// optional int32 deleted = 14;
/**
* <code>optional int32 deleted = 14;</code>
*/
boolean hasDeleted();
/**
* <code>optional int32 deleted = 14;</code>
*/
int getDeleted();
}
/**
* Protobuf type {@code User}
@@ -22309,6 +22319,11 @@ public final class WFCMessage {
type_ = input.readInt32();
break;
}
case 112: {
bitField0_ |= 0x00002000;
deleted_ = input.readInt32();
break;
}
}
}
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
@@ -22835,6 +22850,22 @@ public final class WFCMessage {
return type_;
}
// optional int32 deleted = 14;
public static final int DELETED_FIELD_NUMBER = 14;
private int deleted_;
/**
* <code>optional int32 deleted = 14;</code>
*/
public boolean hasDeleted() {
return ((bitField0_ & 0x00002000) == 0x00002000);
}
/**
* <code>optional int32 deleted = 14;</code>
*/
public int getDeleted() {
return deleted_;
}
private void initFields() {
uid_ = "";
name_ = "";
@@ -22849,6 +22880,7 @@ public final class WFCMessage {
gender_ = 0;
social_ = "";
type_ = 0;
deleted_ = 0;
}
private byte memoizedIsInitialized = -1;
public final boolean isInitialized() {
@@ -22905,6 +22937,9 @@ public final class WFCMessage {
if (((bitField0_ & 0x00001000) == 0x00001000)) {
output.writeInt32(13, type_);
}
if (((bitField0_ & 0x00002000) == 0x00002000)) {
output.writeInt32(14, deleted_);
}
getUnknownFields().writeTo(output);
}
@@ -22966,6 +23001,10 @@ public final class WFCMessage {
size += com.google.protobuf.CodedOutputStream
.computeInt32Size(13, type_);
}
if (((bitField0_ & 0x00002000) == 0x00002000)) {
size += com.google.protobuf.CodedOutputStream
.computeInt32Size(14, deleted_);
}
size += getUnknownFields().getSerializedSize();
memoizedSerializedSize = size;
return size;
@@ -23108,6 +23147,8 @@ public final class WFCMessage {
bitField0_ = (bitField0_ & ~0x00000800);
type_ = 0;
bitField0_ = (bitField0_ & ~0x00001000);
deleted_ = 0;
bitField0_ = (bitField0_ & ~0x00002000);
return this;
}
@@ -23188,6 +23229,10 @@ public final class WFCMessage {
to_bitField0_ |= 0x00001000;
}
result.type_ = type_;
if (((from_bitField0_ & 0x00002000) == 0x00002000)) {
to_bitField0_ |= 0x00002000;
}
result.deleted_ = deleted_;
result.bitField0_ = to_bitField0_;
onBuilt();
return result;
@@ -23263,6 +23308,9 @@ public final class WFCMessage {
if (other.hasType()) {
setType(other.getType());
}
if (other.hasDeleted()) {
setDeleted(other.getDeleted());
}
this.mergeUnknownFields(other.getUnknownFields());
return this;
}
@@ -24149,6 +24197,39 @@ public final class WFCMessage {
return this;
}
// optional int32 deleted = 14;
private int deleted_ ;
/**
* <code>optional int32 deleted = 14;</code>
*/
public boolean hasDeleted() {
return ((bitField0_ & 0x00002000) == 0x00002000);
}
/**
* <code>optional int32 deleted = 14;</code>
*/
public int getDeleted() {
return deleted_;
}
/**
* <code>optional int32 deleted = 14;</code>
*/
public Builder setDeleted(int value) {
bitField0_ |= 0x00002000;
deleted_ = value;
onChanged();
return this;
}
/**
* <code>optional int32 deleted = 14;</code>
*/
public Builder clearDeleted() {
bitField0_ = (bitField0_ & ~0x00002000);
deleted_ = 0;
onChanged();
return this;
}
// @@protoc_insertion_point(builder_scope:User)
}
@@ -60355,102 +60436,102 @@ public final class WFCMessage {
"om_user\030\002 \002(\t\022 \n\007content\030\003 \002(\0132\017.Message" +
"Content\022\022\n\nmessage_id\030\004 \001(\003\022\030\n\020server_ti",
"mestamp\030\005 \001(\003\022\017\n\007to_user\030\006 \001(\t\022\n\n\002to\030\007 \003" +
"(\t\"\332\001\n\004User\022\013\n\003uid\030\001 \002(\t\022\014\n\004name\030\002 \001(\t\022\024" +
"(\t\"\353\001\n\004User\022\013\n\003uid\030\001 \002(\t\022\014\n\004name\030\002 \001(\t\022\024" +
"\n\014display_name\030\003 \001(\t\022\020\n\010portrait\030\004 \001(\t\022\016" +
"\n\006mobile\030\005 \001(\t\022\r\n\005email\030\006 \001(\t\022\017\n\007address" +
"\030\007 \001(\t\022\017\n\007company\030\010 \001(\t\022\r\n\005extra\030\t \001(\t\022\021" +
"\n\tupdate_dt\030\n \001(\003\022\016\n\006gender\030\013 \001(\005\022\016\n\006soc" +
"ial\030\014 \001(\t\022\014\n\004type\030\r \001(\005\"c\n\005Robot\022\013\n\003uid\030" +
"\001 \002(\t\022\r\n\005state\030\002 \002(\005\022\r\n\005owner\030\003 \001(\t\022\016\n\006s" +
"ecret\030\004 \001(\t\022\020\n\010callback\030\005 \001(\t\022\r\n\005extra\030\006" +
" \001(\t\"(\n\017GetRobotsResult\022\025\n\005entry\030\001 \003(\0132\006",
".Robot\"P\n\005Thing\022\013\n\003uid\030\001 \002(\t\022\r\n\005state\030\002 " +
"\002(\005\022\r\n\005token\030\003 \002(\t\022\r\n\005owner\030\004 \001(\t\022\r\n\005ext" +
"ra\030\005 \001(\t\"(\n\017GetThingsResult\022\025\n\005entry\030\001 \003" +
"(\0132\006.Thing\"g\n\030UploadDeviceTokenRequest\022\020" +
"\n\010platform\030\001 \002(\005\022\020\n\010app_name\030\002 \002(\t\022\024\n\014de" +
"vice_token\030\003 \002(\t\022\021\n\tpush_type\030\004 \002(\005\"\201\001\n\026" +
"ModifyGroupInfoRequest\022\020\n\010group_id\030\001 \002(\t" +
"\022\014\n\004type\030\002 \002(\005\022\r\n\005value\030\003 \002(\t\022\017\n\007to_line" +
"\030\004 \003(\005\022\'\n\016notify_content\030\005 \001(\0132\017.Message" +
"Content\"\203\001\n\026SetGroupManagerRequest\022\020\n\010gr",
"oup_id\030\001 \002(\t\022\014\n\004type\030\002 \002(\005\022\017\n\007user_id\030\003 " +
"\003(\t\022\017\n\007to_line\030\004 \003(\005\022\'\n\016notify_content\030\005" +
" \001(\0132\017.MessageContent\"(\n\tInfoEntry\022\014\n\004ty" +
"pe\030\001 \002(\005\022\r\n\005value\030\002 \002(\t\"0\n\023ModifyMyInfoR" +
"equest\022\031\n\005entry\030\001 \003(\0132\n.InfoEntry\";\n\rNot" +
"ifyMessage\022\014\n\004type\030\001 \002(\005\022\014\n\004head\030\002 \002(\003\022\016" +
"\n\006target\030\003 \001(\t\"=\n\022PullMessageRequest\022\n\n\002" +
"id\030\001 \002(\003\022\014\n\004type\030\002 \002(\005\022\r\n\005delay\030\003 \001(\003\"M\n" +
"\021PullMessageResult\022\031\n\007message\030\001 \003(\0132\010.Me" +
"ssage\022\017\n\007current\030\002 \002(\003\022\014\n\004head\030\003 \002(\003\"/\n\023",
"PullGroupInfoResult\022\030\n\004info\030\001 \003(\0132\n.Grou" +
"pInfo\"6\n\026PullGroupMemberRequest\022\016\n\006targe" +
"t\030\001 \002(\t\022\014\n\004head\030\002 \002(\003\"5\n\025PullGroupMember" +
"Result\022\034\n\006member\030\001 \003(\0132\014.GroupMember\"-\n\013" +
"UserRequest\022\013\n\003uid\030\001 \002(\t\022\021\n\tupdate_dt\030\002 " +
"\001(\003\"0\n\017PullUserRequest\022\035\n\007request\030\001 \003(\0132" +
"\014.UserRequest\"/\n\nUserResult\022\023\n\004user\030\001 \002(" +
"\0132\005.User\022\014\n\004code\030\002 \002(\005\"-\n\016PullUserResult" +
"\022\033\n\006result\030\001 \003(\0132\013.UserResult\"^\n\020QuitGro" +
"upRequest\022\020\n\010group_id\030\001 \002(\t\022\017\n\007to_line\030\002",
" \003(\005\022\'\n\016notify_content\030\003 \001(\0132\017.MessageCo" +
"ntent\"~\n\030RemoveGroupMemberRequest\022\020\n\010gro" +
"up_id\030\001 \002(\t\022\026\n\016removed_member\030\002 \003(\t\022\017\n\007t" +
"o_line\030\003 \003(\005\022\'\n\016notify_content\030\004 \001(\0132\017.M" +
"essageContent\"u\n\024TransferGroupRequest\022\020\n" +
"\010group_id\030\001 \002(\t\022\021\n\tnew_owner\030\002 \002(\t\022\017\n\007to" +
"_line\030\003 \003(\005\022\'\n\016notify_content\030\004 \001(\0132\017.Me" +
"ssageContent\"s\n\026ModifyGroupMemberAlias\022\020" +
"\n\010group_id\030\001 \002(\t\022\r\n\005alias\030\002 \002(\t\022\017\n\007to_li" +
"ne\030\003 \003(\005\022\'\n\016notify_content\030\004 \001(\0132\017.Messa",
"geContent\"P\n\020UserSettingEntry\022\r\n\005scope\030\001" +
" \002(\005\022\013\n\003key\030\002 \002(\t\022\r\n\005value\030\003 \002(\t\022\021\n\tupda" +
"te_dt\030\004 \002(\003\"A\n\024ModifyUserSettingReq\022\r\n\005s" +
"cope\030\001 \002(\005\022\013\n\003key\030\002 \002(\t\022\r\n\005value\030\003 \002(\t\"\032" +
"\n\007Version\022\017\n\007version\030\001 \002(\003\"8\n\024GetUserSet" +
"tingResult\022 \n\005entry\030\001 \003(\0132\021.UserSettingE" +
"ntry\"W\n\006Friend\022\013\n\003uid\030\001 \002(\t\022\r\n\005state\030\002 \002" +
"(\005\022\021\n\tupdate_dt\030\003 \002(\003\022\r\n\005alias\030\004 \001(\t\022\017\n\007" +
"blacked\030\005 \001(\005\"*\n\020GetFriendsResult\022\026\n\005ent" +
"ry\030\001 \003(\0132\007.Friend\"7\n\026GetFriendRequestRes",
"ult\022\035\n\005entry\030\001 \003(\0132\016.FriendRequest\"\243\001\n\021C" +
"onnectAckPayload\022\020\n\010msg_head\030\001 \001(\003\022\023\n\013fr" +
"iend_head\030\002 \001(\003\022\026\n\016friend_rq_head\030\003 \001(\003\022" +
"\024\n\014setting_head\030\004 \001(\003\022\021\n\tnode_addr\030\005 \001(\t" +
"\022\021\n\tnode_port\030\006 \001(\005\022\023\n\013server_time\030\007 \001(\003" +
"\"P\n\rIMHttpWrapper\022\r\n\005token\030\001 \002(\t\022\021\n\tclie" +
"nt_id\030\002 \002(\t\022\017\n\007request\030\003 \002(\t\022\014\n\004data\030\004 \001" +
"(\014\"A\n\021SearchUserRequest\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\020SearchU" +
"serResult\022\024\n\005entry\030\001 \003(\0132\005.User\"@\n\026GetCh",
"atroomInfoRequest\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\005ti" +
"tle\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\005" +
"state\030\010 \001(\005\"F\n\034GetChatroomMemberInfoRequ" +
"est\022\023\n\013chatroom_id\030\001 \002(\t\022\021\n\tmax_count\030\002 " +
"\001(\005\";\n\022ChatroomMemberInfo\022\024\n\014member_coun" +
"t\030\001 \001(\005\022\017\n\007members\030\002 \003(\t\"\026\n\010INT64Buf\022\n\n\002" +
"id\030\001 \002(\003\"4\n\023NotifyRecallMessage\022\n\n\002id\030\001 ",
"\002(\003\022\021\n\tfrom_user\030\002 \002(\t\"/\n\020BlackUserReque" +
"st\022\013\n\003uid\030\001 \002(\t\022\016\n\006status\030\002 \002(\005\"\323\001\n\014Rout" +
"eRequest\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\rRouteResponse\022\014\n\004host\030\001 \002(\t\022\021\n\t" +
"long_port\030\002 \002(\005\022\022\n\nshort_port\030\003 \002(\005\"G\n\017G" +
"etTokenRequest\022\017\n\007user_id\030\001 \002(\t\022\021\n\tclien",
"t_id\030\002 \002(\t\022\020\n\010platform\030\003 \001(\005\"\\\n\022LoadRemo" +
"teMessages\022#\n\014conversation\030\001 \002(\0132\r.Conve" +
"rsation\022\022\n\nbefore_uid\030\002 \002(\003\022\r\n\005count\030\003 \002" +
"(\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\002t" +
"o\030\003 \003(\t\022\014\n\004line\030\004 \002(\005B#\n\025cn.wildfirechat" +
".protoB\nWFCMessage"
"ial\030\014 \001(\t\022\014\n\004type\030\r \001(\005\022\017\n\007deleted\030\016 \001(\005" +
"\"c\n\005Robot\022\013\n\003uid\030\001 \002(\t\022\r\n\005state\030\002 \002(\005\022\r\n" +
"\005owner\030\003 \001(\t\022\016\n\006secret\030\004 \001(\t\022\020\n\010callback" +
"\030\005 \001(\t\022\r\n\005extra\030\006 \001(\t\"(\n\017GetRobotsResult",
"\022\025\n\005entry\030\001 \003(\0132\006.Robot\"P\n\005Thing\022\013\n\003uid\030" +
"\001 \002(\t\022\r\n\005state\030\002 \002(\005\022\r\n\005token\030\003 \002(\t\022\r\n\005o" +
"wner\030\004 \001(\t\022\r\n\005extra\030\005 \001(\t\"(\n\017GetThingsRe" +
"sult\022\025\n\005entry\030\001 \003(\0132\006.Thing\"g\n\030UploadDev" +
"iceTokenRequest\022\020\n\010platform\030\001 \002(\005\022\020\n\010app" +
"_name\030\002 \002(\t\022\024\n\014device_token\030\003 \002(\t\022\021\n\tpus" +
"h_type\030\004 \002(\005\"\201\001\n\026ModifyGroupInfoRequest\022" +
"\020\n\010group_id\030\001 \002(\t\022\014\n\004type\030\002 \002(\005\022\r\n\005value" +
"\030\003 \002(\t\022\017\n\007to_line\030\004 \003(\005\022\'\n\016notify_conten" +
"t\030\005 \001(\0132\017.MessageContent\"\203\001\n\026SetGroupMan",
"agerRequest\022\020\n\010group_id\030\001 \002(\t\022\014\n\004type\030\002 " +
"\002(\005\022\017\n\007user_id\030\003 \003(\t\022\017\n\007to_line\030\004 \003(\005\022\'\n" +
"\016notify_content\030\005 \001(\0132\017.MessageContent\"(" +
"\n\tInfoEntry\022\014\n\004type\030\001 \002(\005\022\r\n\005value\030\002 \002(\t" +
"\"0\n\023ModifyMyInfoRequest\022\031\n\005entry\030\001 \003(\0132\n" +
".InfoEntry\";\n\rNotifyMessage\022\014\n\004type\030\001 \002(" +
"\005\022\014\n\004head\030\002 \002(\003\022\016\n\006target\030\003 \001(\t\"=\n\022PullM" +
"essageRequest\022\n\n\002id\030\001 \002(\003\022\014\n\004type\030\002 \002(\005\022" +
"\r\n\005delay\030\003 \001(\003\"M\n\021PullMessageResult\022\031\n\007m" +
"essage\030\001 \003(\0132\010.Message\022\017\n\007current\030\002 \002(\003\022",
"\014\n\004head\030\003 \002(\003\"/\n\023PullGroupInfoResult\022\030\n\004" +
"info\030\001 \003(\0132\n.GroupInfo\"6\n\026PullGroupMembe" +
"rRequest\022\016\n\006target\030\001 \002(\t\022\014\n\004head\030\002 \002(\003\"5" +
"\n\025PullGroupMemberResult\022\034\n\006member\030\001 \003(\0132" +
"\014.GroupMember\"-\n\013UserRequest\022\013\n\003uid\030\001 \002(" +
"\t\022\021\n\tupdate_dt\030\002 \001(\003\"0\n\017PullUserRequest\022" +
"\035\n\007request\030\001 \003(\0132\014.UserRequest\"/\n\nUserRe" +
"sult\022\023\n\004user\030\001 \002(\0132\005.User\022\014\n\004code\030\002 \002(\005\"" +
"-\n\016PullUserResult\022\033\n\006result\030\001 \003(\0132\013.User" +
"Result\"^\n\020QuitGroupRequest\022\020\n\010group_id\030\001",
" \002(\t\022\017\n\007to_line\030\002 \003(\005\022\'\n\016notify_content\030" +
"\003 \001(\0132\017.MessageContent\"~\n\030RemoveGroupMem" +
"berRequest\022\020\n\010group_id\030\001 \002(\t\022\026\n\016removed_" +
"member\030\002 \003(\t\022\017\n\007to_line\030\003 \003(\005\022\'\n\016notify_" +
"content\030\004 \001(\0132\017.MessageContent\"u\n\024Transf" +
"erGroupRequest\022\020\n\010group_id\030\001 \002(\t\022\021\n\tnew_" +
"owner\030\002 \002(\t\022\017\n\007to_line\030\003 \003(\005\022\'\n\016notify_c" +
"ontent\030\004 \001(\0132\017.MessageContent\"s\n\026ModifyG" +
"roupMemberAlias\022\020\n\010group_id\030\001 \002(\t\022\r\n\005ali" +
"as\030\002 \002(\t\022\017\n\007to_line\030\003 \003(\005\022\'\n\016notify_cont",
"ent\030\004 \001(\0132\017.MessageContent\"P\n\020UserSettin" +
"gEntry\022\r\n\005scope\030\001 \002(\005\022\013\n\003key\030\002 \002(\t\022\r\n\005va" +
"lue\030\003 \002(\t\022\021\n\tupdate_dt\030\004 \002(\003\"A\n\024ModifyUs" +
"erSettingReq\022\r\n\005scope\030\001 \002(\005\022\013\n\003key\030\002 \002(\t" +
"\022\r\n\005value\030\003 \002(\t\"\032\n\007Version\022\017\n\007version\030\001 " +
"\002(\003\"8\n\024GetUserSettingResult\022 \n\005entry\030\001 \003" +
"(\0132\021.UserSettingEntry\"W\n\006Friend\022\013\n\003uid\030\001" +
" \002(\t\022\r\n\005state\030\002 \002(\005\022\021\n\tupdate_dt\030\003 \002(\003\022\r" +
"\n\005alias\030\004 \001(\t\022\017\n\007blacked\030\005 \001(\005\"*\n\020GetFri" +
"endsResult\022\026\n\005entry\030\001 \003(\0132\007.Friend\"7\n\026Ge",
"tFriendRequestResult\022\035\n\005entry\030\001 \003(\0132\016.Fr" +
"iendRequest\"\243\001\n\021ConnectAckPayload\022\020\n\010msg" +
"_head\030\001 \001(\003\022\023\n\013friend_head\030\002 \001(\003\022\026\n\016frie" +
"nd_rq_head\030\003 \001(\003\022\024\n\014setting_head\030\004 \001(\003\022\021" +
"\n\tnode_addr\030\005 \001(\t\022\021\n\tnode_port\030\006 \001(\005\022\023\n\013" +
"server_time\030\007 \001(\003\"P\n\rIMHttpWrapper\022\r\n\005to" +
"ken\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\021SearchUserRequest" +
"\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\026GetChatroomInfoRequest\022\023\n\013ch" +
"atroom_id\030\001 \002(\t\022\021\n\tupdate_dt\030\002 \001(\003\"\227\001\n\014C" +
"hatroomInfo\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\034GetChatr" +
"oomMemberInfoRequest\022\023\n\013chatroom_id\030\001 \002(" +
"\t\022\021\n\tmax_count\030\002 \001(\005\";\n\022ChatroomMemberIn" +
"fo\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\023NotifyRecal",
"lMessage\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\006stat" +
"us\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\013d" +
"evice_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\rRouteResponse\022" +
"\014\n\004host\030\001 \002(\t\022\021\n\tlong_port\030\002 \002(\005\022\022\n\nshor" +
"t_port\030\003 \002(\005\"G\n\017GetTokenRequest\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\"\\\n\022LoadRemoteMessages\022#\n\014conversat" +
"ion\030\001 \002(\0132\r.Conversation\022\022\n\nbefore_uid\030\002" +
" \002(\003\022\r\n\005count\030\003 \002(\005\"a\n\020MultiCastMessage\022" +
"\021\n\tfrom_user\030\001 \002(\t\022 \n\007content\030\002 \002(\0132\017.Me" +
"ssageContent\022\n\n\002to\030\003 \003(\t\022\014\n\004line\030\004 \002(\005B#" +
"\n\025cn.wildfirechat.protoB\nWFCMessage"
};
com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
@@ -60612,7 +60693,7 @@ public final class WFCMessage {
internal_static_User_fieldAccessorTable = new
com.google.protobuf.GeneratedMessage.FieldAccessorTable(
internal_static_User_descriptor,
new java.lang.String[] { "Uid", "Name", "DisplayName", "Portrait", "Mobile", "Email", "Address", "Company", "Extra", "UpdateDt", "Gender", "Social", "Type", });
new java.lang.String[] { "Uid", "Name", "DisplayName", "Portrait", "Mobile", "Email", "Address", "Company", "Extra", "UpdateDt", "Gender", "Social", "Type", "Deleted", });
internal_static_Robot_descriptor =
getDescriptor().getMessageTypes().get(26);
internal_static_Robot_fieldAccessorTable = new
+1 -1
View File
@@ -6,7 +6,7 @@
<!--<relativePath>../pom.xml</relativePath>-->
<artifactId>wildfirechat-parent</artifactId>
<groupId>cn.wildfirechat</groupId>
<version>0.33</version>
<version>0.37</version>
</parent>
<artifactId>distribution</artifactId>
@@ -49,6 +49,27 @@ message.roaming 0
##是否开启拉取远程历史消息
message.remote_history_message 0
##服务器为每个用户缓存的消息数量。这个值改得太大,拉取消息时间变长,另外会占用大量内存。
message.max_queue 1024
##是否禁止陌生人聊天
message.disable_stranger_chat false
##黑名单处理策略,0 发送失败,返回被拉黑的错误码;1 发送成功但消息被服务器直接丢弃;
message.blacklist.strategy 0
##好友请求重复发送的间隔,单位是毫秒,默认是7天,0为不限制
friend.repeat_request_duration 604800000
##好友请求被拒绝后再次发送的间隔,单位是毫秒,默认是30天,0为不限制
friend.reject_request_duration 2592000000
## 聊天室观众空闲退出时间,单位为毫秒,默认为15分钟,0为永远不退出
chatroom.participant_idle_time 900000
## 用户向聊天室发送消息,自动加入聊天室
chatroom.rejoin_when_active true
#*********************************************************************
# hazelcase configuration
#*********************************************************************
@@ -107,6 +128,14 @@ push.android.server.address http://localhost:8085/android/push
##苹果推送服务器地址
push.ios.server.address http://localhost:8085/ios/push
#*********************************************************************
# User online status event callback
#*********************************************************************
##用户在线状态事件回调地址
#user.online_status_callback http://localhost:8888/user/online_event
#*********************************************************************
# MongoDB configuration
#*********************************************************************
+1 -1
View File
@@ -12,7 +12,7 @@
<artifactId>wildfirechat-parent</artifactId>
<packaging>pom</packaging>
<version>0.33</version>
<version>0.37</version>
<name>Wildfire Chat</name>
<description>Wildfire Chat Server</description>
<inceptionYear>2019</inceptionYear>
+1 -1
View File
@@ -5,7 +5,7 @@
<parent>
<artifactId>wildfirechat-parent</artifactId>
<groupId>cn.wildfirechat</groupId>
<version>0.33</version>
<version>0.37</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -0,0 +1,70 @@
package cn.wildfirechat.sdk;
import cn.wildfirechat.common.APIPath;
import cn.wildfirechat.pojos.*;
import cn.wildfirechat.proto.ProtoConstants;
import cn.wildfirechat.sdk.model.IMResult;
import cn.wildfirechat.sdk.utilities.AdminHttpUtils;
import cn.wildfirechat.sdk.utilities.ChannelHttpUtils;
import cn.wildfirechat.sdk.utilities.RobotHttpUtils;
import java.util.List;
//仅专业版支持,社区版不支持
public class ChannelServiceApi {
private ChannelHttpUtils httpUtils;
public ChannelServiceApi(String imurl, String channelId, String secret) {
httpUtils = new ChannelHttpUtils(imurl, channelId, secret);
}
public IMResult<InputOutputUserInfo> getUserInfo(String userId) throws Exception {
String path = APIPath.Channel_User_Info;
InputGetUserInfo getUserInfo = new InputGetUserInfo(userId, null, null);
return httpUtils.httpJsonPost(path, getUserInfo, InputOutputUserInfo.class);
}
public IMResult<Void> modifyChannelInfo(/*ProtoConstants.ModifyChannelInfoType*/int type, String value) throws Exception {
String path = APIPath.Channel_Update_Profile;
InputModifyChannelInfo modifyChannelInfo = new InputModifyChannelInfo();
modifyChannelInfo.setType(type);
modifyChannelInfo.setValue(value);
return httpUtils.httpJsonPost(path, modifyChannelInfo, Void.class);
}
public IMResult<OutputGetChannelInfo> getChannelInfo() throws Exception {
String path = APIPath.Channel_Get_Profile;
return httpUtils.httpJsonPost(path, null, OutputGetChannelInfo.class);
}
public IMResult<SendMessageResult> sendMessage(int line, List<String> targets, MessagePayload payload) throws Exception {
String path = APIPath.Channel_Message_Send;
SendChannelMessageData messageData = new SendChannelMessageData();
messageData.setLine(0);
messageData.setTargets(targets);
messageData.setPayload(payload);
return httpUtils.httpJsonPost(path, messageData, SendMessageResult.class);
}
public IMResult<Void> subscribe(String target) throws Exception {
String path = APIPath.Channel_Subscribe;
InputChannelSubscribe input = new InputChannelSubscribe();
input.setTarget(target);
input.setSubscribe(1);
return httpUtils.httpJsonPost(path, input, Void.class);
}
public IMResult<Void> unsubscribe(String target) throws Exception {
String path = APIPath.Channel_Subscribe;
InputChannelSubscribe input = new InputChannelSubscribe();
input.setTarget(target);
input.setSubscribe(0);
return httpUtils.httpJsonPost(path, input, Void.class);
}
public IMResult<OutputStringList> getSubscriberList() throws Exception {
String path = APIPath.Channel_Subscriber_List;
return httpUtils.httpJsonPost(path, null, OutputStringList.class);
}
}
@@ -12,8 +12,4 @@ public class ChatConfig {
public static void initRobot(String url, String robotId, String secret) {
RobotHttpUtils.init(url, robotId, secret);
}
public static void initChannel(String url, String channelId, String secret) {
ChannelHttpUtils.init(url, channelId, secret);
}
}
@@ -6,21 +6,37 @@ import cn.wildfirechat.sdk.model.IMResult;
import cn.wildfirechat.sdk.utilities.AdminHttpUtils;
public class FriendAdmin {
public static IMResult<Void> updateFriendStatus(String userId, String targetId, int status) throws Exception {
public static IMResult<Void> updateFriendStatus(String operator, String targetId, int status) throws Exception {
String path = APIPath.Friend_Update_Status;
InputFriendRequest input = new InputFriendRequest();
input.setUserId(userId);
input.setUserId(operator);
input.setFriendUid(targetId);
input.setStatus(status);
return AdminHttpUtils.httpJsonPost(path, input, Void.class);
}
public static IMResult<Void> getFriendStatusList(String userId, int status) throws Exception {
public static IMResult<OutputStringList> getFriendStatusList(String operator, int status) throws Exception {
String path = APIPath.Friend_Get_List;
InputGetFriendList input = new InputGetFriendList();
input.setUserId(userId);
input.setUserId(operator);
input.setStatus(status);
return AdminHttpUtils.httpJsonPost(path, input, OutputStringList.class);
}
public static IMResult<Void> updateFriendAlias(String operator, String targetId, String alias) throws Exception {
String path = APIPath.Friend_Set_Alias;
InputUpdateAlias input = new InputUpdateAlias();
input.setOperator(operator);
input.setTargetId(targetId);
input.setAlias(alias);
return AdminHttpUtils.httpJsonPost(path, input, Void.class);
}
public static IMResult<OutputGetAlias> getFriendAlias(String operator, String targetId) throws Exception {
String path = APIPath.Friend_Get_Alias;
InputGetAlias input = new InputGetAlias();
input.setOperator(operator);
input.setTargetId(targetId);
return AdminHttpUtils.httpJsonPost(path, input, OutputGetAlias.class);
}
}
@@ -113,4 +113,22 @@ public class GroupAdmin {
return AdminHttpUtils.httpJsonPost(path, kickoffGroupMember, Void.class);
}
public static IMResult<Void> quitGroup(String operator, String groupId, List<Integer> to_lines, MessagePayload notify_message) throws Exception {
String path = APIPath.Group_Member_Quit;
InputQuitGroup quitGroup = new InputQuitGroup();
quitGroup.setGroup_id(groupId);
quitGroup.setOperator(operator);
quitGroup.setTo_lines(to_lines);
quitGroup.setNotify_message(notify_message);
return AdminHttpUtils.httpJsonPost(path, quitGroup, Void.class);
}
public static IMResult<OutputGroupIds> getUserGroups(String user) throws Exception {
String path = APIPath.Get_User_Groups;
InputUserId inputUserId = new InputUserId();
inputUserId.setUserId(user);
return AdminHttpUtils.httpJsonPost(path, inputUserId, OutputGroupIds.class);
}
}
+262 -3
View File
@@ -10,12 +10,19 @@ import cn.wildfirechat.sdk.utilities.RobotHttpUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import static cn.wildfirechat.proto.ProtoConstants.SystemSettingType.Group_Max_Member_Count;
public class Main {
public static void main(String[] args) throws Exception {
testAdmin();
testRobot();
// testChannel();
}
static void testAdmin() throws Exception {
//初始化服务API
AdminHttpUtils.init("http://localhost:18080", "123456");
@@ -40,6 +47,7 @@ public class Main {
createRobot.setUserId("robot1");
createRobot.setName("robot1");
createRobot.setDisplayName("机器人");
createRobot.setOwner("userId1");
createRobot.setSecret("123456");
createRobot.setCallback("http://127.0.0.1:8883/robot/recvmsg");
IMResult<OutputCreateRobot> resultCreateRobot = UserAdmin.createRobot(createRobot);
@@ -285,6 +293,27 @@ public class Main {
}
voidIMResult = GroupAdmin.quitGroup("user4", groupInfo.getTarget_id(), null, null);
if (voidIMResult != null && voidIMResult.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS) {
System.out.println("quit group success");
} else {
System.out.println("quit group failure");
System.exit(-1);
}
IMResult<OutputGroupIds> groupIdsIMResult = GroupAdmin.getUserGroups("user1");
if (groupIdsIMResult != null && groupIdsIMResult.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS) {
if (groupIdsIMResult.getResult().getGroupIds().contains(groupInfo.getTarget_id())) {
System.out.println("get user groups success");
} else {
System.out.println("get user groups failure");
System.exit(-1);
}
} else {
System.out.println("get user groups failure");
System.exit(-1);
}
//***********************************************
//**** 消息相关功能
@@ -330,7 +359,7 @@ public class Main {
System.out.println("multi message failure");
System.exit(-1);
}
IMResult<SystemSettingPojo> resultGetSystemSetting = GeneralAdmin.getSystemSetting(Group_Max_Member_Count);
if (resultGetSystemSetting != null && resultGetSystemSetting.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS) {
System.out.println("success");
@@ -357,6 +386,7 @@ public class Main {
InputCreateChannel inputCreateChannel = new InputCreateChannel();
inputCreateChannel.setName("MyChannel");
inputCreateChannel.setOwner("user1");
IMResult<OutputCreateChannel> resultCreateChannel = GeneralAdmin.createChannel(inputCreateChannel);
if (resultCreateChannel != null && resultCreateChannel.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS) {
System.out.println("success");
@@ -365,15 +395,92 @@ public class Main {
System.exit(-1);
}
//***********************************************
//**** 好友相关功能
//***********************************************
//先创建2个用户
userInfo = new InputOutputUserInfo();
userInfo.setUserId("ff1");
userInfo.setName("ff1");
userInfo.setMobile("13800000000");
userInfo.setDisplayName("ff1");
resultCreateUser = UserAdmin.createUser(userInfo);
if (resultCreateUser != null && resultCreateUser.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS) {
System.out.println("Create user " + resultCreateUser.getResult().getName() + " success");
} else {
System.out.println("Create user failure");
System.exit(-1);
}
userInfo = new InputOutputUserInfo();
userInfo.setUserId("ff2");
userInfo.setName("ff2");
userInfo.setMobile("13800000001");
userInfo.setDisplayName("ff2");
resultCreateUser = UserAdmin.createUser(userInfo);
if (resultCreateUser != null && resultCreateUser.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS) {
System.out.println("Create user " + resultCreateUser.getResult().getName() + " success");
} else {
System.out.println("Create user failure");
System.exit(-1);
}
IMResult<Void> updateFriendStatusResult = FriendAdmin.updateFriendStatus("ff1", "ff2", 1);
if (updateFriendStatusResult != null && updateFriendStatusResult.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS) {
System.out.println("update friend status success");
} else {
System.out.println("update friend status failure");
System.exit(-1);
}
IMResult<OutputStringList> resultGetFriendList = FriendAdmin.getFriendStatusList("ff1", 1);
if (resultGetFriendList != null && resultGetFriendList.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS && resultGetFriendList.getResult().getList().contains("ff2")) {
System.out.println("get friend status success");
} else {
System.out.println("get friend status failure");
System.exit(-1);
}
String alias = "hello" + System.currentTimeMillis();
IMResult<Void> updateFriendAlias = FriendAdmin.updateFriendAlias("ff1", "ff2", alias);
if (updateFriendAlias != null && updateFriendAlias.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS) {
System.out.println("update friend status success");
} else {
System.out.println("update friend status failure");
System.exit(-1);
}
IMResult<OutputGetAlias> getFriendAlias = FriendAdmin.getFriendAlias("ff1", "ff2");
if (getFriendAlias != null && getFriendAlias.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS && getFriendAlias.getResult().getAlias().equals(alias)) {
System.out.println("update friend status success");
} else {
System.out.println("update friend status failure");
System.exit(-1);
}
voidIMResult = UserAdmin.destroyUser("user11");
if (voidIMResult != null && voidIMResult.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS) {
System.out.println("destroy user success");
} else {
System.out.println("destroy user failure");
System.exit(-1);
}
}
static void testRobot() throws Exception {
//初始化机器人API
RobotHttpUtils.init("http://localhost", "robot1", "123456");
//***********************************************
//**** 机器人API
//***********************************************
conversation = new Conversation();
Conversation conversation = new Conversation();
conversation.setTarget("user2");
conversation.setType(ProtoConstants.ConversationType.ConversationType_Private);
payload = new MessagePayload();
MessagePayload payload = new MessagePayload();
payload.setType(1);
payload.setSearchableContent("hello world");
@@ -393,4 +500,156 @@ public class Main {
System.exit(-1);
}
}
//***测试频道API功能,仅专业版支持***
static void testChannel() throws Exception {
//初始化服务API
AdminHttpUtils.init("http://localhost:18080", "123456");
//先创建3个用户
InputOutputUserInfo userInfo = new InputOutputUserInfo();
userInfo.setUserId("userId1");
userInfo.setName("user1");
userInfo.setMobile("13900000000");
userInfo.setDisplayName("user 1");
IMResult<OutputCreateUser> resultCreateUser = UserAdmin.createUser(userInfo);
if (resultCreateUser != null && resultCreateUser.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS) {
System.out.println("Create user " + resultCreateUser.getResult().getName() + " success");
} else {
System.out.println("Create user failure");
System.exit(-1);
}
userInfo = new InputOutputUserInfo();
userInfo.setUserId("userId2");
userInfo.setName("user2");
userInfo.setMobile("13900000002");
userInfo.setDisplayName("user 2");
resultCreateUser = UserAdmin.createUser(userInfo);
if (resultCreateUser != null && resultCreateUser.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS) {
System.out.println("Create user " + resultCreateUser.getResult().getName() + " success");
} else {
System.out.println("Create user failure");
System.exit(-1);
}
userInfo = new InputOutputUserInfo();
userInfo.setUserId("userId3");
userInfo.setName("user3");
userInfo.setMobile("13900000003");
userInfo.setDisplayName("user 3");
resultCreateUser = UserAdmin.createUser(userInfo);
if (resultCreateUser != null && resultCreateUser.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS) {
System.out.println("Create user " + resultCreateUser.getResult().getName() + " success");
} else {
System.out.println("Create user failure");
System.exit(-1);
}
//1. 先使用admin api创建频道
InputCreateChannel inputCreateChannel = new InputCreateChannel();
inputCreateChannel.setName("testChannel");
inputCreateChannel.setOwner("userId1");
IMResult<OutputCreateChannel> resultCreateChannel = GeneralAdmin.createChannel(inputCreateChannel);
if (resultCreateChannel != null && resultCreateChannel.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS) {
System.out.println("create channel success");
} else {
System.out.println("create channel failure");
System.exit(-1);
}
//2. 初始化api
ChannelServiceApi channelServiceApi = new ChannelServiceApi("http://localhost", resultCreateChannel.getResult().getTargetId(), resultCreateChannel.getResult().getSecret());
//3. 测试channel api功能
IMResult<Void> resultVoid = channelServiceApi.subscribe("userId2");
if (resultVoid != null && resultVoid.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS) {
System.out.println("subscribe success");
} else {
System.out.println("subscribe failure");
System.exit(-1);
}
resultVoid = channelServiceApi.subscribe("userId3");
if (resultVoid != null && resultVoid.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS) {
System.out.println("subscribe done");
} else {
System.out.println("subscribe failure");
System.exit(-1);
}
IMResult<OutputStringList> resultStringList = channelServiceApi.getSubscriberList();
if (resultStringList != null && resultStringList.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS && resultStringList.getResult().getList().contains("userId2") && resultStringList.getResult().getList().contains("userId3")) {
System.out.println("get subscriber done");
} else {
System.out.println("get subscriber failure");
System.exit(-1);
}
resultVoid = channelServiceApi.unsubscribe("userId2");
if (resultVoid != null && resultVoid.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS) {
System.out.println("unsubscriber done");
} else {
System.out.println("unsubscriber failure");
System.exit(-1);
}
resultStringList = channelServiceApi.getSubscriberList();
if (resultStringList != null && resultStringList.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS && resultStringList.getResult().getList().contains("userId3") && !resultStringList.getResult().getList().contains("userId2")) {
System.out.println("get subscriber done");
} else {
System.out.println("get subscriber failure");
System.exit(-1);
}
IMResult<InputOutputUserInfo> resultGetUserInfo1 = channelServiceApi.getUserInfo("userId3");
if (resultGetUserInfo1 != null && resultGetUserInfo1.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS) {
System.out.println("get user info success");
} else {
System.out.println("get user info failure");
System.exit(-1);
}
MessagePayload payload = new MessagePayload();
payload.setType(1);
payload.setSearchableContent("hello world");
IMResult<SendMessageResult> resultSendMessage = channelServiceApi.sendMessage(0, null,payload);
if (resultSendMessage != null && resultSendMessage.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS) {
System.out.println("send message to all the subscriber success");
} else {
System.out.println("send message to all the subscriber failure");
System.exit(-1);
}
payload.setSearchableContent("hello to user2");
resultSendMessage = channelServiceApi.sendMessage(0, Arrays.asList("userId2"),payload);
if (resultSendMessage != null && resultSendMessage.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS) {
System.out.println("send message to user2 success");
} else {
System.out.println("send message to user2 failure");
System.exit(-1);
}
IMResult<Void> voidIMResult = channelServiceApi.modifyChannelInfo(ProtoConstants.ModifyChannelInfoType.Modify_Channel_Desc, "this is a test channel, update at:" + new Date().toString());
if (voidIMResult != null && voidIMResult.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS) {
System.out.println("modify channel profile success");
} else {
System.out.println("modify channel profile failure");
System.exit(-1);
}
IMResult<OutputGetChannelInfo> outputGetChannelInfoIMResult = channelServiceApi.getChannelInfo();
if (outputGetChannelInfoIMResult != null && outputGetChannelInfoIMResult.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS) {
System.out.println("destroy user success");
} else {
System.out.println("destroy user failure");
System.exit(-1);
}
}
}
@@ -58,6 +58,13 @@ public class UserAdmin {
return AdminHttpUtils.httpJsonPost(path, null, OutputUserBlockStatusList.class);
}
public static IMResult<Void> destroyUser(String userId) throws Exception {
String path = APIPath.Destroy_User;
InputDestroyUser inputDestroyUser = new InputDestroyUser();
inputDestroyUser.setUserId(userId);
return AdminHttpUtils.httpJsonPost(path, inputDestroyUser, Void.class);
}
//not implement
// public static IMResult<OutputUserBlockStatusList> getUserOnlineStatus(String userId) throws Exception {
// String path = APIPath.User_Get_Online_Status;
@@ -67,31 +67,33 @@ public class AdminHttpUtils {
HttpResponse response = httpClient.execute(post);
int statusCode = response.getStatusLine().getStatusCode();
if(statusCode != HttpStatus.SC_OK){
LOG.info("Request error: "+statusCode);
throw new Exception("Http request error with code:" + statusCode);
}else{
BufferedReader in = new BufferedReader(new InputStreamReader(response.getEntity()
.getContent(),"utf-8"));
StringBuffer sb = new StringBuffer();
String content = null;
if (response.getEntity().getContentLength() > 0) {
BufferedReader in = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "utf-8"));
StringBuilder sb = new StringBuilder();
String line;
String NL = System.getProperty("line.separator");
while ((line = in.readLine()) != null) {
sb.append(line + NL);
sb.append(line).append(NL);
}
in.close();
String content = sb.toString();
content = sb.toString();
LOG.info("http request response content: {}", content);
}
if(statusCode != HttpStatus.SC_OK){
LOG.info("Request error: " + statusCode + " error msg:" + content);
throw new Exception("Http request error with code:" + statusCode);
} else {
return fromJsonObject(content, clazz);
}
} catch (Exception e) {
e.printStackTrace();
throw e;
}finally{
if(post != null){
} finally {
if(post != null) {
post.releaseConnection();
}
}
@@ -22,23 +22,23 @@ import java.nio.charset.Charset;
public class ChannelHttpUtils {
private static final Logger LOG = LoggerFactory.getLogger(ChannelHttpUtils.class);
private static String url;
private static String channelId;
private static String channelSecret;
private String imurl;
private String channelId;
private String channelSecret;
public static void init(String url, String channelId, String secret) {
ChannelHttpUtils.url = url;
ChannelHttpUtils.channelId = channelId;
ChannelHttpUtils.channelSecret = secret;
public ChannelHttpUtils(String imurl, String channelId, String secret) {
this.imurl = imurl;
this.channelId = channelId;
this.channelSecret = secret;
}
public static <T> IMResult<T> httpJsonPost(String path, Object object, Class<T> clazz) throws Exception{
if (isNullOrEmpty(url) || isNullOrEmpty(path)) {
public <T> IMResult<T> httpJsonPost(String path, Object object, Class<T> clazz) throws Exception{
if (isNullOrEmpty(imurl) || isNullOrEmpty(path)) {
LOG.error("Not init IM SDK correctly. Do you forget init it?");
throw new Exception("SDK url or secret lack!");
}
String url = ChannelHttpUtils.url + path;
String url = imurl + path;
HttpPost post = null;
try {
HttpClient httpClient = HttpClientBuilder.create().build();
@@ -54,9 +54,11 @@ public class ChannelHttpUtils {
post.setHeader("Connection", "Keep-Alive");
post.setHeader("nonce", nonce + "");
post.setHeader("timestamp", "" + timestamp);
post.setHeader("cid", channelId);
post.setHeader("sign", sign);
String jsonStr = null;
String jsonStr = "";
if (object != null) {
jsonStr = new Gson().toJson(object);
}