Compare commits

...
60 Commits
Author SHA1 Message Date
heavyrian2012 0a7b8f9587 version and release note 2023-06-20 17:59:11 +08:00
heavyrian2012 c8ff39c2ab 添加获取所有用户的Server API 2023-06-20 15:14:57 +08:00
heavyrian2012 252204a760 添加好友时,只检查对方的黑名单状态 2023-05-27 10:15:07 +08:00
heavyrian2012 26fbde676e stop脚本等待时间延长到30秒 2023-05-17 17:58:03 +08:00
heavyrian2012 81585ec146 docker file 为启动脚本添加执行属性 2023-05-17 17:57:47 +08:00
heavyrian2012 4ad0437730 更新版本号和release note 2023-05-10 20:19:45 +08:00
heavyrian2012 6245fe37fc 添加配置,请求机器人好友时,是否自动接受 2023-05-04 21:39:45 +08:00
heavyrian2012 ca50872913 server api添加获取单个群成员信息的接口 2023-05-04 19:00:08 +08:00
heavyrian2012 3c11c368a3 update readme 2023-04-28 11:32:47 +08:00
heavyrian2012 145709fd76 支持AES256配置 2023-04-24 11:51:13 +08:00
heavyrian2012 758c5de2c7 解决pc多端登录互踢时pc在线状态没有更新的问题 2023-04-24 11:26:55 +08:00
heavyrian2012 c159ff90e3 去掉windows脚本中的中文,解决windows平台下启动失败的问题 2023-04-19 09:28:30 +08:00
heavyrian2012 083b07fdba 修改版本号和release note 2023-04-13 09:36:49 +08:00
heavyrian2012 c6a8462ece 修改启动注释 2023-04-13 09:30:42 +08:00
heavyrian2012 afee0466e7 用户状态和频道订阅状态修改改成同步模式,防止高并发时出现问题 2023-04-13 09:18:43 +08:00
heavyrian2012 62b36cd2b4 超级群组协议 2023-04-13 09:04:55 +08:00
heavyrian2012 99c5210935 同步专业版IM服务超级群组的数据库和SDK 2023-04-13 08:50:07 +08:00
heavyrian2012 75cb7f8b98 修正当server api设置好友关系时,回调状态错误问题 #604 2023-04-07 22:25:01 +08:00
heavyrian2012 c89259e892 修改群昵称时检查是否在群中 2023-04-04 13:57:22 +08:00
heavyrian2012 d40835aa18 解决grouptype为0时被删除用户还能修改群名称的问题 2023-04-03 16:54:36 +08:00
heavyrian2012 b93c76c6c7 优化群组撤回逻辑。 2023-04-03 13:33:07 +08:00
heavyrian2012 c29370ac61 添加撤回消息回调 2023-03-24 15:55:11 +08:00
heavyrian2012 68abeed907 添加一些异常数据的处理 2023-03-20 13:49:29 +08:00
imndx 11b7851b9f 启动脚本里面,打印 JAVA 版本信息 2023-03-20 12:25:07 +08:00
heavyrian2012 329791e70e 解决用户被block后,session失效问题 2023-03-14 14:54:22 +08:00
heavyrian2012 b7b262be00 服务检查时间是否一致 2023-03-12 18:55:14 +08:00
heavyrian2012 6a806aa10b fix build error 2023-03-10 11:02:52 +08:00
heavyrian2012 6542b8ba55 version and release note 2023-03-10 10:55:32 +08:00
heavyrian2012 c3bc62f1e1 单聊会话发送定向消息时,分发目标需要包括自己。 2023-03-10 10:48:39 +08:00
heavyrian2012 8b649200d2 添加检查会议是否存在的接口 2023-03-06 15:17:46 +08:00
heavyrian2012 5f95b18e77 release note 2023-03-06 12:25:11 +08:00
imndx 4d45aedc73 禁止客户端群操作flag 解析错误 2023-03-06 11:41:23 +08:00
heavyrian2012 a038bedb12 version and release note 2023-03-06 10:54:26 +08:00
heavyrian2012 43892dbe41 解决关闭roaming,且message.compensate_time_limit配置为-1时,首次消息无法同步的问题 2023-03-02 08:52:43 +08:00
heavyrian2012 ad33abc424 用户消息表中的target优化 2023-02-28 21:01:20 +08:00
heavyrian2012 290a3cea0e 支持单聊会话的定向消息 2023-02-28 20:45:41 +08:00
imndx ca3bbb6435 添加日志 2023-02-23 10:41:11 +08:00
heavyrian2012 704e6e0ec2 搜索用户时,过滤掉被删除的用户 2023-02-20 19:30:08 +08:00
heavyrian2012 23871487e4 当用户获取群组信息时,如果不在群中返回-1,如果已经离开群了返回离开时间的负数 2023-02-20 19:27:30 +08:00
heavyrian2012 6e1ba9440e 更新版本号和release note 2023-02-15 15:25:33 +08:00
heavyrian2012 c284272b06 文件存储路径中加上分钟和秒 2023-02-15 15:20:57 +08:00
heavyrian2012 6746a54659 优化内置存储功能 2023-02-14 21:35:58 +08:00
heavyrian2012 93be667e17 日志文件精确到分钟,避免出现问题时被复写 2023-02-14 08:45:34 +08:00
heavyrian2012 f11da6225d 添加修改频道菜单接口 2023-02-12 11:06:35 +08:00
heavyrian2012 e28a4c6cbf server api发送消息检查对象是否存在 2023-02-11 13:51:05 +08:00
heavyrian2012 fa8a2bef32 channel api添加检查是否是订阅者的接口 2023-02-08 11:13:32 +08:00
heavyrian2012 1c9d238734 update readme 2023-01-19 16:14:17 +08:00
heavyrian2012 2f7f4e6456 update readme 2023-01-10 11:57:35 +08:00
heavyrian2012 6e83ec85c7 server sdk http request add log 2023-01-04 09:20:12 +08:00
heavyrian2012 cc561b846e 更新版本号和release note 2022-12-28 08:49:40 +08:00
heavyrian2012 4628b3b0b6 sdk add conference rtp forward api 2022-12-22 11:53:38 +08:00
heavyrian2012 9c69fbc7d4 sdk add conference rtp forward api 2022-12-13 17:38:21 +08:00
heavyrian2012 9047020d69 添加停止命令 2022-12-12 12:37:31 +08:00
heavyrian2012 1c18d862a1 会议离开加上原因 2022-12-07 16:25:18 +08:00
heavyrian2012 b0ddca985a route时可能不能携带正确的推送类型 2022-12-06 14:35:16 +08:00
heavyrian2012 996e06c451 添加禁止客户端群操作配置 2022-11-26 22:21:43 +08:00
imndx 612747203a 创建群组时,支持组织群 2022-11-25 10:48:29 +08:00
heavyrian2012 f7853ae299 解决短连接端口被扫描时打印出异常日志的问题 2022-11-24 19:06:27 +08:00
heavyrian2012 7443db3078 检查工具添加help命令 2022-11-22 10:12:09 +08:00
heavyrian2012 ad5f6cb228 添加注释 2022-11-21 08:34:08 +08:00
73 changed files with 4302 additions and 414 deletions
+4 -2
View File
@@ -20,7 +20,8 @@
* 结构设计合理,客户端分功能库、UI库和应用三层。应用成熟完善,开箱即用,也可把SDK嵌入其它应用。 * 结构设计合理,客户端分功能库、UI库和应用三层。应用成熟完善,开箱即用,也可把SDK嵌入其它应用。
* 拥有应用开放平台,可以开发和创建自建应用,扩展您的工作台。 * 拥有应用开放平台,可以开发和创建自建应用,扩展您的工作台。
* API丰富,方便与其它服务系统的对接。 * API丰富,方便与其它服务系统的对接。
* 拥有机器人和公众号功能。 * 拥有机器人和公众号功能,免费的频道(公众号)管理后台。
* 超级群组功能,可以支持万人大群。
* 社区版IM服务和移动端免费商用,可以免费构建出完备的移动互联网应用。 * 社区版IM服务和移动端免费商用,可以免费构建出完备的移动互联网应用。
* 收费项目非常便宜,野火独有的试用模式,可以先部署到客户环境试用6个月,试用满意后再购买,避免上当受骗。 * 收费项目非常便宜,野火独有的试用模式,可以先部署到客户环境试用6个月,试用满意后再购买,避免上当受骗。
* 技术支持专业和高效,核心研发人员及时处理issue和论坛回复。 * 技术支持专业和高效,核心研发人员及时处理issue和论坛回复。
@@ -39,6 +40,7 @@
| [open-platform](https://github.com/wildfirechat/open-platform) | [open-platform](https://gitee.com/wfchat/open-platform) | 野火开放平台服务。 | | [open-platform](https://github.com/wildfirechat/open-platform) | [open-platform](https://gitee.com/wfchat/open-platform) | 野火开放平台服务。 |
| [daily-report](https://github.com/wildfirechat/daily-report) | [daily-report](https://github.com/wildfirechat/daily-report) | 野火开放平台日报 demo服务。 | | [daily-report](https://github.com/wildfirechat/daily-report) | [daily-report](https://github.com/wildfirechat/daily-report) | 野火开放平台日报 demo服务。 |
| [channel-platform](https://github.com/wildfirechat/channel-platform) | [channel-platform](https://gitee.com/wfchat/channel-platform) | 野火频道(公众号)平台服务。 | | [channel-platform](https://github.com/wildfirechat/channel-platform) | [channel-platform](https://gitee.com/wfchat/channel-platform) | 野火频道(公众号)平台服务。 |
| [organization-platform](https://github.com/wildfirechat/organization-platform) | [organization-platform](https://gitee.com/wfchat/organization-platform) | 野火组织通讯录服务。 |
| [android-chat](https://github.com/wildfirechat/android-chat) | [android-chat](https://gitee.com/wfchat/android-chat) | 野火IM Android SDK源码和App源码。 | | [android-chat](https://github.com/wildfirechat/android-chat) | [android-chat](https://gitee.com/wfchat/android-chat) | 野火IM Android SDK源码和App源码。 |
| [ios-chat](https://github.com/wildfirechat/ios-chat) | [ios-chat](https://gitee.com/wfchat/ios-chat) | 野火IM iOS SDK源码和App源码。| | [ios-chat](https://github.com/wildfirechat/ios-chat) | [ios-chat](https://gitee.com/wfchat/ios-chat) | 野火IM iOS SDK源码和App源码。|
| [pc-chat](https://github.com/wildfirechat/vue-pc-chat) | [pc-chat](https://gitee.com/wfchat/vue-pc-chat) | 基于[Electron](https://electronjs.org/)的PC 端,支持Windows、Mac、Linux(包括国产化linux系统和CPU)。 | | [pc-chat](https://github.com/wildfirechat/vue-pc-chat) | [pc-chat](https://gitee.com/wfchat/vue-pc-chat) | 基于[Electron](https://electronjs.org/)的PC 端,支持Windows、Mac、Linux(包括国产化linux系统和CPU)。 |
@@ -46,7 +48,7 @@
| [wx-chat](https://github.com/wildfirechat/wx-chat) | [wx-chat](https://gitee.com/wfchat/wx-chat) | 小程序平台的Demo(支持微信、百度、阿里、字节、QQ 等小程序平台)。 | | [wx-chat](https://github.com/wildfirechat/wx-chat) | [wx-chat](https://gitee.com/wfchat/wx-chat) | 小程序平台的Demo(支持微信、百度、阿里、字节、QQ 等小程序平台)。 |
| [uni-chat](https://github.com/wildfirechat/uni-chat) | [uni-chat](https://gitee.com/wfchat/uni-chat) | UniApp平台移动端应用(使用原生插件)。 | | [uni-chat](https://github.com/wildfirechat/uni-chat) | [uni-chat](https://gitee.com/wfchat/uni-chat) | UniApp平台移动端应用(使用原生插件)。 |
| [uni-wfc-client](https://github.com/wildfirechat/uni-wfc-client) | [uni-wfc-client](https://gitee.com/wfchat/uni-wfc-client) | UniApp平台原生插件。已[商店](https://ext.dcloud.net.cn/plugin?id=7895)上架 | | [uni-wfc-client](https://github.com/wildfirechat/uni-wfc-client) | [uni-wfc-client](https://gitee.com/wfchat/uni-wfc-client) | UniApp平台原生插件。已[商店](https://ext.dcloud.net.cn/plugin?id=7895)上架 |
| [flutter_imclient](https://github.com/wildfirechat/flutter_imclient) | [flutter_imclient](https://gitee.com/wfchat/flutter_imclient) | Flutter平台原生插件。 | | [wfc_flutter_plugins](https://github.com/wildfirechat/wfc_flutter_plugins) | [flutter_imclient](https://gitee.com/wfchat/wfc_flutter_plugins) | Flutter平台原生插件,支持IM和音视频通话。 |
| [docs](https://github.com/wildfirechat/docs) | [docs](https://gitee.com/wfchat/docs) | 野火IM相关文档,包含设计、概念、开发、使用说明,[在线查看](https://docs.wildfirechat.cn/)。 | | [docs](https://github.com/wildfirechat/docs) | [docs](https://gitee.com/wfchat/docs) | 野火IM相关文档,包含设计、概念、开发、使用说明,[在线查看](https://docs.wildfirechat.cn/)。 |
## 野火开发文档 ## 野火开发文档
+14 -1
View File
@@ -12,7 +12,7 @@
#服务器的接入IP。给客户端提供是${server.ip}和${http_port}。 #服务器的接入IP。给客户端提供是${server.ip}和${http_port}。
#客户端会从${http_port}端口获取到长链接端口。这个地址一定要改成客户端可以访问到的IP地址 #客户端会从${http_port}端口获取到长链接端口。这个地址一定要改成客户端可以访问到的IP地址
#(如果您部署云服务器上或者具有独立公网出口的服务器上,请改为对应的公网IP;如果您部署在在内网环境下,在内网使用,这个地方改成内网地址) #(如果您部署云服务器上或者具有独立公网出口的服务器上,请改为对应的公网IP;如果您部署在在内网环境下,在内网使用,这个地方改成内网地址)
server.ip 192.168.3.124 server.ip 192.168.1.81
##原生客户端长链接端口 ##原生客户端长链接端口
port 1883 port 1883
@@ -65,6 +65,9 @@ token.key testim
##是否拒绝空签名的android客户端, 默认为true。当有旧的客户端需要兼容时改成false,当所有都是新客户端时,改成true。 ##是否拒绝空签名的android客户端, 默认为true。当有旧的客户端需要兼容时改成false,当所有都是新客户端时,改成true。
#connect.reject_empty_signature true #connect.reject_empty_signature true
##是否使用AES256加密。默认客户端和服务器都是AES128加密,如果需要开启AES256,需要客户端和IM服务同时开通。
#encrypt.use_aes256 true
##首次登录,是否接收之前的历史消息。 ##首次登录,是否接收之前的历史消息。
##0 不接收历史消息,只接收${message.compensate_time_limit}毫秒以内的消息,由于服务器没有保存已经收取记录,所以如果有超过${message.compensate_time_limit}毫秒之前未收取的消息也不会收取下拉; ##0 不接收历史消息,只接收${message.compensate_time_limit}毫秒以内的消息,由于服务器没有保存已经收取记录,所以如果有超过${message.compensate_time_limit}毫秒之前未收取的消息也不会收取下拉;
##1接收,会接收 message.max_queue 配置的条数的历史消息 ##1接收,会接收 message.max_queue 配置的条数的历史消息
@@ -151,6 +154,9 @@ friend.reject_request_duration 2592000000
##好友请求过期时间,单位是毫秒,默认是7天,0为无限长期限。 ##好友请求过期时间,单位是毫秒,默认是7天,0为无限长期限。
friend.request_expiration_duration 604800000 friend.request_expiration_duration 604800000
##请求添加机器人为好友时,机器人是否自动接受,默认为true
friend.robot_auto_accept true
## 聊天室观众空闲退出时间,单位为毫秒,默认为15分钟,0为永远不退出 ## 聊天室观众空闲退出时间,单位为毫秒,默认为15分钟,0为永远不退出
chatroom.participant_idle_time 900000 chatroom.participant_idle_time 900000
@@ -170,6 +176,10 @@ group.allow_robot_custom_operation_notification true
## 0 不发送,1 退群时发送,2 踢人时发送,3 退群和踢人时都发送。 ## 0 不发送,1 退群时发送,2 踢人时发送,3 退群和踢人时都发送。
group.visible_quit_or_kickoff_notification 0 group.visible_quit_or_kickoff_notification 0
## 禁止客户端群操作。第1位是禁止创建群组,第2位是禁止销毁群组,3位禁止加入群,4位禁止退出群,5位禁止邀请群成员,6位禁止移出群成员,7位禁止转移群,8位禁止设置群管理员,9位禁止白名单处理,10位禁止群禁言,11位禁止修改群组信息,12位禁止群成员禁言。
## Server API不受此限制。
#group.forbidden_client_operation 0xFFF
## 隐藏用户信息属性类型,2是性别,3是电话号码,4是邮箱,5是地址,6是公司信息,7是社交账号,8是Extra信息。当需要隐藏多个时以英文逗号分开; ## 隐藏用户信息属性类型,2是性别,3是电话号码,4是邮箱,5是地址,6是公司信息,7是社交账号,8是Extra信息。当需要隐藏多个时以英文逗号分开;
## 本配置是为了提高安全性,避免把对应信息同步到客户端,这样就能防止程序被破解从而拿到用户关键信息。仅对客户端有效,server api不受影响。 ## 本配置是为了提高安全性,避免把对应信息同步到客户端,这样就能防止程序被破解从而拿到用户关键信息。仅对客户端有效,server api不受影响。
## 注意,修改本配置不会对已经同步的信息产生影响。 ## 注意,修改本配置不会对已经同步的信息产生影响。
@@ -316,6 +326,9 @@ push.ios.server.address http://localhost:8085/ios/push
##注意回调是单线程回调,接收服务必须在同一内网,且异步处理快速返回,否则会有延迟问题!! ##注意回调是单线程回调,接收服务必须在同一内网,且异步处理快速返回,否则会有延迟问题!!
#message.mentionmsg.forward.url http://localhost:8888/im_event/message #message.mentionmsg.forward.url http://localhost:8888/im_event/message
##撤回消息转发地址,当用户撤回消息会回调此地址。
##注意回调是单线程回调,接收服务必须在同一内网,且异步处理快速返回,否则会有延迟问题!!
#message.recallmsg.forward.url http://localhost:8888/im_event/recall_message
##设备信息转发地址 ##设备信息转发地址
##注意回调是单线程回调,接收服务必须在同一内网,且异步处理快速返回,否则会有延迟问题!! ##注意回调是单线程回调,接收服务必须在同一内网,且异步处理快速返回,否则会有延迟问题!!
+19
View File
@@ -0,0 +1,19 @@
alter table `t_group` add column `_super_group` tinyint NOT NULL DEFAULT 0;
DROP TABLE IF EXISTS `t_group_messages`;
CREATE TABLE `t_group_messages` (
`_mid` bigint(20) NOT NULL PRIMARY KEY,
`_sender` varchar(64) NOT NULL,
`_gid` varchar(64) NOT NULL,
`_line` int(11) NOT NULL,
`_client_id` varchar(64) NULL,
`_seq` bigint(20) NOT NULL,
`_persist_flag` int(11) NOT NULL,
`_mentioned_type` int(11) NOT NULL,
`_mentioned_targets` BLOB NULL,
`_to` BLOB NULL,
`_cont_type` int(11) NOT NULL DEFAULT 0,
`_duration` int(11) NOT NULL DEFAULT 0,
`_dt` bigint(20) NOT NULL DEFAULT 0,
INDEX `group_message_seq_uid_index` (`_gid` DESC, `_line`, `_seq` DESC)
);
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -5,7 +5,7 @@
<relativePath>../</relativePath> <relativePath>../</relativePath>
<artifactId>wildfirechat-parent</artifactId> <artifactId>wildfirechat-parent</artifactId>
<groupId>cn.wildfirechat</groupId> <groupId>cn.wildfirechat</groupId>
<version>0.99</version> <version>1.1.5</version>
</parent> </parent>
<artifactId>moquette-broker</artifactId> <artifactId>moquette-broker</artifactId>
@@ -90,6 +90,8 @@ public class FileAction extends Action {
} }
response.setContent(file); response.setContent(file);
response.setHeader("Content-Disposition", "attachment; filename=\"" + file.getName() + "\"");
return true; return true;
} }
@@ -80,6 +80,11 @@ public class IMAction extends Action {
if (userId == null) { if (userId == null) {
sendResponse(response, ErrorCode.ERROR_CODE_TOKEN_ERROR, null); sendResponse(response, ErrorCode.ERROR_CODE_TOKEN_ERROR, null);
} else { } else {
if(messagesStore.getUserStatus(userId) == ProtoConstants.UserStatus.Forbidden) {
sendResponse(response, ErrorCode.ERROR_CODE_USER_BLOCKED, null);
return true;
}
ServerAPIHelper.sendRequest(userId, wrapper.getClientId(), wrapper.getRequest(), wrapper.getData().toByteArray(), new ServerAPIHelper.Callback() { ServerAPIHelper.sendRequest(userId, wrapper.getClientId(), wrapper.getRequest(), wrapper.getData().toByteArray(), new ServerAPIHelper.Callback() {
@Override @Override
public void onSuccess(byte[] result) { public void onSuccess(byte[] result) {
@@ -39,17 +39,10 @@ public class RouteAction extends Action {
@Override @Override
public boolean action(Request request, Response response) { public boolean action(Request request, Response response) {
if (request.getNettyRequest() instanceof FullHttpRequest) { if (request.getNettyRequest() instanceof FullHttpRequest) {
response.setContentType("application/octet-stream"); response.setContentType("application/octet-stream");
response.setHeader("Access-Control-Allow-Origin", "*"); response.setHeader("Access-Control-Allow-Origin", "*");
FullHttpRequest fullHttpRequest = (FullHttpRequest) request.getNettyRequest(); FullHttpRequest fullHttpRequest = (FullHttpRequest) request.getNettyRequest();
boolean b = false;
if ("web".equalsIgnoreCase(fullHttpRequest.headers().get("p"))) {
b = true;
}
final boolean base64Response = b;
byte[] bytes = Utils.readBytesAndRewind(fullHttpRequest.content()); byte[] bytes = Utils.readBytesAndRewind(fullHttpRequest.content());
@@ -57,15 +50,20 @@ public class RouteAction extends Action {
try { try {
bytes = Base64.getDecoder().decode(str); bytes = Base64.getDecoder().decode(str);
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
sendResponse(response, ErrorCode.ERROR_CODE_INVALID_DATA, null, base64Response); sendResponse(response, ErrorCode.ERROR_CODE_INVALID_DATA, null);
return true; return true;
} }
String cid = fullHttpRequest.headers().get("cid"); String cid = fullHttpRequest.headers().get("cid");
byte[] cbytes = Base64.getDecoder().decode(cid); byte[] cbytes = Base64.getDecoder().decode(cid);
cbytes = AES.AESDecrypt(cbytes, "", true); boolean[] invalidTime = new boolean[1];
cbytes = AES.AESDecrypt(cbytes, "", true, invalidTime);
if (cbytes == null) { if (cbytes == null) {
sendResponse(response, ErrorCode.ERROR_CODE_INVALID_DATA, null, base64Response); if(invalidTime[0]) {
sendResponse(response, ErrorCode.ERROR_CODE_TIME_INCONSISTENT, null);
} else {
sendResponse(response, ErrorCode.ERROR_CODE_INVALID_DATA, null);
}
return true; return true;
} }
cid = new String(cbytes); cid = new String(cbytes);
@@ -74,7 +72,7 @@ public class RouteAction extends Action {
byte[] ubytes = Base64.getDecoder().decode(uid); byte[] ubytes = Base64.getDecoder().decode(uid);
ubytes = AES.AESDecrypt(ubytes, "", true); ubytes = AES.AESDecrypt(ubytes, "", true);
if (ubytes == null) { if (ubytes == null) {
sendResponse(response, ErrorCode.ERROR_CODE_INVALID_DATA, null, base64Response); sendResponse(response, ErrorCode.ERROR_CODE_INVALID_DATA, null);
return true; return true;
} }
uid = new String(ubytes); uid = new String(ubytes);
@@ -84,7 +82,7 @@ public class RouteAction extends Action {
if (session == null) { if (session == null) {
ErrorCode errorCode = sessionsStore.loadActiveSession(uid, cid); ErrorCode errorCode = sessionsStore.loadActiveSession(uid, cid);
if (errorCode != ErrorCode.ERROR_CODE_SUCCESS) { if (errorCode != ErrorCode.ERROR_CODE_SUCCESS) {
sendResponse(response, errorCode, null, base64Response); sendResponse(response, errorCode, null);
return true; return true;
} }
session = sessionsStore.sessionForClientAndUser(uid, cid); session = sessionsStore.sessionForClientAndUser(uid, cid);
@@ -94,16 +92,20 @@ public class RouteAction extends Action {
if (session != null) { if (session != null) {
bytes = AES.AESDecrypt(bytes, session.getSecret(), true); bytes = AES.AESDecrypt(bytes, session.getSecret(), true);
} else { } else {
sendResponse(response, ErrorCode.ERROR_CODE_SECRECT_KEY_MISMATCH, null, base64Response); sendResponse(response, ErrorCode.ERROR_CODE_SECRECT_KEY_MISMATCH, null);
return true; return true;
} }
if (bytes == null) { if (bytes == null) {
sendResponse(response, ErrorCode.ERROR_CODE_SECRECT_KEY_MISMATCH, null, base64Response); sendResponse(response, ErrorCode.ERROR_CODE_SECRECT_KEY_MISMATCH, null);
return true; return true;
} }
if(messagesStore.getUserStatus(uid) == ProtoConstants.UserStatus.Forbidden) {
sendResponse(response, ErrorCode.ERROR_CODE_USER_BLOCKED, null);
return true;
}
try { try {
WFCMessage.IMHttpWrapper wrapper = WFCMessage.IMHttpWrapper.parseFrom(bytes); WFCMessage.IMHttpWrapper wrapper = WFCMessage.IMHttpWrapper.parseFrom(bytes);
@@ -111,22 +113,22 @@ public class RouteAction extends Action {
String userId = Tokenor.getUserId(token.getBytes()); String userId = Tokenor.getUserId(token.getBytes());
LOG.info("RouteAction token={}, userId={}", token, userId); LOG.info("RouteAction token={}, userId={}", token, userId);
if (userId == null) { if (userId == null) {
sendResponse(response, ErrorCode.ERROR_CODE_TOKEN_ERROR, null, base64Response); sendResponse(response, ErrorCode.ERROR_CODE_TOKEN_ERROR, null);
} else { } else {
ServerAPIHelper.sendRequest(userId, wrapper.getClientId(), wrapper.getRequest(), wrapper.getData().toByteArray(), new ServerAPIHelper.Callback() { ServerAPIHelper.sendRequest(userId, wrapper.getClientId(), wrapper.getRequest(), wrapper.getData().toByteArray(), new ServerAPIHelper.Callback() {
@Override @Override
public void onSuccess(byte[] result) { public void onSuccess(byte[] result) {
sendResponse(response, null, result, base64Response); sendResponse(response, null, result);
} }
@Override @Override
public void onError(ErrorCode errorCode) { public void onError(ErrorCode errorCode) {
sendResponse(response, errorCode, null, base64Response); sendResponse(response, errorCode, null);
} }
@Override @Override
public void onTimeout() { public void onTimeout() {
sendResponse(response, ErrorCode.ERROR_CODE_TIMEOUT, null, base64Response); sendResponse(response, ErrorCode.ERROR_CODE_TIMEOUT, null);
} }
@Override @Override
@@ -139,25 +141,21 @@ public class RouteAction extends Action {
return false; return false;
} }
} catch (InvalidProtocolBufferException e) { } catch (InvalidProtocolBufferException e) {
sendResponse(response, ErrorCode.ERROR_CODE_INVALID_DATA, null, false); sendResponse(response, ErrorCode.ERROR_CODE_INVALID_DATA, null);
} }
} }
return true; return true;
} }
private void sendResponse(Response response, ErrorCode errorCode, byte[] contents, boolean base64Response) { private void sendResponse(Response response, ErrorCode errorCode, byte[] contents) {
response.setStatus(HttpResponseStatus.OK); response.setStatus(HttpResponseStatus.OK);
if (contents == null) { if (contents == null) {
ByteBuf ackPayload = Unpooled.buffer(); ByteBuf ackPayload = Unpooled.buffer();
ackPayload.ensureWritable(1).writeByte(errorCode.getCode()); ackPayload.ensureWritable(1).writeByte(errorCode.getCode());
contents = ackPayload.array(); contents = ackPayload.array();
} }
if (base64Response) {
byte[] base64Data = Base64.getEncoder().encode(contents); response.setContent(contents);
response.setContent(base64Data);
} else {
response.setContent(contents);
}
response.send(); response.send();
} }
} }
@@ -187,6 +187,10 @@ public class UploadFileAction extends Action {
return false; return false;
} }
if(remoteFileName != null && remoteFileName.length() > 2 && remoteFileName.startsWith("'") && remoteFileName.endsWith("'")) {
remoteFileName = remoteFileName.substring(1, remoteFileName.length()-1);
}
if (StringUtil.isNullOrEmpty(remoteFileName)) { if (StringUtil.isNullOrEmpty(remoteFileName)) {
logger.warn("remoteFileName is empty!"); logger.warn("remoteFileName is empty!");
@@ -235,7 +239,7 @@ public class UploadFileAction extends Action {
int offset = 0; // 断点续传开始位置 int offset = 0; // 断点续传开始位置
Date nowTime=new Date(); Date nowTime=new Date();
SimpleDateFormat time=new SimpleDateFormat("yyyy/MM/dd/HH"); SimpleDateFormat time=new SimpleDateFormat("yyyy/MM/dd/HH/mm/ss");
String datePath = time.format(nowTime); String datePath = time.format(nowTime);
datePath = "fs/" + bucket[0] + "/" + datePath; //add bucket datePath = "fs/" + bucket[0] + "/" + datePath; //add bucket
@@ -253,6 +257,7 @@ public class UploadFileAction extends Action {
if(!bFile) { if(!bFile) {
bFile = dirFile.mkdirs(); bFile = dirFile.mkdirs();
if (!bFile) { if (!bFile) {
logger.error("create dirs error! {}", dir);
response.setStatus(HttpResponseStatus.INTERNAL_SERVER_ERROR); response.setStatus(HttpResponseStatus.INTERNAL_SERVER_ERROR);
response.setContent("服务器错误:无法创建文件"); response.setContent("服务器错误:无法创建文件");
return false; return false;
@@ -0,0 +1,59 @@
/*
* 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.InputGetUserInfo;
import cn.wildfirechat.pojos.InputGetUserList;
import cn.wildfirechat.pojos.InputOutputUserInfo;
import cn.wildfirechat.pojos.OutputGetUserList;
import cn.wildfirechat.proto.WFCMessage;
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.util.internal.StringUtil;
import java.util.ArrayList;
import java.util.List;
@Route(APIPath.User_Get_All)
@HttpMethod("POST")
public class GetAllUserAction extends AdminAction {
@Override
public boolean isTransactionAction() {
return true;
}
@Override
public boolean action(Request request, Response response) {
if (request.getNettyRequest() instanceof FullHttpRequest) {
InputGetUserList input = getRequestBody(request.getNettyRequest(), InputGetUserList.class);
if (input != null && input.count > 0 && input.offset >= 0) {
List<WFCMessage.User> users = messagesStore.getUserInfoList(input.count, input.offset);
OutputGetUserList outputGetUserList = new OutputGetUserList();
outputGetUserList.userInfoList = new ArrayList<>();
for (WFCMessage.User user : users) {
outputGetUserList.userInfoList.add(InputOutputUserInfo.fromPbUser(user));
}
RestResult result = RestResult.ok(outputGetUserList);
setResponseContent(result, response);
} else {
setResponseContent(RestResult.resultOf(ErrorCode.INVALID_PARAMETER), response);
}
}
return true;
}
}
@@ -0,0 +1,69 @@
/*
* 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.InputGetGroupMember;
import cn.wildfirechat.pojos.OutputGroupMemberList;
import cn.wildfirechat.pojos.PojoGroupMember;
import cn.wildfirechat.proto.ProtoConstants;
import cn.wildfirechat.proto.WFCMessage;
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.util.internal.StringUtil;
import java.util.ArrayList;
import java.util.List;
@Route(APIPath.Group_Member_Get)
@HttpMethod("POST")
public class GetGroupMemberAction extends AdminAction {
@Override
public boolean isTransactionAction() {
return true;
}
@Override
public boolean action(Request request, Response response) {
if (request.getNettyRequest() instanceof FullHttpRequest) {
InputGetGroupMember input = getRequestBody(request.getNettyRequest(), InputGetGroupMember.class);
if (input != null
&& (!StringUtil.isNullOrEmpty(input.getGroupId()))
&& (!StringUtil.isNullOrEmpty(input.getMemberId()))) {
WFCMessage.GroupMember groupMember = messagesStore.getGroupMember(input.getGroupId(), input.getMemberId());
RestResult result;
if (groupMember == null || StringUtil.isNullOrEmpty(groupMember.getMemberId()) || groupMember.getType() == ProtoConstants.GroupMemberType.GroupMemberType_Removed) {
result = RestResult.resultOf(ErrorCode.ERROR_CODE_NOT_EXIST);
} else {
PojoGroupMember pm = new PojoGroupMember();
pm.setMember_id(groupMember.getMemberId());
pm.setAlias(groupMember.getAlias());
pm.setType(groupMember.getType());
pm.setExtra(groupMember.getExtra());
pm.setCreateDt(groupMember.getCreateDt());
result = RestResult.ok(pm);
}
setResponseContent(result, response);
} else {
setResponseContent(RestResult.resultOf(ErrorCode.INVALID_PARAMETER), response);
}
}
return true;
}
}
@@ -0,0 +1,37 @@
/*
* 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.channel;
import cn.wildfirechat.common.APIPath;
import cn.wildfirechat.pojos.InputChannelSubscribe;
import cn.wildfirechat.pojos.InputUserId;
import cn.wildfirechat.pojos.OutputStringList;
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 java.util.ArrayList;
@Route(APIPath.Channel_Is_Subscriber)
@HttpMethod("POST")
public class GetIsChannelSubscriberAction extends ChannelAction {
@Override
public boolean action(Request request, Response response) {
if (request.getNettyRequest() instanceof FullHttpRequest) {
InputUserId input = getRequestBody(request.getNettyRequest(), InputUserId.class);
boolean isSubscriber = messagesStore.checkUserInChannel(input.getUserId(), channelInfo.getTargetId());
setResponseContent(RestResult.ok(isSubscriber), response);
}
return true;
}
}
@@ -0,0 +1,98 @@
/*
* 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.robot;
import cn.wildfirechat.common.APIPath;
import cn.wildfirechat.common.ErrorCode;
import cn.wildfirechat.pojos.InputGetGroup;
import cn.wildfirechat.pojos.InputGetGroupMember;
import cn.wildfirechat.pojos.OutputGroupMemberList;
import cn.wildfirechat.pojos.PojoGroupMember;
import cn.wildfirechat.proto.ProtoConstants;
import cn.wildfirechat.proto.WFCMessage;
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.util.internal.StringUtil;
import java.util.ArrayList;
import java.util.List;
@Route(APIPath.Robot_Group_Member_Get)
@HttpMethod("POST")
public class GetGroupMemberAction extends RobotAction {
@Override
public boolean isTransactionAction() {
return true;
}
@Override
public boolean action(Request request, Response response) {
if (request.getNettyRequest() instanceof FullHttpRequest) {
InputGetGroupMember input = getRequestBody(request.getNettyRequest(), InputGetGroupMember.class);
String robotId = robot.getUid();
if (input != null
&& (!StringUtil.isNullOrEmpty(input.getGroupId()))
&& (!StringUtil.isNullOrEmpty(input.getMemberId()))) {
List<WFCMessage.GroupMember> members = new ArrayList<>();
ErrorCode errorCode = messagesStore.getGroupMembers(null, input.getGroupId(), 0, members);
RestResult result;
if (errorCode != ErrorCode.ERROR_CODE_SUCCESS) {
result = RestResult.resultOf(errorCode);
} else {
WFCMessage.GroupMember groupMember = null;
boolean isInGroup = false;
for (WFCMessage.GroupMember member : members) {
if (member.getType() == ProtoConstants.GroupMemberType.GroupMemberType_Removed) {
continue;
}
if(member.getMemberId().equals(robotId)) {
isInGroup = true;
if(groupMember != null) {
break;
}
}
if(member.getMemberId().equals(input.getMemberId())) {
groupMember = member;
if(isInGroup) {
break;
}
}
}
if(!isInGroup) {
result = RestResult.resultOf(ErrorCode.ERROR_CODE_NOT_IN_GROUP);
} else {
if(groupMember == null) {
result = RestResult.resultOf(ErrorCode.ERROR_CODE_NOT_EXIST);
} else {
PojoGroupMember pm = new PojoGroupMember();
pm.setMember_id(groupMember.getMemberId());
pm.setAlias(groupMember.getAlias());
pm.setType(groupMember.getType());
pm.setExtra(groupMember.getExtra());
pm.setCreateDt(groupMember.getCreateDt());
result = RestResult.ok(pm);
}
}
}
setResponseContent(result, response);
} else {
setResponseContent(RestResult.resultOf(ErrorCode.INVALID_PARAMETER), response);
}
}
return true;
}
}
@@ -15,6 +15,7 @@ import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.util.internal.StringUtil;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import win.liyufan.im.Utility; import win.liyufan.im.Utility;
@@ -108,7 +109,7 @@ abstract public class ActionHandler extends SimpleChannelInboundHandler<FullHttp
* @param response 响应对象 * @param response 响应对象
*/ */
private void doAction(ChannelHandlerContext ctx, Request request, Response response){ private void doAction(ChannelHandlerContext ctx, Request request, Response response){
if(("/route".equalsIgnoreCase(request.getPath()) || request.getPath().startsWith("/fs/")) if(("/route".equalsIgnoreCase(request.getPath()) || (!StringUtil.isNullOrEmpty(request.getPath()) && request.getPath().startsWith("/fs/")))
&& "OPTIONS".equalsIgnoreCase(request.getMethod())){ && "OPTIONS".equalsIgnoreCase(request.getMethod())){
handleOptions(ctx, request, response); handleOptions(ctx, request, response);
return; return;
@@ -29,6 +29,8 @@ public final class BrokerConstants {
public static final String HTTP_SERVER_PORT = "http_port"; public static final String HTTP_SERVER_PORT = "http_port";
public static final String HTTP_LOCAL_PORT = "local_port"; public static final String HTTP_LOCAL_PORT = "local_port";
public static final String ENCRYPT_AES256 = "encrypt.use_aes256";
public static final String HTTP_ADMIN_PORT = "http.admin.port"; public static final String HTTP_ADMIN_PORT = "http.admin.port";
public static final String DEFAULT_MOQUETTE_STORE_MAP_DB_FILENAME = "moquette_store.mapdb"; public static final String DEFAULT_MOQUETTE_STORE_MAP_DB_FILENAME = "moquette_store.mapdb";
public static final String DEFAULT_PERSISTENT_PATH = System.getProperty("user.dir") + File.separator public static final String DEFAULT_PERSISTENT_PATH = System.getProperty("user.dir") + File.separator
@@ -129,7 +131,7 @@ public final class BrokerConstants {
public static final String MESSAGE_Forward_Types = "message.forward.types"; public static final String MESSAGE_Forward_Types = "message.forward.types";
public static final String MESSAGE_Forward_Exclude_Types = "message.forward.exclude_types"; public static final String MESSAGE_Forward_Exclude_Types = "message.forward.exclude_types";
public static final String MESSAGE_MentionMsg_Forward_Url = "message.mentionmsg.forward.url"; public static final String MESSAGE_MentionMsg_Forward_Url = "message.mentionmsg.forward.url";
public static final String MESSAGE_RecallMsg_Forward_Url = "message.recallmsg.forward.url";
public static final String SERVER_MULTI_ENDPOINT = "server.multi_endpoint"; public static final String SERVER_MULTI_ENDPOINT = "server.multi_endpoint";
public static final String SERVER_MULTI_PC_ENDPOINT = "server.multi_pc_endpoint"; public static final String SERVER_MULTI_PC_ENDPOINT = "server.multi_pc_endpoint";
@@ -161,6 +163,8 @@ public final class BrokerConstants {
public static final String FRIEND_Repeat_Request_Duration = "friend.repeat_request_duration"; 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 FRIEND_Reject_Request_Duration = "friend.reject_request_duration";
public static final String FRIEND_Request_Expiration_Duration = "friend.request_expiration_duration"; public static final String FRIEND_Request_Expiration_Duration = "friend.request_expiration_duration";
public static final String FRIEND_Request_Robot_Auto_Accept = "friend.robot_auto_accept";
public static final String CHATROOM_Participant_Idle_Time = "chatroom.participant_idle_time"; public static final String CHATROOM_Participant_Idle_Time = "chatroom.participant_idle_time";
public static final String CHATROOM_Rejoin_When_Active = "chatroom.rejoin_when_active"; public static final String CHATROOM_Rejoin_When_Active = "chatroom.rejoin_when_active";
@@ -171,6 +175,7 @@ public final class BrokerConstants {
public static final String GROUP_Allow_Robot_Custom_Operation_Notification = "group.allow_robot_custom_operation_notificatio"; public static final String GROUP_Allow_Robot_Custom_Operation_Notification = "group.allow_robot_custom_operation_notificatio";
public static final String GROUP_Visible_Quit_Kickoff_Notification = "group.visible_quit_or_kickoff_notification"; public static final String GROUP_Visible_Quit_Kickoff_Notification = "group.visible_quit_or_kickoff_notification";
public static final String GROUP_Forbidden_Client_Operation = "group.forbidden_client_operation";
public static final String USER_HIDE_PROPERTIES = "user.hide_properties"; public static final String USER_HIDE_PROPERTIES = "user.hide_properties";
public static final String USER_KEEP_DISPLAY_NAME_WHEN_DESTROY = "user.keep_display_name_when_destroy"; public static final String USER_KEEP_DISPLAY_NAME_WHEN_DESTROY = "user.keep_display_name_when_destroy";
@@ -30,8 +30,10 @@ public class AddFriendHandler extends GroupHandler<WFCMessage.AddFriendRequest>
if (user != null && user.getType() == ProtoConstants.UserType.UserType_Normal) { if (user != null && user.getType() == ProtoConstants.UserType.UserType_Normal) {
publisher.publishNotification(IMTopic.NotifyFriendRequestTopic, request.getTargetUid(), head[0], fromUser, request.getReason()); publisher.publishNotification(IMTopic.NotifyFriendRequestTopic, request.getTargetUid(), head[0], fromUser, request.getReason());
} else if(user != null && user.getType() == ProtoConstants.UserType.UserType_Robot) { } else if(user != null && user.getType() == ProtoConstants.UserType.UserType_Robot) {
WFCMessage.HandleFriendRequest handleFriendRequest = WFCMessage.HandleFriendRequest.newBuilder().setTargetUid(fromUser).setStatus(ProtoConstants.FriendRequestStatus.RequestStatus_Accepted).build(); if(m_messagesStore.isRobotAutoAcceptFriendRequest()) {
mServer.onApiMessage(request.getTargetUid(), null, handleFriendRequest.toByteArray(), 0, fromUser, HandleFriendRequestTopic, requestSourceType); WFCMessage.HandleFriendRequest handleFriendRequest = WFCMessage.HandleFriendRequest.newBuilder().setTargetUid(fromUser).setStatus(ProtoConstants.FriendRequestStatus.RequestStatus_Accepted).build();
mServer.onApiMessage(request.getTargetUid(), null, handleFriendRequest.toByteArray(), 0, fromUser, HandleFriendRequestTopic, requestSourceType);
}
} }
} }
return errorCode; return errorCode;
@@ -24,6 +24,20 @@ public class AddGroupMember extends GroupHandler<WFCMessage.AddGroupMemberReques
@Override @Override
public ErrorCode action(ByteBuf ackPayload, String clientID, String fromUser, ProtoConstants.RequestSourceType requestSourceType, WFCMessage.AddGroupMemberRequest request, Qos1PublishHandler.IMCallback callback) { public ErrorCode action(ByteBuf ackPayload, String clientID, String fromUser, ProtoConstants.RequestSourceType requestSourceType, WFCMessage.AddGroupMemberRequest request, Qos1PublishHandler.IMCallback callback) {
boolean isAdmin = requestSourceType == ProtoConstants.RequestSourceType.Request_From_Admin; boolean isAdmin = requestSourceType == ProtoConstants.RequestSourceType.Request_From_Admin;
if(requestSourceType == ProtoConstants.RequestSourceType.Request_From_User) {
int forbiddenClientOperation = m_messagesStore.getGroupForbiddenClientOperation();
if(request.getAddedMemberList().size() == 1 && request.getAddedMember(0).getMemberId().equals(fromUser)) {
if ((forbiddenClientOperation & ProtoConstants.ForbiddenClientGroupOperationMask.Forbidden_Join_Group) > 0) {
return ErrorCode.ERROR_CODE_NOT_RIGHT;
}
} else {
if ((forbiddenClientOperation & ProtoConstants.ForbiddenClientGroupOperationMask.Forbidden_Invite_Group_Member) > 0) {
return ErrorCode.ERROR_CODE_NOT_RIGHT;
}
}
}
ErrorCode errorCode = m_messagesStore.addGroupMembers(fromUser, isAdmin, request.getGroupId(), request.getAddedMemberList(), request.getExtra()); ErrorCode errorCode = m_messagesStore.addGroupMembers(fromUser, isAdmin, request.getGroupId(), request.getAddedMemberList(), request.getExtra());
if (errorCode == ERROR_CODE_SUCCESS) { if (errorCode == ERROR_CODE_SUCCESS) {
if (request.hasNotifyContent() && request.getNotifyContent().getType() > 0) { if (request.hasNotifyContent() && request.getNotifyContent().getType() > 0) {
@@ -21,7 +21,7 @@ import win.liyufan.im.IMTopic;
public class CreateGroupHandler extends GroupHandler<WFCMessage.CreateGroupRequest> { public class CreateGroupHandler extends GroupHandler<WFCMessage.CreateGroupRequest> {
@Override @Override
public ErrorCode action(ByteBuf ackPayload, String clientID, String fromUser, ProtoConstants.RequestSourceType requestSourceType, WFCMessage.CreateGroupRequest request, Qos1PublishHandler.IMCallback callback) { public ErrorCode action(ByteBuf ackPayload, String clientID, String fromUser, ProtoConstants.RequestSourceType requestSourceType, WFCMessage.CreateGroupRequest request, Qos1PublishHandler.IMCallback callback) {
if(request.getGroup().getGroupInfo().getType() < 0 || request.getGroup().getGroupInfo().getType() > 2) { if(request.getGroup().getGroupInfo().getType() < 0 || request.getGroup().getGroupInfo().getType() > 3) {
return ErrorCode.ERROR_CODE_INVALID_DATA; return ErrorCode.ERROR_CODE_INVALID_DATA;
} }
@@ -44,6 +44,12 @@ public class CreateGroupHandler extends GroupHandler<WFCMessage.CreateGroupReque
return ErrorCode.ERROR_CODE_NOT_RIGHT; return ErrorCode.ERROR_CODE_NOT_RIGHT;
} }
if(requestSourceType == ProtoConstants.RequestSourceType.Request_From_User) {
int forbiddenClientOperation = m_messagesStore.getGroupForbiddenClientOperation();
if((forbiddenClientOperation & ProtoConstants.ForbiddenClientGroupOperationMask.Forbidden_Create_Group) > 0) {
return ErrorCode.ERROR_CODE_NOT_RIGHT;
}
}
WFCMessage.GroupInfo groupInfo = m_messagesStore.createGroup(fromUser, request.getGroup().getGroupInfo(), request.getGroup().getMembersList(), request.getMemberExtra(), isAdmin); WFCMessage.GroupInfo groupInfo = m_messagesStore.createGroup(fromUser, request.getGroup().getGroupInfo(), request.getGroup().getMembersList(), request.getMemberExtra(), isAdmin);
if (groupInfo != null) { if (groupInfo != null) {
if(request.hasNotifyContent() && request.getNotifyContent().getType() > 0) { if(request.hasNotifyContent() && request.getNotifyContent().getType() > 0) {
@@ -26,7 +26,6 @@ public class DismissGroupHandler extends GroupHandler<WFCMessage.DismissGroupReq
ErrorCode errorCode; ErrorCode errorCode;
if (groupInfo == null) { if (groupInfo == null) {
errorCode = m_messagesStore.dismissGroup(fromUser, request.getGroupId(), isAdmin); errorCode = m_messagesStore.dismissGroup(fromUser, request.getGroupId(), isAdmin);
} else if (isAdmin || (groupInfo.getType() == ProtoConstants.GroupType.GroupType_Normal || groupInfo.getType() == ProtoConstants.GroupType.GroupType_Restricted) } else if (isAdmin || (groupInfo.getType() == ProtoConstants.GroupType.GroupType_Normal || groupInfo.getType() == ProtoConstants.GroupType.GroupType_Restricted)
&& groupInfo.getOwner() != null && groupInfo.getOwner().equals(fromUser)) { && groupInfo.getOwner() != null && groupInfo.getOwner().equals(fromUser)) {
@@ -38,6 +37,13 @@ public class DismissGroupHandler extends GroupHandler<WFCMessage.DismissGroupReq
return ErrorCode.ERROR_CODE_NOT_RIGHT; return ErrorCode.ERROR_CODE_NOT_RIGHT;
} }
if(requestSourceType == ProtoConstants.RequestSourceType.Request_From_User) {
int forbiddenClientOperation = m_messagesStore.getGroupForbiddenClientOperation();
if((forbiddenClientOperation & ProtoConstants.ForbiddenClientGroupOperationMask.Forbidden_Dismiss_Group) > 0) {
return ErrorCode.ERROR_CODE_NOT_RIGHT;
}
}
//send notify message first, then dismiss group //send notify message first, then dismiss group
if (request.hasNotifyContent() && request.getNotifyContent().getType() > 0) { if (request.hasNotifyContent() && request.getNotifyContent().getType() > 0) {
sendGroupNotification(fromUser, groupInfo.getTargetId(), request.getToLineList(), request.getNotifyContent()); sendGroupNotification(fromUser, groupInfo.getTargetId(), request.getToLineList(), request.getNotifyContent());
@@ -21,7 +21,7 @@ import java.util.List;
public class GetGroupInfoHandler extends IMHandler<WFCMessage.PullUserRequest> { public class GetGroupInfoHandler extends IMHandler<WFCMessage.PullUserRequest> {
@Override @Override
public ErrorCode action(ByteBuf ackPayload, String clientID, String fromUser, ProtoConstants.RequestSourceType requestSourceType, WFCMessage.PullUserRequest request, Qos1PublishHandler.IMCallback callback) { public ErrorCode action(ByteBuf ackPayload, String clientID, String fromUser, ProtoConstants.RequestSourceType requestSourceType, WFCMessage.PullUserRequest request, Qos1PublishHandler.IMCallback callback) {
List<WFCMessage.GroupInfo> infos = m_messagesStore.getGroupInfos(request.getRequestList()); List<WFCMessage.GroupInfo> infos = m_messagesStore.getGroupInfos(request.getRequestList(), fromUser, requestSourceType == ProtoConstants.RequestSourceType.Request_From_Admin);
WFCMessage.PullGroupInfoResult result = WFCMessage.PullGroupInfoResult.newBuilder().addAllInfo(infos).build(); WFCMessage.PullGroupInfoResult result = WFCMessage.PullGroupInfoResult.newBuilder().addAllInfo(infos).build();
byte[] data = result.toByteArray(); byte[] data = result.toByteArray();
@@ -62,6 +62,13 @@ public class KickoffGroupMember extends GroupHandler<WFCMessage.RemoveGroupMembe
return ErrorCode.ERROR_CODE_NOT_RIGHT; return ErrorCode.ERROR_CODE_NOT_RIGHT;
} }
if(requestSourceType == ProtoConstants.RequestSourceType.Request_From_User) {
int forbiddenClientOperation = m_messagesStore.getGroupForbiddenClientOperation();
if((forbiddenClientOperation & ProtoConstants.ForbiddenClientGroupOperationMask.Forbidden_Kickoff_Group_Member) > 0) {
return ErrorCode.ERROR_CODE_NOT_RIGHT;
}
}
//send notify message first, then kickoff the member //send notify message first, then kickoff the member
if (request.hasNotifyContent() && request.getNotifyContent().getType() > 0) { if (request.hasNotifyContent() && request.getNotifyContent().getType() > 0) {
sendGroupNotification(fromUser, groupInfo.getTargetId(), request.getToLineList(), request.getNotifyContent()); sendGroupNotification(fromUser, groupInfo.getTargetId(), request.getToLineList(), request.getNotifyContent());
@@ -31,6 +31,19 @@ public class ModifyGroupInfoHandler extends GroupHandler<WFCMessage.ModifyGroupI
return ErrorCode.ERROR_CODE_NOT_RIGHT; return ErrorCode.ERROR_CODE_NOT_RIGHT;
} }
if(requestSourceType == ProtoConstants.RequestSourceType.Request_From_User) {
int forbiddenClientOperation = m_messagesStore.getGroupForbiddenClientOperation();
if(request.getType() == Modify_Group_Mute) {
if((forbiddenClientOperation & ProtoConstants.ForbiddenClientGroupOperationMask.Forbidden_Mute_Group) > 0) {
return ErrorCode.ERROR_CODE_NOT_RIGHT;
}
} else {
if((forbiddenClientOperation & ProtoConstants.ForbiddenClientGroupOperationMask.Forbidden_Modify_Group_Info) > 0) {
return ErrorCode.ERROR_CODE_NOT_RIGHT;
}
}
}
ErrorCode errorCode= m_messagesStore.modifyGroupInfo(fromUser, request.getGroupId(), request.getType(), request.getValue(), isAdmin); ErrorCode errorCode= m_messagesStore.modifyGroupInfo(fromUser, request.getGroupId(), request.getType(), request.getValue(), isAdmin);
if (errorCode == ERROR_CODE_SUCCESS) { if (errorCode == ERROR_CODE_SUCCESS) {
if(request.hasNotifyContent() && request.getNotifyContent().getType() > 0) { if(request.hasNotifyContent() && request.getNotifyContent().getType() > 0) {
@@ -31,6 +31,13 @@ public class QuitGroupHandler extends GroupHandler<WFCMessage.QuitGroupRequest>
return ErrorCode.ERROR_CODE_NOT_RIGHT; return ErrorCode.ERROR_CODE_NOT_RIGHT;
} }
if(requestSourceType == ProtoConstants.RequestSourceType.Request_From_User) {
int forbiddenClientOperation = m_messagesStore.getGroupForbiddenClientOperation();
if((forbiddenClientOperation & ProtoConstants.ForbiddenClientGroupOperationMask.Forbidden_Quit_Group) > 0) {
return ErrorCode.ERROR_CODE_NOT_RIGHT;
}
}
ErrorCode errorCode = m_messagesStore.quitGroup(fromUser, request.getGroupId(), isAdmin); ErrorCode errorCode = m_messagesStore.quitGroup(fromUser, request.getGroupId(), isAdmin);
if (errorCode == ErrorCode.ERROR_CODE_SUCCESS) { if (errorCode == ErrorCode.ERROR_CODE_SUCCESS) {
if (request.hasNotifyContent() && request.getNotifyContent().getType() > 0) { if (request.hasNotifyContent() && request.getNotifyContent().getType() > 0) {
@@ -182,6 +182,15 @@ public class SendMessageHandler extends IMHandler<WFCMessage.Message> {
} }
} }
} }
} else if (message.getConversation().getType() == ProtoConstants.ConversationType.ConversationType_Group) {
if(m_messagesStore.getGroupInfo(message.getConversation().getTarget()) == null) {
return ErrorCode.ERROR_CODE_NOT_EXIST;
}
} else if (message.getConversation().getType() == ProtoConstants.ConversationType.ConversationType_Channel) {
WFCMessage.ChannelInfo channelData = m_messagesStore.getChannelInfo(message.getConversation().getTarget());
if(channelData == null || channelData.getStatus() == ProtoConstants.ChannelState.Channel_State_Mask_Deleted) {
return ErrorCode.ERROR_CODE_NOT_EXIST;
}
} }
long timestamp = System.currentTimeMillis(); long timestamp = System.currentTimeMillis();
@@ -30,6 +30,13 @@ public class SetGroupManagerHandler extends GroupHandler<WFCMessage.SetGroupMana
return ErrorCode.ERROR_CODE_NOT_RIGHT; return ErrorCode.ERROR_CODE_NOT_RIGHT;
} }
if(requestSourceType == ProtoConstants.RequestSourceType.Request_From_User) {
int forbiddenClientOperation = m_messagesStore.getGroupForbiddenClientOperation();
if((forbiddenClientOperation & ProtoConstants.ForbiddenClientGroupOperationMask.Forbidden_Set_Group_Manage) > 0) {
return ErrorCode.ERROR_CODE_NOT_RIGHT;
}
}
ErrorCode errorCode = m_messagesStore.setGroupManager(fromUser, request.getGroupId(), request.getType(), request.getUserIdList(), isAdmin); ErrorCode errorCode = m_messagesStore.setGroupManager(fromUser, request.getGroupId(), request.getType(), request.getUserIdList(), isAdmin);
if (errorCode == ERROR_CODE_SUCCESS) { if (errorCode == ERROR_CODE_SUCCESS) {
if (request.hasNotifyContent() && request.getNotifyContent().getType() > 0) { if (request.hasNotifyContent() && request.getNotifyContent().getType() > 0) {
@@ -30,6 +30,13 @@ public class TransferGroupHandler extends GroupHandler<WFCMessage.TransferGroupR
return ErrorCode.ERROR_CODE_NOT_RIGHT; return ErrorCode.ERROR_CODE_NOT_RIGHT;
} }
if(requestSourceType == ProtoConstants.RequestSourceType.Request_From_User) {
int forbiddenClientOperation = m_messagesStore.getGroupForbiddenClientOperation();
if((forbiddenClientOperation & ProtoConstants.ForbiddenClientGroupOperationMask.Forbidden_Transfer_Group) > 0) {
return ErrorCode.ERROR_CODE_NOT_RIGHT;
}
}
ErrorCode errorCode = m_messagesStore.transferGroup(fromUser, request.getGroupId(), request.getNewOwner(), isAdmin); ErrorCode errorCode = m_messagesStore.transferGroup(fromUser, request.getGroupId(), request.getNewOwner(), isAdmin);
if (errorCode == ERROR_CODE_SUCCESS) { if (errorCode == ERROR_CODE_SUCCESS) {
if (request.hasNotifyContent() && request.getNotifyContent().getType() > 0) { if (request.hasNotifyContent() && request.getNotifyContent().getType() > 0) {
@@ -25,9 +25,11 @@ public class UploadDeviceTokenHandler extends IMHandler<WFCMessage.UploadDeviceT
session.setPlatform(request.getPlatform()); session.setPlatform(request.getPlatform());
session.setAppName(request.getAppName()); session.setAppName(request.getAppName());
if (request.getPlatform() == ProtoConstants.Platform.Platform_iOS && request.getPushType() == 2) { if (request.getPlatform() == ProtoConstants.Platform.Platform_iOS && request.getPushType() == 2) {
LOG.info("Set device token, userId {}", fromUser);
session.setVoipDeviceToken(request.getDeviceToken()); session.setVoipDeviceToken(request.getDeviceToken());
m_sessionsStore.updateSessionToken(session, true); m_sessionsStore.updateSessionToken(session, true);
} else { } else {
LOG.info("Set device token, userId {}, platform {}, pushType {}", fromUser, session.getPlatform(), request.getPushType());
session.setDeviceToken(request.getDeviceToken()); session.setDeviceToken(request.getDeviceToken());
session.setPushType(request.getPushType()); session.setPushType(request.getPushType());
m_sessionsStore.updateSessionToken(session, false); m_sessionsStore.updateSessionToken(session, false);
@@ -203,7 +203,7 @@ public class DatabaseStore {
} }
sql += " and _type <> 2"; //can search normal user(0) and robot(1) and admin(100), can not search things sql += " and `_type` <> 2 and `_deleted` = 0"; //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) { if (searchType == SearchUserType_Name_Mobile || searchType == SearchUserType_Name || searchType == SearchUserType_Mobile) {
sql += " limit 1"; sql += " limit 1";
@@ -815,7 +815,7 @@ public class DatabaseStore {
long beforeUid = before[0]; long beforeUid = before[0];
String sql = "select `_mid`, `_from`, `_type`, `_target`, `_line`, `_data`, `_dt`, `_to` from " + table +" where"; String sql = "select `_mid`, `_from`, `_type`, `_target`, `_line`, `_data`, `_dt`, `_to` from " + table +" where";
if (conversation.getType() == ProtoConstants.ConversationType.ConversationType_Private) { if (conversation.getType() == ProtoConstants.ConversationType.ConversationType_Private) {
sql += " _type = ? and _line = ? and _mid < ? and ((_target = ? and _from = ?) or (_target = ? and _from = ?))"; sql += " _type = ? and _line = ? and _mid < ? and ((_target = ? and _from = ?) or (_target = ? and _from = ?)) and (_to = '' or _to = ?)";
} else if (conversation.getType() == ProtoConstants.ConversationType.ConversationType_Channel && !user.equals(channelOwner)) { } else if (conversation.getType() == ProtoConstants.ConversationType.ConversationType_Channel && !user.equals(channelOwner)) {
sql += " _type = ? and _line = ? and _mid < ? and _target = ? and ((_from = ? and (_to = '' or _to = ?)) or (_from = ?))"; sql += " _type = ? and _line = ? and _mid < ? and _target = ? and ((_from = ? and (_to = '' or _to = ?)) or (_from = ?))";
} else { } else {
@@ -853,6 +853,7 @@ public class DatabaseStore {
statement.setString(index++, user); statement.setString(index++, user);
statement.setString(index++, user); statement.setString(index++, user);
statement.setString(index++, conversation.getTarget()); statement.setString(index++, conversation.getTarget());
statement.setString(index++, user);
} else if (conversation.getType() == ProtoConstants.ConversationType.ConversationType_Channel && !user.equals(channelOwner)) { } else if (conversation.getType() == ProtoConstants.ConversationType.ConversationType_Channel && !user.equals(channelOwner)) {
statement.setString(index++, channelOwner); statement.setString(index++, channelOwner);
statement.setString(index++, user); statement.setString(index++, user);
@@ -914,7 +915,7 @@ public class DatabaseStore {
return false; return false;
} }
void persistUserMessage(final String userId, final long messageId, final long messageSeq, int type, String target, int line, boolean directing, final int messageContentType) { void persistUserMessage(final String userId, final String sender, final long messageId, final long messageSeq, int type, String target, int line, boolean directing, final int messageContentType) {
mScheduler.execute(()->{ mScheduler.execute(()->{
Connection connection = null; Connection connection = null;
PreparedStatement statement = null; PreparedStatement statement = null;
@@ -929,7 +930,7 @@ public class DatabaseStore {
statement.setString(index++, userId); statement.setString(index++, userId);
statement.setLong(index++, messageSeq); statement.setLong(index++, messageSeq);
statement.setInt(index++, type); statement.setInt(index++, type);
statement.setString(index++, target); statement.setString(index++, getPrivateChatUserMessageTarget(type, target, sender));
statement.setInt(index++, line); statement.setInt(index++, line);
statement.setInt(index++, directing ? 1 :0); statement.setInt(index++, directing ? 1 :0);
statement.setInt(index++, messageContentType); statement.setInt(index++, messageContentType);
@@ -945,6 +946,14 @@ public class DatabaseStore {
}); });
} }
String getPrivateChatUserMessageTarget(int conversationType, String target, String userId) {
if(conversationType == ProtoConstants.ConversationType.ConversationType_Private) {
return target.compareTo(userId) > 0 ? (userId + "|" + target) : (target + "|" + userId);
} else {
return target;
}
}
void clearUserMessage(final String userId) { void clearUserMessage(final String userId) {
mScheduler.execute(()->{ mScheduler.execute(()->{
String tableName = getUserMessageTable(userId); String tableName = getUserMessageTable(userId);
@@ -1493,12 +1502,6 @@ public class DatabaseStore {
if (!strEqual(session.getAppName(), request.getApp())) { if (!strEqual(session.getAppName(), request.getApp())) {
sql += " `_package_name` = ?,"; sql += " `_package_name` = ?,";
} }
if (session.getPlatform() != request.getPlatform()) {
sql += " `_platform` = ?,";
}
if (session.getPushType() != request.getPushType()) {
sql += " `_push_type` = ?,";
}
if (!strEqual(session.getDeviceName(), request.getDeviceName())) { if (!strEqual(session.getDeviceName(), request.getDeviceName())) {
sql += " `_device_name` = ?,"; sql += " `_device_name` = ?,";
} }
@@ -1526,12 +1529,6 @@ public class DatabaseStore {
if (!strEqual(session.getAppName(), request.getApp())) { if (!strEqual(session.getAppName(), request.getApp())) {
statement.setString(index++, request.getApp()); statement.setString(index++, request.getApp());
} }
if (session.getPlatform() != request.getPlatform()) {
statement.setInt(index++, request.getPlatform());
}
if (session.getPushType() != request.getPushType()) {
statement.setInt(index++, request.getPushType() >= 32 ? 0 : request.getPushType());
}
if (!strEqual(session.getDeviceName(), request.getDeviceName())) { if (!strEqual(session.getDeviceName(), request.getDeviceName())) {
statement.setString(index++, request.getDeviceName()); statement.setString(index++, request.getDeviceName());
} }
@@ -2414,59 +2411,55 @@ public class DatabaseStore {
} }
void deleteUserStatus(String userId) { void deleteUserStatus(String userId) {
mScheduler.execute(()->{ Connection connection = null;
Connection connection = null; PreparedStatement statement = null;
PreparedStatement statement = null; try {
try { connection = DBUtil.getConnection();
connection = DBUtil.getConnection(); String sql = "delete from t_user_status where _uid = ?";
statement = connection.prepareStatement(sql);
statement.setString(1, userId);
int count = statement.executeUpdate();
LOG.info("Update rows {}", count);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Utility.printExecption(LOG, e, RDBS_Exception);
} finally {
DBUtil.closeDB(connection, statement);
}
}
void updateUserStatus(String userId, int status) {
Connection connection = null;
PreparedStatement statement = null;
try {
connection = DBUtil.getConnection();
if (status == 0) {
String sql = "delete from t_user_status where _uid = ?"; String sql = "delete from t_user_status where _uid = ?";
statement = connection.prepareStatement(sql); statement = connection.prepareStatement(sql);
statement.setString(1, userId); statement.setString(1, userId);
int count = statement.executeUpdate(); int count = statement.executeUpdate();
LOG.info("Update rows {}", count); LOG.info("Update rows {}", count);
} catch (SQLException e) { } else {
// TODO Auto-generated catch block String sql = "insert into t_user_status (`_uid`, `_status`, `_dt`) values(?,?,?) ON DUPLICATE KEY UPDATE `_status` = ?";
e.printStackTrace();
Utility.printExecption(LOG, e, RDBS_Exception); statement = connection.prepareStatement(sql);
} finally { int index = 1;
DBUtil.closeDB(connection, statement); statement.setString(index++, userId);
statement.setInt(index++, status);
statement.setLong(index++, System.currentTimeMillis());
statement.setInt(index++, status);
int count = statement.executeUpdate();
LOG.info("Update rows {}", count);
} }
}); } catch (SQLException e) {
} // TODO Auto-generated catch block
e.printStackTrace();
void updateUserStatus(String userId, int status) { Utility.printExecption(LOG, e, RDBS_Exception);
mScheduler.execute(()->{ } finally {
Connection connection = null; DBUtil.closeDB(connection, statement);
PreparedStatement statement = null; }
try {
connection = DBUtil.getConnection();
if (status == 0) {
String sql = "delete from t_user_status where _uid = ?";
statement = connection.prepareStatement(sql);
statement.setString(1, userId);
int count = statement.executeUpdate();
LOG.info("Update rows {}", count);
} else {
String sql = "insert into t_user_status (`_uid`, `_status`, `_dt`) values(?,?,?) ON DUPLICATE KEY UPDATE `_status` = ?";
statement = connection.prepareStatement(sql);
int index = 1;
statement.setString(index++, userId);
statement.setInt(index++, status);
statement.setLong(index++, System.currentTimeMillis());
statement.setInt(index++, status);
int count = statement.executeUpdate();
LOG.info("Update rows {}", count);
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Utility.printExecption(LOG, e, RDBS_Exception);
} finally {
DBUtil.closeDB(connection, statement);
}
});
} }
int getGeneratedId() { int getGeneratedId() {
@@ -2647,6 +2640,103 @@ public class DatabaseStore {
return null; return null;
} }
List<WFCMessage.User> getAllUsers(int count, int offset) {
Connection connection = null;
PreparedStatement statement = null;
ResultSet rs = null;
List<WFCMessage.User> outList = new ArrayList<>();
try {
connection = DBUtil.getConnection();
String sql = "select `_uid`, `_name`" +
", `_display_name`" +
", `_portrait`" +
", `_mobile`" +
", `_gender`" +
", `_email`" +
", `_address`" +
", `_company`" +
", `_social`" +
", `_extra`" +
", `_type`" +
", `_deleted`" +
", `_dt` from t_user where `_deleted` = 0 order by _createTime limit ? offset ?";
statement = connection.prepareStatement(sql);
int index = 1;
statement.setInt(1, count);
statement.setInt(2, offset);
rs = statement.executeQuery();
while (rs.next()) {
WFCMessage.User.Builder builder = WFCMessage.User.newBuilder();
index = 1;
String value = rs.getString(index++);
value = (value == null ? "" : value);
builder.setUid(value);
value = rs.getString(index++);
value = (value == null ? "" : value);
builder.setName(value);
value = rs.getString(index++);
value = (value == null ? "" : value);
builder.setDisplayName(value);
value = rs.getString(index++);
value = (value == null ? "" : value);
builder.setPortrait(value);
value = rs.getString(index++);
value = (value == null ? "" : value);
builder.setMobile(value);
int gender = rs.getInt(index++);
builder.setGender(gender);
value = rs.getString(index++);
value = (value == null ? "" : value);
builder.setEmail(value);
value = rs.getString(index++);
value = (value == null ? "" : value);
builder.setAddress(value);
value = rs.getString(index++);
value = (value == null ? "" : value);
builder.setCompany(value);
value = rs.getString(index++);
value = (value == null ? "" : value);
builder.setSocial(value);
value = rs.getString(index++);
value = (value == null ? "" : value);
builder.setExtra(value);
int type = rs.getInt(index++);
builder.setType(type);
int deleted = rs.getInt(index++);
builder.setDeleted(deleted);
long longValue = rs.getLong(index++);
if(longValue <= 0)
longValue = 1;
builder.setUpdateDt(longValue);
outList.add(builder.build());
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Utility.printExecption(LOG, e, RDBS_Exception);
} finally {
DBUtil.closeDB(connection, statement, rs);
}
return outList;
}
Set<String> getAllEnds() { Set<String> getAllEnds() {
Connection connection = null; Connection connection = null;
PreparedStatement statement = null; PreparedStatement statement = null;
@@ -3345,47 +3435,45 @@ public class DatabaseStore {
} }
void updateChannelListener(final String channelId, final String listener, final boolean listen) { void updateChannelListener(final String channelId, final String listener, final boolean listen) {
LOG.info("Database remove channel {}", channelId); LOG.info("updateChannelListener channel {}, listener {}, listen {}", channelId, listener, listen);
mScheduler.execute(()->{ Connection connection = null;
Connection connection = null; PreparedStatement statement = null;
PreparedStatement statement = null; try {
try { connection = DBUtil.getConnection();
connection = DBUtil.getConnection(); String sql;
String sql; if (listen) {
if (listen) { sql = "insert into t_channel_listener (`_cid`" +
sql = "insert into t_channel_listener (`_cid`" + ", `_mid`" +
", `_mid`" + ", `_dt`) values(?, ?, ?)" +
", `_dt`) values(?, ?, ?)" + " ON DUPLICATE KEY UPDATE " +
" ON DUPLICATE KEY UPDATE " + "`_dt` = ?";
"`_dt` = ?"; statement = connection.prepareStatement(sql);
statement = connection.prepareStatement(sql); int index = 1;
int index = 1; statement.setString(index++, channelId);
statement.setString(index++, channelId); statement.setString(index++, listener);
statement.setString(index++, listener); statement.setLong(index++, System.currentTimeMillis());
statement.setLong(index++, System.currentTimeMillis()); statement.setLong(index++, System.currentTimeMillis());
statement.setLong(index++, System.currentTimeMillis());
int count = statement.executeUpdate(); int count = statement.executeUpdate();
LOG.info("Update rows {}", count); LOG.info("Update rows {}", count);
} else { } else {
sql = "delete from t_channel_listener where `_cid`=? and `_mid`=?"; sql = "delete from t_channel_listener where `_cid`=? and `_mid`=?";
statement = connection.prepareStatement(sql); statement = connection.prepareStatement(sql);
int index = 1; int index = 1;
statement.setString(index++, channelId); statement.setString(index++, channelId);
statement.setString(index++, listener); statement.setString(index++, listener);
int count = statement.executeUpdate(); int count = statement.executeUpdate();
LOG.info("Update rows {}", count); LOG.info("Update rows {}", count);
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Utility.printExecption(LOG, e, RDBS_Exception);
} finally {
DBUtil.closeDB(connection, statement);
} }
}); } catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Utility.printExecption(LOG, e, RDBS_Exception);
} finally {
DBUtil.closeDB(connection, statement);
}
} }
List<String> getUserChannels(String userId) { List<String> getUserChannels(String userId) {
@@ -141,6 +141,7 @@ public class MemoryMessagesStore implements IMessagesStore {
private long mFriendRequestDuration = 7 * 24 * 60 * 60 * 1000; private long mFriendRequestDuration = 7 * 24 * 60 * 60 * 1000;
private long mFriendRejectDuration = 30 * 24 * 60 * 60 * 1000; private long mFriendRejectDuration = 30 * 24 * 60 * 60 * 1000;
private long mFriendRequestExpiration = 7 * 24 * 60 * 60 * 1000; private long mFriendRequestExpiration = 7 * 24 * 60 * 60 * 1000;
private boolean mFriendRobotAutoAccept = true;
private boolean mMultiPlatformNotification = false; private boolean mMultiPlatformNotification = false;
private boolean mMobileDefaultSilentWhenPCOnline = true; private boolean mMobileDefaultSilentWhenPCOnline = true;
@@ -171,8 +172,10 @@ public class MemoryMessagesStore implements IMessagesStore {
private boolean mGroupAllowClientCustomOperationNotification; private boolean mGroupAllowClientCustomOperationNotification;
private boolean mGroupAllowRobotCustomOperationNotification; private boolean mGroupAllowRobotCustomOperationNotification;
private int mGroupVisibleQuitKickoffNotification; private int mGroupVisibleQuitKickoffNotification;
private int mGroupForbiddenClientOperation;
private int mSyncDataPartSize = 0; private int mSyncDataPartSize = 0;
private boolean keepDisplayNameWhenDestroyUser = true; private boolean keepDisplayNameWhenDestroyUser = true;
private String mRecallForwardUrl = null;
private boolean mForwardMessageWithClientInfo = false; private boolean mForwardMessageWithClientInfo = false;
private boolean mRobotCallbackWithClientInfo = false; private boolean mRobotCallbackWithClientInfo = false;
@@ -295,6 +298,12 @@ public class MemoryMessagesStore implements IMessagesStore {
printMissConfigLog(FRIEND_Request_Expiration_Duration, mFriendRequestExpiration + ""); printMissConfigLog(FRIEND_Request_Expiration_Duration, mFriendRequestExpiration + "");
} }
try {
mFriendRobotAutoAccept = Boolean.parseBoolean(m_Server.getConfig().getProperty(BrokerConstants.FRIEND_Request_Robot_Auto_Accept, "true"));
} catch (Exception e) {
}
try { try {
mChatroomRejoinWhenActive = Boolean.parseBoolean(m_Server.getConfig().getProperty(BrokerConstants.CHATROOM_Rejoin_When_Active)); mChatroomRejoinWhenActive = Boolean.parseBoolean(m_Server.getConfig().getProperty(BrokerConstants.CHATROOM_Rejoin_When_Active));
} catch (Exception e) { } catch (Exception e) {
@@ -460,6 +469,21 @@ public class MemoryMessagesStore implements IMessagesStore {
} }
try {
String s = server.getConfig().getProperty(GROUP_Forbidden_Client_Operation, null);
if(!StringUtil.isNullOrEmptyAfterTrim(s)) {
s = s.toLowerCase();
if(s.startsWith("0x")) {
s = s.substring(2);
mGroupForbiddenClientOperation = Integer.parseInt(s, 16);
} else {
mGroupForbiddenClientOperation = Integer.parseInt(s);
}
}
} catch (NumberFormatException e) {
LOG.error("Invalid group.forbidden_client_operation {}", server.getConfig().getProperty(GROUP_Forbidden_Client_Operation, null));
}
try { try {
mSyncDataPartSize = Integer.parseInt(server.getConfig().getProperty(SYNC_Data_Part_Size, "0")); mSyncDataPartSize = Integer.parseInt(server.getConfig().getProperty(SYNC_Data_Part_Size, "0"));
} catch (Exception e) { } catch (Exception e) {
@@ -502,7 +526,11 @@ public class MemoryMessagesStore implements IMessagesStore {
} catch (Exception e) { } catch (Exception e) {
} }
try {
mRecallForwardUrl = server.getConfig().getProperty(BrokerConstants.MESSAGE_RecallMsg_Forward_Url);
} catch (Exception e) {
}
} }
private void printMissConfigLog(String config, String defaultValue) { private void printMissConfigLog(String config, String defaultValue) {
@@ -569,21 +597,17 @@ public class MemoryMessagesStore implements IMessagesStore {
int pullType = ProtoConstants.PullType.Pull_Normal; int pullType = ProtoConstants.PullType.Pull_Normal;
if (type == ProtoConstants.ConversationType.ConversationType_Private) { if (type == ProtoConstants.ConversationType.ConversationType_Private) {
notifyReceivers.add(fromUser);
if(message.getToCount() > 0) { if(message.getToCount() > 0) {
if(message.getToList().contains(fromUser)) {
notifyReceivers.add(fromUser);
}
if(message.getToList().contains(message.getConversation().getTarget())) { if(message.getToList().contains(message.getConversation().getTarget())) {
notifyReceivers.add(message.getConversation().getTarget()); notifyReceivers.add(message.getConversation().getTarget());
} }
} else { } else {
notifyReceivers.add(fromUser);
notifyReceivers.add(message.getConversation().getTarget()); notifyReceivers.add(message.getConversation().getTarget());
} }
pullType = ProtoConstants.PullType.Pull_Normal; pullType = ProtoConstants.PullType.Pull_Normal;
} else if (type == ProtoConstants.ConversationType.ConversationType_Group) { } else if (type == ProtoConstants.ConversationType.ConversationType_Group) {
notifyReceivers.add(fromUser); notifyReceivers.add(fromUser);
if (!StringUtil.isNullOrEmpty(message.getToUser())) { if (!StringUtil.isNullOrEmpty(message.getToUser())) {
notifyReceivers.add(message.getToUser()); notifyReceivers.add(message.getToUser());
} else if(message.getToList()!=null && !message.getToList().isEmpty()) { } else if(message.getToList()!=null && !message.getToList().isEmpty()) {
@@ -609,9 +633,6 @@ public class MemoryMessagesStore implements IMessagesStore {
} }
} }
} }
//如果是群助手的消息,返回pull type group,否则返回normal
//群助手还没有实现
pullType = ProtoConstants.PullType.Pull_Normal; pullType = ProtoConstants.PullType.Pull_Normal;
} else if (type == ProtoConstants.ConversationType.ConversationType_ChatRoom) { } else if (type == ProtoConstants.ConversationType.ConversationType_ChatRoom) {
boolean isDirect = !StringUtil.isNullOrEmpty(message.getToUser()); boolean isDirect = !StringUtil.isNullOrEmpty(message.getToUser());
@@ -817,6 +838,10 @@ public class MemoryMessagesStore implements IMessagesStore {
mReadLock.unlock(); mReadLock.unlock();
} }
if(current == 0) {
current = 2;
head = 2;
}
builder.setCurrent(current); builder.setCurrent(current);
builder.setHead(head); builder.setHead(head);
return builder.build(); return builder.build();
@@ -970,7 +995,7 @@ public class MemoryMessagesStore implements IMessagesStore {
messageSeq = maxPullSeq + 1; messageSeq = maxPullSeq + 1;
} }
if (messageSeq == 0) { if (messageSeq < messageId) {
messageSeq = messageId; messageSeq = messageId;
} }
@@ -982,7 +1007,7 @@ public class MemoryMessagesStore implements IMessagesStore {
mWriteLock.unlock(); mWriteLock.unlock();
} }
databaseStore.persistUserMessage(user, messageId, messageSeq, conversationType, target, line, directing, messageContentType); databaseStore.persistUserMessage(user, sender, messageId, messageSeq, conversationType, target, line, directing, messageContentType);
return messageSeq; return messageSeq;
} }
@@ -1614,13 +1639,17 @@ public class MemoryMessagesStore implements IMessagesStore {
return ErrorCode.ERROR_CODE_NOT_RIGHT; return ErrorCode.ERROR_CODE_NOT_RIGHT;
} }
WFCMessage.GroupMember gm = getGroupMember(groupId, operator);
if (gm == null || gm.getType() == GroupMemberType_Removed) {
return ErrorCode.ERROR_CODE_NOT_IN_GROUP;
}
if (oldInfo.getType() == ProtoConstants.GroupType.GroupType_Restricted || oldInfo.getType() == ProtoConstants.GroupType.GroupType_Organization) { if (oldInfo.getType() == ProtoConstants.GroupType.GroupType_Restricted || oldInfo.getType() == ProtoConstants.GroupType.GroupType_Organization) {
boolean isAllow = false; boolean isAllow = false;
if ((oldInfo.getOwner() != null && oldInfo.getOwner().equals(operator))) { if ((oldInfo.getOwner() != null && oldInfo.getOwner().equals(operator))) {
isAllow = true; isAllow = true;
} else { } else {
WFCMessage.GroupMember gm = getGroupMember(groupId, operator); if (gm.getType() == GroupMemberType_Manager) {
if (gm != null && gm.getType() == GroupMemberType_Manager) {
isAllow = true; isAllow = true;
} }
} }
@@ -1631,9 +1660,8 @@ public class MemoryMessagesStore implements IMessagesStore {
if (oldInfo.getType() == ProtoConstants.GroupType.GroupType_Normal) { if (oldInfo.getType() == ProtoConstants.GroupType.GroupType_Normal) {
if (!operator.equals(oldInfo.getOwner())) { if (!operator.equals(oldInfo.getOwner())) {
WFCMessage.GroupMember gm = getGroupMember(groupId, operator);
boolean isManager = false; boolean isManager = false;
if (gm != null && gm.getType() == GroupMemberType_Manager) { if (gm.getType() == GroupMemberType_Manager) {
isManager = true; isManager = true;
} }
if (!isManager && modifyType != Modify_Group_Name && modifyType != Modify_Group_Portrait && modifyType != Modify_Group_Extra) { if (!isManager && modifyType != Modify_Group_Name && modifyType != Modify_Group_Portrait && modifyType != Modify_Group_Extra) {
@@ -1727,12 +1755,12 @@ public class MemoryMessagesStore implements IMessagesStore {
} }
} }
if (operatorMember == null) { if (operatorMember == null || operatorMember.getType() == GroupMemberType_Removed) {
LOG.error("Modify group member alias error, the operator {} is not in group", operator); LOG.error("Modify group member alias error, the operator {} is not in group", operator);
return ErrorCode.ERROR_CODE_NOT_IN_GROUP; return ErrorCode.ERROR_CODE_NOT_IN_GROUP;
} }
if (targetMember == null) { if (targetMember == null || targetMember.getType() == GroupMemberType_Removed) {
LOG.error("Modify group member alias error, the member {} is not in group", memberId); LOG.error("Modify group member alias error, the member {} is not in group", memberId);
return ErrorCode.ERROR_CODE_NOT_IN_GROUP; return ErrorCode.ERROR_CODE_NOT_IN_GROUP;
} }
@@ -1856,7 +1884,7 @@ public class MemoryMessagesStore implements IMessagesStore {
} }
@Override @Override
public List<WFCMessage.GroupInfo> getGroupInfos(List<WFCMessage.UserRequest> requests) { public List<WFCMessage.GroupInfo> getGroupInfos(List<WFCMessage.UserRequest> requests, String fromUser, boolean isAdmin) {
HazelcastInstance hzInstance = m_Server.getHazelcastInstance(); HazelcastInstance hzInstance = m_Server.getHazelcastInstance();
IMap<String, WFCMessage.GroupInfo> mIMap = hzInstance.getMap(GROUPS_MAP); IMap<String, WFCMessage.GroupInfo> mIMap = hzInstance.getMap(GROUPS_MAP);
ArrayList<WFCMessage.GroupInfo> out = new ArrayList<>(); ArrayList<WFCMessage.GroupInfo> out = new ArrayList<>();
@@ -1870,6 +1898,14 @@ public class MemoryMessagesStore implements IMessagesStore {
} }
if (groupInfo != null && groupInfo.getUpdateDt() > request.getUpdateDt()) { if (groupInfo != null && groupInfo.getUpdateDt() > request.getUpdateDt()) {
if(!isAdmin && !StringUtil.isNullOrEmpty(fromUser)) {
WFCMessage.GroupMember gm = getGroupMember(groupInfo.getTargetId(), fromUser);
if(gm == null) {
groupInfo = groupInfo.toBuilder().setMemberUpdateDt(-1).build();
} else if(gm.getType() == GroupMemberType_Removed) {
groupInfo = groupInfo.toBuilder().setMemberUpdateDt(-groupInfo.getMemberUpdateDt()).build();
}
}
out.add(groupInfo); out.add(groupInfo);
} }
} }
@@ -2153,9 +2189,10 @@ public class MemoryMessagesStore implements IMessagesStore {
if (isAdmin) { if (isAdmin) {
canRecall = true; canRecall = true;
} }
if (!isAdmin && message.getFromUser().equals(operatorId)) { boolean isExpired = false;
if (!canRecall && message.getFromUser().equals(operatorId)) {
if (now - message.getServerTimestamp() > mRecallTimeLimit * 1000) { if (now - message.getServerTimestamp() > mRecallTimeLimit * 1000) {
return ErrorCode.ERROR_CODE_RECALL_TIME_EXPIRED; isExpired = true;
} else { } else {
canRecall = true; canRecall = true;
} }
@@ -2172,17 +2209,26 @@ public class MemoryMessagesStore implements IMessagesStore {
canRecall = true; canRecall = true;
} }
MultiMap<String, WFCMessage.GroupMember> groupMembers = hzInstance.getMultiMap(GROUP_MEMBERS); if(!canRecall && !message.getFromUser().equals(operatorId)) {
Collection<WFCMessage.GroupMember> members = groupMembers.get(message.getConversation().getTarget()); boolean isOperatorManager = false;
if (members == null || members.size() == 0) { int senderType = GroupMemberType_Normal;
members = loadGroupMemberFromDB(hzInstance, message.getConversation().getTarget()); MultiMap<String, WFCMessage.GroupMember> groupMembers = hzInstance.getMultiMap(GROUP_MEMBERS);
} Collection<WFCMessage.GroupMember> members = groupMembers.get(message.getConversation().getTarget());
for (WFCMessage.GroupMember member : members) { if (members == null || members.size() == 0) {
if (member.getMemberId().equals(operatorId)) { members = loadGroupMemberFromDB(hzInstance, message.getConversation().getTarget());
if (member.getType() == GroupMemberType_Manager || member.getType() == ProtoConstants.GroupMemberType.GroupMemberType_Owner) { }
canRecall = true; for (WFCMessage.GroupMember member : members) {
if (member.getMemberId().equals(operatorId)) {
if (member.getType() == GroupMemberType_Manager || member.getType() == ProtoConstants.GroupMemberType.GroupMemberType_Owner) {
isOperatorManager = true;
}
} }
break; if(member.getMemberId().equals(message.getFromUser())) {
senderType = member.getType();
}
}
if(isOperatorManager && senderType != GroupMemberType_Manager && senderType != GroupMemberType_Owner) {
canRecall = true;
} }
} }
} }
@@ -2194,13 +2240,30 @@ public class MemoryMessagesStore implements IMessagesStore {
} }
if (!canRecall) { if (!canRecall) {
return ErrorCode.ERROR_CODE_NOT_RIGHT; if(isExpired) {
return ErrorCode.ERROR_CODE_RECALL_TIME_EXPIRED;
} else {
return ErrorCode.ERROR_CODE_NOT_RIGHT;
}
} }
if(message.getContent().getType() == 80) { if(message.getContent().getType() == 80) {
return ErrorCode.ERROR_CODE_SUCCESS; return ErrorCode.ERROR_CODE_SUCCESS;
} }
if(!StringUtil.isNullOrEmpty(mRecallForwardUrl)) {
OutputRecallMessageData event = new OutputRecallMessageData(OutputMessageData.fromProtoMessage(message, null), operatorId, System.currentTimeMillis(), isAdmin);
m_Server.getCallbackScheduler().execute(() -> {
try {
HttpUtils.httpJsonPost(mRecallForwardUrl, GsonUtil.gson.toJson(event), HttpUtils.HttpPostType.POST_TYPE_Forward_Recall_Callback);
} catch (Exception e) {
e.printStackTrace();
Utility.printExecption(LOG, e, EVENT_CALLBACK_Exception);
}
});
}
JSONObject json = new JSONObject(); JSONObject json = new JSONObject();
json.put("s", message.getFromUser()); json.put("s", message.getFromUser());
json.put("ts", message.getServerTimestamp()); json.put("ts", message.getServerTimestamp());
@@ -2454,6 +2517,28 @@ public class MemoryMessagesStore implements IMessagesStore {
} }
} }
private boolean isOnlineValueEqual(WFCMessage.UserSettingEntry pcentry, String newValue) {
if(pcentry == null) {
return StringUtil.isNullOrEmpty(newValue);
}
String oldValue = pcentry.getValue();
if(StringUtil.isNullOrEmpty(oldValue) && StringUtil.isNullOrEmpty(newValue)) {
return true;
}
if(StringUtil.isNullOrEmpty(oldValue) || StringUtil.isNullOrEmpty(newValue)) {
return false;
}
String[] ssOld = oldValue.split("\\|");
String[] ssNew = newValue.split("\\|");
if(ssOld.length != 4 || ssNew.length != 4 || !ssOld[1].equals(ssNew[1]) || !ssOld[2].equals(ssNew[2]) || !ssOld[3].equals(ssNew[3])) {
return false;
}
return true;
}
@Override @Override
public void updateUserOnlineSetting(MemorySessionStore.Session session, boolean online) { public void updateUserOnlineSetting(MemorySessionStore.Session session, boolean online) {
if(!mMultiPlatformNotification) { if(!mMultiPlatformNotification) {
@@ -2485,14 +2570,8 @@ public class MemoryMessagesStore implements IMessagesStore {
} }
WFCMessage.UserSettingEntry pcentry = getUserSetting(session.getUsername(), kUserSettingPCOnline, "PC"); WFCMessage.UserSettingEntry pcentry = getUserSetting(session.getUsername(), kUserSettingPCOnline, "PC");
if (pcValue != null) { if (!isOnlineValueEqual(pcentry, pcValue)) {
if (pcentry == null || StringUtil.isNullOrEmpty(pcentry.getValue())) { updateUserSettings(session.username, WFCMessage.ModifyUserSettingReq.newBuilder().setScope(kUserSettingPCOnline).setKey("PC").setValue(pcValue==null?"":pcValue).build(), session.clientID);
updateUserSettings(session.username, WFCMessage.ModifyUserSettingReq.newBuilder().setScope(kUserSettingPCOnline).setKey("PC").setValue(pcValue).build(), session.clientID);
}
} else {
if (pcentry != null && !StringUtil.isNullOrEmpty(pcentry.getValue())) {
updateUserSettings(session.username, WFCMessage.ModifyUserSettingReq.newBuilder().setScope(kUserSettingPCOnline).setKey("PC").setValue("").build(), session.clientID);
}
} }
} }
@@ -2685,6 +2764,12 @@ public class MemoryMessagesStore implements IMessagesStore {
String userId = databaseStore.getUserIdByMobile(mobile); String userId = databaseStore.getUserIdByMobile(mobile);
return getUserInfo(userId); return getUserInfo(userId);
} }
@Override
public List<WFCMessage.User> getUserInfoList(int count, int offset) {
return databaseStore.getAllUsers(count, offset);
}
@Override @Override
public List<WFCMessage.User> searchUser(String keyword, int searchType, int page) { public List<WFCMessage.User> searchUser(String keyword, int searchType, int page) {
if (mDisableSearch) { if (mDisableSearch) {
@@ -3022,27 +3107,16 @@ public class MemoryMessagesStore implements IMessagesStore {
} }
} }
MultiMap<String, FriendData> friendsMap = hzInstance.getMultiMap(USER_FRIENDS); FriendData friendData1 = getFriendData(userId, request.getTargetUid());
FriendData friendData1 = null;
Collection<FriendData> friendDatas = friendsMap.get(userId);
if (friendDatas == null || friendDatas.size() == 0) {
friendDatas = loadFriend(friendsMap, userId);
}
for (FriendData fd : friendDatas) {
if (fd.getFriendUid().equals(request.getTargetUid())) {
friendData1 = fd;
break;
}
}
if (friendData1 != null && friendData1.getBlacked() > 0 && !isAdmin) {
return ErrorCode.ERROR_CODE_IN_BLACK_LIST;
}
if (friendData1 != null && friendData1.getState() == 0) { if (friendData1 != null && friendData1.getState() == 0) {
return ErrorCode.ERROR_CODE_ALREADY_FRIENDS; return ErrorCode.ERROR_CODE_ALREADY_FRIENDS;
} }
FriendData friendData2 = getFriendData(request.getTargetUid(), userId);
if (friendData2 != null && friendData2.getBlacked() > 0 && !isAdmin) {
return ErrorCode.ERROR_CODE_IN_BLACK_LIST;
}
WFCMessage.FriendRequest newRequest = WFCMessage.FriendRequest WFCMessage.FriendRequest newRequest = WFCMessage.FriendRequest
.newBuilder() .newBuilder()
.setFromUid(userId) .setFromUid(userId)
@@ -3154,7 +3228,7 @@ public class MemoryMessagesStore implements IMessagesStore {
friendsMap.remove(userId); friendsMap.remove(userId);
friendsMap.remove(request.getTargetUid()); friendsMap.remove(request.getTargetUid());
callbackRelationEvent(userId, request.getTargetUid(), 0, "" + request.getStatus()); callbackRelationEvent(userId, request.getTargetUid(), 0, request.getStatus() == 0?"1":"0");
return ErrorCode.ERROR_CODE_SUCCESS; return ErrorCode.ERROR_CODE_SUCCESS;
} }
@@ -3420,7 +3494,7 @@ public class MemoryMessagesStore implements IMessagesStore {
} }
private String ensureSecretLength(String secret) { private String ensureSecretLength(String secret) {
while ( secret.length() < 16) { while ( secret.length() < AES.keyLen) {
secret += "w"; secret += "w";
secret += secret; secret += secret;
} }
@@ -4214,6 +4288,11 @@ public class MemoryMessagesStore implements IMessagesStore {
return mGroupVisibleQuitKickoffNotification; return mGroupVisibleQuitKickoffNotification;
} }
@Override
public int getGroupForbiddenClientOperation() {
return mGroupForbiddenClientOperation;
}
@Override @Override
public boolean isForwardMessageWithClientInfo() { public boolean isForwardMessageWithClientInfo() {
return mForwardMessageWithClientInfo; return mForwardMessageWithClientInfo;
@@ -4229,6 +4308,11 @@ public class MemoryMessagesStore implements IMessagesStore {
return mChannelCallbackWithClientInfo; return mChannelCallbackWithClientInfo;
} }
@Override
public boolean isRobotAutoAcceptFriendRequest() {
return mFriendRobotAutoAccept;
}
@Override @Override
public List<Integer> getClientForbiddenSendTypes() { public List<Integer> getClientForbiddenSendTypes() {
return mForbiddenClientSendTypes; return mForbiddenClientSendTypes;
@@ -232,18 +232,6 @@ public class Server {
handlers = Collections.emptyList(); handlers = Collections.emptyList();
} }
DBUtil.init(config); DBUtil.init(config);
String strKey = "0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x78,0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x7F";
String[] strs = strKey.split(",");
if(strs.length != 16) {
LOG.error("Key error, it length should be 16");
}
byte[] keys = new byte[16];
for (int i = 0; i < 16; i++) {
keys[i] = (byte)(Integer.parseInt(strs[i].replace("0X", "").replace("0x", ""), 16));
}
AES.init(keys);
LOG.info("Starting Moquette Server. MQTT message interceptors={}", getInterceptorIds(handlers)); LOG.info("Starting Moquette Server. MQTT message interceptors={}", getInterceptorIds(handlers));
@@ -393,9 +381,13 @@ public class Server {
longPort = config.getProperty(BrokerConstants.PORT_PROPERTY_NAME); longPort = config.getProperty(BrokerConstants.PORT_PROPERTY_NAME);
shortPort = config.getProperty(BrokerConstants.HTTP_SERVER_PORT); shortPort = config.getProperty(BrokerConstants.HTTP_SERVER_PORT);
boolean aes256 = Boolean.parseBoolean(config.getProperty(ENCRYPT_AES256, "false"));
MessageShardingUtil.setNodeId(1); MessageShardingUtil.setNodeId(1);
Tokenor.setKey(config.getProperty(BrokerConstants.TOKEN_SECRET_KEY)); Tokenor.setKey(config.getProperty(BrokerConstants.TOKEN_SECRET_KEY));
AES.useAes256(aes256);
String expirTimeStr = config.getProperty(TOKEN_EXPIRE_TIME); String expirTimeStr = config.getProperty(TOKEN_EXPIRE_TIME);
if (!StringUtil.isNullOrEmpty(expirTimeStr)) { if (!StringUtil.isNullOrEmpty(expirTimeStr)) {
try { try {
@@ -116,7 +116,7 @@ public interface IMessagesStore {
ErrorCode modifyGroupInfo(String operator, String groupId, int modifyType, String value, boolean isAdmin); ErrorCode modifyGroupInfo(String operator, String groupId, int modifyType, String value, boolean isAdmin);
ErrorCode modifyGroupMemberAlias(String operator, String groupId, String alias, String memberId, boolean isAdmin); ErrorCode modifyGroupMemberAlias(String operator, String groupId, String alias, String memberId, boolean isAdmin);
ErrorCode modifyGroupMemberExtra(String operator, String groupId, String extra, String memberId, boolean isAdmin); ErrorCode modifyGroupMemberExtra(String operator, String groupId, String extra, String memberId, boolean isAdmin);
List<WFCMessage.GroupInfo> getGroupInfos(List<WFCMessage.UserRequest> requests); List<WFCMessage.GroupInfo> getGroupInfos(List<WFCMessage.UserRequest> requests, String fromUser, boolean isAdmin);
WFCMessage.GroupInfo getGroupInfo(String groupId); WFCMessage.GroupInfo getGroupInfo(String groupId);
Set<String> getUserGroupIds(String userId); Set<String> getUserGroupIds(String userId);
Set<String> getCommonGroupIds(String userId1, String userId2); Set<String> getCommonGroupIds(String userId1, String userId2);
@@ -158,6 +158,8 @@ public interface IMessagesStore {
WFCMessage.User getUserInfoByMobile(String mobile); WFCMessage.User getUserInfoByMobile(String mobile);
List<WFCMessage.User> searchUser(String keyword, int searchType, int page); List<WFCMessage.User> searchUser(String keyword, int searchType, int page);
List<WFCMessage.User> getUserInfoList(int count, int offset);
boolean updateSystemSetting(int id, String value, String desc); boolean updateSystemSetting(int id, String value, String desc);
SystemSettingPojo getSystemSetting(int id); SystemSettingPojo getSystemSetting(int id);
void createChatroom(String chatroomId, WFCMessage.ChatroomInfo chatroomInfo); void createChatroom(String chatroomId, WFCMessage.ChatroomInfo chatroomInfo);
@@ -233,10 +235,14 @@ public interface IMessagesStore {
boolean isAllowRobotCustomGroupNotification(); boolean isAllowRobotCustomGroupNotification();
int getVisibleQuitKickoffNotification(); int getVisibleQuitKickoffNotification();
int getGroupForbiddenClientOperation();
boolean isForwardMessageWithClientInfo(); boolean isForwardMessageWithClientInfo();
boolean isRobotCallbackWithClientInfo(); boolean isRobotCallbackWithClientInfo();
boolean isChannelCallbackWithClientInfo(); boolean isChannelCallbackWithClientInfo();
boolean isRobotAutoAcceptFriendRequest();
List<Integer> getClientForbiddenSendTypes(); List<Integer> getClientForbiddenSendTypes();
List<Integer> getBlackListExceptionTypes(); List<Integer> getBlackListExceptionTypes();
List<Integer> getGroupMuteExceptionTypes(); List<Integer> getGroupMuteExceptionTypes();
@@ -108,7 +108,7 @@ public class ProtocolProcessor {
ConnectionDescriptor descriptor = connectionDescriptors.getConnection(session.getClientID()); ConnectionDescriptor descriptor = connectionDescriptors.getConnection(session.getClientID());
try { try {
if (descriptor != null) { if (descriptor != null) {
processDisconnect(descriptor.getChannel(), true, false); processDisconnect(descriptor.getChannel(), false, false);
} }
} catch (InterruptedException e) { } catch (InterruptedException e) {
e.printStackTrace(); e.printStackTrace();
@@ -608,8 +608,9 @@ public class ProtocolProcessor {
channel.closeFuture(); channel.closeFuture();
//disconnect the session //disconnect the session
if(session != null) {
m_sessionsStore.sessionForClient(clientID).disconnect(session.getUsername(), isDup, isRetain); m_sessionsStore.sessionForClient(clientID).disconnect(session.getUsername(), isDup, isRetain);
}
} }
@@ -650,12 +651,22 @@ public class ProtocolProcessor {
if(connectionDescriptors.removeConnection(oldConnDescr)) { if(connectionDescriptors.removeConnection(oldConnDescr)) {
m_interceptor.notifyClientConnectionLost(clientID, username); m_interceptor.notifyClientConnectionLost(clientID, username);
} }
try {
channel.close();
} catch (Exception e) {
e.printStackTrace();
}
}); });
} else { } else {
ConnectionDescriptor oldConnDescr = new ConnectionDescriptor(clientID, channel); ConnectionDescriptor oldConnDescr = new ConnectionDescriptor(clientID, channel);
if(connectionDescriptors.removeConnection(oldConnDescr)) { if(connectionDescriptors.removeConnection(oldConnDescr)) {
m_interceptor.notifyClientConnectionLost(clientID, username); m_interceptor.notifyClientConnectionLost(clientID, username);
} }
try {
channel.close();
} catch (Exception e) {
e.printStackTrace();
}
} }
} }
@@ -252,6 +252,13 @@ public class Qos1PublishHandler extends QosPublishHandler {
MemorySessionStore.Session session = m_sessionStore.getSession(clientID); MemorySessionStore.Session session = m_sessionStore.getSession(clientID);
payloadContent = AES.AESDecrypt(payloadContent, session.getSecret(), true); payloadContent = AES.AESDecrypt(payloadContent, session.getSecret(), true);
if(payloadContent == null) {
ByteBuf ackPayload = Unpooled.buffer();
ackPayload.ensureWritable(1).writeByte(ERROR_CODE_INVALID_DATA.getCode());
sendPubAck(clientID, messageID, ackPayload, ERROR_CODE_INVALID_DATA);
return;
}
imHandler(clientID, username, imtopic, payloadContent, (errorCode, ackPayload) -> sendPubAck(clientID, messageID, ackPayload, errorCode), ProtoConstants.RequestSourceType.Request_From_User); imHandler(clientID, username, imtopic, payloadContent, (errorCode, ackPayload) -> sendPubAck(clientID, messageID, ackPayload, errorCode), ProtoConstants.RequestSourceType.Request_From_User);
} }
@@ -50,7 +50,8 @@ public class HttpUtils {
POST_TYPE_Channel_Message_Callback, POST_TYPE_Channel_Message_Callback,
POST_TYPE_Forward_Message_Callback, POST_TYPE_Forward_Message_Callback,
POST_TYPE_User_Online_Event_Callback, POST_TYPE_User_Online_Event_Callback,
POST_TYPE_Server_Exception_Callback; POST_TYPE_Server_Exception_Callback,
POST_TYPE_Forward_Recall_Callback;
} }
public static void httpJsonPost(String url, String jsonStr, HttpPostType postType) { public static void httpJsonPost(String url, String jsonStr, HttpPostType postType) {
+2 -2
View File
@@ -20,14 +20,14 @@
<RollingRandomAccessFile name="RollingFileInfo" immediateFlush="false" <RollingRandomAccessFile name="RollingFileInfo" immediateFlush="false"
fileName="${MSG_LOG_HOME}/wildfirechat.log" fileName="${MSG_LOG_HOME}/wildfirechat.log"
filePattern="${MSG_LOG_HOME}/backup/wildfirechat.%d{yyyyMMddHH}.zip"> filePattern="${MSG_LOG_HOME}/backup/wildfirechat.%d{yyyyMMddHHmm}.zip">
<Filters> <Filters>
<ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/> <ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/>
</Filters> </Filters>
<PatternLayout pattern="${pattern}" /> <PatternLayout pattern="${pattern}" />
<Policies> <Policies>
<!-- TimeBasedTriggeringPolicy :时间滚动策略,默认0点小时产生新的文件,interval="6" : 自定义文件滚动时间间隔,每隔6小时产生新文件, modulate="true" : 产生文件是否以0点偏移时间,即6点,12点,18点,0点--> <!-- TimeBasedTriggeringPolicy :时间滚动策略,默认0点小时产生新的文件,interval="6" : 自定义文件滚动时间间隔,每隔6小时产生新文件, modulate="true" : 产生文件是否以0点偏移时间,即6点,12点,18点,0点-->
<!-- <TimeBasedTriggeringPolicy interval="6" modulate="true"/>--> <TimeBasedTriggeringPolicy interval="6" modulate="true"/>
<!-- SizeBasedTriggeringPolicy :文件大小滚动策略--> <!-- SizeBasedTriggeringPolicy :文件大小滚动策略-->
<SizeBasedTriggeringPolicy size="100 MB"/> <SizeBasedTriggeringPolicy size="100 MB"/>
</Policies> </Policies>
+1 -1
View File
@@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>wildfirechat-parent</artifactId> <artifactId>wildfirechat-parent</artifactId>
<groupId>cn.wildfirechat</groupId> <groupId>cn.wildfirechat</groupId>
<version>0.99</version> <version>1.1.5</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@@ -26,6 +26,7 @@ public interface APIPath {
String User_Get_Token = "/admin/user/get_token"; String User_Get_Token = "/admin/user/get_token";
String User_Update_Block_Status = "/admin/user/update_block_status"; String User_Update_Block_Status = "/admin/user/update_block_status";
String User_Get_Info = "/admin/user/get_info"; String User_Get_Info = "/admin/user/get_info";
String User_Get_All = "/admin/user/all";
String User_Get_Robot_Info = "/admin/user/get_robot_info"; String User_Get_Robot_Info = "/admin/user/get_robot_info";
String User_Get_Blocked_List = "/admin/user/get_blocked_list"; String User_Get_Blocked_List = "/admin/user/get_blocked_list";
String User_Check_Block_Status = "/admin/user/check_block_status"; String User_Check_Block_Status = "/admin/user/check_block_status";
@@ -68,6 +69,7 @@ public interface APIPath {
String Group_Get_Info = "/admin/group/get_info"; String Group_Get_Info = "/admin/group/get_info";
String Group_Modify_Info = "/admin/group/modify"; String Group_Modify_Info = "/admin/group/modify";
String Group_Member_List = "/admin/group/member/list"; String Group_Member_List = "/admin/group/member/list";
String Group_Member_Get = "/admin/group/member/get";
String Group_Member_Add = "/admin/group/member/add"; String Group_Member_Add = "/admin/group/member/add";
String Group_Member_Kickoff = "/admin/group/member/del"; String Group_Member_Kickoff = "/admin/group/member/del";
String Group_Member_Quit = "/admin/group/member/quit"; String Group_Member_Quit = "/admin/group/member/quit";
@@ -90,10 +92,14 @@ public interface APIPath {
String Health = "/admin/health"; String Health = "/admin/health";
String Conference_List = "/admin/conference/list"; String Conference_List = "/admin/conference/list";
String Conference_Exist = "/admin/conference/exist";
String Conference_List_Participant = "/admin/conference/list_participant"; String Conference_List_Participant = "/admin/conference/list_participant";
String Conference_Create = "/admin/conference/create"; String Conference_Create = "/admin/conference/create";
String Conference_Destroy = "/admin/conference/destroy"; String Conference_Destroy = "/admin/conference/destroy";
String Conference_Recording = "/admin/conference/recording"; String Conference_Recording = "/admin/conference/recording";
String Conference_Rtp_Forward = "/admin/conference/rtp_forward";
String Conference_Stop_Rtp_Forward = "/admin/conference/stop_rtp_forward";
String Conference_List_Rtp_Forward = "/admin/conference/list_rtp_forward";
String Channel_User_Info = "/channel/user_info"; String Channel_User_Info = "/channel/user_info";
String Channel_Update_Profile = "/channel/update_profile"; String Channel_Update_Profile = "/channel/update_profile";
@@ -101,6 +107,7 @@ public interface APIPath {
String Channel_Message_Send = "/channel/message/send"; String Channel_Message_Send = "/channel/message/send";
String Channel_Subscribe = "/channel/subscribe"; String Channel_Subscribe = "/channel/subscribe";
String Channel_Subscriber_List = "/channel/subscriber_list"; String Channel_Subscriber_List = "/channel/subscriber_list";
String Channel_Is_Subscriber = "/channel/is_subscriber";
String Channel_Application_Get_UserInfo = "/channel/application/get_user_info"; String Channel_Application_Get_UserInfo = "/channel/application/get_user_info";
String Robot_User_Info = "/robot/user_info"; String Robot_User_Info = "/robot/user_info";
@@ -117,6 +124,7 @@ public interface APIPath {
String Robot_Group_Dismiss = "/robot/group/del"; String Robot_Group_Dismiss = "/robot/group/del";
String Robot_Group_Get_Info = "/robot/group/get_info"; String Robot_Group_Get_Info = "/robot/group/get_info";
String Robot_Group_Member_List = "/robot/group/member/list"; String Robot_Group_Member_List = "/robot/group/member/list";
String Robot_Group_Member_Get = "/robot/group/member/get";
String Robot_Group_Member_Kickoff = "/robot/group/member/del"; String Robot_Group_Member_Kickoff = "/robot/group/member/del";
String Robot_Group_Modify_Info = "/robot/group/modify"; String Robot_Group_Modify_Info = "/robot/group/modify";
String Robot_Group_Set_Member_Alias = "/robot/group/member/set_alias"; String Robot_Group_Set_Member_Alias = "/robot/group/member/set_alias";
@@ -48,6 +48,7 @@ public enum ErrorCode {
ERROR_CODE_NOT_YOUR_LOCKED(26, "unload failure, not your lock"), ERROR_CODE_NOT_YOUR_LOCKED(26, "unload failure, not your lock"),
ERROR_CODE_ROBOT_NO_TOKEN(27, "robot no token"), ERROR_CODE_ROBOT_NO_TOKEN(27, "robot no token"),
ERROR_CODE_WS_NOT_CONFIGURED_CORRECTLY(28, "ws not configured correctly"), ERROR_CODE_WS_NOT_CONFIGURED_CORRECTLY(28, "ws not configured correctly"),
ERROR_CODE_TIME_INCONSISTENT(30, "time inconsistent"),
ERROR_CODE_CONFERENCE_ROOM_NOT_EXIST(60, "conference room not exist"), ERROR_CODE_CONFERENCE_ROOM_NOT_EXIST(60, "conference room not exist"),
ERROR_CODE_CONFERENCE_SERVICE_NOT_AVAILABLE(61, "conference service not available"), ERROR_CODE_CONFERENCE_SERVICE_NOT_AVAILABLE(61, "conference service not available"),
@@ -61,6 +62,8 @@ public enum ErrorCode {
ERROR_CODE_SECRET_CHAT_MO_DISABLED(86, "origin side disable secret chat"), ERROR_CODE_SECRET_CHAT_MO_DISABLED(86, "origin side disable secret chat"),
ERROR_CODE_SECRET_CHAT_MT_DISABLED(87, "target side disable secret chat"), ERROR_CODE_SECRET_CHAT_MT_DISABLED(87, "target side disable secret chat"),
ERROR_CODE_CONFERENCE_ERROR(90, "Conference server response error"),
ERROR_CODE_FUNCTION_DISABLED(220, "function disabled"), ERROR_CODE_FUNCTION_DISABLED(220, "function disabled"),
ERROR_CODE_CHANNEL_NO_EXIST(236, "channel no exist"), ERROR_CODE_CHANNEL_NO_EXIST(236, "channel no exist"),
@@ -72,7 +75,7 @@ public enum ErrorCode {
ERROR_CODE_SENSITIVE_MATCHED(242, "sensitive matched"), ERROR_CODE_SENSITIVE_MATCHED(242, "sensitive matched"),
ERROR_CODE_SIGN_EXPIRED(243, "sign expired"), ERROR_CODE_SIGN_EXPIRED(243, "sign expired"),
ERROR_CODE_AUTH_FAILURE(244, "auth failure"), ERROR_CODE_AUTH_FAILURE(244, "auth failure"),
ERROR_CODE_CLIENT_COUNT_OUT_OF_LIMIT(245, "client count out of limit"), ERROR_CODE_USER_BLOCKED(245, "user is blocked"),
ERROR_CODE_IN_BLACK_LIST(246, "user in black list"), ERROR_CODE_IN_BLACK_LIST(246, "user in black list"),
ERROR_CODE_FORBIDDEN_SEND_MSG(247, "forbidden send msg globally"), ERROR_CODE_FORBIDDEN_SEND_MSG(247, "forbidden send msg globally"),
ERROR_CODE_NOT_RIGHT(248, "no right to operate"), ERROR_CODE_NOT_RIGHT(248, "no right to operate"),
@@ -3,5 +3,7 @@ package cn.wildfirechat.pojos;
public class ConferenceLeaveEvent { public class ConferenceLeaveEvent {
public String userId; public String userId;
public String roomId; public String roomId;
public boolean rejoin;
public boolean kicked;
public boolean screenSharing; public boolean screenSharing;
} }
@@ -65,6 +65,9 @@ public class InputCreateGroup extends InputGroupBase {
if(group_info.max_member_count > 0) { if(group_info.max_member_count > 0) {
groupInfoBuilder.setMaxMemberCount(group_info.max_member_count); groupInfoBuilder.setMaxMemberCount(group_info.max_member_count);
} }
if(group_info.isSuper_group()) {
groupInfoBuilder.setSuperGroup(1);
}
groupBuilder.setGroupInfo(groupInfoBuilder); groupBuilder.setGroupInfo(groupInfoBuilder);
if(group.getMembers() != null) { if(group.getMembers() != null) {
@@ -0,0 +1,30 @@
/*
* 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 InputGetGroupMember {
private String groupId;
private String memberId;
public String getGroupId() {
return groupId;
}
public void setGroupId(String groupId) {
this.groupId = groupId;
}
public String getMemberId() {
return memberId;
}
public void setMemberId(String memberId) {
this.memberId = memberId;
}
}
@@ -0,0 +1,6 @@
package cn.wildfirechat.pojos;
public class InputGetUserList {
public int count;
public int offset;
}
@@ -0,0 +1,7 @@
package cn.wildfirechat.pojos;
import java.util.List;
public class OutputGetUserList {
public List<InputOutputUserInfo> userInfoList;
}
@@ -0,0 +1,58 @@
/*
* 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 OutputRecallMessageData {
private OutputMessageData message;
private String userId;
private long timestamp;
private boolean isAdmin;
public OutputRecallMessageData() {
}
public OutputRecallMessageData(OutputMessageData message, String userId, long timestamp, boolean isAdmin) {
this.message = message;
this.userId = userId;
this.timestamp = timestamp;
this.isAdmin = isAdmin;
}
public OutputMessageData getMessage() {
return message;
}
public void setMessage(OutputMessageData message) {
this.message = message;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public long getTimestamp() {
return timestamp;
}
public void setTimestamp(long timestamp) {
this.timestamp = timestamp;
}
public boolean isAdmin() {
return isAdmin;
}
public void setAdmin(boolean admin) {
isAdmin = admin;
}
}
@@ -1,6 +1,15 @@
package cn.wildfirechat.pojos; package cn.wildfirechat.pojos;
import java.util.List;
public class PojoConferenceParticipant { public class PojoConferenceParticipant {
public static class Stream {
public String type;
public String mid;
public String codec;
}
public String userId; public String userId;
public boolean publishing; public boolean publishing;
public List<Stream> streams;
} }
@@ -0,0 +1,28 @@
package cn.wildfirechat.pojos;
public class PojoConferenceRtpForwardReq {
public String roomId;
public String publisherId;
public String host;
public int audioPort;
public int audioPt;
public long audioSSRC;
public int videoPort;
public int videoPt;
public long videoSSRC;
public PojoConferenceRtpForwardReq() {
}
public PojoConferenceRtpForwardReq(String roomId, String publisherId, String host, int audioPort, int audioPt, long audioSSRC, int videoPort, int videoPt, long videoSSRC) {
this.roomId = roomId;
this.publisherId = publisherId;
this.host = host;
this.audioPort = audioPort;
this.audioPt = audioPt;
this.audioSSRC = audioSSRC;
this.videoPort = videoPort;
this.videoPt = videoPt;
this.videoSSRC = videoSSRC;
}
}
@@ -0,0 +1,21 @@
package cn.wildfirechat.pojos;
import java.util.List;
public class PojoConferenceRtpForwarders {
public static class RtpForwarder {
public static class RtpStream {
public long streamId;
public String type;
public String host;
public int port;
public long ssrc;
public int pt;
}
public String publisherId;
public List<RtpStream> streams;
}
public String roomId;
public List<RtpForwarder> forwarders;
}
@@ -0,0 +1,16 @@
package cn.wildfirechat.pojos;
public class PojoConferenceStopRtpForwardReq {
public String roomId;
public String publisherId;
public long streamId;
public PojoConferenceStopRtpForwardReq() {
}
public PojoConferenceStopRtpForwardReq(String roomId, String publisherId, long streamId) {
this.roomId = roomId;
this.publisherId = publisherId;
this.streamId = streamId;
}
}
@@ -21,6 +21,7 @@ public class PojoGroupInfo {
int searchable; int searchable;
int max_member_count; int max_member_count;
int history_message; int history_message;
boolean super_group;
public String getTarget_id() { public String getTarget_id() {
return target_id; return target_id;
@@ -117,4 +118,12 @@ public class PojoGroupInfo {
public void setHistory_message(int history_message) { public void setHistory_message(int history_message) {
this.history_message = history_message; this.history_message = history_message;
} }
public boolean isSuper_group() {
return super_group;
}
public void setSuper_group(boolean super_group) {
this.super_group = super_group;
}
} }
@@ -9,6 +9,7 @@ public class ProtoConstants {
int ConversationType_ChatRoom = 2; int ConversationType_ChatRoom = 2;
int ConversationType_Channel = 3; int ConversationType_Channel = 3;
int ConversationType_Things = 4; int ConversationType_Things = 4;
int ConversationType_SecretChat = 5;
} }
//message GroupInfo -> type //message GroupInfo -> type
@@ -292,6 +293,34 @@ public class ProtoConstants {
int ApplicationType_Admin = 2; int ApplicationType_Admin = 2;
} }
//禁止客户端群操作。
// 第1位是禁止创建群组,
// 第2位是禁止销毁群组,
// 3位禁止加入群,
// 4位禁止退出群,
// 5位禁止邀请群成员,
// 6位禁止移出群成员,
// 7位禁止转移群
// 8位禁止设置群管理员
// 9位禁止允许群成员(专业版支持),
// 10位禁止群禁言
// 11位禁止修改群组信息,
// 12位禁止群成员禁言(专业版支持)
public interface ForbiddenClientGroupOperationMask {
int Forbidden_Create_Group = 0x01;
int Forbidden_Dismiss_Group = 0x02;
int Forbidden_Join_Group = 0x04;
int Forbidden_Quit_Group = 0x08;
int Forbidden_Invite_Group_Member = 0x10;
int Forbidden_Kickoff_Group_Member = 0x20;
int Forbidden_Transfer_Group = 0x40;
int Forbidden_Set_Group_Manage = 0x80;
int Forbidden_Allow_Group_Member = 0x100;
int Forbidden_Mute_Group = 0x200;
int Forbidden_Modify_Group_Info = 0x400;
int Forbidden_Mute_Group_Member = 0x800;
}
public static final int MESSAGE_CONTENT_TYPE_CREATE_GROUP = 104; public static final int MESSAGE_CONTENT_TYPE_CREATE_GROUP = 104;
public static final int MESSAGE_CONTENT_TYPE_ADD_GROUP_MEMBER = 105; public static final int MESSAGE_CONTENT_TYPE_ADD_GROUP_MEMBER = 105;
public static final int MESSAGE_CONTENT_TYPE_KICKOF_GROUP_MEMBER = 106; public static final int MESSAGE_CONTENT_TYPE_KICKOF_GROUP_MEMBER = 106;
@@ -1641,6 +1641,16 @@ public final class WFCMessage {
* <code>optional int32 history_message = 15;</code> * <code>optional int32 history_message = 15;</code>
*/ */
int getHistoryMessage(); int getHistoryMessage();
// optional int32 super_group = 16;
/**
* <code>optional int32 super_group = 16;</code>
*/
boolean hasSuperGroup();
/**
* <code>optional int32 super_group = 16;</code>
*/
int getSuperGroup();
} }
/** /**
* Protobuf type {@code GroupInfo} * Protobuf type {@code GroupInfo}
@@ -1768,6 +1778,11 @@ public final class WFCMessage {
historyMessage_ = input.readInt32(); historyMessage_ = input.readInt32();
break; break;
} }
case 128: {
bitField0_ |= 0x00008000;
superGroup_ = input.readInt32();
break;
}
} }
} }
} catch (com.google.protobuf.InvalidProtocolBufferException e) { } catch (com.google.protobuf.InvalidProtocolBufferException e) {
@@ -2183,6 +2198,22 @@ public final class WFCMessage {
return historyMessage_; return historyMessage_;
} }
// optional int32 super_group = 16;
public static final int SUPER_GROUP_FIELD_NUMBER = 16;
private int superGroup_;
/**
* <code>optional int32 super_group = 16;</code>
*/
public boolean hasSuperGroup() {
return ((bitField0_ & 0x00008000) == 0x00008000);
}
/**
* <code>optional int32 super_group = 16;</code>
*/
public int getSuperGroup() {
return superGroup_;
}
private void initFields() { private void initFields() {
targetId_ = ""; targetId_ = "";
name_ = ""; name_ = "";
@@ -2199,6 +2230,7 @@ public final class WFCMessage {
searchable_ = 0; searchable_ = 0;
maxMemberCount_ = 0; maxMemberCount_ = 0;
historyMessage_ = 0; historyMessage_ = 0;
superGroup_ = 0;
} }
private byte memoizedIsInitialized = -1; private byte memoizedIsInitialized = -1;
public final boolean isInitialized() { public final boolean isInitialized() {
@@ -2265,6 +2297,9 @@ public final class WFCMessage {
if (((bitField0_ & 0x00004000) == 0x00004000)) { if (((bitField0_ & 0x00004000) == 0x00004000)) {
output.writeInt32(15, historyMessage_); output.writeInt32(15, historyMessage_);
} }
if (((bitField0_ & 0x00008000) == 0x00008000)) {
output.writeInt32(16, superGroup_);
}
getUnknownFields().writeTo(output); getUnknownFields().writeTo(output);
} }
@@ -2334,6 +2369,10 @@ public final class WFCMessage {
size += com.google.protobuf.CodedOutputStream size += com.google.protobuf.CodedOutputStream
.computeInt32Size(15, historyMessage_); .computeInt32Size(15, historyMessage_);
} }
if (((bitField0_ & 0x00008000) == 0x00008000)) {
size += com.google.protobuf.CodedOutputStream
.computeInt32Size(16, superGroup_);
}
size += getUnknownFields().getSerializedSize(); size += getUnknownFields().getSerializedSize();
memoizedSerializedSize = size; memoizedSerializedSize = size;
return size; return size;
@@ -2480,6 +2519,8 @@ public final class WFCMessage {
bitField0_ = (bitField0_ & ~0x00002000); bitField0_ = (bitField0_ & ~0x00002000);
historyMessage_ = 0; historyMessage_ = 0;
bitField0_ = (bitField0_ & ~0x00004000); bitField0_ = (bitField0_ & ~0x00004000);
superGroup_ = 0;
bitField0_ = (bitField0_ & ~0x00008000);
return this; return this;
} }
@@ -2568,6 +2609,10 @@ public final class WFCMessage {
to_bitField0_ |= 0x00004000; to_bitField0_ |= 0x00004000;
} }
result.historyMessage_ = historyMessage_; result.historyMessage_ = historyMessage_;
if (((from_bitField0_ & 0x00008000) == 0x00008000)) {
to_bitField0_ |= 0x00008000;
}
result.superGroup_ = superGroup_;
result.bitField0_ = to_bitField0_; result.bitField0_ = to_bitField0_;
onBuilt(); onBuilt();
return result; return result;
@@ -2639,6 +2684,9 @@ public final class WFCMessage {
if (other.hasHistoryMessage()) { if (other.hasHistoryMessage()) {
setHistoryMessage(other.getHistoryMessage()); setHistoryMessage(other.getHistoryMessage());
} }
if (other.hasSuperGroup()) {
setSuperGroup(other.getSuperGroup());
}
this.mergeUnknownFields(other.getUnknownFields()); this.mergeUnknownFields(other.getUnknownFields());
return this; return this;
} }
@@ -3374,6 +3422,39 @@ public final class WFCMessage {
return this; return this;
} }
// optional int32 super_group = 16;
private int superGroup_ ;
/**
* <code>optional int32 super_group = 16;</code>
*/
public boolean hasSuperGroup() {
return ((bitField0_ & 0x00008000) == 0x00008000);
}
/**
* <code>optional int32 super_group = 16;</code>
*/
public int getSuperGroup() {
return superGroup_;
}
/**
* <code>optional int32 super_group = 16;</code>
*/
public Builder setSuperGroup(int value) {
bitField0_ |= 0x00008000;
superGroup_ = value;
onChanged();
return this;
}
/**
* <code>optional int32 super_group = 16;</code>
*/
public Builder clearSuperGroup() {
bitField0_ = (bitField0_ & ~0x00008000);
superGroup_ = 0;
onChanged();
return this;
}
// @@protoc_insertion_point(builder_scope:GroupInfo) // @@protoc_insertion_point(builder_scope:GroupInfo)
} }
@@ -67224,179 +67305,180 @@ public final class WFCMessage {
"dRequest\022\022\n\ntarget_uid\030\001 \002(\t\022\016\n\006reason\030\002" + "dRequest\022\022\n\ntarget_uid\030\001 \002(\t\022\016\n\006reason\030\002" +
" \002(\t\022\r\n\005extra\030\003 \001(\t\":\n\014Conversation\022\014\n\004t" + " \002(\t\022\r\n\005extra\030\003 \001(\t\":\n\014Conversation\022\014\n\004t" +
"ype\030\001 \002(\005\022\016\n\006target\030\002 \002(\t\022\014\n\004line\030\003 \002(\005\"" + "ype\030\001 \002(\005\022\016\n\006target\030\002 \002(\t\022\014\n\004line\030\003 \002(\005\"" +
"\253\002\n\tGroupInfo\022\021\n\ttarget_id\030\001 \001(\t\022\014\n\004name" + "\300\002\n\tGroupInfo\022\021\n\ttarget_id\030\001 \001(\t\022\014\n\004name" +
"\030\002 \002(\t\022\020\n\010portrait\030\003 \001(\t\022\r\n\005owner\030\004 \001(\t\022" + "\030\002 \002(\t\022\020\n\010portrait\030\003 \001(\t\022\r\n\005owner\030\004 \001(\t\022" +
"\014\n\004type\030\005 \002(\005\022\024\n\014member_count\030\006 \001(\005\022\r\n\005e" + "\014\n\004type\030\005 \002(\005\022\024\n\014member_count\030\006 \001(\005\022\r\n\005e" +
"xtra\030\007 \001(\t\022\021\n\tupdate_dt\030\010 \001(\003\022\030\n\020member_" + "xtra\030\007 \001(\t\022\021\n\tupdate_dt\030\010 \001(\003\022\030\n\020member_" +
"update_dt\030\t \001(\003\022\014\n\004mute\030\n \001(\005\022\021\n\tjoin_ty" + "update_dt\030\t \001(\003\022\014\n\004mute\030\n \001(\005\022\021\n\tjoin_ty" +
"pe\030\013 \001(\005\022\024\n\014private_chat\030\014 \001(\005\022\022\n\nsearch", "pe\030\013 \001(\005\022\024\n\014private_chat\030\014 \001(\005\022\022\n\nsearch",
"able\030\r \001(\005\022\030\n\020max_member_count\030\016 \001(\005\022\027\n\017" + "able\030\r \001(\005\022\030\n\020max_member_count\030\016 \001(\005\022\027\n\017" +
"history_message\030\017 \001(\005\"r\n\013GroupMember\022\021\n\t" + "history_message\030\017 \001(\005\022\023\n\013super_group\030\020 \001" +
"member_id\030\001 \002(\t\022\r\n\005alias\030\002 \001(\t\022\014\n\004type\030\003" + "(\005\"r\n\013GroupMember\022\021\n\tmember_id\030\001 \002(\t\022\r\n\005" +
" \002(\005\022\021\n\tupdate_dt\030\004 \001(\003\022\021\n\tcreate_dt\030\005 \001" + "alias\030\002 \001(\t\022\014\n\004type\030\003 \002(\005\022\021\n\tupdate_dt\030\004" +
"(\003\022\r\n\005extra\030\006 \001(\t\"F\n\005Group\022\036\n\ngroup_info" + " \001(\003\022\021\n\tcreate_dt\030\005 \001(\003\022\r\n\005extra\030\006 \001(\t\"F" +
"\030\001 \002(\0132\n.GroupInfo\022\035\n\007members\030\002 \003(\0132\014.Gr" + "\n\005Group\022\036\n\ngroup_info\030\001 \002(\0132\n.GroupInfo\022" +
"oupMember\"\313\001\n\013ChannelMenu\022\014\n\004type\030\001 \002(\t\022" + "\035\n\007members\030\002 \003(\0132\014.GroupMember\"\313\001\n\013Chann" +
"\014\n\004name\030\002 \002(\t\022\013\n\003key\030\003 \001(\t\022\013\n\003url\030\004 \001(\t\022" + "elMenu\022\014\n\004type\030\001 \002(\t\022\014\n\004name\030\002 \002(\t\022\013\n\003ke" +
"\020\n\010media_id\030\005 \001(\t\022\022\n\narticle_id\030\006 \001(\t\022\016\n" + "y\030\003 \001(\t\022\013\n\003url\030\004 \001(\t\022\020\n\010media_id\030\005 \001(\t\022\022" +
"\006app_id\030\007 \001(\t\022\020\n\010app_page\030\010 \001(\t\022\036\n\010sub_m", "\n\narticle_id\030\006 \001(\t\022\016\n\006app_id\030\007 \001(\t\022\020\n\010ap",
"enu\030\t \003(\0132\014.ChannelMenu\022\017\n\007menu_id\030\n \001(\t" + "p_page\030\010 \001(\t\022\036\n\010sub_menu\030\t \003(\0132\014.Channel" +
"\022\r\n\005extra\030\013 \001(\t\"-\n\017ChannelMenuList\022\032\n\004me" + "Menu\022\017\n\007menu_id\030\n \001(\t\022\r\n\005extra\030\013 \001(\t\"-\n\017" +
"nu\030\001 \003(\0132\014.ChannelMenu\"\340\001\n\013ChannelInfo\022\021" + "ChannelMenuList\022\032\n\004menu\030\001 \003(\0132\014.ChannelM" +
"\n\ttarget_id\030\001 \001(\t\022\014\n\004name\030\002 \002(\t\022\020\n\010portr" + "enu\"\340\001\n\013ChannelInfo\022\021\n\ttarget_id\030\001 \001(\t\022\014" +
"ait\030\003 \001(\t\022\r\n\005owner\030\004 \001(\t\022\016\n\006status\030\005 \001(\005" + "\n\004name\030\002 \002(\t\022\020\n\010portrait\030\003 \001(\t\022\r\n\005owner\030" +
"\022\014\n\004desc\030\006 \001(\t\022\r\n\005extra\030\007 \001(\t\022\021\n\tupdate_" + "\004 \001(\t\022\016\n\006status\030\005 \001(\005\022\014\n\004desc\030\006 \001(\t\022\r\n\005e" +
"dt\030\010 \001(\003\022\016\n\006secret\030\t \001(\t\022\020\n\010callback\030\n \001" + "xtra\030\007 \001(\t\022\021\n\tupdate_dt\030\010 \001(\003\022\016\n\006secret\030" +
"(\t\022\021\n\tautomatic\030\013 \001(\005\022\032\n\004menu\030\014 \003(\0132\014.Ch" + "\t \001(\t\022\020\n\010callback\030\n \001(\t\022\021\n\tautomatic\030\013 \001" +
"annelMenu\"D\n\021ModifyChannelInfo\022\022\n\nchanne" + "(\005\022\032\n\004menu\030\014 \003(\0132\014.ChannelMenu\"D\n\021Modify" +
"l_id\030\001 \002(\t\022\014\n\004type\030\002 \002(\005\022\r\n\005value\030\003 \002(\t\"", "ChannelInfo\022\022\n\nchannel_id\030\001 \002(\t\022\014\n\004type\030",
"8\n\017TransferChannel\022\022\n\nchannel_id\030\001 \002(\t\022\021" + "\002 \002(\005\022\r\n\005value\030\003 \002(\t\"8\n\017TransferChannel\022" +
"\n\tnew_owner\030\002 \002(\t\"3\n\017PullChannelInfo\022\022\n\n" + "\022\n\nchannel_id\030\001 \002(\t\022\021\n\tnew_owner\030\002 \002(\t\"3" +
"channel_id\030\001 \002(\t\022\014\n\004head\030\002 \002(\003\"H\n\023PullCh" + "\n\017PullChannelInfo\022\022\n\nchannel_id\030\001 \002(\t\022\014\n" +
"annelListener\022\022\n\nchannel_id\030\001 \002(\t\022\016\n\006off" + "\004head\030\002 \002(\003\"H\n\023PullChannelListener\022\022\n\nch" +
"set\030\002 \002(\005\022\r\n\005count\030\003 \002(\005\"R\n\031PullChannelL" + "annel_id\030\001 \002(\t\022\016\n\006offset\030\002 \002(\005\022\r\n\005count\030" +
"istenerResult\022\023\n\013total_count\030\001 \002(\005\022\016\n\006of" + "\003 \002(\005\"R\n\031PullChannelListenerResult\022\023\n\013to" +
"fset\030\002 \002(\005\022\020\n\010listener\030\003 \003(\t\"3\n\rListenCh" + "tal_count\030\001 \002(\005\022\016\n\006offset\030\002 \002(\005\022\020\n\010liste" +
"annel\022\022\n\nchannel_id\030\001 \002(\t\022\016\n\006listen\030\002 \002(" + "ner\030\003 \003(\t\"3\n\rListenChannel\022\022\n\nchannel_id" +
"\005\"E\n\023SearchChannelResult\022\035\n\007channel\030\001 \003(" + "\030\001 \002(\t\022\016\n\006listen\030\002 \002(\005\"E\n\023SearchChannelR" +
"\0132\014.ChannelInfo\022\017\n\007keyword\030\002 \002(\t\"\235\002\n\016Mes", "esult\022\035\n\007channel\030\001 \003(\0132\014.ChannelInfo\022\017\n\007",
"sageContent\022\014\n\004type\030\001 \002(\005\022\032\n\022searchable_" + "keyword\030\002 \002(\t\"\235\002\n\016MessageContent\022\014\n\004type" +
"content\030\002 \001(\t\022\024\n\014push_content\030\003 \001(\t\022\017\n\007c" + "\030\001 \002(\005\022\032\n\022searchable_content\030\002 \001(\t\022\024\n\014pu" +
"ontent\030\004 \001(\t\022\014\n\004data\030\005 \001(\014\022\021\n\tmediaType\030" + "sh_content\030\003 \001(\t\022\017\n\007content\030\004 \001(\t\022\014\n\004dat" +
"\006 \001(\005\022\026\n\016remoteMediaUrl\030\007 \001(\t\022\024\n\014persist" + "a\030\005 \001(\014\022\021\n\tmediaType\030\006 \001(\005\022\026\n\016remoteMedi" +
"_flag\030\010 \001(\005\022\027\n\017expire_duration\030\t \001(\005\022\026\n\016" + "aUrl\030\007 \001(\t\022\024\n\014persist_flag\030\010 \001(\005\022\027\n\017expi" +
"mentioned_type\030\n \001(\005\022\030\n\020mentioned_target" + "re_duration\030\t \001(\005\022\026\n\016mentioned_type\030\n \001(" +
"\030\013 \003(\t\022\r\n\005extra\030\014 \001(\t\022\021\n\tpush_data\030\r \001(\t" + "\005\022\030\n\020mentioned_target\030\013 \003(\t\022\r\n\005extra\030\014 \001" +
"\"\226\001\n\025AddGroupMemberRequest\022\020\n\010group_id\030\001" + "(\t\022\021\n\tpush_data\030\r \001(\t\"\226\001\n\025AddGroupMember" +
" \002(\t\022\"\n\014added_member\030\002 \003(\0132\014.GroupMember" + "Request\022\020\n\010group_id\030\001 \002(\t\022\"\n\014added_membe" +
"\022\017\n\007to_line\030\003 \003(\005\022\'\n\016notify_content\030\004 \001(", "r\030\002 \003(\0132\014.GroupMember\022\017\n\007to_line\030\003 \003(\005\022\'",
"\0132\017.MessageContent\022\r\n\005extra\030\005 \001(\t\"{\n\022Cre" + "\n\016notify_content\030\004 \001(\0132\017.MessageContent\022" +
"ateGroupRequest\022\025\n\005group\030\001 \002(\0132\006.Group\022\017" + "\r\n\005extra\030\005 \001(\t\"{\n\022CreateGroupRequest\022\025\n\005" +
"\n\007to_line\030\002 \003(\005\022\'\n\016notify_content\030\003 \001(\0132" + "group\030\001 \002(\0132\006.Group\022\017\n\007to_line\030\002 \003(\005\022\'\n\016" +
"\017.MessageContent\022\024\n\014member_extra\030\004 \001(\t\"a" + "notify_content\030\003 \001(\0132\017.MessageContent\022\024\n" +
"\n\023DismissGroupRequest\022\020\n\010group_id\030\001 \002(\t\022" + "\014member_extra\030\004 \001(\t\"a\n\023DismissGroupReque" +
"\017\n\007to_line\030\002 \003(\005\022\'\n\016notify_content\030\003 \001(\013" + "st\022\020\n\010group_id\030\001 \002(\t\022\017\n\007to_line\030\002 \003(\005\022\'\n" +
"2\017.MessageContent\"\245\001\n\rFriendRequest\022\020\n\010f" + "\016notify_content\030\003 \001(\0132\017.MessageContent\"\245" +
"rom_uid\030\001 \001(\t\022\016\n\006to_uid\030\002 \002(\t\022\016\n\006reason\030" + "\001\n\rFriendRequest\022\020\n\010from_uid\030\001 \001(\t\022\016\n\006to" +
"\003 \002(\t\022\016\n\006status\030\004 \001(\005\022\021\n\tupdate_dt\030\005 \001(\003" + "_uid\030\002 \002(\t\022\016\n\006reason\030\003 \002(\t\022\016\n\006status\030\004 \001" +
"\022\030\n\020from_read_status\030\006 \001(\010\022\026\n\016to_read_st", "(\005\022\021\n\tupdate_dt\030\005 \001(\003\022\030\n\020from_read_statu",
"atus\030\007 \001(\010\022\r\n\005extra\030\010 \001(\t\"#\n\rGeneralResu" + "s\030\006 \001(\010\022\026\n\016to_read_status\030\007 \001(\010\022\r\n\005extra" +
"lt\022\022\n\nerror_code\030\001 \002(\005\"?\n\025GetUploadToken" + "\030\010 \001(\t\"#\n\rGeneralResult\022\022\n\nerror_code\030\001 " +
"Request\022\022\n\nmedia_type\030\001 \002(\005\022\022\n\nmedia_pat" + "\002(\005\"?\n\025GetUploadTokenRequest\022\022\n\nmedia_ty" +
"h\030\002 \002(\t\"S\n\024GetUploadTokenResult\022\016\n\006domai" + "pe\030\001 \002(\005\022\022\n\nmedia_path\030\002 \002(\t\"S\n\024GetUploa" +
"n\030\001 \002(\t\022\r\n\005token\030\002 \002(\t\022\016\n\006server\030\003 \002(\t\022\014" + "dTokenResult\022\016\n\006domain\030\001 \002(\t\022\r\n\005token\030\002 " +
"\n\004port\030\004 \001(\005\"H\n\023HandleFriendRequest\022\022\n\nt" + "\002(\t\022\016\n\006server\030\003 \002(\t\022\014\n\004port\030\004 \001(\005\"H\n\023Han" +
"arget_uid\030\001 \002(\t\022\016\n\006status\030\002 \002(\005\022\r\n\005extra" + "dleFriendRequest\022\022\n\ntarget_uid\030\001 \002(\t\022\016\n\006" +
"\030\003 \001(\t\"\023\n\005IDBuf\022\n\n\002id\030\001 \002(\t\"\027\n\tIDListBuf" + "status\030\002 \002(\005\022\r\n\005extra\030\003 \001(\t\"\023\n\005IDBuf\022\n\n\002" +
"\022\n\n\002id\030\001 \003(\t\"\256\001\n\007Message\022#\n\014conversation" + "id\030\001 \002(\t\"\027\n\tIDListBuf\022\n\n\002id\030\001 \003(\t\"\256\001\n\007Me" +
"\030\001 \002(\0132\r.Conversation\022\021\n\tfrom_user\030\002 \002(\t", "ssage\022#\n\014conversation\030\001 \002(\0132\r.Conversati",
"\022 \n\007content\030\003 \002(\0132\017.MessageContent\022\022\n\nme" + "on\022\021\n\tfrom_user\030\002 \002(\t\022 \n\007content\030\003 \002(\0132\017" +
"ssage_id\030\004 \001(\003\022\030\n\020server_timestamp\030\005 \001(\003" + ".MessageContent\022\022\n\nmessage_id\030\004 \001(\003\022\030\n\020s" +
"\022\017\n\007to_user\030\006 \001(\t\022\n\n\002to\030\007 \003(\t\"\353\001\n\004User\022\013" + "erver_timestamp\030\005 \001(\003\022\017\n\007to_user\030\006 \001(\t\022\n" +
"\n\003uid\030\001 \002(\t\022\014\n\004name\030\002 \001(\t\022\024\n\014display_nam" + "\n\002to\030\007 \003(\t\"\353\001\n\004User\022\013\n\003uid\030\001 \002(\t\022\014\n\004name" +
"e\030\003 \001(\t\022\020\n\010portrait\030\004 \001(\t\022\016\n\006mobile\030\005 \001(" + "\030\002 \001(\t\022\024\n\014display_name\030\003 \001(\t\022\020\n\010portrait" +
"\t\022\r\n\005email\030\006 \001(\t\022\017\n\007address\030\007 \001(\t\022\017\n\007com" + "\030\004 \001(\t\022\016\n\006mobile\030\005 \001(\t\022\r\n\005email\030\006 \001(\t\022\017\n" +
"pany\030\010 \001(\t\022\r\n\005extra\030\t \001(\t\022\021\n\tupdate_dt\030\n" + "\007address\030\007 \001(\t\022\017\n\007company\030\010 \001(\t\022\r\n\005extra" +
" \001(\003\022\016\n\006gender\030\013 \001(\005\022\016\n\006social\030\014 \001(\t\022\014\n\004" + "\030\t \001(\t\022\021\n\tupdate_dt\030\n \001(\003\022\016\n\006gender\030\013 \001(" +
"type\030\r \001(\005\022\017\n\007deleted\030\016 \001(\005\"c\n\005Robot\022\013\n\003" + "\005\022\016\n\006social\030\014 \001(\t\022\014\n\004type\030\r \001(\005\022\017\n\007delet" +
"uid\030\001 \002(\t\022\r\n\005state\030\002 \002(\005\022\r\n\005owner\030\003 \001(\t\022", "ed\030\016 \001(\005\"c\n\005Robot\022\013\n\003uid\030\001 \002(\t\022\r\n\005state\030",
"\016\n\006secret\030\004 \001(\t\022\020\n\010callback\030\005 \001(\t\022\r\n\005ext" + "\002 \002(\005\022\r\n\005owner\030\003 \001(\t\022\016\n\006secret\030\004 \001(\t\022\020\n\010" +
"ra\030\006 \001(\t\"(\n\017GetRobotsResult\022\025\n\005entry\030\001 \003" + "callback\030\005 \001(\t\022\r\n\005extra\030\006 \001(\t\"(\n\017GetRobo" +
"(\0132\006.Robot\"g\n\030UploadDeviceTokenRequest\022\020" + "tsResult\022\025\n\005entry\030\001 \003(\0132\006.Robot\"g\n\030Uploa" +
"\n\010platform\030\001 \002(\005\022\020\n\010app_name\030\002 \002(\t\022\024\n\014de" + "dDeviceTokenRequest\022\020\n\010platform\030\001 \002(\005\022\020\n" +
"vice_token\030\003 \002(\t\022\021\n\tpush_type\030\004 \002(\005\"\201\001\n\026" + "\010app_name\030\002 \002(\t\022\024\n\014device_token\030\003 \002(\t\022\021\n" +
"ModifyGroupInfoRequest\022\020\n\010group_id\030\001 \002(\t" + "\tpush_type\030\004 \002(\005\"\201\001\n\026ModifyGroupInfoRequ" +
"\022\014\n\004type\030\002 \002(\005\022\r\n\005value\030\003 \002(\t\022\017\n\007to_line" + "est\022\020\n\010group_id\030\001 \002(\t\022\014\n\004type\030\002 \002(\005\022\r\n\005v" +
"\030\004 \003(\005\022\'\n\016notify_content\030\005 \001(\0132\017.Message" + "alue\030\003 \002(\t\022\017\n\007to_line\030\004 \003(\005\022\'\n\016notify_co" +
"Content\"\203\001\n\026SetGroupManagerRequest\022\020\n\010gr" + "ntent\030\005 \001(\0132\017.MessageContent\"\203\001\n\026SetGrou" +
"oup_id\030\001 \002(\t\022\014\n\004type\030\002 \002(\005\022\017\n\007user_id\030\003 ", "pManagerRequest\022\020\n\010group_id\030\001 \002(\t\022\014\n\004typ",
"\003(\t\022\017\n\007to_line\030\004 \003(\005\022\'\n\016notify_content\030\005" + "e\030\002 \002(\005\022\017\n\007user_id\030\003 \003(\t\022\017\n\007to_line\030\004 \003(" +
" \001(\0132\017.MessageContent\"(\n\tInfoEntry\022\014\n\004ty" + "\005\022\'\n\016notify_content\030\005 \001(\0132\017.MessageConte" +
"pe\030\001 \002(\005\022\r\n\005value\030\002 \002(\t\"0\n\023ModifyMyInfoR" + "nt\"(\n\tInfoEntry\022\014\n\004type\030\001 \002(\005\022\r\n\005value\030\002" +
"equest\022\031\n\005entry\030\001 \003(\0132\n.InfoEntry\";\n\rNot" + " \002(\t\"0\n\023ModifyMyInfoRequest\022\031\n\005entry\030\001 \003" +
"ifyMessage\022\014\n\004type\030\001 \002(\005\022\014\n\004head\030\002 \002(\003\022\016" + "(\0132\n.InfoEntry\";\n\rNotifyMessage\022\014\n\004type\030" +
"\n\006target\030\003 \001(\t\"=\n\022PullMessageRequest\022\n\n\002" + "\001 \002(\005\022\014\n\004head\030\002 \002(\003\022\016\n\006target\030\003 \001(\t\"=\n\022P" +
"id\030\001 \002(\003\022\014\n\004type\030\002 \002(\005\022\r\n\005delay\030\003 \001(\003\"M\n" + "ullMessageRequest\022\n\n\002id\030\001 \002(\003\022\014\n\004type\030\002 " +
"\021PullMessageResult\022\031\n\007message\030\001 \003(\0132\010.Me" + "\002(\005\022\r\n\005delay\030\003 \001(\003\"M\n\021PullMessageResult\022" +
"ssage\022\017\n\007current\030\002 \002(\003\022\014\n\004head\030\003 \002(\003\"/\n\023" + "\031\n\007message\030\001 \003(\0132\010.Message\022\017\n\007current\030\002 " +
"PullGroupInfoResult\022\030\n\004info\030\001 \003(\0132\n.Grou", "\002(\003\022\014\n\004head\030\003 \002(\003\"/\n\023PullGroupInfoResult",
"pInfo\"6\n\026PullGroupMemberRequest\022\016\n\006targe" + "\022\030\n\004info\030\001 \003(\0132\n.GroupInfo\"6\n\026PullGroupM" +
"t\030\001 \002(\t\022\014\n\004head\030\002 \002(\003\"5\n\025PullGroupMember" + "emberRequest\022\016\n\006target\030\001 \002(\t\022\014\n\004head\030\002 \002" +
"Result\022\034\n\006member\030\001 \003(\0132\014.GroupMember\"-\n\013" + "(\003\"5\n\025PullGroupMemberResult\022\034\n\006member\030\001 " +
"UserRequest\022\013\n\003uid\030\001 \002(\t\022\021\n\tupdate_dt\030\002 " + "\003(\0132\014.GroupMember\"-\n\013UserRequest\022\013\n\003uid\030" +
"\001(\003\"0\n\017PullUserRequest\022\035\n\007request\030\001 \003(\0132" + "\001 \002(\t\022\021\n\tupdate_dt\030\002 \001(\003\"0\n\017PullUserRequ" +
"\014.UserRequest\"/\n\nUserResult\022\023\n\004user\030\001 \002(" + "est\022\035\n\007request\030\001 \003(\0132\014.UserRequest\"/\n\nUs" +
"\0132\005.User\022\014\n\004code\030\002 \002(\005\"-\n\016PullUserResult" + "erResult\022\023\n\004user\030\001 \002(\0132\005.User\022\014\n\004code\030\002 " +
"\022\033\n\006result\030\001 \003(\0132\013.UserResult\"^\n\020QuitGro" + "\002(\005\"-\n\016PullUserResult\022\033\n\006result\030\001 \003(\0132\013." +
"upRequest\022\020\n\010group_id\030\001 \002(\t\022\017\n\007to_line\030\002" + "UserResult\"^\n\020QuitGroupRequest\022\020\n\010group_" +
" \003(\005\022\'\n\016notify_content\030\003 \001(\0132\017.MessageCo", "id\030\001 \002(\t\022\017\n\007to_line\030\002 \003(\005\022\'\n\016notify_cont",
"ntent\"~\n\030RemoveGroupMemberRequest\022\020\n\010gro" + "ent\030\003 \001(\0132\017.MessageContent\"~\n\030RemoveGrou" +
"up_id\030\001 \002(\t\022\026\n\016removed_member\030\002 \003(\t\022\017\n\007t" + "pMemberRequest\022\020\n\010group_id\030\001 \002(\t\022\026\n\016remo" +
"o_line\030\003 \003(\005\022\'\n\016notify_content\030\004 \001(\0132\017.M" + "ved_member\030\002 \003(\t\022\017\n\007to_line\030\003 \003(\005\022\'\n\016not" +
"essageContent\"u\n\024TransferGroupRequest\022\020\n" + "ify_content\030\004 \001(\0132\017.MessageContent\"u\n\024Tr" +
"\010group_id\030\001 \002(\t\022\021\n\tnew_owner\030\002 \002(\t\022\017\n\007to" + "ansferGroupRequest\022\020\n\010group_id\030\001 \002(\t\022\021\n\t" +
"_line\030\003 \003(\005\022\'\n\016notify_content\030\004 \001(\0132\017.Me" + "new_owner\030\002 \002(\t\022\017\n\007to_line\030\003 \003(\005\022\'\n\016noti" +
"ssageContent\"\206\001\n\026ModifyGroupMemberAlias\022" + "fy_content\030\004 \001(\0132\017.MessageContent\"\206\001\n\026Mo" +
"\020\n\010group_id\030\001 \002(\t\022\r\n\005alias\030\002 \002(\t\022\017\n\007to_l" + "difyGroupMemberAlias\022\020\n\010group_id\030\001 \002(\t\022\r" +
"ine\030\003 \003(\005\022\'\n\016notify_content\030\004 \001(\0132\017.Mess" + "\n\005alias\030\002 \002(\t\022\017\n\007to_line\030\003 \003(\005\022\'\n\016notify" +
"ageContent\022\021\n\tmember_id\030\005 \001(\t\"\206\001\n\026Modify", "_content\030\004 \001(\0132\017.MessageContent\022\021\n\tmembe",
"GroupMemberExtra\022\020\n\010group_id\030\001 \002(\t\022\017\n\007to" + "r_id\030\005 \001(\t\"\206\001\n\026ModifyGroupMemberExtra\022\020\n" +
"_line\030\002 \003(\005\022\'\n\016notify_content\030\003 \001(\0132\017.Me" + "\010group_id\030\001 \002(\t\022\017\n\007to_line\030\002 \003(\005\022\'\n\016noti" +
"ssageContent\022\r\n\005extra\030\004 \001(\t\022\021\n\tmember_id" + "fy_content\030\003 \001(\0132\017.MessageContent\022\r\n\005ext" +
"\030\005 \001(\t\"P\n\020UserSettingEntry\022\r\n\005scope\030\001 \002(" + "ra\030\004 \001(\t\022\021\n\tmember_id\030\005 \001(\t\"P\n\020UserSetti" +
"\005\022\013\n\003key\030\002 \002(\t\022\r\n\005value\030\003 \002(\t\022\021\n\tupdate_" + "ngEntry\022\r\n\005scope\030\001 \002(\005\022\013\n\003key\030\002 \002(\t\022\r\n\005v" +
"dt\030\004 \002(\003\"A\n\024ModifyUserSettingReq\022\r\n\005scop" + "alue\030\003 \002(\t\022\021\n\tupdate_dt\030\004 \002(\003\"A\n\024ModifyU" +
"e\030\001 \002(\005\022\013\n\003key\030\002 \002(\t\022\r\n\005value\030\003 \002(\t\"\032\n\007V" + "serSettingReq\022\r\n\005scope\030\001 \002(\005\022\013\n\003key\030\002 \002(" +
"ersion\022\017\n\007version\030\001 \002(\003\"8\n\024GetUserSettin" + "\t\022\r\n\005value\030\003 \002(\t\"\032\n\007Version\022\017\n\007version\030\001" +
"gResult\022 \n\005entry\030\001 \003(\0132\021.UserSettingEntr" + " \002(\003\"8\n\024GetUserSettingResult\022 \n\005entry\030\001 " +
"y\"f\n\006Friend\022\013\n\003uid\030\001 \002(\t\022\r\n\005state\030\002 \002(\005\022", "\003(\0132\021.UserSettingEntry\"f\n\006Friend\022\013\n\003uid\030",
"\021\n\tupdate_dt\030\003 \002(\003\022\r\n\005alias\030\004 \001(\t\022\017\n\007bla" + "\001 \002(\t\022\r\n\005state\030\002 \002(\005\022\021\n\tupdate_dt\030\003 \002(\003\022" +
"cked\030\005 \001(\005\022\r\n\005extra\030\006 \001(\t\"*\n\020GetFriendsR" + "\r\n\005alias\030\004 \001(\t\022\017\n\007blacked\030\005 \001(\005\022\r\n\005extra" +
"esult\022\026\n\005entry\030\001 \003(\0132\007.Friend\"7\n\026GetFrie" + "\030\006 \001(\t\"*\n\020GetFriendsResult\022\026\n\005entry\030\001 \003(" +
"ndRequestResult\022\035\n\005entry\030\001 \003(\0132\016.FriendR" + "\0132\007.Friend\"7\n\026GetFriendRequestResult\022\035\n\005" +
"equest\"\243\001\n\021ConnectAckPayload\022\020\n\010msg_head" + "entry\030\001 \003(\0132\016.FriendRequest\"\243\001\n\021ConnectA" +
"\030\001 \001(\003\022\023\n\013friend_head\030\002 \001(\003\022\026\n\016friend_rq" + "ckPayload\022\020\n\010msg_head\030\001 \001(\003\022\023\n\013friend_he" +
"_head\030\003 \001(\003\022\024\n\014setting_head\030\004 \001(\003\022\021\n\tnod" + "ad\030\002 \001(\003\022\026\n\016friend_rq_head\030\003 \001(\003\022\024\n\014sett" +
"e_addr\030\005 \001(\t\022\021\n\tnode_port\030\006 \001(\005\022\023\n\013serve" + "ing_head\030\004 \001(\003\022\021\n\tnode_addr\030\005 \001(\t\022\021\n\tnod" +
"r_time\030\007 \001(\003\"P\n\rIMHttpWrapper\022\r\n\005token\030\001" + "e_port\030\006 \001(\005\022\023\n\013server_time\030\007 \001(\003\"P\n\rIMH" +
" \002(\t\022\021\n\tclient_id\030\002 \002(\t\022\017\n\007request\030\003 \002(\t", "ttpWrapper\022\r\n\005token\030\001 \002(\t\022\021\n\tclient_id\030\002",
"\022\014\n\004data\030\004 \001(\014\"A\n\021SearchUserRequest\022\017\n\007k" + " \002(\t\022\017\n\007request\030\003 \002(\t\022\014\n\004data\030\004 \001(\014\"A\n\021S" +
"eyword\030\001 \002(\t\022\r\n\005fuzzy\030\002 \001(\005\022\014\n\004page\030\003 \001(" + "earchUserRequest\022\017\n\007keyword\030\001 \002(\t\022\r\n\005fuz" +
"\005\"(\n\020SearchUserResult\022\024\n\005entry\030\001 \003(\0132\005.U" + "zy\030\002 \001(\005\022\014\n\004page\030\003 \001(\005\"(\n\020SearchUserResu" +
"ser\"@\n\026GetChatroomInfoRequest\022\023\n\013chatroo" + "lt\022\024\n\005entry\030\001 \003(\0132\005.User\"@\n\026GetChatroomI" +
"m_id\030\001 \002(\t\022\021\n\tupdate_dt\030\002 \001(\003\"\227\001\n\014Chatro" + "nfoRequest\022\023\n\013chatroom_id\030\001 \002(\t\022\021\n\tupdat" +
"omInfo\022\r\n\005title\030\001 \002(\t\022\014\n\004desc\030\002 \001(\t\022\020\n\010p" + "e_dt\030\002 \001(\003\"\227\001\n\014ChatroomInfo\022\r\n\005title\030\001 \002" +
"ortrait\030\003 \001(\t\022\024\n\014member_count\030\004 \001(\005\022\021\n\tc" + "(\t\022\014\n\004desc\030\002 \001(\t\022\020\n\010portrait\030\003 \001(\t\022\024\n\014me" +
"reate_dt\030\005 \001(\003\022\021\n\tupdate_dt\030\006 \001(\003\022\r\n\005ext" + "mber_count\030\004 \001(\005\022\021\n\tcreate_dt\030\005 \001(\003\022\021\n\tu" +
"ra\030\007 \001(\t\022\r\n\005state\030\010 \001(\005\"F\n\034GetChatroomMe" + "pdate_dt\030\006 \001(\003\022\r\n\005extra\030\007 \001(\t\022\r\n\005state\030\010" +
"mberInfoRequest\022\023\n\013chatroom_id\030\001 \002(\t\022\021\n\t", " \001(\005\"F\n\034GetChatroomMemberInfoRequest\022\023\n\013",
"max_count\030\002 \001(\005\";\n\022ChatroomMemberInfo\022\024\n" + "chatroom_id\030\001 \002(\t\022\021\n\tmax_count\030\002 \001(\005\";\n\022" +
"\014member_count\030\001 \001(\005\022\017\n\007members\030\002 \003(\t\"\026\n\010" + "ChatroomMemberInfo\022\024\n\014member_count\030\001 \001(\005" +
"INT64Buf\022\n\n\002id\030\001 \002(\003\"4\n\023NotifyRecallMess" + "\022\017\n\007members\030\002 \003(\t\"\026\n\010INT64Buf\022\n\n\002id\030\001 \002(" +
"age\022\n\n\002id\030\001 \002(\003\022\021\n\tfrom_user\030\002 \002(\t\"/\n\020Bl" + "\003\"4\n\023NotifyRecallMessage\022\n\n\002id\030\001 \002(\003\022\021\n\t" +
"ackUserRequest\022\013\n\003uid\030\001 \002(\t\022\016\n\006status\030\002 " + "from_user\030\002 \002(\t\"/\n\020BlackUserRequest\022\013\n\003u" +
"\002(\005\"\323\001\n\014RouteRequest\022\013\n\003app\030\001 \001(\t\022\020\n\010pla" + "id\030\001 \002(\t\022\016\n\006status\030\002 \002(\005\"\323\001\n\014RouteReques" +
"tform\030\002 \001(\005\022\021\n\tpush_type\030\003 \001(\005\022\023\n\013device" + "t\022\013\n\003app\030\001 \001(\t\022\020\n\010platform\030\002 \001(\005\022\021\n\tpush" +
"_name\030\004 \001(\t\022\026\n\016device_version\030\005 \001(\t\022\022\n\np" + "_type\030\003 \001(\005\022\023\n\013device_name\030\004 \001(\t\022\026\n\016devi" +
"hone_name\030\006 \001(\t\022\020\n\010language\030\007 \001(\t\022\024\n\014car" + "ce_version\030\005 \001(\t\022\022\n\nphone_name\030\006 \001(\t\022\020\n\010" +
"rier_name\030\010 \001(\t\022\023\n\013app_version\030\t \001(\t\022\023\n\013", "language\030\007 \001(\t\022\024\n\014carrier_name\030\010 \001(\t\022\023\n\013",
"sdk_version\030\n \001(\t\"D\n\rRouteResponse\022\014\n\004ho" + "app_version\030\t \001(\t\022\023\n\013sdk_version\030\n \001(\t\"D" +
"st\030\001 \002(\t\022\021\n\tlong_port\030\002 \002(\005\022\022\n\nshort_por" + "\n\rRouteResponse\022\014\n\004host\030\001 \002(\t\022\021\n\tlong_po" +
"t\030\003 \002(\005\"G\n\017GetTokenRequest\022\017\n\007user_id\030\001 " + "rt\030\002 \002(\005\022\022\n\nshort_port\030\003 \002(\005\"G\n\017GetToken" +
"\002(\t\022\021\n\tclient_id\030\002 \002(\t\022\020\n\010platform\030\003 \001(\005" + "Request\022\017\n\007user_id\030\001 \002(\t\022\021\n\tclient_id\030\002 " +
"\"r\n\022LoadRemoteMessages\022#\n\014conversation\030\001" + "\002(\t\022\020\n\010platform\030\003 \001(\005\"r\n\022LoadRemoteMessa" +
" \002(\0132\r.Conversation\022\022\n\nbefore_uid\030\002 \002(\003\022" + "ges\022#\n\014conversation\030\001 \002(\0132\r.Conversation" +
"\r\n\005count\030\003 \002(\005\022\024\n\014content_type\030\004 \003(\005\"a\n\020" + "\022\022\n\nbefore_uid\030\002 \002(\003\022\r\n\005count\030\003 \002(\005\022\024\n\014c" +
"MultiCastMessage\022\021\n\tfrom_user\030\001 \002(\t\022 \n\007c" + "ontent_type\030\004 \003(\005\"a\n\020MultiCastMessage\022\021\n" +
"ontent\030\002 \002(\0132\017.MessageContent\022\n\n\002to\030\003 \003(" + "\tfrom_user\030\001 \002(\t\022 \n\007content\030\002 \002(\0132\017.Mess" +
"\t\022\014\n\004line\030\004 \002(\005\"E\n\035RecallMultiCastMessag", "ageContent\022\n\n\002to\030\003 \003(\t\022\014\n\004line\030\004 \002(\005\"E\n\035",
"eRequest\022\022\n\nmessage_id\030\001 \002(\003\022\020\n\010receiver" + "RecallMultiCastMessageRequest\022\022\n\nmessage" +
"\030\002 \003(\t\"@\n\017AuthCodeRequest\022\021\n\ttarget_id\030\001" + "_id\030\001 \002(\003\022\020\n\010receiver\030\002 \003(\t\"@\n\017AuthCodeR" +
" \002(\t\022\014\n\004type\030\002 \002(\005\022\014\n\004host\030\003 \002(\t\"o\n\030Appl" + "equest\022\021\n\ttarget_id\030\001 \002(\t\022\014\n\004type\030\002 \002(\005\022" +
"icationConfigRequest\022\r\n\005appId\030\001 \002(\t\022\017\n\007a" + "\014\n\004host\030\003 \002(\t\"o\n\030ApplicationConfigReques" +
"ppType\030\002 \002(\005\022\021\n\ttimestamp\030\003 \002(\003\022\r\n\005nonce" + "t\022\r\n\005appId\030\001 \002(\t\022\017\n\007appType\030\002 \002(\005\022\021\n\ttim" +
"\030\004 \002(\t\022\021\n\tsignature\030\005 \002(\tB#\n\025cn.wildfire" + "estamp\030\003 \002(\003\022\r\n\005nonce\030\004 \002(\t\022\021\n\tsignature" +
"chat.protoB\nWFCMessage" "\030\005 \002(\tB/\n\025cn.wildfirechat.protoB\nWFCMess" +
"ageZ\n./go;proto"
}; };
com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() { new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
@@ -67420,7 +67502,7 @@ public final class WFCMessage {
internal_static_GroupInfo_fieldAccessorTable = new internal_static_GroupInfo_fieldAccessorTable = new
com.google.protobuf.GeneratedMessage.FieldAccessorTable( com.google.protobuf.GeneratedMessage.FieldAccessorTable(
internal_static_GroupInfo_descriptor, internal_static_GroupInfo_descriptor,
new java.lang.String[] { "TargetId", "Name", "Portrait", "Owner", "Type", "MemberCount", "Extra", "UpdateDt", "MemberUpdateDt", "Mute", "JoinType", "PrivateChat", "Searchable", "MaxMemberCount", "HistoryMessage", }); new java.lang.String[] { "TargetId", "Name", "Portrait", "Owner", "Type", "MemberCount", "Extra", "UpdateDt", "MemberUpdateDt", "Mute", "JoinType", "PrivateChat", "Searchable", "MaxMemberCount", "HistoryMessage", "SuperGroup", });
internal_static_GroupMember_descriptor = internal_static_GroupMember_descriptor =
getDescriptor().getMessageTypes().get(3); getDescriptor().getMessageTypes().get(3);
internal_static_GroupMember_fieldAccessorTable = new internal_static_GroupMember_fieldAccessorTable = new
@@ -5,6 +5,7 @@ import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom; import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException; import java.security.spec.InvalidKeySpecException;
import java.util.Arrays;
import java.util.Base64; import java.util.Base64;
import javax.crypto.BadPaddingException; import javax.crypto.BadPaddingException;
@@ -18,38 +19,46 @@ import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec; import javax.crypto.spec.SecretKeySpec;
public class AES { public class AES {
private static byte[] aes_key= {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x78,0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x7F}; public static int keyLen = 16;
public static void init(byte[] secret) { private final static int ivLen = 16;
if (secret != null && secret.length == 16) { private static byte[] aes_key= {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x78,0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x7F,0x3A,0x1F,0x28,0x39,0x4F,0x52,0x68,0x79,0x71,0x73,0x7A,0x7B,0x7C,0x7D,0x7E,0x7F};
aes_key = new byte[16];
for (int i = 0; i < 16; i++) {
aes_key[i] = secret[i];
}
} else {
System.out.println("Error int key error, secret incorrect");
}
}
public static byte[] AESEncrypt(String sSrc, String userKey) { public static byte[] AESEncrypt(String sSrc, String userKey) {
return AESEncrypt(sSrc.getBytes(), userKey); return AESEncrypt(sSrc.getBytes(), userKey);
} }
public static void useAes256(boolean aes256) {
if(aes256)
keyLen = 32;
else
keyLen = 16;
}
public static byte[] AESEncrypt(byte[] tobeencrypdata, byte[] aesKey) { public static byte[] AESEncrypt(byte[] tobeencrypdata, byte[] aesKey) {
if (aesKey == null) { if (aesKey == null) {
System.out.print("Key为空null"); System.out.print("Key为空null");
return null; return null;
} }
// 判断Key是否为16位 // 判断Key是否为16位
if (aesKey.length != 16) { if (aesKey.length < keyLen) {
System.out.print("Key长度不是16位"); System.out.print("Key长度不是16位");
return null; return null;
} }
if(aesKey.length > keyLen) {
aesKey = Arrays.copyOfRange(aesKey, 0, keyLen);
}
byte[] ivKeys;
if(aesKey.length == ivLen) {
ivKeys = aesKey;
} else {
ivKeys = Arrays.copyOfRange(aesKey, 0, ivLen);
}
try { try {
SecretKeySpec skeySpec = new SecretKeySpec(aesKey, "AES"); SecretKeySpec skeySpec = new SecretKeySpec(aesKey, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");//"算法/模式/补码方式" Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");//"算法/模式/补码方式"
IvParameterSpec iv = new IvParameterSpec(aesKey);//使用CBC模式,需要一个向量iv,可增加加密算法的强度 IvParameterSpec iv = new IvParameterSpec(ivKeys);//使用CBC模式,需要一个向量iv,可增加加密算法的强度
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv); cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
//2018.1.1 0:0:0 以来的小时数 //2018.1.1 0:0:0 以来的小时数
@@ -101,21 +110,26 @@ public class AES {
} }
private static byte[] convertUserKey(String userKey) { private static byte[] convertUserKey(String userKey) {
byte[] key = new byte[16]; byte[] key = new byte[keyLen];
for (int i = 0; i < 16; i++) { for (int i = 0; i < keyLen; i++) {
key[i] = (byte) (userKey.charAt(i) & 0xFF); key[i] = (byte) (userKey.charAt(i) & 0xFF);
} }
return key; return key;
} }
public static byte[] AESDecrypt(byte[] sSrc, String userKey, boolean checkTime) { public static byte[] AESDecrypt(byte[] sSrc, String userKey, boolean checkTime) {
return AESDecrypt(sSrc, userKey, checkTime, null);
}
public static byte[] AESDecrypt(byte[] sSrc, String userKey, boolean checkTime, boolean[] invalidTime) {
byte[] aesKey = aes_key; byte[] aesKey = aes_key;
if (userKey != null && !userKey.isEmpty()) { if (userKey != null && !userKey.isEmpty()) {
aesKey = convertUserKey(userKey); aesKey = convertUserKey(userKey);
} }
return AESDecrypt(sSrc, aesKey, checkTime); return AESDecrypt(sSrc, aesKey, checkTime, invalidTime);
} }
public static byte[] AESDecrypt(byte[] sSrc, byte[] aesKey, boolean checkTime) { public static byte[] AESDecrypt(byte[] sSrc, byte[] aesKey, boolean checkTime, boolean[] invalidTime) {
try { try {
// 判断Key是否正确 // 判断Key是否正确
@@ -123,14 +137,25 @@ public class AES {
aesKey = aes_key; aesKey = aes_key;
} }
// 判断Key是否为16位 // 判断Key是否为16位
if (aesKey.length != 16) { if (aesKey.length < keyLen) {
System.out.print("Key长度不是16位"); System.out.print("Key长度不是16位");
return null; return null;
} }
if(aesKey.length > keyLen) {
aesKey = Arrays.copyOfRange(aesKey, 0, keyLen);
}
byte[] ivKeys;
if(aesKey.length == ivLen) {
ivKeys = aesKey;
} else {
ivKeys = Arrays.copyOfRange(aesKey, 0, ivLen);
}
SecretKeySpec skeySpec = new SecretKeySpec(aesKey, "AES"); SecretKeySpec skeySpec = new SecretKeySpec(aesKey, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
IvParameterSpec iv = new IvParameterSpec(aesKey); IvParameterSpec iv = new IvParameterSpec(ivKeys);
cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv); cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
try { try {
byte[] original = cipher.doFinal(sSrc); byte[] original = cipher.doFinal(sSrc);
@@ -152,6 +177,9 @@ public class AES {
int curhour = (int) ((System.currentTimeMillis()/1000 - 1514736000)/3600); int curhour = (int) ((System.currentTimeMillis()/1000 - 1514736000)/3600);
if (curhour - hours > 24 && checkTime) { if (curhour - hours > 24 && checkTime) {
if(invalidTime != null) {
invalidTime[0] = true;
}
return null; return null;
} }
byte[] neworiginal = new byte[original.length - 4]; byte[] neworiginal = new byte[original.length - 4];
+1 -1
View File
@@ -6,7 +6,7 @@
<!--<relativePath>../pom.xml</relativePath>--> <!--<relativePath>../pom.xml</relativePath>-->
<artifactId>wildfirechat-parent</artifactId> <artifactId>wildfirechat-parent</artifactId>
<groupId>cn.wildfirechat</groupId> <groupId>cn.wildfirechat</groupId>
<version>0.99</version> <version>1.1.5</version>
</parent> </parent>
<artifactId>distribution</artifactId> <artifactId>distribution</artifactId>
@@ -44,6 +44,12 @@
<fileMode>0755</fileMode> <fileMode>0755</fileMode>
</file> </file>
<file>
<source>src/main/scripts/stop.sh</source>
<outputDirectory>bin</outputDirectory>
<fileMode>0755</fileMode>
</file>
<file> <file>
<source>src/main/scripts/wildfirechat.bat</source> <source>src/main/scripts/wildfirechat.bat</source>
<outputDirectory>bin</outputDirectory> <outputDirectory>bin</outputDirectory>
+2 -2
View File
@@ -20,14 +20,14 @@
<RollingRandomAccessFile name="RollingFileInfo" immediateFlush="false" <RollingRandomAccessFile name="RollingFileInfo" immediateFlush="false"
fileName="${MSG_LOG_HOME}/wildfirechat.log" fileName="${MSG_LOG_HOME}/wildfirechat.log"
filePattern="${MSG_LOG_HOME}/backup/wildfirechat.%d{yyyyMMddHH}.zip"> filePattern="${MSG_LOG_HOME}/backup/wildfirechat.%d{yyyyMMddHHmm}.zip">
<Filters> <Filters>
<ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/> <ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/>
</Filters> </Filters>
<PatternLayout pattern="${pattern}" /> <PatternLayout pattern="${pattern}" />
<Policies> <Policies>
<!-- TimeBasedTriggeringPolicy :时间滚动策略,默认0点小时产生新的文件,interval="6" : 自定义文件滚动时间间隔,每隔6小时产生新文件, modulate="true" : 产生文件是否以0点偏移时间,即6点,12点,18点,0点--> <!-- TimeBasedTriggeringPolicy :时间滚动策略,默认0点小时产生新的文件,interval="6" : 自定义文件滚动时间间隔,每隔6小时产生新文件, modulate="true" : 产生文件是否以0点偏移时间,即6点,12点,18点,0点-->
<!-- <TimeBasedTriggeringPolicy interval="6" modulate="true"/>--> <TimeBasedTriggeringPolicy interval="6" modulate="true"/>
<!-- SizeBasedTriggeringPolicy :文件大小滚动策略--> <!-- SizeBasedTriggeringPolicy :文件大小滚动策略-->
<SizeBasedTriggeringPolicy size="100 MB"/> <SizeBasedTriggeringPolicy size="100 MB"/>
</Policies> </Policies>
@@ -32,6 +32,7 @@ local_port 80
## 是否使用内置DB。0使用mysql;1使用h2db。 ## 是否使用内置DB。0使用mysql;1使用h2db。
## MySQL需要把事物隔离级别改成"Read committed",使用命令来修改"set global transaction_isolation='read-committed';",其他数据库默认已经是这个级别不用修改 ## MySQL需要把事物隔离级别改成"Read committed",使用命令来修改"set global transaction_isolation='read-committed';",其他数据库默认已经是这个级别不用修改
## 如果使用MySQL,请在c3p0.xml文件中配置JDBC信息。 ## 如果使用MySQL,请在c3p0.xml文件中配置JDBC信息。
## 如果是MySQL5.7,需要开启长索引的支持,在数据库中执行命令:"set global innodb_large_prefix=on;"。其他版本默认支持,不用修改。
embed.db 1 embed.db 1
## 是否自动清理历史消息记录,当为true时,IM服务会定时扫描t_messages_x和t_user_messages_x表,清除掉3年前的历史消息。 ## 是否自动清理历史消息记录,当为true时,IM服务会定时扫描t_messages_x和t_user_messages_x表,清除掉3年前的历史消息。
@@ -62,6 +63,9 @@ token.key testim
##是否拒绝空签名的android客户端, 默认为true。当有旧的客户端需要兼容时改成false,当所有都是新客户端时,改成true。 ##是否拒绝空签名的android客户端, 默认为true。当有旧的客户端需要兼容时改成false,当所有都是新客户端时,改成true。
#connect.reject_empty_signature true #connect.reject_empty_signature true
##是否使用AES256加密。默认客户端和服务器都是AES128加密,如果需要开启AES256,需要客户端和IM服务同时开通。
#encrypt.use_aes256 true
##首次登录,是否接收之前的历史消息。 ##首次登录,是否接收之前的历史消息。
##0 不接收历史消息,只接收${message.compensate_time_limit}毫秒以内的消息,由于服务器没有保存已经收取记录,所以如果有超过${message.compensate_time_limit}毫秒之前未收取的消息也不会收取下拉; ##0 不接收历史消息,只接收${message.compensate_time_limit}毫秒以内的消息,由于服务器没有保存已经收取记录,所以如果有超过${message.compensate_time_limit}毫秒之前未收取的消息也不会收取下拉;
##1接收,会接收 message.max_queue 配置的条数的历史消息 ##1接收,会接收 message.max_queue 配置的条数的历史消息
@@ -148,6 +152,9 @@ friend.reject_request_duration 2592000000
##好友请求过期时间,单位是毫秒,默认是7天,0为无限长期限。 ##好友请求过期时间,单位是毫秒,默认是7天,0为无限长期限。
friend.request_expiration_duration 604800000 friend.request_expiration_duration 604800000
##请求添加机器人为好友时,机器人是否自动接受,默认为true
friend.robot_auto_accept true
## 聊天室观众空闲退出时间,单位为毫秒,默认为15分钟,0为永远不退出 ## 聊天室观众空闲退出时间,单位为毫秒,默认为15分钟,0为永远不退出
chatroom.participant_idle_time 900000 chatroom.participant_idle_time 900000
@@ -168,6 +175,10 @@ group.allow_robot_custom_operation_notification true
## 如果应用需要退群或者踢人不通知普通成员,请设置此参数为3,然后修改客户端踢人或退群消息的flag为not_presist。 ## 如果应用需要退群或者踢人不通知普通成员,请设置此参数为3,然后修改客户端踢人或退群消息的flag为not_presist。
group.visible_quit_or_kickoff_notification 0 group.visible_quit_or_kickoff_notification 0
## 禁止客户端群操作。第1位是禁止创建群组,第2位是禁止销毁群组,3位禁止加入群,4位禁止退出群,5位禁止邀请群成员,6位禁止移出群成员,7位禁止转移群,8位禁止设置群管理员,9位禁止白名单处理,10位禁止群禁言,11位禁止修改群组信息,12位禁止群成员禁言。
## 如果有客户端有被破解的风险,可以禁止客户端群操作,然后通过Server API操作。Server API不受限制。
#group.forbidden_client_operation 0xFFF
## 隐藏用户信息属性类型,2是性别,3是电话号码,4是邮箱,5是地址,6是公司信息,7是社交账号,8是Extra信息。当需要隐藏多个时以英文逗号分开; ## 隐藏用户信息属性类型,2是性别,3是电话号码,4是邮箱,5是地址,6是公司信息,7是社交账号,8是Extra信息。当需要隐藏多个时以英文逗号分开;
## 本配置是为了提高安全性,避免把对应信息同步到客户端,这样就能防止程序被破解从而拿到用户关键信息。仅对客户端有效,server api不受影响。 ## 本配置是为了提高安全性,避免把对应信息同步到客户端,这样就能防止程序被破解从而拿到用户关键信息。仅对客户端有效,server api不受影响。
## 注意,修改本配置不会对已经同步的信息产生影响。 ## 注意,修改本配置不会对已经同步的信息产生影响。
@@ -313,6 +324,10 @@ push.ios.server.address http://localhost:8085/ios/push
##注意回调是单线程回调,接收服务必须在同一内网,且异步处理快速返回,否则会有延迟问题!! ##注意回调是单线程回调,接收服务必须在同一内网,且异步处理快速返回,否则会有延迟问题!!
#message.mentionmsg.forward.url http://localhost:8888/im_event/message #message.mentionmsg.forward.url http://localhost:8888/im_event/message
##撤回消息转发地址,当用户撤回消息会回调此地址。
##注意回调是单线程回调,接收服务必须在同一内网,且异步处理快速返回,否则会有延迟问题!!
#message.recallmsg.forward.url http://localhost:8888/im_event/recall_message
##设备信息转发地址 ##设备信息转发地址
##注意回调是单线程回调,接收服务必须在同一内网,且异步处理快速返回,否则会有延迟问题!! ##注意回调是单线程回调,接收服务必须在同一内网,且异步处理快速返回,否则会有延迟问题!!
#things_message.forward.url http://localhost:8087/im_event/things/message #things_message.forward.url http://localhost:8087/im_event/things/message
+25
View File
@@ -0,0 +1,25 @@
#!/bin/sh
pid=`ps -ef | grep wildfirechat.server.Server | grep -v grep | awk '{print $2}'`
if [ -z $pid ]; then
echo "野火IM服务不存在"
exit 0
fi
kill -15 $pid
for i in {1..30}
do
pid=`ps -ef | grep wildfirechat.server.Server | grep -v grep | awk '{print $2}'`
if [ -z $pid ]; then
echo "野火IM服务已结束"
exit 0
else
echo "正在结束中,请等待..."
sleep 1
fi
done
echo "正常结束失败,强制结束!"
kill -9 $pid
@@ -72,6 +72,9 @@ rem set JAVA_OPTS=%JAVA_OPTS% -XX:+UseGCLogFileRotation
rem set JAVA_OPTS=%JAVA_OPTS% -XX:NumberOfGCLogFiles=10 rem set JAVA_OPTS=%JAVA_OPTS% -XX:NumberOfGCLogFiles=10
rem set JAVA_OPTS=%JAVA_OPTS% -XX:GCLogFileSize=10M" rem set JAVA_OPTS=%JAVA_OPTS% -XX:GCLogFileSize=10M"
rem If the JDK version is 9 or above, please open this configuration.
rem set JAVA_OPTS=%JAVA_OPTS% --add-modules java.se --add-exports java.base/jdk.internal.ref=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.nio=ALL-UNNAMED --add-opens java.base/sun.nio.ch=ALL-UNNAMED --add-opens java.management/sun.management=ALL-UNNAMED --add-opens jdk.management/com.sun.management.internal=ALL-UNNAMED
echo echo
echo "Please set Xmx and Xms parameters!" echo "Please set Xmx and Xms parameters!"
echo "Please set Xmx and Xms parameters!" echo "Please set Xmx and Xms parameters!"
@@ -33,6 +33,8 @@ else
fi fi
export JAVA export JAVA
$JAVA -version
WILDFIRECHAT_CONFIG_PATH=$WILDFIRECHAT_HOME WILDFIRECHAT_CONFIG_PATH=$WILDFIRECHAT_HOME
LOG_FILE=$WILDFIRECHAT_CONFIG_PATH/config/log4j2.xml LOG_FILE=$WILDFIRECHAT_CONFIG_PATH/config/log4j2.xml
@@ -84,6 +86,8 @@ JAVA_OPTS="$JAVA_OPTS -XX:MaxGCPauseMillis=500"
#JAVA_OPTS="$JAVA_OPTS -XX:NumberOfGCLogFiles=10" #JAVA_OPTS="$JAVA_OPTS -XX:NumberOfGCLogFiles=10"
#JAVA_OPTS="$JAVA_OPTS -XX:GCLogFileSize=10M" #JAVA_OPTS="$JAVA_OPTS -XX:GCLogFileSize=10M"
#如果JDK版本是9及以上,请打开这个配置
#JAVA_OPTS="$JAVA_OPTS --add-modules java.se --add-exports java.base/jdk.internal.ref=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.nio=ALL-UNNAMED --add-opens java.base/sun.nio.ch=ALL-UNNAMED --add-opens java.management/sun.management=ALL-UNNAMED --add-opens jdk.management/com.sun.management.internal=ALL-UNNAMED"
echo "警告:没有设置JVM内存参数!" echo "警告:没有设置JVM内存参数!"
echo "请设置JVM参数Xmx和Xms,设置为您为IM服务预留的内存大小,注意需要刨除操作系统占用,如果有其它系统也需要相应去除占用。" echo "请设置JVM参数Xmx和Xms,设置为您为IM服务预留的内存大小,注意需要刨除操作系统占用,如果有其它系统也需要相应去除占用。"
+2
View File
@@ -5,6 +5,8 @@ ADD distribution-*-bundle-tar.tar.gz /opt/im-server/
RUN sed -i 's/#JAVA_OPTS="$JAVA_OPTS -Xmx128M"/JAVA_OPTS="$JAVA_OPTS -Xmx$JVM_XMX"/g' /opt/im-server/bin/wildfirechat.sh RUN sed -i 's/#JAVA_OPTS="$JAVA_OPTS -Xmx128M"/JAVA_OPTS="$JAVA_OPTS -Xmx$JVM_XMX"/g' /opt/im-server/bin/wildfirechat.sh
RUN sed -i 's/#JAVA_OPTS="$JAVA_OPTS -Xms128M"/JAVA_OPTS="$JAVA_OPTS -Xms$JVM_XMS"/g' /opt/im-server/bin/wildfirechat.sh RUN sed -i 's/#JAVA_OPTS="$JAVA_OPTS -Xms128M"/JAVA_OPTS="$JAVA_OPTS -Xms$JVM_XMS"/g' /opt/im-server/bin/wildfirechat.sh
RUN chmod a+x /opt/im-server/bin/wildfirechat.sh
WORKDIR /opt/im-server WORKDIR /opt/im-server
VOLUME /opt/im-server/config VOLUME /opt/im-server/config
+1 -1
View File
@@ -12,7 +12,7 @@
<artifactId>wildfirechat-parent</artifactId> <artifactId>wildfirechat-parent</artifactId>
<packaging>pom</packaging> <packaging>pom</packaging>
<version>0.99</version> <version>1.1.5</version>
<name>Wildfire Chat</name> <name>Wildfire Chat</name>
<description>Wildfire Chat Server</description> <description>Wildfire Chat Server</description>
<inceptionYear>2019</inceptionYear> <inceptionYear>2019</inceptionYear>
+53
View File
@@ -12,6 +12,59 @@
# 更新记录 # 更新记录
--------------
Release note 1.1.5:
1. 添加获取所有用户的Server API。
2. 解决添加好友时没有处理黑名单的问题。
--------------
Release note 1.1.4:
1. 添加PC客户端多端登录互踢时没有更新pc在线状态问题。
2. 添加支持使用AES256加密。
3. Server API添加获取单个群成员的接口。
4. 添加配置,添加机器人为好友时是否自动接受。
--------------
Release note 1.1.3:
1. 添加服务器和客户端时间检查功能。
2. 解决用户被block后session失效的问题。
3. 添加消息撤回回调。
4. 优化群组撤回逻辑。
5. 解决用户离开群组后还能修改群昵称的问题。
6. 修改server api修改好友关系回调数据错误问题。
7. 同步超级群组数据库和数据。
--------------
Release note 1.1.2:
1. 会议SDK添加查询会议是否存在的接口
2. 单聊会话定向消息分发包含发送者
--------------
Release note 1.1.1:
1. 当用户获取群组信息,可以根据返回信息判断是否在群中。
2. 搜索用户时,过滤掉已删除用户
3. 支持单聊消息的定向消息
4. 解决关闭roaming,且message.compensate_time_limit配置为-1时,首次消息无法同步的问题
5. 解决禁止客户端群操作flag 解析错误
--------------
Release note 1.1:
1. Channel API添加检查用户是否订阅接口
2. Server API发送消息时添加检查对象是否存在
3. Channel API添加修改频道菜单接口
4. 内置对象存储的优化
--------------
Release note 1.0:
1. SDK检查工具添加help命令
2. 去掉短连接端口被网络爬虫扫描输出的异常日志
3. API支持创建组织群
4. 添加配置禁止客户端进行某些群操作
5. 解决route请求时可能不能正确携带推送类型的问题
6. 会议成员离开加上离开原因
7. 添加停止程序的命令
8. 添加RTP Forward的API
-------------- --------------
Release note 0.99: Release note 0.99:
1. API获取用户信息时,过滤掉已经删除用户。 1. API获取用户信息时,过滤掉已经删除用户。
+1 -1
View File
@@ -3,7 +3,7 @@
<parent> <parent>
<artifactId>wildfirechat-parent</artifactId> <artifactId>wildfirechat-parent</artifactId>
<groupId>cn.wildfirechat</groupId> <groupId>cn.wildfirechat</groupId>
<version>0.99</version> <version>1.1.5</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -27,7 +27,7 @@
<dependency> <dependency>
<groupId>commons-codec</groupId> <groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId> <artifactId>commons-codec</artifactId>
<version>1.11</version> <version>1.15</version>
</dependency> </dependency>
<dependency> <dependency>
@@ -2,14 +2,15 @@ package cn.wildfirechat.sdk;
import cn.wildfirechat.common.APIPath; import cn.wildfirechat.common.APIPath;
import cn.wildfirechat.pojos.*; import cn.wildfirechat.pojos.*;
import cn.wildfirechat.proto.ProtoConstants;
import cn.wildfirechat.sdk.model.IMResult; import cn.wildfirechat.sdk.model.IMResult;
import cn.wildfirechat.sdk.utilities.ChannelHttpUtils; import cn.wildfirechat.sdk.utilities.ChannelHttpUtils;
import com.google.gson.Gson;
import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.codec.digest.DigestUtils;
import java.util.List; import java.util.List;
import static cn.wildfirechat.proto.ProtoConstants.ApplicationType.ApplicationType_Channel; import static cn.wildfirechat.proto.ProtoConstants.ApplicationType.ApplicationType_Channel;
import static cn.wildfirechat.proto.ProtoConstants.ApplicationType.ApplicationType_Robot;
//仅专业版支持,社区版不支持 //仅专业版支持,社区版不支持
public class ChannelServiceApi { public class ChannelServiceApi {
@@ -50,6 +51,11 @@ public class ChannelServiceApi {
return channelHttpUtils.httpJsonPost(path, null, OutputGetChannelInfo.class); return channelHttpUtils.httpJsonPost(path, null, OutputGetChannelInfo.class);
} }
public IMResult<Void> modifyChannelMenu(List<OutputGetChannelInfo.OutputMenu> menus) throws Exception {
String menuStr = new Gson().toJson(menus);
return modifyChannelInfo(ProtoConstants.ModifyChannelInfoType.Modify_Channel_Menu, menuStr);
}
public IMResult<SendMessageResult> sendMessage(int line, List<String> targets, MessagePayload payload) throws Exception { public IMResult<SendMessageResult> sendMessage(int line, List<String> targets, MessagePayload payload) throws Exception {
String path = APIPath.Channel_Message_Send; String path = APIPath.Channel_Message_Send;
SendChannelMessageData messageData = new SendChannelMessageData(); SendChannelMessageData messageData = new SendChannelMessageData();
@@ -80,6 +86,12 @@ public class ChannelServiceApi {
return channelHttpUtils.httpJsonPost(path, null, OutputStringList.class); return channelHttpUtils.httpJsonPost(path, null, OutputStringList.class);
} }
public IMResult<Boolean> isSubscriber(String userId) throws Exception {
String path = APIPath.Channel_Is_Subscriber;
InputUserId input = new InputUserId(userId);
return channelHttpUtils.httpJsonPost(path, input, Boolean.class);
}
public IMResult<OutputApplicationUserInfo> applicationGetUserInfo(String authCode) throws Exception { public IMResult<OutputApplicationUserInfo> applicationGetUserInfo(String authCode) throws Exception {
String path = APIPath.Channel_Application_Get_UserInfo; String path = APIPath.Channel_Application_Get_UserInfo;
InputApplicationGetUserInfo input = new InputApplicationGetUserInfo(); InputApplicationGetUserInfo input = new InputApplicationGetUserInfo();
@@ -11,6 +11,12 @@ public class ConferenceAdmin {
return AdminHttpUtils.httpJsonPost(path, null, PojoConferenceInfoList.class); return AdminHttpUtils.httpJsonPost(path, null, PojoConferenceInfoList.class);
} }
public static IMResult<Boolean> existsConferences(String conferenceId) throws Exception {
String path = APIPath.Conference_Exist;
PojoConferenceRoomId data = new PojoConferenceRoomId(conferenceId, false);
return AdminHttpUtils.httpJsonPost(path, data, Boolean.class);
}
public static IMResult<PojoConferenceParticipantList> listParticipants(String roomId, boolean advance) throws Exception { public static IMResult<PojoConferenceParticipantList> listParticipants(String roomId, boolean advance) throws Exception {
String path = APIPath.Conference_List_Participant; String path = APIPath.Conference_List_Participant;
PojoConferenceRoomId data = new PojoConferenceRoomId(roomId, advance); PojoConferenceRoomId data = new PojoConferenceRoomId(roomId, advance);
@@ -45,4 +51,23 @@ public class ConferenceAdmin {
PojoConferenceRoomId conferenceRoomId = new PojoConferenceRoomId(roomId, advance); PojoConferenceRoomId conferenceRoomId = new PojoConferenceRoomId(roomId, advance);
return AdminHttpUtils.httpJsonPost(path, conferenceRoomId, Void.class); return AdminHttpUtils.httpJsonPost(path, conferenceRoomId, Void.class);
} }
public static IMResult<Void> rtpForward(String roomId, String userId, String rtpHost, int audioPort, int audioPt, long audioSSRC, int videoPort, int videoPt, long videoSSRC) throws Exception {
String path = APIPath.Conference_Rtp_Forward;
PojoConferenceRtpForwardReq req = new PojoConferenceRtpForwardReq(roomId, userId, rtpHost, audioPort, audioPt, audioSSRC, videoPort, videoPt, videoSSRC);
return AdminHttpUtils.httpJsonPost(path, req, Void.class);
}
public static IMResult<Void> stopRtpForward(String roomId, String userId, long streamId) throws Exception {
String path = APIPath.Conference_Stop_Rtp_Forward;
PojoConferenceStopRtpForwardReq req = new PojoConferenceStopRtpForwardReq(roomId, userId, streamId);
return AdminHttpUtils.httpJsonPost(path, req, Void.class);
}
public static IMResult<PojoConferenceRtpForwarders> listRtpForwarders(String roomId) throws Exception {
String path = APIPath.Conference_List_Rtp_Forward;
PojoConferenceRoomId req = new PojoConferenceRoomId();
req.roomId = roomId;
return AdminHttpUtils.httpJsonPost(path, req, PojoConferenceRtpForwarders.class);
}
} }
@@ -71,6 +71,14 @@ public class GroupAdmin {
return AdminHttpUtils.httpJsonPost(path, input, OutputGroupMemberList.class); return AdminHttpUtils.httpJsonPost(path, input, OutputGroupMemberList.class);
} }
public static IMResult<PojoGroupMember> getGroupMember(String groupId, String memberId) throws Exception {
String path = APIPath.Group_Member_Get;
InputGetGroupMember input = new InputGetGroupMember();
input.setGroupId(groupId);
input.setMemberId(memberId);
return AdminHttpUtils.httpJsonPost(path, input, PojoGroupMember.class);
}
public static IMResult<Void> addGroupMembers(String operator, String groupId, List<PojoGroupMember> groupMembers, List<Integer> to_lines, MessagePayload notify_message) throws Exception { public static IMResult<Void> addGroupMembers(String operator, String groupId, List<PojoGroupMember> groupMembers, List<Integer> to_lines, MessagePayload notify_message) throws Exception {
String path = APIPath.Group_Member_Add; String path = APIPath.Group_Member_Add;
InputAddGroupMember addGroupMember = new InputAddGroupMember(); InputAddGroupMember addGroupMember = new InputAddGroupMember();
@@ -38,6 +38,10 @@ public class Main {
commercialServer = Boolean.parseBoolean(args[3]); commercialServer = Boolean.parseBoolean(args[3]);
advanceVoip = Boolean.parseBoolean(args[4]); advanceVoip = Boolean.parseBoolean(args[4]);
} else { } else {
if(args.length == 1 && (args[0].equals("-h") || args[0].equals("--help") || args[0].equals("-help"))) {
System.out.println("Usage: java -jar checker.jar adminUrl adminSecret imUrl commercialServer advanceVoip \n e.g. java -jar checker.jar http://192.168.1.80:18080 123456 http://192.168.1.80 false false");
return;
}
System.out.println("Usage: java -jar checker.jar adminUrl adminSecret imUrl commercialServer advanceVoip \n e.g. java -jar checker.jar http://192.168.1.80:18080 123456 http://192.168.1.80 false false"); System.out.println("Usage: java -jar checker.jar adminUrl adminSecret imUrl commercialServer advanceVoip \n e.g. java -jar checker.jar http://192.168.1.80:18080 123456 http://192.168.1.80 false false");
System.out.println(); System.out.println();
System.out.println(); System.out.println();
@@ -296,6 +300,20 @@ public class Main {
System.exit(-1); System.exit(-1);
} }
int limit = 5;
for (int i = 0; i < 100; i++) {
IMResult<OutputGetUserList> getUserListIMResult = UserAdmin.getAllUsers(limit, i*limit);
if (getUserListIMResult != null && getUserListIMResult.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS) {
System.out.println("getUserListIMResult success");
if(getUserListIMResult.getResult().userInfoList.size() < limit) {
break;
}
} else {
System.out.println("getUserListIMResult failure");
System.exit(-1);
}
}
if (commercialServer) { if (commercialServer) {
IMResult<GetOnlineUserCountResult> getOnlineUserCountResultIMResult = UserAdmin.getOnlineUserCount(); IMResult<GetOnlineUserCountResult> getOnlineUserCountResultIMResult = UserAdmin.getOnlineUserCount();
if (getOnlineUserCountResultIMResult != null && getOnlineUserCountResultIMResult.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS) { if (getOnlineUserCountResultIMResult != null && getOnlineUserCountResultIMResult.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS) {
@@ -568,6 +586,14 @@ public class Main {
System.exit(-1); System.exit(-1);
} }
IMResult<PojoGroupMember> groupMemberIMResult = GroupAdmin.getGroupMember(groupInfo.getTarget_id(), "user1");
if (groupMemberIMResult != null && groupMemberIMResult.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS) {
System.out.println("get group member success");
} else {
System.out.println("get group member failure");
System.exit(-1);
}
voidIMResult = GroupAdmin.kickoffGroupMembers("user1", groupInfo.getTarget_id(), Arrays.asList("user3"), null, null); voidIMResult = GroupAdmin.kickoffGroupMembers("user1", groupInfo.getTarget_id(), Arrays.asList("user3"), null, null);
if (voidIMResult != null && voidIMResult.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS) { if (voidIMResult != null && voidIMResult.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS) {
System.out.println("kickoff group member success"); System.out.println("kickoff group member success");
@@ -1211,7 +1237,7 @@ public class Main {
if (resultGetMembers != null && resultGetMembers.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS) { if (resultGetMembers != null && resultGetMembers.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS) {
System.out.println("get group member success"); System.out.println("get group member success");
} else { } else {
System.out.println("create group failure"); System.out.println("get group member failure");
System.exit(-1); System.exit(-1);
} }
@@ -1227,6 +1253,14 @@ public class Main {
System.exit(-1); System.exit(-1);
} }
IMResult<PojoGroupMember> groupMemberIMResult = robotService.getGroupMember(groupInfo.getTarget_id(), "user0");
if (groupMemberIMResult != null && groupMemberIMResult.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS) {
System.out.println("get group member success");
} else {
System.out.println("get group member failure");
System.exit(-1);
}
voidIMResult = robotService.kickoffGroupMembers(groupInfo.getTarget_id(), Arrays.asList("user3"), null, null); voidIMResult = robotService.kickoffGroupMembers(groupInfo.getTarget_id(), Arrays.asList("user3"), null, null);
if (voidIMResult != null && voidIMResult.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS) { if (voidIMResult != null && voidIMResult.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS) {
System.out.println("kickoff group member success"); System.out.println("kickoff group member success");
@@ -1439,6 +1473,14 @@ public class Main {
System.exit(-1); System.exit(-1);
} }
IMResult<Boolean> booleanIMResult = channelServiceApi.isSubscriber("userId2");
if(booleanIMResult != null && booleanIMResult.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS && booleanIMResult.getResult()) {
System.out.println("is subscriber success");
} else {
System.out.println("is subscriber failure");
System.exit(-1);
}
resultVoid = channelServiceApi.unsubscribe("userId2"); resultVoid = channelServiceApi.unsubscribe("userId2");
if (resultVoid != null && resultVoid.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS) { if (resultVoid != null && resultVoid.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS) {
System.out.println("unsubscriber done"); System.out.println("unsubscriber done");
@@ -1679,6 +1721,14 @@ public class Main {
System.out.println("create conference"); System.out.println("create conference");
} }
IMResult<Boolean> booleanIMResult = ConferenceAdmin.existsConferences("helloroomid2");
if(booleanIMResult == null || booleanIMResult.getErrorCode() != ErrorCode.ERROR_CODE_SUCCESS) {
System.out.println("exist conference failure");
System.exit(-1);
} else {
System.out.println("exit conference success");
}
voidIMResult = ConferenceAdmin.enableRecording("helloroomid2", true, true); voidIMResult = ConferenceAdmin.enableRecording("helloroomid2", true, true);
if(voidIMResult == null || voidIMResult.getErrorCode() != ErrorCode.ERROR_CODE_SUCCESS) { if(voidIMResult == null || voidIMResult.getErrorCode() != ErrorCode.ERROR_CODE_SUCCESS) {
System.out.println("recording conference failure"); System.out.println("recording conference failure");
@@ -1704,5 +1754,31 @@ public class Main {
System.out.println("list participants success"); System.out.println("list participants success");
} }
} }
IMResult<PojoConferenceRtpForwarders> listForwarderResult = ConferenceAdmin.listRtpForwarders("6366963312");
if(listForwarderResult == null || listForwarderResult.getErrorCode() != ErrorCode.ERROR_CODE_SUCCESS) {
System.out.println("list rtp forward failure");
} else {
System.out.println("list rtp forward success");
listForwarderResult.getResult().forwarders.forEach(rtpForwarder -> rtpForwarder.streams.forEach(rtpStream -> {
try {
IMResult<Void> stopRtpForwardResult = ConferenceAdmin.stopRtpForward(listForwarderResult.getResult().roomId, rtpForwarder.publisherId, rtpStream.streamId);
if(stopRtpForwardResult == null || stopRtpForwardResult.getErrorCode() != ErrorCode.ERROR_CODE_SUCCESS) {
System.out.println("rtp forward stop failure");
} else {
System.out.println("rtp forward stop success");
}
} catch (Exception e) {
e.printStackTrace();
}
}));
}
IMResult<Void> rtpForwardResult = ConferenceAdmin.rtpForward("6366963312", "cygqmws2k", "192.168.1.81", 10000, 111, 0, 10005, 98, 0);
if(rtpForwardResult == null || rtpForwardResult.getErrorCode() != ErrorCode.ERROR_CODE_SUCCESS) {
System.out.println("rtp forward failure");
} else {
System.out.println("rtp forward success");
}
} }
} }
@@ -134,6 +134,14 @@ public class RobotService {
return robotHttpUtils.httpJsonPost(path, input, OutputGroupMemberList.class); return robotHttpUtils.httpJsonPost(path, input, OutputGroupMemberList.class);
} }
public IMResult<PojoGroupMember> getGroupMember(String groupId, String memberId) throws Exception {
String path = APIPath.Robot_Group_Member_Get;
InputGetGroupMember input = new InputGetGroupMember();
input.setGroupId(groupId);
input.setMemberId(memberId);
return robotHttpUtils.httpJsonPost(path, input, PojoGroupMember.class);
}
public IMResult<Void> addGroupMembers(String groupId, List<PojoGroupMember> groupMembers, List<Integer> to_lines, MessagePayload notify_message) throws Exception { public IMResult<Void> addGroupMembers(String groupId, List<PojoGroupMember> groupMembers, List<Integer> to_lines, MessagePayload notify_message) throws Exception {
String path = APIPath.Robot_Group_Member_Add; String path = APIPath.Robot_Group_Member_Add;
InputAddGroupMember addGroupMember = new InputAddGroupMember(); InputAddGroupMember addGroupMember = new InputAddGroupMember();
@@ -24,6 +24,14 @@ public class UserAdmin {
return AdminHttpUtils.httpJsonPost(path, getUserInfo, InputOutputUserInfo.class); return AdminHttpUtils.httpJsonPost(path, getUserInfo, InputOutputUserInfo.class);
} }
public static IMResult<OutputGetUserList> getAllUsers(int count, int offset) throws Exception {
String path = APIPath.User_Get_All;
InputGetUserList input = new InputGetUserList();
input.count = count;
input.offset = offset;
return AdminHttpUtils.httpJsonPost(path, input, OutputGetUserList.class);
}
public static IMResult<OutputCreateUser> createUser(InputOutputUserInfo user) throws Exception { public static IMResult<OutputCreateUser> createUser(InputOutputUserInfo user) throws Exception {
String path = APIPath.Create_User; String path = APIPath.Create_User;
return AdminHttpUtils.httpJsonPost(path, user, OutputCreateUser.class); return AdminHttpUtils.httpJsonPost(path, user, OutputCreateUser.class);
@@ -128,7 +128,7 @@ public class AdminHttpUtils extends JsonUtils {
if (object != null) { if (object != null) {
jsonStr = gson.toJson(object); jsonStr = gson.toJson(object);
} }
LOG.info("http request content: {}", jsonStr); LOG.info("http request:{} content: {}", path, jsonStr);
StringEntity entity = new StringEntity(jsonStr, Charset.forName("UTF-8")); StringEntity entity = new StringEntity(jsonStr, Charset.forName("UTF-8"));
entity.setContentEncoding("UTF-8"); entity.setContentEncoding("UTF-8");
@@ -78,7 +78,7 @@ public class ChannelHttpUtils extends JsonUtils {
if (object != null) { if (object != null) {
jsonStr = gson.toJson(object); jsonStr = gson.toJson(object);
} }
LOG.info("http request content: {}", jsonStr); LOG.info("http request:{} content: {}", path, jsonStr);
StringEntity entity = new StringEntity(jsonStr, Charset.forName("UTF-8")); StringEntity entity = new StringEntity(jsonStr, Charset.forName("UTF-8"));
entity.setContentEncoding("UTF-8"); entity.setContentEncoding("UTF-8");
@@ -79,7 +79,7 @@ public class RobotHttpUtils extends JsonUtils {
if (object != null) { if (object != null) {
jsonStr = gson.toJson(object); jsonStr = gson.toJson(object);
} }
LOG.info("http request content: {}", jsonStr); LOG.info("http request:{} content: {}", path, jsonStr);
if(!StringUtil.isNullOrEmpty(jsonStr)) { if(!StringUtil.isNullOrEmpty(jsonStr)) {
StringEntity entity = new StringEntity(jsonStr, Charset.forName("UTF-8")); StringEntity entity = new StringEntity(jsonStr, Charset.forName("UTF-8"));